mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-30 17:21:10 +00:00
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:
parent
0122841626
commit
e190dee7a5
@ -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) { }
|
||||
|
@ -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();
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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<
|
||||
|
@ -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>;
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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()));
|
||||
}
|
||||
|
@ -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?
|
||||
|
@ -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:
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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.
|
||||
|
@ -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()) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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)) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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:
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
32
clang/test/SemaOpenCL/vec_step.cl
Normal file
32
clang/test/SemaOpenCL/vec_step.cl
Normal 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}}
|
||||
}
|
@ -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());
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user