// 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) { }
#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"
}
};
-/// 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;
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 {
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; }
}
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();
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())
// 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.
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<
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>;
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)
BTT_TypeCompatible,
BTT_IsConvertibleTo
};
+
+ /// UnaryExprOrTypeTrait - Names for the "expression or type" traits.
+ enum UnaryExprOrTypeTrait {
+ UETT_SizeOf,
+ UETT_AlignOf,
+ UETT_VecStep
+ };
}
#endif
}
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);
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,
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,
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);
Importer.Import(E->getOperatorLoc()));
}
-Expr *ASTNodeImporter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
+Expr *ASTNodeImporter::VisitUnaryExprOrTypeTraitExpr(
+ UnaryExprOrTypeTraitExpr *E) {
QualType ResultType = Importer.Import(E->getType());
if (E->isArgumentType()) {
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()));
}
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()));
}
// 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?
// 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:
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)
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);
}
-/// 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;
+
+ 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();
- // Get information about the size.
- return Success(Info.Ctx.getTypeSizeInChars(SrcTy), E);
+ // 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) {
// 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();
}
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());
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);
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());
}
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 {
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());
}
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);
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);
return Block;
}
-CFGBlock *CFGBuilder::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E,
- AddStmtChoice asc) {
+CFGBlock *CFGBuilder::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E,
+ AddStmtChoice asc) {
if (asc.alwaysAdd(*this, E)) {
autoCreateBlock();
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) {
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.
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()));
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()) {
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);
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();
}
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))
}
}
-/// 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
/// 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;
}
-/// 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 ')'
/// [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();
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);
}
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
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();
*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)) {
/// 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;
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;
}
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);
}
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();
template<typename Derived>
ExprResult
-TreeTransform<Derived>::TransformSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
+TreeTransform<Derived>::TransformUnaryExprOrTypeTraitExpr(
+ UnaryExprOrTypeTraitExpr *E) {
if (E->isArgumentType()) {
TypeSourceInfo *OldT = E->getArgumentTypeInfo();
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;
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>
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);
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;
break;
case EXPR_SIZEOF_ALIGN_OF:
- S = new (Context) SizeOfAlignOfExpr(Empty);
+ S = new (Context) UnaryExprOrTypeTraitExpr(Empty);
break;
case EXPR_ARRAY_SUBSCRIPT:
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);
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 {
public:
WalkAST(BugReporter &br) : BR(br) {}
- void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
+ void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E);
void VisitStmt(Stmt *S) { VisitChildren(S); }
void 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
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();
}
// 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;
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: {
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.
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,
// 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;
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;
--- /dev/null
+// 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}}
+}
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);
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());
case Stmt::ParenExprClass:
case Stmt::UnaryOperatorClass:
case Stmt::OffsetOfExprClass:
- case Stmt::SizeOfAlignOfExprClass:
+ case Stmt::UnaryExprOrTypeTraitExprClass:
case Stmt::ArraySubscriptExprClass:
case Stmt::BinaryOperatorClass:
case Stmt::CompoundAssignOperatorClass: