]> granicus.if.org Git - clang/commitdiff
Implementation of Embarcadero array type traits
authorJohn Wiegley <johnw@boostpro.com>
Thu, 28 Apr 2011 00:16:57 +0000 (00:16 +0000)
committerJohn Wiegley <johnw@boostpro.com>
Thu, 28 Apr 2011 00:16:57 +0000 (00:16 +0000)
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

24 files changed:
include/clang/AST/ExprCXX.h
include/clang/AST/RecursiveASTVisitor.h
include/clang/Basic/StmtNodes.td
include/clang/Basic/TokenKinds.def
include/clang/Basic/TypeTraits.h
include/clang/Parse/Parser.h
include/clang/Sema/Sema.h
include/clang/Serialization/ASTBitCodes.h
lib/AST/ExprClassification.cpp
lib/AST/ExprConstant.cpp
lib/AST/ItaniumMangle.cpp
lib/AST/StmtPrinter.cpp
lib/AST/StmtProfile.cpp
lib/CodeGen/CGExprScalar.cpp
lib/Parse/ParseExpr.cpp
lib/Parse/ParseExprCXX.cpp
lib/Sema/SemaExprCXX.cpp
lib/Sema/TreeTransform.h
lib/Serialization/ASTReaderStmt.cpp
lib/Serialization/ASTWriterStmt.cpp
lib/StaticAnalyzer/Core/ExprEngine.cpp
test/SemaCXX/type-traits.cpp
tools/libclang/CIndex.cpp
tools/libclang/CXCursor.cpp

index 5aaeb8e7ab7ffc65dc39096a1c6ee0bac1cad20a..1311030e7705f6e4e2bc38a45a2f65752f9c95fe 100644 (file)
@@ -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<ArrayTypeTrait>(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
index 93cc446afd1b180c65427c581f1c78dc28141231..28daf51dd9e9cbba421ce672c1bfcf37d3c6695c 100644 (file)
@@ -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()));
   })
index de3fedb724e88817910d0651c07b7216d71b5c08..d87d14ff53a0ee4c6d66381b6695e2505b74b24d 100644 (file)
@@ -104,6 +104,7 @@ def CXXDeleteExpr : DStmt<Expr>;
 def CXXPseudoDestructorExpr : DStmt<Expr>;
 def UnaryTypeTraitExpr : DStmt<Expr>;
 def BinaryTypeTraitExpr : DStmt<Expr>;
+def ArrayTypeTraitExpr : DStmt<Expr>;
 def ExpressionTraitExpr : DStmt<Expr>;
 def DependentScopeDeclRefExpr : DStmt<Expr>;
 def CXXConstructExpr : DStmt<Expr>;
index e66922eaa29aad46a708611919ff97214e017b8f..1d121a1596fce6b435fa560dbbcc2baffdcc3ac8 100644 (file)
@@ -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)
index 6ba1bbdeeeed79b74ee75bc2bdccf39a3463a594..cafc3878816adbe98fde8baf6f90ed246f8eb882 100644 (file)
@@ -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,
index 43089773f48b85dd7a282344f8d2e05fac6c3247..cda9a61b33cf28a850504179d5e3854cbb4bf1a7 100644 (file)
@@ -1816,7 +1816,8 @@ private:
   ExprResult ParseBinaryTypeTrait();
 
   //===--------------------------------------------------------------------===//
-  // Embarcadero: Expression Traits
+  // Embarcadero: Arary and Expression Traits
+  ExprResult ParseArrayTypeTrait();
   ExprResult ParseExpressionTrait();
 
   //===--------------------------------------------------------------------===//
index 691a17b63c76b57d4c668d5d3e6dd443ead3450f..72878de0477e71175163b072f0ae9bc92e6c413a 100644 (file)
@@ -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,
index 06be21791566fcb9671d0af8b8676c610c14f6a4..1cfd458a38647425fb0050ce5bdebbc196f8cbff 100644 (file)
@@ -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
index ebbdf94f100aa3b4ab4df8865c5a65b3d7b19eb5..888a93c8aac0817ebc6b354a9358a6896fb4300d 100644 (file)
@@ -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:
index 519bbaa115ecd70f3e277d523d1a4b1632c8150c..c2caf8d40b16718ef7e2d5c4abbf02f5cda9f50e 100644 (file)
@@ -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();
index 14ee74be124b93a3ba01c7c7d0caac4088e70cd9..82de578412218a86c908615133d4134050031cf2 100644 (file)
@@ -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:
index b96591b661460dab28e5ef2d928f0a2a8042575f..62f06dba165b152e76b9c0cc758b14e2d887c2ae 100644 (file)
@@ -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());
index fe9a10b01e0fff021c8b3162487e49a5156ac0a3..7a3fc5417c463b2260b4afe317c1e59518e2d4f3 100644 (file)
@@ -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());
index f6de1fa1273e08806e9447dfbf322a39e3cd90cc..6bcc425ce62fb424ecda9068e653cf68c3290023 100644 (file)
@@ -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());
   }
index 1c4a9427801d3e67c71f061e0013ba72fdc73add..8b9e5e752b023ea0cedd7ea27c1a6d117d83056a 100644 (file)
@@ -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();
index aade050df449ef20bf72170a86b212cb69747aba..50752058cdffc43d97275528b7027039941ceb27 100644 (file)
@@ -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 ).
 ///
index 7086176d89f60141b74153fc6c5311f7037f0b46..0617abd6805f4d85177142f6c004329e1fc22c62 100644 (file)
@@ -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,
index b2aa85e7198beed14af3085dcb9963cacb896113..f5ec3a2170184f891d332b280c8280150737e7bf 100644 (file)
@@ -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<Derived>::TransformBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
                                             E->getLocEnd());
 }
 
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::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<typename Derived>
 ExprResult
 TreeTransform<Derived>::TransformExpressionTraitExpr(ExpressionTraitExpr *E) {
index 3435fd92d3e6393abf9182f6acdac5b9227536c4..83b3907f5818bb4a211c89ed0588b5ae62e345f2 100644 (file)
@@ -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;
index 53fb9738e62104fabf96969d32609ad7635fc032..4fe3bae91a27aae3d01f5eb6ca1348ac0ca695a7 100644 (file)
@@ -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());
index 49af4304b05467164b938e4c45f9c11569a93f7b..5c1dfb80ecfddf3a184038630f418f86a3bb3df2 100644 (file)
@@ -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:
index ef5607b20c833c73236de0d24b476caabf544049..1dec7f923a5857dc20c5b4593f536d255ffc0a10 100644 (file)
@@ -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)];
+}
index a0e204d61fe52ad73730361e7135752f76a0b6eb..673f3eb5091d0398b744227baab0a54c23422608 100644 (file)
@@ -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);
 }
index 81beba822f9166e62633e879889d30bcd6a97ff1..b8c44aa8116fefe4074e094228775c77b3285fcf 100644 (file)
@@ -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: