Add support for the OpenCL vec_step operator, by generalising and

extending the existing support for sizeof and alignof.  Original
patch by Guy Benyei.

llvm-svn: 127475
This commit is contained in:
Peter Collingbourne 2011-03-11 19:24:49 +00:00
parent 0122841626
commit e190dee7a5
40 changed files with 395 additions and 228 deletions

View File

@ -37,7 +37,7 @@ public:
// other sub-expressions).
void VisitDeclRefExpr(DeclRefExpr *E) { }
void VisitOffsetOfExpr(OffsetOfExpr *E) { }
void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { }
void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) { }
void VisitBlockExpr(BlockExpr *E) { }
void VisitCXXUuidofExpr(CXXUuidofExpr *E) { }
void VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { }

View File

@ -21,6 +21,7 @@
#include "clang/AST/OperationKinds.h"
#include "clang/AST/ASTVector.h"
#include "clang/AST/UsuallyTinyPtrVector.h"
#include "clang/Basic/TypeTraits.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/SmallVector.h"
@ -1554,10 +1555,11 @@ public:
}
};
/// SizeOfAlignOfExpr - [C99 6.5.3.4] - This is for sizeof/alignof, both of
/// types and expressions.
class SizeOfAlignOfExpr : public Expr {
bool isSizeof : 1; // true if sizeof, false if alignof.
/// UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated)
/// expression operand. Used for sizeof/alignof (C99 6.5.3.4) and
/// vec_step (OpenCL 1.1 6.11.12).
class UnaryExprOrTypeTraitExpr : public Expr {
unsigned Kind : 2;
bool isType : 1; // true if operand is a type, false if an expression
union {
TypeSourceInfo *Ty;
@ -1566,36 +1568,38 @@ class SizeOfAlignOfExpr : public Expr {
SourceLocation OpLoc, RParenLoc;
public:
SizeOfAlignOfExpr(bool issizeof, TypeSourceInfo *TInfo,
QualType resultType, SourceLocation op,
SourceLocation rp) :
Expr(SizeOfAlignOfExprClass, resultType, VK_RValue, OK_Ordinary,
UnaryExprOrTypeTraitExpr(UnaryExprOrTypeTrait ExprKind, TypeSourceInfo *TInfo,
QualType resultType, SourceLocation op,
SourceLocation rp) :
Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary,
false, // Never type-dependent (C++ [temp.dep.expr]p3).
// Value-dependent if the argument is type-dependent.
TInfo->getType()->isDependentType(),
TInfo->getType()->containsUnexpandedParameterPack()),
isSizeof(issizeof), isType(true), OpLoc(op), RParenLoc(rp) {
Kind(ExprKind), isType(true), OpLoc(op), RParenLoc(rp) {
Argument.Ty = TInfo;
}
SizeOfAlignOfExpr(bool issizeof, Expr *E,
QualType resultType, SourceLocation op,
SourceLocation rp) :
Expr(SizeOfAlignOfExprClass, resultType, VK_RValue, OK_Ordinary,
UnaryExprOrTypeTraitExpr(UnaryExprOrTypeTrait ExprKind, Expr *E,
QualType resultType, SourceLocation op,
SourceLocation rp) :
Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary,
false, // Never type-dependent (C++ [temp.dep.expr]p3).
// Value-dependent if the argument is type-dependent.
E->isTypeDependent(),
E->containsUnexpandedParameterPack()),
isSizeof(issizeof), isType(false), OpLoc(op), RParenLoc(rp) {
Kind(ExprKind), isType(false), OpLoc(op), RParenLoc(rp) {
Argument.Ex = E;
}
/// \brief Construct an empty sizeof/alignof expression.
explicit SizeOfAlignOfExpr(EmptyShell Empty)
: Expr(SizeOfAlignOfExprClass, Empty) { }
explicit UnaryExprOrTypeTraitExpr(EmptyShell Empty)
: Expr(UnaryExprOrTypeTraitExprClass, Empty) { }
bool isSizeOf() const { return isSizeof; }
void setSizeof(bool S) { isSizeof = S; }
UnaryExprOrTypeTrait getKind() const {
return static_cast<UnaryExprOrTypeTrait>(Kind);
}
void setKind(UnaryExprOrTypeTrait K) { Kind = K; }
bool isArgumentType() const { return isType; }
QualType getArgumentType() const {
@ -1610,7 +1614,7 @@ public:
return static_cast<Expr*>(Argument.Ex);
}
const Expr *getArgumentExpr() const {
return const_cast<SizeOfAlignOfExpr*>(this)->getArgumentExpr();
return const_cast<UnaryExprOrTypeTraitExpr*>(this)->getArgumentExpr();
}
void setArgument(Expr *E) { Argument.Ex = E; isType = false; }
@ -1636,9 +1640,9 @@ public:
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == SizeOfAlignOfExprClass;
return T->getStmtClass() == UnaryExprOrTypeTraitExprClass;
}
static bool classof(const SizeOfAlignOfExpr *) { return true; }
static bool classof(const UnaryExprOrTypeTraitExpr *) { return true; }
// Iterators
child_range children();

View File

@ -1787,7 +1787,7 @@ DEF_TRAVERSE_STMT(OffsetOfExpr, {
TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
})
DEF_TRAVERSE_STMT(SizeOfAlignOfExpr, {
DEF_TRAVERSE_STMT(UnaryExprOrTypeTraitExpr, {
// The child-iterator will pick up the arg if it's an expression,
// but not if it's a type.
if (S->isArgumentType())
@ -1930,7 +1930,7 @@ DEF_TRAVERSE_STMT(ObjCStringLiteral, { })
// Candidates:
//
// http://clang.llvm.org/doxygen/classclang_1_1CXXTypeidExpr.html
// http://clang.llvm.org/doxygen/classclang_1_1SizeOfAlignOfExpr.html
// http://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html
// http://clang.llvm.org/doxygen/classclang_1_1TypesCompatibleExpr.html
// Every class that has getQualifier.

View File

@ -2343,14 +2343,18 @@ def err_func_def_incomplete_result : Error<
def ext_sizeof_function_type : Extension<
"invalid application of 'sizeof' to a function type">, InGroup<PointerArith>;
def err_sizeof_alignof_overloaded_function_type : Error<
"invalid application of '%select{sizeof|__alignof}0' to an overloaded "
"function">;
"invalid application of '%select{sizeof|__alignof|vec_step}0' to an "
"overloaded function">;
def ext_sizeof_void_type : Extension<
"invalid application of '%0' to a void type">, InGroup<PointerArith>;
"invalid application of '%select{sizeof|__alignof|vec_step}0' to a void "
"type">, InGroup<PointerArith>;
def err_sizeof_alignof_incomplete_type : Error<
"invalid application of '%select{sizeof|__alignof}0' to an incomplete type %1">;
"invalid application of '%select{sizeof|__alignof|vec_step}0' to an "
"incomplete type %1">;
def err_sizeof_alignof_bitfield : Error<
"invalid application of '%select{sizeof|__alignof}0' to bit-field">;
def err_vecstep_non_scalar_vector_type : Error<
"'vec_step' requires built-in scalar or vector type, %0 invalid">;
def err_offsetof_incomplete_type : Error<
"offsetof of incomplete type %0">;
def err_offsetof_record_type : Error<

View File

@ -54,7 +54,7 @@ def CharacterLiteral : DStmt<Expr>;
def ParenExpr : DStmt<Expr>;
def UnaryOperator : DStmt<Expr>;
def OffsetOfExpr : DStmt<Expr>;
def SizeOfAlignOfExpr : DStmt<Expr>;
def UnaryExprOrTypeTraitExpr : DStmt<Expr>;
def ArraySubscriptExpr : DStmt<Expr>;
def CallExpr : DStmt<Expr>;
def MemberExpr : DStmt<Expr>;

View File

@ -346,9 +346,10 @@ KEYWORD(__fastcall , KEYALL)
KEYWORD(__thiscall , KEYALL)
KEYWORD(__forceinline , KEYALL)
// OpenCL-specific keywords (see OpenCL 1.1 [6.1.9])
// OpenCL-specific keywords
KEYWORD(__kernel , KEYOPENCL)
ALIAS("kernel", __kernel , KEYOPENCL)
KEYWORD(vec_step , KEYOPENCL)
// Borland Extensions.
KEYWORD(__pascal , KEYALL)

View File

@ -42,6 +42,13 @@ namespace clang {
BTT_TypeCompatible,
BTT_IsConvertibleTo
};
/// UnaryExprOrTypeTrait - Names for the "expression or type" traits.
enum UnaryExprOrTypeTrait {
UETT_SizeOf,
UETT_AlignOf,
UETT_VecStep
};
}
#endif

View File

@ -1041,10 +1041,10 @@ private:
}
ExprResult ParsePostfixExpressionSuffix(ExprResult LHS);
ExprResult ParseSizeofAlignofExpression();
ExprResult ParseUnaryExprOrTypeTraitExpression();
ExprResult ParseBuiltinPrimaryExpression();
ExprResult ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
ExprResult ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
bool &isCastExpr,
ParsedType &CastTy,
SourceRange &CastRange);

View File

@ -1990,19 +1990,25 @@ public:
ExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
tok::TokenKind Op, Expr *Input);
ExprResult CreateSizeOfAlignOfExpr(TypeSourceInfo *T,
SourceLocation OpLoc,
bool isSizeOf, SourceRange R);
ExprResult CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc,
bool isSizeOf, SourceRange R);
ExprResult CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *T,
SourceLocation OpLoc,
UnaryExprOrTypeTrait ExprKind,
SourceRange R);
ExprResult CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
UnaryExprOrTypeTrait ExprKind,
SourceRange R);
ExprResult
ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
void *TyOrEx, const SourceRange &ArgRange);
ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc,
UnaryExprOrTypeTrait ExprKind,
bool isType, void *TyOrEx,
const SourceRange &ArgRange);
ExprResult CheckPlaceholderExpr(Expr *E, SourceLocation Loc);
bool CheckVecStepExpr(Expr *E, SourceLocation OpLoc, SourceRange R);
bool CheckSizeOfAlignOfOperand(QualType type, SourceLocation OpLoc,
SourceRange R, bool isSizeof);
bool CheckUnaryExprOrTypeTraitOperand(QualType type, SourceLocation OpLoc,
SourceRange R,
UnaryExprOrTypeTrait ExprKind);
ExprResult ActOnSizeofParameterPackExpr(Scope *S,
SourceLocation OpLoc,
IdentifierInfo &Name,

View File

@ -339,9 +339,9 @@ public:
void VisitOffsetOfExpr(const OffsetOfExpr* Ex, ExplodedNode* Pred,
ExplodedNodeSet& Dst);
/// VisitSizeOfAlignOfExpr - Transfer function for sizeof.
void VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr* Ex, ExplodedNode* Pred,
ExplodedNodeSet& Dst);
/// VisitUnaryExprOrTypeTraitExpr - Transfer function for sizeof.
void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr* Ex,
ExplodedNode* Pred, ExplodedNodeSet& Dst);
/// VisitUnaryOperator - Transfer function logic for unary operators.
void VisitUnaryOperator(const UnaryOperator* B, ExplodedNode* Pred,

View File

@ -139,7 +139,7 @@ namespace {
Expr *VisitCharacterLiteral(CharacterLiteral *E);
Expr *VisitParenExpr(ParenExpr *E);
Expr *VisitUnaryOperator(UnaryOperator *E);
Expr *VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
Expr *VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E);
Expr *VisitBinaryOperator(BinaryOperator *E);
Expr *VisitCompoundAssignOperator(CompoundAssignOperator *E);
Expr *VisitImplicitCastExpr(ImplicitCastExpr *E);
@ -3799,7 +3799,8 @@ Expr *ASTNodeImporter::VisitUnaryOperator(UnaryOperator *E) {
Importer.Import(E->getOperatorLoc()));
}
Expr *ASTNodeImporter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
Expr *ASTNodeImporter::VisitUnaryExprOrTypeTraitExpr(
UnaryExprOrTypeTraitExpr *E) {
QualType ResultType = Importer.Import(E->getType());
if (E->isArgumentType()) {
@ -3807,8 +3808,8 @@ Expr *ASTNodeImporter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
if (!TInfo)
return 0;
return new (Importer.getToContext()) SizeOfAlignOfExpr(E->isSizeOf(),
TInfo, ResultType,
return new (Importer.getToContext()) UnaryExprOrTypeTraitExpr(E->getKind(),
TInfo, ResultType,
Importer.Import(E->getOperatorLoc()),
Importer.Import(E->getRParenLoc()));
}
@ -3817,8 +3818,8 @@ Expr *ASTNodeImporter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
if (!SubExpr)
return 0;
return new (Importer.getToContext()) SizeOfAlignOfExpr(E->isSizeOf(),
SubExpr, ResultType,
return new (Importer.getToContext()) UnaryExprOrTypeTraitExpr(E->getKind(),
SubExpr, ResultType,
Importer.Import(E->getOperatorLoc()),
Importer.Import(E->getRParenLoc()));
}

View File

@ -2854,8 +2854,8 @@ const Expr* ConstExprIterator::operator->() const { return cast<Expr>(*I); }
// Child Iterators for iterating over subexpressions/substatements
//===----------------------------------------------------------------------===//
// SizeOfAlignOfExpr
Stmt::child_range SizeOfAlignOfExpr::children() {
// UnaryExprOrTypeTraitExpr
Stmt::child_range UnaryExprOrTypeTraitExpr::children() {
// If this is of a type and the type is a VLA type (and not a typedef), the
// size expression of the VLA needs to be treated as an executable expression.
// Why isn't this weirdness documented better in StmtIterator?

View File

@ -128,7 +128,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
// Expressions that are prvalues.
case Expr::CXXBoolLiteralExprClass:
case Expr::CXXPseudoDestructorExprClass:
case Expr::SizeOfAlignOfExprClass:
case Expr::UnaryExprOrTypeTraitExprClass:
case Expr::CXXNewExprClass:
case Expr::CXXThisExprClass:
case Expr::CXXNullPtrLiteralExprClass:

View File

@ -290,7 +290,8 @@ public:
bool VisitFloatingLiteral(FloatingLiteral *E) { return false; }
bool VisitStringLiteral(StringLiteral *E) { return false; }
bool VisitCharacterLiteral(CharacterLiteral *E) { return false; }
bool VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { return false; }
bool VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E)
{ return false; }
bool VisitArraySubscriptExpr(ArraySubscriptExpr *E)
{ return Visit(E->getLHS()) || Visit(E->getRHS()); }
bool VisitChooseExpr(ChooseExpr *E)
@ -1020,7 +1021,7 @@ public:
bool VisitBinaryConditionalOperator(const BinaryConditionalOperator *E);
bool VisitCastExpr(CastExpr* E);
bool VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E);
bool VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E);
bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E) {
return Success(E->getValue(), E);
@ -1601,36 +1602,59 @@ CharUnits IntExprEvaluator::GetAlignOfExpr(const Expr *E) {
}
/// VisitSizeAlignOfExpr - Evaluate a sizeof or alignof with a result as the
/// expression's type.
bool IntExprEvaluator::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E) {
// Handle alignof separately.
if (!E->isSizeOf()) {
/// VisitUnaryExprOrTypeTraitExpr - Evaluate a sizeof, alignof or vec_step with
/// a result as the expression's type.
bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(
const UnaryExprOrTypeTraitExpr *E) {
switch(E->getKind()) {
case UETT_AlignOf: {
if (E->isArgumentType())
return Success(GetAlignOfType(E->getArgumentType()), E);
else
return Success(GetAlignOfExpr(E->getArgumentExpr()), E);
}
QualType SrcTy = E->getTypeOfArgument();
// C++ [expr.sizeof]p2: "When applied to a reference or a reference type,
// the result is the size of the referenced type."
// C++ [expr.alignof]p3: "When alignof is applied to a reference type, the
// result shall be the alignment of the referenced type."
if (const ReferenceType *Ref = SrcTy->getAs<ReferenceType>())
SrcTy = Ref->getPointeeType();
case UETT_VecStep: {
QualType Ty = E->getTypeOfArgument();
// sizeof(void), __alignof__(void), sizeof(function) = 1 as a gcc
// extension.
if (SrcTy->isVoidType() || SrcTy->isFunctionType())
return Success(1, E);
if (Ty->isVectorType()) {
unsigned n = Ty->getAs<VectorType>()->getNumElements();
// sizeof(vla) is not a constantexpr: C99 6.5.3.4p2.
if (!SrcTy->isConstantSizeType())
return false;
// The vec_step built-in functions that take a 3-component
// vector return 4. (OpenCL 1.1 spec 6.11.12)
if (n == 3)
n = 4;
// Get information about the size.
return Success(Info.Ctx.getTypeSizeInChars(SrcTy), E);
return Success(n, E);
} else
return Success(1, E);
}
case UETT_SizeOf: {
QualType SrcTy = E->getTypeOfArgument();
// C++ [expr.sizeof]p2: "When applied to a reference or a reference type,
// the result is the size of the referenced type."
// C++ [expr.alignof]p3: "When alignof is applied to a reference type, the
// result shall be the alignment of the referenced type."
if (const ReferenceType *Ref = SrcTy->getAs<ReferenceType>())
SrcTy = Ref->getPointeeType();
// sizeof(void), __alignof__(void), sizeof(function) = 1 as a gcc
// extension.
if (SrcTy->isVoidType() || SrcTy->isFunctionType())
return Success(1, E);
// sizeof(vla) is not a constantexpr: C99 6.5.3.4p2.
if (!SrcTy->isConstantSizeType())
return false;
// Get information about the size.
return Success(Info.Ctx.getTypeSizeInChars(SrcTy), E);
}
}
llvm_unreachable("unknown expr/type trait");
return false;
}
bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *E) {
@ -2884,9 +2908,10 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
// are ICEs, the value of the offsetof must be an integer constant.
return CheckEvalInICE(E, Ctx);
}
case Expr::SizeOfAlignOfExprClass: {
const SizeOfAlignOfExpr *Exp = cast<SizeOfAlignOfExpr>(E);
if (Exp->isSizeOf() && Exp->getTypeOfArgument()->isVariableArrayType())
case Expr::UnaryExprOrTypeTraitExprClass: {
const UnaryExprOrTypeTraitExpr *Exp = cast<UnaryExprOrTypeTraitExpr>(E);
if ((Exp->getKind() == UETT_SizeOf) &&
Exp->getTypeOfArgument()->isVariableArrayType())
return ICEDiag(2, E->getLocStart());
return NoDiag();
}

View File

@ -1888,10 +1888,22 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
break;
}
case Expr::SizeOfAlignOfExprClass: {
const SizeOfAlignOfExpr *SAE = cast<SizeOfAlignOfExpr>(E);
if (SAE->isSizeOf()) Out << 's';
else Out << 'a';
case Expr::UnaryExprOrTypeTraitExprClass: {
const UnaryExprOrTypeTraitExpr *SAE = cast<UnaryExprOrTypeTraitExpr>(E);
switch(SAE->getKind()) {
case UETT_SizeOf:
Out << 's';
break;
case UETT_AlignOf:
Out << 'a';
break;
case UETT_VecStep:
Diagnostic &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Error,
"cannot yet mangle vec_step expression");
Diags.Report(DiagID);
return;
}
if (SAE->isArgumentType()) {
Out << 't';
mangleType(SAE->getArgumentType());

View File

@ -141,7 +141,7 @@ namespace {
void VisitFloatingLiteral(FloatingLiteral *Node);
void VisitStringLiteral(StringLiteral *Str);
void VisitUnaryOperator(UnaryOperator *Node);
void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node);
void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node);
void VisitMemberExpr(MemberExpr *Node);
void VisitExtVectorElementExpr(ExtVectorElementExpr *Node);
void VisitBinaryOperator(BinaryOperator *Node);
@ -441,9 +441,19 @@ void StmtDumper::VisitUnaryOperator(UnaryOperator *Node) {
OS << " " << (Node->isPostfix() ? "postfix" : "prefix")
<< " '" << UnaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
}
void StmtDumper::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) {
void StmtDumper::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node) {
DumpExpr(Node);
OS << " " << (Node->isSizeOf() ? "sizeof" : "alignof") << " ";
switch(Node->getKind()) {
case UETT_SizeOf:
OS << " sizeof ";
break;
case UETT_AlignOf:
OS << " __alignof ";
break;
case UETT_VecStep:
OS << " vec_step ";
break;
}
if (Node->isArgumentType())
DumpType(Node->getArgumentType());
}

View File

@ -706,8 +706,18 @@ void StmtPrinter::VisitOffsetOfExpr(OffsetOfExpr *Node) {
OS << ")";
}
void StmtPrinter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) {
OS << (Node->isSizeOf() ? "sizeof" : "__alignof");
void StmtPrinter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node){
switch(Node->getKind()) {
case UETT_SizeOf:
OS << "sizeof";
break;
case UETT_AlignOf:
OS << "__alignof";
break;
case UETT_VecStep:
OS << "vec_step";
break;
}
if (Node->isArgumentType())
OS << "(" << Node->getArgumentType().getAsString(Policy) << ")";
else {

View File

@ -290,9 +290,9 @@ void StmtProfiler::VisitOffsetOfExpr(OffsetOfExpr *S) {
VisitExpr(S);
}
void StmtProfiler::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *S) {
void StmtProfiler::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *S) {
VisitExpr(S);
ID.AddBoolean(S->isSizeOf());
ID.AddInteger(S->getKind());
if (S->isArgumentType())
VisitType(S->getArgumentType());
}

View File

@ -343,7 +343,8 @@ private:
CFGBlock *VisitObjCAtTryStmt(ObjCAtTryStmt *S);
CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S);
CFGBlock *VisitReturnStmt(ReturnStmt* R);
CFGBlock *VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E, AddStmtChoice asc);
CFGBlock *VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E,
AddStmtChoice asc);
CFGBlock *VisitStmtExpr(StmtExpr *S, AddStmtChoice asc);
CFGBlock *VisitSwitchStmt(SwitchStmt *S);
CFGBlock *VisitUnaryOperator(UnaryOperator *U, AddStmtChoice asc);
@ -951,8 +952,9 @@ tryAgain:
case Stmt::ReturnStmtClass:
return VisitReturnStmt(cast<ReturnStmt>(S));
case Stmt::SizeOfAlignOfExprClass:
return VisitSizeOfAlignOfExpr(cast<SizeOfAlignOfExpr>(S), asc);
case Stmt::UnaryExprOrTypeTraitExprClass:
return VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S),
asc);
case Stmt::StmtExprClass:
return VisitStmtExpr(cast<StmtExpr>(S), asc);
@ -2148,8 +2150,8 @@ CFGBlock* CFGBuilder::VisitContinueStmt(ContinueStmt* C) {
return Block;
}
CFGBlock *CFGBuilder::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E,
AddStmtChoice asc) {
CFGBlock *CFGBuilder::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E,
AddStmtChoice asc) {
if (asc.alwaysAdd(*this, E)) {
autoCreateBlock();

View File

@ -324,7 +324,7 @@ public:
void VisitUnaryOperator(UnaryOperator *uo);
void VisitBinaryOperator(BinaryOperator *bo);
void VisitCastExpr(CastExpr *ce);
void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *se);
void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *se);
void BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt *fs);
bool isTrackedVar(const VarDecl *vd) {
@ -516,8 +516,9 @@ void TransferFunctions::VisitCastExpr(clang::CastExpr *ce) {
Visit(ce->getSubExpr());
}
void TransferFunctions::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *se) {
if (se->isSizeOf()) {
void TransferFunctions::VisitUnaryExprOrTypeTraitExpr(
UnaryExprOrTypeTraitExpr *se) {
if (se->getKind() == UETT_SizeOf) {
if (se->getType()->isConstantSizeType())
return;
// Handle VLAs.

View File

@ -184,7 +184,7 @@ public:
return EmitNullValue(E->getType());
}
Value *VisitOffsetOfExpr(OffsetOfExpr *E);
Value *VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E);
Value *VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E);
Value *VisitAddrLabelExpr(const AddrLabelExpr *E) {
llvm::Value *V = CGF.GetAddrOfLabel(E->getLabel());
return Builder.CreateBitCast(V, ConvertType(E->getType()));
@ -1516,12 +1516,13 @@ Value *ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *E) {
return Result;
}
/// VisitSizeOfAlignOfExpr - Return the size or alignment of the type of
/// VisitUnaryExprOrTypeTraitExpr - Return the size or alignment of the type of
/// argument of the sizeof expression as an integer.
Value *
ScalarExprEmitter::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E) {
ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
const UnaryExprOrTypeTraitExpr *E) {
QualType TypeToSize = E->getTypeOfArgument();
if (E->isSizeOf()) {
if (E->getKind() == UETT_SizeOf) {
if (const VariableArrayType *VAT =
CGF.getContext().getAsVariableArrayType(TypeToSize)) {
if (E->isArgumentType()) {

View File

@ -3660,10 +3660,8 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
bool isCastExpr;
ParsedType CastTy;
SourceRange CastRange;
ExprResult Operand = ParseExprAfterTypeofSizeofAlignof(OpTok,
isCastExpr,
CastTy,
CastRange);
ExprResult Operand = ParseExprAfterUnaryExprOrTypeTrait(OpTok, isCastExpr,
CastTy, CastRange);
if (hasParens)
DS.setTypeofParensRange(CastRange);

View File

@ -2371,8 +2371,8 @@ ExprResult Parser::ParseCXX0XAlignArgument(SourceLocation Start) {
SourceLocation TypeLoc = Tok.getLocation();
ParsedType Ty = ParseTypeName().get();
SourceRange TypeRange(Start, Tok.getLocation());
return Actions.ActOnSizeOfAlignOfExpr(TypeLoc, false, true,
Ty.getAsOpaquePtr(), TypeRange);
return Actions.ActOnUnaryExprOrTypeTraitExpr(TypeLoc, UETT_AlignOf, true,
Ty.getAsOpaquePtr(), TypeRange);
} else
return ParseConstantExpression();
}

View File

@ -788,7 +788,8 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw___alignof: // unary-expression: '__alignof' unary-expression
// unary-expression: '__alignof' '(' type-name ')'
// unary-expression: 'alignof' '(' type-id ')'
return ParseSizeofAlignofExpression();
case tok::kw_vec_step: // unary-expression: OpenCL 'vec_step' expression
return ParseUnaryExprOrTypeTraitExpression();
case tok::ampamp: { // unary-expression: '&&' identifier
SourceLocation AmpAmpLoc = ConsumeToken();
if (Tok.isNot(tok::identifier))
@ -1256,10 +1257,10 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
}
}
/// ParseExprAfterTypeofSizeofAlignof - We parsed a typeof/sizeof/alignof and
/// we are at the start of an expression or a parenthesized type-id.
/// OpTok is the operand token (typeof/sizeof/alignof). Returns the expression
/// (isCastExpr == false) or the type (isCastExpr == true).
/// ParseExprAfterUnaryExprOrTypeTrait - We parsed a typeof/sizeof/alignof/
/// vec_step and we are at the start of an expression or a parenthesized
/// type-id. OpTok is the operand token (typeof/sizeof/alignof). Returns the
/// expression (isCastExpr == false) or the type (isCastExpr == true).
///
/// unary-expression: [C99 6.5.3]
/// 'sizeof' unary-expression
@ -1273,15 +1274,20 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
/// typeof ( type-name )
/// [GNU/C++] typeof unary-expression
///
/// [OpenCL 1.1 6.11.12] vec_step built-in function:
/// vec_step ( expressions )
/// vec_step ( type-name )
///
ExprResult
Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
bool &isCastExpr,
ParsedType &CastTy,
SourceRange &CastRange) {
Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
bool &isCastExpr,
ParsedType &CastTy,
SourceRange &CastRange) {
assert((OpTok.is(tok::kw_typeof) || OpTok.is(tok::kw_sizeof) ||
OpTok.is(tok::kw___alignof) || OpTok.is(tok::kw_alignof)) &&
"Not a typeof/sizeof/alignof expression!");
OpTok.is(tok::kw___alignof) || OpTok.is(tok::kw_alignof) ||
OpTok.is(tok::kw_vec_step)) &&
"Not a typeof/sizeof/alignof/vec_step expression!");
ExprResult Operand;
@ -1345,7 +1351,7 @@ Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
}
/// ParseSizeofAlignofExpression - Parse a sizeof or alignof expression.
/// ParseUnaryExprOrTypeTraitExpression - Parse a sizeof or alignof expression.
/// unary-expression: [C99 6.5.3]
/// 'sizeof' unary-expression
/// 'sizeof' '(' type-name ')'
@ -1353,10 +1359,10 @@ Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
/// [GNU] '__alignof' unary-expression
/// [GNU] '__alignof' '(' type-name ')'
/// [C++0x] 'alignof' '(' type-id ')'
ExprResult Parser::ParseSizeofAlignofExpression() {
ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
assert((Tok.is(tok::kw_sizeof) || Tok.is(tok::kw___alignof)
|| Tok.is(tok::kw_alignof)) &&
"Not a sizeof/alignof expression!");
|| Tok.is(tok::kw_alignof) || Tok.is(tok::kw_vec_step)) &&
"Not a sizeof/alignof/vec_step expression!");
Token OpTok = Tok;
ConsumeToken();
@ -1403,24 +1409,31 @@ ExprResult Parser::ParseSizeofAlignofExpression() {
bool isCastExpr;
ParsedType CastTy;
SourceRange CastRange;
ExprResult Operand = ParseExprAfterTypeofSizeofAlignof(OpTok,
isCastExpr,
CastTy,
CastRange);
ExprResult Operand = ParseExprAfterUnaryExprOrTypeTrait(OpTok,
isCastExpr,
CastTy,
CastRange);
UnaryExprOrTypeTrait ExprKind = UETT_SizeOf;
if (OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw___alignof))
ExprKind = UETT_AlignOf;
else if (OpTok.is(tok::kw_vec_step))
ExprKind = UETT_VecStep;
if (isCastExpr)
return Actions.ActOnSizeOfAlignOfExpr(OpTok.getLocation(),
OpTok.is(tok::kw_sizeof),
/*isType=*/true,
CastTy.getAsOpaquePtr(),
CastRange);
return Actions.ActOnUnaryExprOrTypeTraitExpr(OpTok.getLocation(),
ExprKind,
/*isType=*/true,
CastTy.getAsOpaquePtr(),
CastRange);
// If we get here, the operand to the sizeof/alignof was an expresion.
if (!Operand.isInvalid())
Operand = Actions.ActOnSizeOfAlignOfExpr(OpTok.getLocation(),
OpTok.is(tok::kw_sizeof),
/*isType=*/false,
Operand.release(), CastRange);
Operand = Actions.ActOnUnaryExprOrTypeTraitExpr(OpTok.getLocation(),
ExprKind,
/*isType=*/false,
Operand.release(),
CastRange);
return move(Operand);
}

View File

@ -3116,10 +3116,11 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
SourceLocation());
// Build sizeof(returnType)
SizeOfAlignOfExpr *sizeofExpr = new (Context) SizeOfAlignOfExpr(true,
Context->getTrivialTypeSourceInfo(returnType),
Context->getSizeType(),
SourceLocation(), SourceLocation());
UnaryExprOrTypeTraitExpr *sizeofExpr =
new (Context) UnaryExprOrTypeTraitExpr(UETT_SizeOf,
Context->getTrivialTypeSourceInfo(returnType),
Context->getSizeType(), SourceLocation(),
SourceLocation());
// (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
// FIXME: Value of 8 is base on ppc32/x86 ABI for the most common cases.
// For X86 it is more complicated and some kind of target specific routine

View File

@ -3038,7 +3038,7 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) {
if (isa<StmtExpr>(E)) return;
// Don't descend into unevaluated contexts.
if (isa<SizeOfAlignOfExpr>(E)) return;
if (isa<UnaryExprOrTypeTraitExpr>(E)) return;
// Now just recurse over the expression's children.
CC = E->getExprLoc();

View File

@ -1362,7 +1362,7 @@ static bool InitExprContainsUninitializedFields(const Stmt *S,
*L = ME->getMemberLoc();
return true;
}
} else if (isa<SizeOfAlignOfExpr>(S)) {
} else if (isa<UnaryExprOrTypeTraitExpr>(S)) {
// sizeof/alignof doesn't reference contents, do not warn.
return false;
} else if (const UnaryOperator *UOE = dyn_cast<UnaryOperator>(S)) {

View File

@ -2711,10 +2711,10 @@ ExprResult Sema::ActOnParenExpr(SourceLocation L,
/// The UsualUnaryConversions() function is *not* called by this routine.
/// See C99 6.3.2.1p[2-4] for more details.
bool Sema::CheckSizeOfAlignOfOperand(QualType exprType,
SourceLocation OpLoc,
SourceRange ExprRange,
bool isSizeof) {
bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType exprType,
SourceLocation OpLoc,
SourceRange ExprRange,
UnaryExprOrTypeTrait ExprKind) {
if (exprType->isDependentType())
return false;
@ -2725,30 +2725,47 @@ bool Sema::CheckSizeOfAlignOfOperand(QualType exprType,
if (const ReferenceType *Ref = exprType->getAs<ReferenceType>())
exprType = Ref->getPointeeType();
// [OpenCL 1.1 6.11.12] "The vec_step built-in function takes a built-in
// scalar or vector data type argument..."
// Every built-in scalar type (OpenCL 1.1 6.1.1) is either an arithmetic
// type (C99 6.2.5p18) or void.
if (ExprKind == UETT_VecStep) {
if (!(exprType->isArithmeticType() || exprType->isVoidType() ||
exprType->isVectorType())) {
Diag(OpLoc, diag::err_vecstep_non_scalar_vector_type)
<< exprType << ExprRange;
return true;
}
}
// C99 6.5.3.4p1:
if (exprType->isFunctionType()) {
// alignof(function) is allowed as an extension.
if (isSizeof)
Diag(OpLoc, diag::ext_sizeof_function_type) << ExprRange;
if (ExprKind == UETT_SizeOf)
Diag(OpLoc, diag::ext_sizeof_function_type)
<< ExprRange;
return false;
}
// Allow sizeof(void)/alignof(void) as an extension.
// Allow sizeof(void)/alignof(void) as an extension. vec_step(void) is not
// an extension, as void is a built-in scalar type (OpenCL 1.1 6.1.1).
if (exprType->isVoidType()) {
Diag(OpLoc, diag::ext_sizeof_void_type)
<< (isSizeof ? "sizeof" : "__alignof") << ExprRange;
if (ExprKind != UETT_VecStep)
Diag(OpLoc, diag::ext_sizeof_void_type)
<< ExprKind << ExprRange;
return false;
}
if (RequireCompleteType(OpLoc, exprType,
PDiag(diag::err_sizeof_alignof_incomplete_type)
<< int(!isSizeof) << ExprRange))
<< ExprKind << ExprRange))
return true;
// Reject sizeof(interface) and sizeof(interface<proto>) in 64-bit mode.
if (LangOpts.ObjCNonFragileABI && exprType->isObjCObjectType()) {
Diag(OpLoc, diag::err_sizeof_nonfragile_interface)
<< exprType << isSizeof << ExprRange;
<< exprType << (ExprKind == UETT_SizeOf)
<< ExprRange;
return true;
}
@ -2778,78 +2795,98 @@ static bool CheckAlignOfExpr(Sema &S, Expr *E, SourceLocation OpLoc,
if (isa<FieldDecl>(ME->getMemberDecl()))
return false;
return S.CheckSizeOfAlignOfOperand(E->getType(), OpLoc, ExprRange, false);
return S.CheckUnaryExprOrTypeTraitOperand(E->getType(), OpLoc, ExprRange,
UETT_AlignOf);
}
bool Sema::CheckVecStepExpr(Expr *E, SourceLocation OpLoc,
SourceRange ExprRange) {
E = E->IgnoreParens();
// Cannot know anything else if the expression is dependent.
if (E->isTypeDependent())
return false;
return CheckUnaryExprOrTypeTraitOperand(E->getType(), OpLoc, ExprRange,
UETT_VecStep);
}
/// \brief Build a sizeof or alignof expression given a type operand.
ExprResult
Sema::CreateSizeOfAlignOfExpr(TypeSourceInfo *TInfo,
SourceLocation OpLoc,
bool isSizeOf, SourceRange R) {
Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo,
SourceLocation OpLoc,
UnaryExprOrTypeTrait ExprKind,
SourceRange R) {
if (!TInfo)
return ExprError();
QualType T = TInfo->getType();
if (!T->isDependentType() &&
CheckSizeOfAlignOfOperand(T, OpLoc, R, isSizeOf))
CheckUnaryExprOrTypeTraitOperand(T, OpLoc, R, ExprKind))
return ExprError();
// C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
return Owned(new (Context) SizeOfAlignOfExpr(isSizeOf, TInfo,
Context.getSizeType(), OpLoc,
R.getEnd()));
return Owned(new (Context) UnaryExprOrTypeTraitExpr(ExprKind, TInfo,
Context.getSizeType(),
OpLoc, R.getEnd()));
}
/// \brief Build a sizeof or alignof expression given an expression
/// operand.
ExprResult
Sema::CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc,
bool isSizeOf, SourceRange R) {
Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
UnaryExprOrTypeTrait ExprKind,
SourceRange R) {
// Verify that the operand is valid.
bool isInvalid = false;
if (E->isTypeDependent()) {
// Delay type-checking for type-dependent expressions.
} else if (!isSizeOf) {
} else if (ExprKind == UETT_AlignOf) {
isInvalid = CheckAlignOfExpr(*this, E, OpLoc, R);
} else if (ExprKind == UETT_VecStep) {
isInvalid = CheckVecStepExpr(E, OpLoc, R);
} else if (E->getBitField()) { // C99 6.5.3.4p1.
Diag(OpLoc, diag::err_sizeof_alignof_bitfield) << 0;
isInvalid = true;
} else if (E->getType()->isPlaceholderType()) {
ExprResult PE = CheckPlaceholderExpr(E, OpLoc);
if (PE.isInvalid()) return ExprError();
return CreateSizeOfAlignOfExpr(PE.take(), OpLoc, isSizeOf, R);
return CreateUnaryExprOrTypeTraitExpr(PE.take(), OpLoc, ExprKind, R);
} else {
isInvalid = CheckSizeOfAlignOfOperand(E->getType(), OpLoc, R, true);
isInvalid = CheckUnaryExprOrTypeTraitOperand(E->getType(), OpLoc, R,
UETT_SizeOf);
}
if (isInvalid)
return ExprError();
// C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
return Owned(new (Context) SizeOfAlignOfExpr(isSizeOf, E,
Context.getSizeType(), OpLoc,
R.getEnd()));
return Owned(new (Context) UnaryExprOrTypeTraitExpr(ExprKind, E,
Context.getSizeType(),
OpLoc, R.getEnd()));
}
/// ActOnSizeOfAlignOfExpr - Handle @c sizeof(type) and @c sizeof @c expr and
/// the same for @c alignof and @c __alignof
/// ActOnUnaryExprOrTypeTraitExpr - Handle @c sizeof(type) and @c sizeof @c
/// expr and the same for @c alignof and @c __alignof
/// Note that the ArgRange is invalid if isType is false.
ExprResult
Sema::ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
void *TyOrEx, const SourceRange &ArgRange) {
Sema::ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc,
UnaryExprOrTypeTrait ExprKind, bool isType,
void *TyOrEx, const SourceRange &ArgRange) {
// If error parsing type, ignore.
if (TyOrEx == 0) return ExprError();
if (isType) {
TypeSourceInfo *TInfo;
(void) GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrEx), &TInfo);
return CreateSizeOfAlignOfExpr(TInfo, OpLoc, isSizeof, ArgRange);
return CreateUnaryExprOrTypeTraitExpr(TInfo, OpLoc, ExprKind, ArgRange);
}
Expr *ArgEx = (Expr *)TyOrEx;
ExprResult Result
= CreateSizeOfAlignOfExpr(ArgEx, OpLoc, isSizeof, ArgEx->getSourceRange());
= CreateUnaryExprOrTypeTraitExpr(ArgEx, OpLoc, ExprKind,
ArgEx->getSourceRange());
return move(Result);
}

View File

@ -1300,25 +1300,28 @@ public:
NumComponents, RParenLoc);
}
/// \brief Build a new sizeof or alignof expression with a type argument.
/// \brief Build a new sizeof, alignof or vec_step expression with a
/// type argument.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildSizeOfAlignOf(TypeSourceInfo *TInfo,
SourceLocation OpLoc,
bool isSizeOf, SourceRange R) {
return getSema().CreateSizeOfAlignOfExpr(TInfo, OpLoc, isSizeOf, R);
ExprResult RebuildUnaryExprOrTypeTrait(TypeSourceInfo *TInfo,
SourceLocation OpLoc,
UnaryExprOrTypeTrait ExprKind,
SourceRange R) {
return getSema().CreateUnaryExprOrTypeTraitExpr(TInfo, OpLoc, ExprKind, R);
}
/// \brief Build a new sizeof or alignof expression with an expression
/// argument.
/// \brief Build a new sizeof, alignof or vec step expression with an
/// expression argument.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildSizeOfAlignOf(Expr *SubExpr, SourceLocation OpLoc,
bool isSizeOf, SourceRange R) {
ExprResult RebuildUnaryExprOrTypeTrait(Expr *SubExpr, SourceLocation OpLoc,
UnaryExprOrTypeTrait ExprKind,
SourceRange R) {
ExprResult Result
= getSema().CreateSizeOfAlignOfExpr(SubExpr, OpLoc, isSizeOf, R);
= getSema().CreateUnaryExprOrTypeTraitExpr(SubExpr, OpLoc, ExprKind, R);
if (Result.isInvalid())
return ExprError();
@ -5541,7 +5544,8 @@ TreeTransform<Derived>::TransformOpaqueValueExpr(OpaqueValueExpr *E) {
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
TreeTransform<Derived>::TransformUnaryExprOrTypeTraitExpr(
UnaryExprOrTypeTraitExpr *E) {
if (E->isArgumentType()) {
TypeSourceInfo *OldT = E->getArgumentTypeInfo();
@ -5552,9 +5556,9 @@ TreeTransform<Derived>::TransformSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
if (!getDerived().AlwaysRebuild() && OldT == NewT)
return SemaRef.Owned(E);
return getDerived().RebuildSizeOfAlignOf(NewT, E->getOperatorLoc(),
E->isSizeOf(),
E->getSourceRange());
return getDerived().RebuildUnaryExprOrTypeTrait(NewT, E->getOperatorLoc(),
E->getKind(),
E->getSourceRange());
}
ExprResult SubExpr;
@ -5572,9 +5576,10 @@ TreeTransform<Derived>::TransformSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
return SemaRef.Owned(E);
}
return getDerived().RebuildSizeOfAlignOf(SubExpr.get(), E->getOperatorLoc(),
E->isSizeOf(),
E->getSourceRange());
return getDerived().RebuildUnaryExprOrTypeTrait(SubExpr.get(),
E->getOperatorLoc(),
E->getKind(),
E->getSourceRange());
}
template<typename Derived>

View File

@ -97,7 +97,7 @@ namespace clang {
void VisitParenListExpr(ParenListExpr *E);
void VisitUnaryOperator(UnaryOperator *E);
void VisitOffsetOfExpr(OffsetOfExpr *E);
void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E);
void VisitArraySubscriptExpr(ArraySubscriptExpr *E);
void VisitCallExpr(CallExpr *E);
void VisitMemberExpr(MemberExpr *E);
@ -555,9 +555,9 @@ void ASTStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) {
E->setIndexExpr(I, Reader.ReadSubExpr());
}
void ASTStmtReader::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
void ASTStmtReader::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) {
VisitExpr(E);
E->setSizeof(Record[Idx++]);
E->setKind(static_cast<UnaryExprOrTypeTrait>(Record[Idx++]));
if (Record[Idx] == 0) {
E->setArgument(Reader.ReadSubExpr());
++Idx;
@ -1546,7 +1546,7 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) {
break;
case EXPR_SIZEOF_ALIGN_OF:
S = new (Context) SizeOfAlignOfExpr(Empty);
S = new (Context) UnaryExprOrTypeTraitExpr(Empty);
break;
case EXPR_ARRAY_SUBSCRIPT:

View File

@ -68,7 +68,7 @@ namespace clang {
void VisitParenListExpr(ParenListExpr *E);
void VisitUnaryOperator(UnaryOperator *E);
void VisitOffsetOfExpr(OffsetOfExpr *E);
void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E);
void VisitArraySubscriptExpr(ArraySubscriptExpr *E);
void VisitCallExpr(CallExpr *E);
void VisitMemberExpr(MemberExpr *E);
@ -504,9 +504,9 @@ void ASTStmtWriter::VisitOffsetOfExpr(OffsetOfExpr *E) {
Code = serialization::EXPR_OFFSETOF;
}
void ASTStmtWriter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
void ASTStmtWriter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) {
VisitExpr(E);
Record.push_back(E->isSizeOf());
Record.push_back(E->getKind());
if (E->isArgumentType())
Writer.AddTypeSourceInfo(E->getArgumentTypeInfo(), Record);
else {

View File

@ -26,7 +26,7 @@ class WalkAST : public StmtVisitor<WalkAST> {
public:
WalkAST(BugReporter &br) : BR(br) {}
void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E);
void VisitStmt(Stmt *S) { VisitChildren(S); }
void VisitChildren(Stmt *S);
};
@ -39,8 +39,8 @@ void WalkAST::VisitChildren(Stmt *S) {
}
// CWE-467: Use of sizeof() on a Pointer Type
void WalkAST::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
if (!E->isSizeOf())
void WalkAST::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) {
if (E->getKind() != UETT_SizeOf)
return;
// If an explicit type is used in the code, usually the coder knows what he is

View File

@ -641,9 +641,10 @@ bool IdempotentOperationChecker::CanVary(const Expr *Ex,
return false;
// Cases requiring custom logic
case Stmt::SizeOfAlignOfExprClass: {
const SizeOfAlignOfExpr *SE = cast<const SizeOfAlignOfExpr>(Ex);
if (!SE->isSizeOf())
case Stmt::UnaryExprOrTypeTraitExprClass: {
const UnaryExprOrTypeTraitExpr *SE =
cast<const UnaryExprOrTypeTraitExpr>(Ex);
if (SE->getKind() != UETT_SizeOf)
return false;
return SE->getTypeOfArgument()->isVariableArrayType();
}

View File

@ -204,7 +204,7 @@ bool UnreachableCodeChecker::isInvalidPath(const CFGBlock *CB,
// Run each of the checks on the conditions
if (containsMacro(cond) || containsEnum(cond)
|| containsStaticLocal(cond) || containsBuiltinOffsetOf(cond)
|| containsStmt<SizeOfAlignOfExpr>(cond))
|| containsStmt<UnaryExprOrTypeTraitExpr>(cond))
return true;
return false;

View File

@ -690,8 +690,9 @@ void ExprEngine::Visit(const Stmt* S, ExplodedNode* Pred,
VisitOffsetOfExpr(cast<OffsetOfExpr>(S), Pred, Dst);
break;
case Stmt::SizeOfAlignOfExprClass:
VisitSizeOfAlignOfExpr(cast<SizeOfAlignOfExpr>(S), Pred, Dst);
case Stmt::UnaryExprOrTypeTraitExprClass:
VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S),
Pred, Dst);
break;
case Stmt::StmtExprClass: {
@ -2410,19 +2411,15 @@ void ExprEngine::VisitInitListExpr(const InitListExpr* E, ExplodedNode* Pred,
assert(0 && "unprocessed InitListExpr type");
}
/// VisitSizeOfAlignOfExpr - Transfer function for sizeof(type).
void ExprEngine::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr* Ex,
/// VisitUnaryExprOrTypeTraitExpr - Transfer function for sizeof(type).
void ExprEngine::VisitUnaryExprOrTypeTraitExpr(
const UnaryExprOrTypeTraitExpr* Ex,
ExplodedNode* Pred,
ExplodedNodeSet& Dst) {
QualType T = Ex->getTypeOfArgument();
CharUnits amt;
if (Ex->isSizeOf()) {
if (T == getContext().VoidTy) {
// sizeof(void) == 1 byte.
amt = CharUnits::One();
}
else if (!T->isConstantSizeType()) {
if (Ex->getKind() == UETT_SizeOf) {
if (!T->isIncompleteType() && !T->isConstantSizeType()) {
assert(T->isVariableArrayType() && "Unknown non-constant-sized type.");
// FIXME: Add support for VLA type arguments, not just VLA expressions.
@ -2463,13 +2460,11 @@ void ExprEngine::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr* Ex,
Dst.Add(Pred);
return;
}
else {
// All other cases.
amt = getContext().getTypeSizeInChars(T);
}
}
else // Get alignment of the type.
amt = getContext().getTypeAlignInChars(T);
Expr::EvalResult Result;
Ex->Evaluate(Result, getContext());
CharUnits amt = CharUnits::fromQuantity(Result.Val.getInt().getZExtValue());
MakeNode(Dst, Ex, Pred,
GetState(Pred)->BindExpr(Ex,

View File

@ -39,7 +39,7 @@ negate_enum *int_ptr4 = &integer;
// OffsetOfExpr
offsetof_type *offsetof_ptr = &size_type_value;
// SizeOfAlignOfExpr
// UnaryExprOrTypeTraitExpr
typeof(sizeof(float)) size_t_value;
typeof_sizeof *size_t_ptr = &size_t_value;
typeof_sizeof2 *size_t_ptr2 = &size_t_value;

View File

@ -38,7 +38,7 @@ struct Z {
typedef typeof(__builtin_offsetof(struct Z, y.array[1 + 2].member))
offsetof_type;
// SizeOfAlignOfExpr
// UnaryExprOrTypeTraitExpr
typedef typeof(sizeof(int)) typeof_sizeof;
typedef typeof(sizeof(Enumerator)) typeof_sizeof2;

View File

@ -0,0 +1,32 @@
// RUN: %clang_cc1 -fsyntax-only -pedantic -verify %s
typedef int int2 __attribute__((ext_vector_type(2)));
typedef int int3 __attribute__((ext_vector_type(3)));
typedef int int4 __attribute__((ext_vector_type(4)));
typedef int int8 __attribute__((ext_vector_type(8)));
typedef int int16 __attribute__((ext_vector_type(16)));
void foo(int3 arg1, int8 arg2) {
int4 auto1;
int16 *auto2;
int auto3;
int2 auto4;
struct S *incomplete1;
int res1[vec_step(arg1) == 4 ? 1 : -1];
int res2[vec_step(arg2) == 8 ? 1 : -1];
int res3[vec_step(auto1) == 4 ? 1 : -1];
int res4[vec_step(*auto2) == 16 ? 1 : -1];
int res5[vec_step(auto3) == 1 ? 1 : -1];
int res6[vec_step(auto4) == 2 ? 1 : -1];
int res7[vec_step(int2) == 2 ? 1 : -1];
int res8[vec_step(int3) == 4 ? 1 : -1];
int res9[vec_step(int4) == 4 ? 1 : -1];
int res10[vec_step(int8) == 8 ? 1 : -1];
int res11[vec_step(int16) == 16 ? 1 : -1];
int res12[vec_step(void) == 1 ? 1 : -1];
int res13 = vec_step(*incomplete1); // expected-error {{'vec_step' requires built-in scalar or vector type, 'struct S' invalid}}
int res14 = vec_step(int16*); // expected-error {{'vec_step' requires built-in scalar or vector type, 'int16 *' invalid}}
int res15 = vec_step(void(void)); // expected-error {{'vec_step' requires built-in scalar or vector type, 'void (void)' invalid}}
}

View File

@ -1749,7 +1749,7 @@ public:
void VisitObjCEncodeExpr(ObjCEncodeExpr *E);
void VisitObjCMessageExpr(ObjCMessageExpr *M);
void VisitOverloadExpr(OverloadExpr *E);
void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E);
void VisitStmt(Stmt *S);
void VisitSwitchStmt(SwitchStmt *S);
void VisitWhileStmt(WhileStmt *W);
@ -2014,7 +2014,8 @@ void EnqueueVisitor::VisitOverloadExpr(OverloadExpr *E) {
AddExplicitTemplateArgs(E->getOptionalExplicitTemplateArgs());
WL.push_back(OverloadExprParts(E, Parent));
}
void EnqueueVisitor::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
void EnqueueVisitor::VisitUnaryExprOrTypeTraitExpr(
UnaryExprOrTypeTraitExpr *E) {
EnqueueChildren(E);
if (E->isArgumentType())
AddTypeLoc(E->getArgumentTypeInfo());

View File

@ -111,7 +111,7 @@ CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent,
case Stmt::ParenExprClass:
case Stmt::UnaryOperatorClass:
case Stmt::OffsetOfExprClass:
case Stmt::SizeOfAlignOfExprClass:
case Stmt::UnaryExprOrTypeTraitExprClass:
case Stmt::ArraySubscriptExprClass:
case Stmt::BinaryOperatorClass:
case Stmt::CompoundAssignOperatorClass: