From: John Wiegley Date: Thu, 28 Apr 2011 00:16:57 +0000 (+0000) Subject: Implementation of Embarcadero array type traits X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=21ff2e516b0e0bc8c1dbf965cb3d44bac3c64330;p=clang Implementation of Embarcadero array type traits Patch authored by John Wiegley. These are array type traits used for parsing code that employs certain features of the Embarcadero C++ compiler: __array_rank(T) and __array_extent(T, Dim). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130351 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 5aaeb8e7ab..1311030e77 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -1594,6 +1594,68 @@ public: friend class ASTStmtReader; }; +/// ArrayTypeTraitExpr - An Embarcadero array type trait, as used in the +/// implementation of __array_rank and __array_extent. +/// Example: +/// __array_rank(int[10][20]) == 2 +/// __array_extent(int, 1) == 20 +class ArrayTypeTraitExpr : public Expr { + /// ATT - The trait. An ArrayTypeTrait enum in MSVC compat unsigned. + unsigned ATT : 2; + + /// The value of the type trait. Unspecified if dependent. + uint64_t Value; + + /// The array dimension being queried, or -1 if not used + Expr *Dimension; + + /// Loc - The location of the type trait keyword. + SourceLocation Loc; + + /// RParen - The location of the closing paren. + SourceLocation RParen; + + /// The type being queried. + TypeSourceInfo *QueriedType; + +public: + ArrayTypeTraitExpr(SourceLocation loc, ArrayTypeTrait att, + TypeSourceInfo *queried, uint64_t value, + Expr *dimension, SourceLocation rparen, QualType ty) + : Expr(ArrayTypeTraitExprClass, ty, VK_RValue, OK_Ordinary, + false, queried->getType()->isDependentType(), + queried->getType()->containsUnexpandedParameterPack()), + ATT(att), Value(value), Dimension(dimension), + Loc(loc), RParen(rparen), QueriedType(queried) { } + + + explicit ArrayTypeTraitExpr(EmptyShell Empty) + : Expr(ArrayTypeTraitExprClass, Empty), ATT(0), Value(false), + QueriedType() { } + + virtual SourceRange getSourceRange() const { return SourceRange(Loc, RParen); } + + ArrayTypeTrait getTrait() const { return static_cast(ATT); } + + QualType getQueriedType() const { return QueriedType->getType(); } + + TypeSourceInfo *getQueriedTypeSourceInfo() const { return QueriedType; } + + uint64_t getValue() const { assert(!isTypeDependent()); return Value; } + + Expr *getDimensionExpression() const { return Dimension; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ArrayTypeTraitExprClass; + } + static bool classof(const ArrayTypeTraitExpr *) { return true; } + + // Iterators + child_range children() { return child_range(); } + + friend class ASTStmtReader; +}; + /// ExpressionTraitExpr - An expression trait intrinsic /// Example: /// __is_lvalue_expr(std::cout) == true diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 93cc446afd..28daf51dd9 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -1849,6 +1849,10 @@ DEF_TRAVERSE_STMT(BinaryTypeTraitExpr, { TRY_TO(TraverseTypeLoc(S->getRhsTypeSourceInfo()->getTypeLoc())); }) +DEF_TRAVERSE_STMT(ArrayTypeTraitExpr, { + TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc())); + }) + DEF_TRAVERSE_STMT(ExpressionTraitExpr, { TRY_TO(TraverseStmt(S->getQueriedExpression())); }) diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td index de3fedb724..d87d14ff53 100644 --- a/include/clang/Basic/StmtNodes.td +++ b/include/clang/Basic/StmtNodes.td @@ -104,6 +104,7 @@ def CXXDeleteExpr : DStmt; def CXXPseudoDestructorExpr : DStmt; def UnaryTypeTraitExpr : DStmt; def BinaryTypeTraitExpr : DStmt; +def ArrayTypeTraitExpr : DStmt; def ExpressionTraitExpr : DStmt; def DependentScopeDeclRefExpr : DStmt; def CXXConstructExpr : DStmt; diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index e66922eaa2..1d121a1596 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -378,6 +378,8 @@ KEYWORD(__is_unsigned , KEYCXX) // Embarcadero Binary Type Traits KEYWORD(__is_same , KEYCXX) KEYWORD(__is_convertible , KEYCXX) +KEYWORD(__array_rank , KEYCXX) +KEYWORD(__array_extent , KEYCXX) // Apple Extension. KEYWORD(__private_extern__ , KEYALL) diff --git a/include/clang/Basic/TypeTraits.h b/include/clang/Basic/TypeTraits.h index 6ba1bbdeee..cafc387881 100644 --- a/include/clang/Basic/TypeTraits.h +++ b/include/clang/Basic/TypeTraits.h @@ -71,6 +71,12 @@ namespace clang { BTT_TypeCompatible }; + /// ArrayTypeTrait - Names for the array type traits. + enum ArrayTypeTrait { + ATT_ArrayRank, + ATT_ArrayExtent + }; + /// UnaryExprOrTypeTrait - Names for the "expression or type" traits. enum UnaryExprOrTypeTrait { UETT_SizeOf, diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 43089773f4..cda9a61b33 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -1816,7 +1816,8 @@ private: ExprResult ParseBinaryTypeTrait(); //===--------------------------------------------------------------------===// - // Embarcadero: Expression Traits + // Embarcadero: Arary and Expression Traits + ExprResult ParseArrayTypeTrait(); ExprResult ParseExpressionTrait(); //===--------------------------------------------------------------------===// diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 691a17b63c..72878de047 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -2736,6 +2736,20 @@ public: TypeSourceInfo *RhsT, SourceLocation RParen); + /// ActOnArrayTypeTrait - Parsed one of the bianry type trait support + /// pseudo-functions. + ExprResult ActOnArrayTypeTrait(ArrayTypeTrait ATT, + SourceLocation KWLoc, + ParsedType LhsTy, + Expr *DimExpr, + SourceLocation RParen); + + ExprResult BuildArrayTypeTrait(ArrayTypeTrait ATT, + SourceLocation KWLoc, + TypeSourceInfo *TSInfo, + Expr *DimExpr, + SourceLocation RParen); + /// ActOnExpressionTrait - Parsed one of the unary type trait support /// pseudo-functions. ExprResult ActOnExpressionTrait(ExpressionTrait OET, diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index 06be217915..1cfd458a38 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -978,6 +978,7 @@ namespace clang { EXPR_OPAQUE_VALUE, // OpaqueValueExpr EXPR_BINARY_CONDITIONAL_OPERATOR, // BinaryConditionalOperator EXPR_BINARY_TYPE_TRAIT, // BinaryTypeTraitExpr + EXPR_ARRAY_TYPE_TRAIT, // ArrayTypeTraitIntExpr EXPR_PACK_EXPANSION, // PackExpansionExpr EXPR_SIZEOF_PACK, // SizeOfPackExpr diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index ebbdf94f10..888a93c8aa 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -152,6 +152,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::CXXScalarValueInitExprClass: case Expr::UnaryTypeTraitExprClass: case Expr::BinaryTypeTraitExprClass: + case Expr::ArrayTypeTraitExprClass: case Expr::ExpressionTraitExprClass: case Expr::ObjCSelectorExprClass: case Expr::ObjCProtocolExprClass: diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 519bbaa115..c2caf8d40b 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -1061,6 +1061,10 @@ public: return Success(E->getValue(), E); } + bool VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) { + return Success(E->getValue(), E); + } + bool VisitExpressionTraitExpr(const ExpressionTraitExpr *E) { return Success(E->getValue(), E); } @@ -2879,6 +2883,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::CXXScalarValueInitExprClass: case Expr::UnaryTypeTraitExprClass: case Expr::BinaryTypeTraitExprClass: + case Expr::ArrayTypeTraitExprClass: case Expr::ExpressionTraitExprClass: case Expr::CXXNoexceptExprClass: return NoDiag(); diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index 14ee74be12..82de578412 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -1911,6 +1911,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { case Expr::StmtExprClass: case Expr::UnaryTypeTraitExprClass: case Expr::BinaryTypeTraitExprClass: + case Expr::ArrayTypeTraitExprClass: case Expr::ExpressionTraitExprClass: case Expr::VAArgExprClass: case Expr::CXXUuidofExprClass: diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index b96591b661..62f06dba16 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -1308,6 +1308,14 @@ static const char *getTypeTraitName(BinaryTypeTrait BTT) { return ""; } +static const char *getTypeTraitName(ArrayTypeTrait ATT) { + switch (ATT) { + case ATT_ArrayRank: return "__array_rank"; + case ATT_ArrayExtent: return "__array_extent"; + } + return ""; +} + static const char *getExpressionTraitName(ExpressionTrait ET) { switch (ET) { default: llvm_unreachable("Unknown expression trait"); @@ -1328,6 +1336,11 @@ void StmtPrinter::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) { << E->getRhsType().getAsString(Policy) << ")"; } +void StmtPrinter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { + OS << getTypeTraitName(E->getTrait()) << "(" + << E->getQueriedType().getAsString(Policy) << ")"; +} + void StmtPrinter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) { OS << getExpressionTraitName(E->getTrait()) << "("; PrintExpr(E->getQueriedExpression()); diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index fe9a10b01e..7a3fc5417c 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -802,6 +802,12 @@ void StmtProfiler::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *S) { VisitType(S->getRhsType()); } +void StmtProfiler::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *S) { + VisitExpr(S); + ID.AddInteger(S->getTrait()); + VisitType(S->getQueriedType()); +} + void StmtProfiler::VisitExpressionTraitExpr(ExpressionTraitExpr *S) { VisitExpr(S); ID.AddInteger(S->getTrait()); diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index f6de1fa127..6bcc425ce6 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -367,6 +367,10 @@ public: return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue()); } + Value *VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) { + return llvm::ConstantInt::get(Builder.getInt32Ty(), E->getValue()); + } + Value *VisitExpressionTraitExpr(const ExpressionTraitExpr *E) { return llvm::ConstantInt::get(Builder.getInt1Ty(), E->getValue()); } diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 1c4a942780..8b9e5e752b 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -490,6 +490,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, /// [C++] 'this' [C++ 9.3.2] /// [G++] unary-type-trait '(' type-id ')' /// [G++] binary-type-trait '(' type-id ',' type-id ')' [TODO] +/// [EMBT] array-type-trait '(' type-id ',' integer ')' /// [clang] '^' block-literal /// /// constant: [C99 6.4.4] @@ -571,6 +572,10 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, /// '__is_convertible' /// '__is_same' /// +/// [Embarcadero] array-type-trait: +/// '__array_rank' +/// '__array_extent' +/// /// [Embarcadero] expression-trait: /// '__is_lvalue_expr' /// '__is_rvalue_expr' @@ -1072,6 +1077,10 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw___is_convertible_to: return ParseBinaryTypeTrait(); + case tok::kw___array_rank: + case tok::kw___array_extent: + return ParseArrayTypeTrait(); + case tok::kw___is_lvalue_expr: case tok::kw___is_rvalue_expr: return ParseExpressionTrait(); diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index aade050df4..50752058cd 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -1970,6 +1970,14 @@ static BinaryTypeTrait BinaryTypeTraitFromTokKind(tok::TokenKind kind) { } } +static ArrayTypeTrait ArrayTypeTraitFromTokKind(tok::TokenKind kind) { + switch(kind) { + default: llvm_unreachable("Not a known binary type trait"); + case tok::kw___array_rank: return ATT_ArrayRank; + case tok::kw___array_extent: return ATT_ArrayExtent; + } +} + static ExpressionTrait ExpressionTraitFromTokKind(tok::TokenKind kind) { switch(kind) { default: assert(false && "Not a known unary expression trait."); @@ -2043,6 +2051,50 @@ ExprResult Parser::ParseBinaryTypeTrait() { return Actions.ActOnBinaryTypeTrait(BTT, Loc, LhsTy.get(), RhsTy.get(), RParen); } +/// ParseArrayTypeTrait - Parse the built-in array type-trait +/// pseudo-functions. +/// +/// primary-expression: +/// [Embarcadero] '__array_rank' '(' type-id ')' +/// [Embarcadero] '__array_extent' '(' type-id ',' expression ')' +/// +ExprResult Parser::ParseArrayTypeTrait() { + ArrayTypeTrait ATT = ArrayTypeTraitFromTokKind(Tok.getKind()); + SourceLocation Loc = ConsumeToken(); + + SourceLocation LParen = Tok.getLocation(); + if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen)) + return ExprError(); + + TypeResult Ty = ParseTypeName(); + if (Ty.isInvalid()) { + SkipUntil(tok::comma); + SkipUntil(tok::r_paren); + return ExprError(); + } + + switch (ATT) { + case ATT_ArrayRank: { + SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen); + return Actions.ActOnArrayTypeTrait(ATT, Loc, Ty.get(), NULL, RParen); + } + case ATT_ArrayExtent: { + if (ExpectAndConsume(tok::comma, diag::err_expected_comma)) { + SkipUntil(tok::r_paren); + return ExprError(); + } + + ExprResult DimExpr = ParseExpression(); + SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen); + + return Actions.ActOnArrayTypeTrait(ATT, Loc, Ty.get(), DimExpr.get(), RParen); + } + default: + break; + } + return ExprError(); +} + /// ParseExpressionTrait - Parse built-in expression-trait /// pseudo-functions like __is_lvalue_expr( xxx ). /// diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 7086176d89..0617abd680 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2812,6 +2812,94 @@ ExprResult Sema::BuildBinaryTypeTrait(BinaryTypeTrait BTT, ResultType)); } +ExprResult Sema::ActOnArrayTypeTrait(ArrayTypeTrait ATT, + SourceLocation KWLoc, + ParsedType Ty, + Expr* DimExpr, + SourceLocation RParen) { + TypeSourceInfo *TSInfo; + QualType T = GetTypeFromParser(Ty, &TSInfo); + if (!TSInfo) + TSInfo = Context.getTrivialTypeSourceInfo(T); + + return BuildArrayTypeTrait(ATT, KWLoc, TSInfo, DimExpr, RParen); +} + +static uint64_t EvaluateArrayTypeTrait(Sema &Self, ArrayTypeTrait ATT, + QualType T, Expr *DimExpr, + SourceLocation KeyLoc) { + assert((!T->isDependentType()) && + "Cannot evaluate traits for dependent types."); + + switch(ATT) { + case ATT_ArrayRank: + if (T->isArrayType()) { + unsigned Dim = 0; + while (const ArrayType *AT = Self.Context.getAsArrayType(T)) { + ++Dim; + T = AT->getElementType(); + } + return Dim; + } else { + assert(! "Array type trait applied to non-array type"); + } + case ATT_ArrayExtent: { + llvm::APSInt Value; + uint64_t Dim; + if (DimExpr->isIntegerConstantExpr(Value, Self.Context, 0, false)) + Dim = Value.getLimitedValue(); + else + assert(! "Dimension expression did not evaluate to a constant integer"); + + if (T->isArrayType()) { + unsigned D = 0; + bool Matched = false; + while (const ArrayType *AT = Self.Context.getAsArrayType(T)) { + if (Dim == D) { + Matched = true; + break; + } + ++D; + T = AT->getElementType(); + } + + assert(Matched && T->isArrayType() && + "__array_extent does not refer to an array dimension"); + + llvm::APInt size = Self.Context.getAsConstantArrayType(T)->getSize(); + return size.getLimitedValue(); + } else { + assert(! "Array type trait applied to non-array type"); + } + } + } + llvm_unreachable("Unknown type trait or not implemented"); +} + +ExprResult Sema::BuildArrayTypeTrait(ArrayTypeTrait ATT, + SourceLocation KWLoc, + TypeSourceInfo *TSInfo, + Expr* DimExpr, + SourceLocation RParen) { + QualType T = TSInfo->getType(); + + uint64_t Value; + if (!T->isDependentType()) + Value = EvaluateArrayTypeTrait(*this, ATT, T, DimExpr, KWLoc); + else + return ExprError(); + + // Select trait result type. + QualType ResultType; + switch (ATT) { + case ATT_ArrayRank: ResultType = Context.IntTy; break; + case ATT_ArrayExtent: ResultType = Context.IntTy; break; + } + + return Owned(new (Context) ArrayTypeTraitExpr(KWLoc, ATT, TSInfo, Value, + DimExpr, RParen, ResultType)); +} + ExprResult Sema::ActOnExpressionTrait(ExpressionTrait ET, SourceLocation KWLoc, Expr* Queried, diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index b2aa85e719..f5ec3a2170 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -1915,6 +1915,18 @@ public: return getSema().BuildBinaryTypeTrait(Trait, StartLoc, LhsT, RhsT, RParenLoc); } + /// \brief Build a new array type trait expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildArrayTypeTrait(ArrayTypeTrait Trait, + SourceLocation StartLoc, + TypeSourceInfo *TSInfo, + Expr *DimExpr, + SourceLocation RParenLoc) { + return getSema().BuildArrayTypeTrait(Trait, StartLoc, TSInfo, DimExpr, RParenLoc); + } + /// \brief Build a new expression trait expression. /// /// By default, performs semantic analysis to build the new expression. @@ -6919,6 +6931,35 @@ TreeTransform::TransformBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) { E->getLocEnd()); } +template +ExprResult +TreeTransform::TransformArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { + TypeSourceInfo *T = getDerived().TransformType(E->getQueriedTypeSourceInfo()); + if (!T) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + T == E->getQueriedTypeSourceInfo()) + return SemaRef.Owned(E); + + ExprResult SubExpr; + { + EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + SubExpr = getDerived().TransformExpr(E->getDimensionExpression()); + if (SubExpr.isInvalid()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getDimensionExpression()) + return SemaRef.Owned(E); + } + + return getDerived().RebuildArrayTypeTrait(E->getTrait(), + E->getLocStart(), + T, + SubExpr.get(), + E->getLocEnd()); +} + template ExprResult TreeTransform::TransformExpressionTraitExpr(ExpressionTraitExpr *E) { diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 3435fd92d3..83b3907f58 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -179,6 +179,7 @@ namespace clang { void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E); void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E); + void VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E); void VisitExpressionTraitExpr(ExpressionTraitExpr *E); void VisitCXXNoexceptExpr(CXXNoexceptExpr *E); void VisitPackExpansionExpr(PackExpansionExpr *E); @@ -1344,6 +1345,16 @@ void ASTStmtReader::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) { E->RhsType = GetTypeSourceInfo(Record, Idx); } +void ASTStmtReader::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { + VisitExpr(E); + E->ATT = (ArrayTypeTrait)Record[Idx++]; + E->Value = (unsigned int)Record[Idx++]; + SourceRange Range = ReadSourceRange(Record, Idx); + E->Loc = Range.getBegin(); + E->RParen = Range.getEnd(); + E->QueriedType = GetTypeSourceInfo(Record, Idx); +} + void ASTStmtReader::VisitExpressionTraitExpr(ExpressionTraitExpr *E) { VisitExpr(E); E->ET = (ExpressionTrait)Record[Idx++]; @@ -1946,6 +1957,10 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { S = new (Context) BinaryTypeTraitExpr(Empty); break; + case EXPR_ARRAY_TYPE_TRAIT: + S = new (Context) ArrayTypeTraitExpr(Empty); + break; + case EXPR_CXX_EXPRESSION_TRAIT: S = new (Context) ExpressionTraitExpr(Empty); break; diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index 53fb9738e6..4fe3bae91a 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -153,6 +153,7 @@ namespace clang { void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E); void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E); + void VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E); void VisitExpressionTraitExpr(ExpressionTraitExpr *E); void VisitCXXNoexceptExpr(CXXNoexceptExpr *E); void VisitPackExpansionExpr(PackExpansionExpr *E); @@ -1340,6 +1341,15 @@ void ASTStmtWriter::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) { Code = serialization::EXPR_BINARY_TYPE_TRAIT; } +void ASTStmtWriter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { + VisitExpr(E); + Record.push_back(E->getTrait()); + Record.push_back(E->getValue()); + Writer.AddSourceRange(E->getSourceRange(), Record); + Writer.AddTypeSourceInfo(E->getQueriedTypeSourceInfo(), Record); + Code = serialization::EXPR_ARRAY_TYPE_TRAIT; +} + void ASTStmtWriter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) { VisitExpr(E); Record.push_back(E->getTrait()); diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 49af4304b0..5c1dfb80ec 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -435,6 +435,7 @@ void ExprEngine::Visit(const Stmt* S, ExplodedNode* Pred, case Stmt::DependentScopeDeclRefExprClass: case Stmt::UnaryTypeTraitExprClass: case Stmt::BinaryTypeTraitExprClass: + case Stmt::ArrayTypeTraitExprClass: case Stmt::ExpressionTraitExprClass: case Stmt::UnresolvedLookupExprClass: case Stmt::UnresolvedMemberExprClass: diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp index ef5607b20c..1dec7f923a 100644 --- a/test/SemaCXX/type-traits.cpp +++ b/test/SemaCXX/type-traits.cpp @@ -1464,3 +1464,14 @@ void is_trivial() { int arr[F(__is_trivial(void))]; } { int arr[F(__is_trivial(cvoid))]; } } + +void array_rank() { + int t01[T(__array_rank(IntAr) == 1)]; + int t02[T(__array_rank(ConstIntArAr) == 2)]; +} + +void array_extent() { + int t01[T(__array_extent(IntAr, 0) == 10)]; + int t02[T(__array_extent(ConstIntArAr, 0) == 4)]; + int t03[T(__array_extent(ConstIntArAr, 1) == 10)]; +} diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index a0e204d61f..673f3eb509 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -1790,6 +1790,7 @@ public: void VisitWhileStmt(WhileStmt *W); void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E); void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E); + void VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E); void VisitExpressionTraitExpr(ExpressionTraitExpr *E); void VisitUnresolvedMemberExpr(UnresolvedMemberExpr *U); void VisitVAArgExpr(VAArgExpr *E); @@ -2070,6 +2071,7 @@ void EnqueueVisitor::VisitWhileStmt(WhileStmt *W) { AddStmt(W->getCond()); AddDecl(W->getConditionVariable()); } + void EnqueueVisitor::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) { AddTypeLoc(E->getQueriedTypeSourceInfo()); } @@ -2079,6 +2081,10 @@ void EnqueueVisitor::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) { AddTypeLoc(E->getLhsTypeSourceInfo()); } +void EnqueueVisitor::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { + AddTypeLoc(E->getQueriedTypeSourceInfo()); +} + void EnqueueVisitor::VisitExpressionTraitExpr(ExpressionTraitExpr *E) { EnqueueChildren(E); } diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp index 81beba822f..b8c44aa811 100644 --- a/tools/libclang/CXCursor.cpp +++ b/tools/libclang/CXCursor.cpp @@ -151,6 +151,7 @@ CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent, case Stmt::UnresolvedLookupExprClass: case Stmt::UnaryTypeTraitExprClass: case Stmt::BinaryTypeTraitExprClass: + case Stmt::ArrayTypeTraitExprClass: case Stmt::ExpressionTraitExprClass: case Stmt::DependentScopeDeclRefExprClass: case Stmt::CXXBindTemporaryExprClass: