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).

llvm-svn: 130351
This commit is contained in:
John Wiegley 2011-04-28 00:16:57 +00:00
parent 1e34241abd
commit 6242b6a688
24 changed files with 356 additions and 1 deletions

View 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

View 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()));
})

View 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>;

View 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)

View 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,

View File

@ -1816,7 +1816,8 @@ private:
ExprResult ParseBinaryTypeTrait();
//===--------------------------------------------------------------------===//
// Embarcadero: Expression Traits
// Embarcadero: Arary and Expression Traits
ExprResult ParseArrayTypeTrait();
ExprResult ParseExpressionTrait();
//===--------------------------------------------------------------------===//

View 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,

View 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

View 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:

View 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();

View 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:

View 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());

View 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());

View 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());
}

View 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();

View 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 ).
///

View 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,

View 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) {

View 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;

View 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());

View 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:

View 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)];
}

View 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);
}

View 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: