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 5aaeb8e..1311030 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -1594,6 +1594,68 @@
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
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index 93cc446..28daf51 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -1849,6 +1849,10 @@
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 de3fedb..d87d14f 100644
--- a/include/clang/Basic/StmtNodes.td
+++ b/include/clang/Basic/StmtNodes.td
@@ -104,6 +104,7 @@
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>;
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index e66922e..1d121a1 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -378,6 +378,8 @@
// 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 6ba1bbd..cafc387 100644
--- a/include/clang/Basic/TypeTraits.h
+++ b/include/clang/Basic/TypeTraits.h
@@ -71,6 +71,12 @@
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 4308977..cda9a61 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -1816,7 +1816,8 @@
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 691a17b..72878de 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -2736,6 +2736,20 @@
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 06be217..1cfd458 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -978,6 +978,7 @@
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 ebbdf94..888a93c 100644
--- a/lib/AST/ExprClassification.cpp
+++ b/lib/AST/ExprClassification.cpp
@@ -152,6 +152,7 @@
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 519bbaa..c2caf8d 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -1061,6 +1061,10 @@
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 @@
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 14ee74b..82de578 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -1911,6 +1911,7 @@
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 b96591b..62f06db 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -1308,6 +1308,14 @@
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 @@
<< 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 fe9a10b..7a3fc54 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -802,6 +802,12 @@
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 f6de1fa..6bcc425 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -367,6 +367,10 @@
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 1c4a942..8b9e5e7 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -490,6 +490,7 @@
/// [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 @@
/// '__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 @@
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 aade050..5075205 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -1970,6 +1970,14 @@
}
}
+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 @@
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 7086176..0617abd 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -2812,6 +2812,94 @@
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 b2aa85e..f5ec3a2 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -1915,6 +1915,18 @@
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.
@@ -6921,6 +6933,35 @@
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) {
ExprResult SubExpr;
{
diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp
index 3435fd9..83b3907 100644
--- a/lib/Serialization/ASTReaderStmt.cpp
+++ b/lib/Serialization/ASTReaderStmt.cpp
@@ -179,6 +179,7 @@
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 @@
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 @@
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 53fb973..4fe3bae 100644
--- a/lib/Serialization/ASTWriterStmt.cpp
+++ b/lib/Serialization/ASTWriterStmt.cpp
@@ -153,6 +153,7 @@
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 @@
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 49af430..5c1dfb8 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -435,6 +435,7 @@
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 ef5607b..1dec7f9 100644
--- a/test/SemaCXX/type-traits.cpp
+++ b/test/SemaCXX/type-traits.cpp
@@ -1464,3 +1464,14 @@
{ 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 a0e204d..673f3eb 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -1790,6 +1790,7 @@
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 @@
AddStmt(W->getCond());
AddDecl(W->getConditionVariable());
}
+
void EnqueueVisitor::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
AddTypeLoc(E->getQueriedTypeSourceInfo());
}
@@ -2079,6 +2081,10 @@
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 81beba8..b8c44aa 100644
--- a/tools/libclang/CXCursor.cpp
+++ b/tools/libclang/CXCursor.cpp
@@ -151,6 +151,7 @@
case Stmt::UnresolvedLookupExprClass:
case Stmt::UnaryTypeTraitExprClass:
case Stmt::BinaryTypeTraitExprClass:
+ case Stmt::ArrayTypeTraitExprClass:
case Stmt::ExpressionTraitExprClass:
case Stmt::DependentScopeDeclRefExprClass:
case Stmt::CXXBindTemporaryExprClass: