forked from OSchip/llvm-project
Add proper type-source information to UnaryTypeTraitExpr, including
libclang visitation. llvm-svn: 113492
This commit is contained in:
parent
db0ddaa50b
commit
54e5b13a27
|
@ -1378,24 +1378,28 @@ class UnaryTypeTraitExpr : public Expr {
|
|||
/// RParen - The location of the closing paren.
|
||||
SourceLocation RParen;
|
||||
|
||||
/// QueriedType - The type we're testing.
|
||||
QualType QueriedType;
|
||||
TypeSourceInfo *QueriedType;
|
||||
|
||||
public:
|
||||
UnaryTypeTraitExpr(SourceLocation loc, UnaryTypeTrait utt, QualType queried,
|
||||
UnaryTypeTraitExpr(SourceLocation loc, UnaryTypeTrait utt,
|
||||
TypeSourceInfo *queried,
|
||||
SourceLocation rparen, QualType ty)
|
||||
: Expr(UnaryTypeTraitExprClass, ty, false, queried->isDependentType()),
|
||||
: Expr(UnaryTypeTraitExprClass, ty, false,
|
||||
queried->getType()->isDependentType()),
|
||||
UTT(utt), Loc(loc), RParen(rparen), QueriedType(queried) { }
|
||||
|
||||
explicit UnaryTypeTraitExpr(EmptyShell Empty)
|
||||
: Expr(UnaryTypeTraitExprClass, Empty), UTT((UnaryTypeTrait)0) { }
|
||||
: Expr(UnaryTypeTraitExprClass, Empty), UTT((UnaryTypeTrait)0),
|
||||
QueriedType() { }
|
||||
|
||||
virtual SourceRange getSourceRange() const { return SourceRange(Loc, RParen);}
|
||||
|
||||
UnaryTypeTrait getTrait() const { return UTT; }
|
||||
|
||||
QualType getQueriedType() const { return QueriedType; }
|
||||
QualType getQueriedType() const { return QueriedType->getType(); }
|
||||
|
||||
TypeSourceInfo *getQueriedTypeSourceInfo() const { return QueriedType; }
|
||||
|
||||
bool EvaluateTrait(ASTContext&) const;
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
|
|
|
@ -1782,7 +1782,7 @@ DEF_TRAVERSE_STMT(TypesCompatibleExpr, {
|
|||
})
|
||||
|
||||
DEF_TRAVERSE_STMT(UnaryTypeTraitExpr, {
|
||||
TRY_TO(TraverseType(S->getQueriedType()));
|
||||
TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc()));
|
||||
})
|
||||
|
||||
// These exprs (most of them), do not need any action except iterating
|
||||
|
|
|
@ -2260,10 +2260,14 @@ public:
|
|||
/// pseudo-functions.
|
||||
ExprResult ActOnUnaryTypeTrait(UnaryTypeTrait OTT,
|
||||
SourceLocation KWLoc,
|
||||
SourceLocation LParen,
|
||||
ParsedType Ty,
|
||||
SourceLocation RParen);
|
||||
|
||||
ExprResult BuildUnaryTypeTrait(UnaryTypeTrait OTT,
|
||||
SourceLocation KWLoc,
|
||||
TypeSourceInfo *T,
|
||||
SourceLocation RParen);
|
||||
|
||||
ExprResult ActOnStartCXXMemberReference(Scope *S,
|
||||
Expr *Base,
|
||||
SourceLocation OpLoc,
|
||||
|
|
|
@ -328,30 +328,31 @@ StmtIterator DependentScopeDeclRefExpr::child_end() {
|
|||
}
|
||||
|
||||
bool UnaryTypeTraitExpr::EvaluateTrait(ASTContext& C) const {
|
||||
QualType T = getQueriedType();
|
||||
switch(UTT) {
|
||||
default: assert(false && "Unknown type trait or not implemented");
|
||||
case UTT_IsPOD: return QueriedType->isPODType();
|
||||
case UTT_IsLiteral: return QueriedType->isLiteralType();
|
||||
case UTT_IsPOD: return T->isPODType();
|
||||
case UTT_IsLiteral: return T->isLiteralType();
|
||||
case UTT_IsClass: // Fallthrough
|
||||
case UTT_IsUnion:
|
||||
if (const RecordType *Record = QueriedType->getAs<RecordType>()) {
|
||||
if (const RecordType *Record = T->getAs<RecordType>()) {
|
||||
bool Union = Record->getDecl()->isUnion();
|
||||
return UTT == UTT_IsUnion ? Union : !Union;
|
||||
}
|
||||
return false;
|
||||
case UTT_IsEnum: return QueriedType->isEnumeralType();
|
||||
case UTT_IsEnum: return T->isEnumeralType();
|
||||
case UTT_IsPolymorphic:
|
||||
if (const RecordType *Record = QueriedType->getAs<RecordType>()) {
|
||||
if (const RecordType *Record = T->getAs<RecordType>()) {
|
||||
// Type traits are only parsed in C++, so we've got CXXRecords.
|
||||
return cast<CXXRecordDecl>(Record->getDecl())->isPolymorphic();
|
||||
}
|
||||
return false;
|
||||
case UTT_IsAbstract:
|
||||
if (const RecordType *RT = QueriedType->getAs<RecordType>())
|
||||
if (const RecordType *RT = T->getAs<RecordType>())
|
||||
return cast<CXXRecordDecl>(RT->getDecl())->isAbstract();
|
||||
return false;
|
||||
case UTT_IsEmpty:
|
||||
if (const RecordType *Record = QueriedType->getAs<RecordType>()) {
|
||||
if (const RecordType *Record = T->getAs<RecordType>()) {
|
||||
return !Record->getDecl()->isUnion()
|
||||
&& cast<CXXRecordDecl>(Record->getDecl())->isEmpty();
|
||||
}
|
||||
|
@ -361,10 +362,10 @@ bool UnaryTypeTraitExpr::EvaluateTrait(ASTContext& C) const {
|
|||
// If __is_pod (type) is true then the trait is true, else if type is
|
||||
// a cv class or union type (or array thereof) with a trivial default
|
||||
// constructor ([class.ctor]) then the trait is true, else it is false.
|
||||
if (QueriedType->isPODType())
|
||||
if (T->isPODType())
|
||||
return true;
|
||||
if (const RecordType *RT =
|
||||
C.getBaseElementType(QueriedType)->getAs<RecordType>())
|
||||
C.getBaseElementType(T)->getAs<RecordType>())
|
||||
return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialConstructor();
|
||||
return false;
|
||||
case UTT_HasTrivialCopy:
|
||||
|
@ -373,9 +374,9 @@ bool UnaryTypeTraitExpr::EvaluateTrait(ASTContext& C) const {
|
|||
// the trait is true, else if type is a cv class or union type
|
||||
// with a trivial copy constructor ([class.copy]) then the trait
|
||||
// is true, else it is false.
|
||||
if (QueriedType->isPODType() || QueriedType->isReferenceType())
|
||||
if (T->isPODType() || T->isReferenceType())
|
||||
return true;
|
||||
if (const RecordType *RT = QueriedType->getAs<RecordType>())
|
||||
if (const RecordType *RT = T->getAs<RecordType>())
|
||||
return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialCopyConstructor();
|
||||
return false;
|
||||
case UTT_HasTrivialAssign:
|
||||
|
@ -391,11 +392,11 @@ bool UnaryTypeTraitExpr::EvaluateTrait(ASTContext& C) const {
|
|||
// errors if the copy assignment operator is actually used, q.v.
|
||||
// [class.copy]p12).
|
||||
|
||||
if (C.getBaseElementType(QueriedType).isConstQualified())
|
||||
if (C.getBaseElementType(T).isConstQualified())
|
||||
return false;
|
||||
if (QueriedType->isPODType())
|
||||
if (T->isPODType())
|
||||
return true;
|
||||
if (const RecordType *RT = QueriedType->getAs<RecordType>())
|
||||
if (const RecordType *RT = T->getAs<RecordType>())
|
||||
return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialCopyAssignment();
|
||||
return false;
|
||||
case UTT_HasTrivialDestructor:
|
||||
|
@ -405,10 +406,10 @@ bool UnaryTypeTraitExpr::EvaluateTrait(ASTContext& C) const {
|
|||
// type (or array thereof) with a trivial destructor
|
||||
// ([class.dtor]) then the trait is true, else it is
|
||||
// false.
|
||||
if (QueriedType->isPODType() || QueriedType->isReferenceType())
|
||||
if (T->isPODType() || T->isReferenceType())
|
||||
return true;
|
||||
if (const RecordType *RT =
|
||||
C.getBaseElementType(QueriedType)->getAs<RecordType>())
|
||||
C.getBaseElementType(T)->getAs<RecordType>())
|
||||
return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDestructor();
|
||||
return false;
|
||||
// TODO: Propagate nothrowness for implicitly declared special members.
|
||||
|
@ -420,13 +421,13 @@ bool UnaryTypeTraitExpr::EvaluateTrait(ASTContext& C) const {
|
|||
// or union type with copy assignment operators that are known
|
||||
// not to throw an exception then the trait is true, else it is
|
||||
// false.
|
||||
if (C.getBaseElementType(QueriedType).isConstQualified())
|
||||
if (C.getBaseElementType(T).isConstQualified())
|
||||
return false;
|
||||
if (QueriedType->isReferenceType())
|
||||
if (T->isReferenceType())
|
||||
return false;
|
||||
if (QueriedType->isPODType())
|
||||
if (T->isPODType())
|
||||
return true;
|
||||
if (const RecordType *RT = QueriedType->getAs<RecordType>()) {
|
||||
if (const RecordType *RT = T->getAs<RecordType>()) {
|
||||
CXXRecordDecl* RD = cast<CXXRecordDecl>(RT->getDecl());
|
||||
if (RD->hasTrivialCopyAssignment())
|
||||
return true;
|
||||
|
@ -458,9 +459,9 @@ bool UnaryTypeTraitExpr::EvaluateTrait(ASTContext& C) const {
|
|||
// if type is a cv class or union type with copy constructors that are
|
||||
// known not to throw an exception then the trait is true, else it is
|
||||
// false.
|
||||
if (QueriedType->isPODType() || QueriedType->isReferenceType())
|
||||
if (T->isPODType() || T->isReferenceType())
|
||||
return true;
|
||||
if (const RecordType *RT = QueriedType->getAs<RecordType>()) {
|
||||
if (const RecordType *RT = T->getAs<RecordType>()) {
|
||||
CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
|
||||
if (RD->hasTrivialCopyConstructor())
|
||||
return true;
|
||||
|
@ -469,8 +470,7 @@ bool UnaryTypeTraitExpr::EvaluateTrait(ASTContext& C) const {
|
|||
bool AllNoThrow = true;
|
||||
unsigned FoundTQs;
|
||||
DeclarationName ConstructorName
|
||||
= C.DeclarationNames.getCXXConstructorName(
|
||||
C.getCanonicalType(QueriedType));
|
||||
= C.DeclarationNames.getCXXConstructorName(C.getCanonicalType(T));
|
||||
DeclContext::lookup_const_iterator Con, ConEnd;
|
||||
for (llvm::tie(Con, ConEnd) = RD->lookup(ConstructorName);
|
||||
Con != ConEnd; ++Con) {
|
||||
|
@ -495,10 +495,9 @@ bool UnaryTypeTraitExpr::EvaluateTrait(ASTContext& C) const {
|
|||
// true, else if type is a cv class or union type (or array
|
||||
// thereof) with a default constructor that is known not to
|
||||
// throw an exception then the trait is true, else it is false.
|
||||
if (QueriedType->isPODType())
|
||||
if (T->isPODType())
|
||||
return true;
|
||||
if (const RecordType *RT =
|
||||
C.getBaseElementType(QueriedType)->getAs<RecordType>()) {
|
||||
if (const RecordType *RT = C.getBaseElementType(T)->getAs<RecordType>()) {
|
||||
CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
|
||||
if (RD->hasTrivialConstructor())
|
||||
return true;
|
||||
|
@ -517,7 +516,7 @@ bool UnaryTypeTraitExpr::EvaluateTrait(ASTContext& C) const {
|
|||
// http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
|
||||
// If type is a class type with a virtual destructor ([class.dtor])
|
||||
// then the trait is true, else it is false.
|
||||
if (const RecordType *Record = QueriedType->getAs<RecordType>()) {
|
||||
if (const RecordType *Record = T->getAs<RecordType>()) {
|
||||
CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
|
||||
if (CXXDestructorDecl *Destructor = RD->getDestructor())
|
||||
return Destructor->isVirtual();
|
||||
|
|
|
@ -1832,7 +1832,7 @@ ExprResult Parser::ParseUnaryTypeTrait() {
|
|||
if (Ty.isInvalid())
|
||||
return ExprError();
|
||||
|
||||
return Actions.ActOnUnaryTypeTrait(UTT, Loc, LParen, Ty.get(), RParen);
|
||||
return Actions.ActOnUnaryTypeTrait(UTT, Loc, Ty.get(), RParen);
|
||||
}
|
||||
|
||||
/// ParseCXXAmbiguousParenExpression - We have parsed the left paren of a
|
||||
|
|
|
@ -1982,12 +1982,23 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
|
|||
}
|
||||
|
||||
ExprResult Sema::ActOnUnaryTypeTrait(UnaryTypeTrait OTT,
|
||||
SourceLocation KWLoc,
|
||||
SourceLocation LParen,
|
||||
ParsedType Ty,
|
||||
SourceLocation RParen) {
|
||||
QualType T = GetTypeFromParser(Ty);
|
||||
SourceLocation KWLoc,
|
||||
ParsedType Ty,
|
||||
SourceLocation RParen) {
|
||||
TypeSourceInfo *TSInfo;
|
||||
QualType T = GetTypeFromParser(Ty, &TSInfo);
|
||||
|
||||
if (!TSInfo)
|
||||
TSInfo = Context.getTrivialTypeSourceInfo(T);
|
||||
return BuildUnaryTypeTrait(OTT, KWLoc, TSInfo, RParen);
|
||||
}
|
||||
|
||||
ExprResult Sema::BuildUnaryTypeTrait(UnaryTypeTrait OTT,
|
||||
SourceLocation KWLoc,
|
||||
TypeSourceInfo *TSInfo,
|
||||
SourceLocation RParen) {
|
||||
QualType T = TSInfo->getType();
|
||||
|
||||
// According to http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html
|
||||
// all traits except __is_class, __is_enum and __is_union require a the type
|
||||
// to be complete, an array of unknown bound, or void.
|
||||
|
@ -2004,7 +2015,7 @@ ExprResult Sema::ActOnUnaryTypeTrait(UnaryTypeTrait OTT,
|
|||
// There is no point in eagerly computing the value. The traits are designed
|
||||
// to be used from type trait templates, so Ty will be a template parameter
|
||||
// 99% of the time.
|
||||
return Owned(new (Context) UnaryTypeTraitExpr(KWLoc, OTT, T,
|
||||
return Owned(new (Context) UnaryTypeTraitExpr(KWLoc, OTT, TSInfo,
|
||||
RParen, Context.BoolTy));
|
||||
}
|
||||
|
||||
|
|
|
@ -1643,12 +1643,10 @@ public:
|
|||
/// By default, performs semantic analysis to build the new expression.
|
||||
/// Subclasses may override this routine to provide different behavior.
|
||||
ExprResult RebuildUnaryTypeTrait(UnaryTypeTrait Trait,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
QualType T,
|
||||
SourceLocation RParenLoc) {
|
||||
return getSema().ActOnUnaryTypeTrait(Trait, StartLoc, LParenLoc,
|
||||
ParsedType::make(T), RParenLoc);
|
||||
SourceLocation StartLoc,
|
||||
TypeSourceInfo *T,
|
||||
SourceLocation RParenLoc) {
|
||||
return getSema().BuildUnaryTypeTrait(Trait, StartLoc, T, RParenLoc);
|
||||
}
|
||||
|
||||
/// \brief Build a new (previously unresolved) declaration reference
|
||||
|
@ -5614,23 +5612,16 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr(
|
|||
template<typename Derived>
|
||||
ExprResult
|
||||
TreeTransform<Derived>::TransformUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
|
||||
TemporaryBase Rebase(*this, /*FIXME*/E->getLocStart(), DeclarationName());
|
||||
|
||||
QualType T = getDerived().TransformType(E->getQueriedType());
|
||||
if (T.isNull())
|
||||
TypeSourceInfo *T = getDerived().TransformType(E->getQueriedTypeSourceInfo());
|
||||
if (!T)
|
||||
return ExprError();
|
||||
|
||||
if (!getDerived().AlwaysRebuild() &&
|
||||
T == E->getQueriedType())
|
||||
T == E->getQueriedTypeSourceInfo())
|
||||
return SemaRef.Owned(E->Retain());
|
||||
|
||||
// FIXME: Bad location information
|
||||
SourceLocation FakeLParenLoc
|
||||
= SemaRef.PP.getLocForEndOfToken(E->getLocStart());
|
||||
|
||||
return getDerived().RebuildUnaryTypeTrait(E->getTrait(),
|
||||
E->getLocStart(),
|
||||
/*FIXME:*/FakeLParenLoc,
|
||||
T,
|
||||
E->getLocEnd());
|
||||
}
|
||||
|
|
|
@ -1249,7 +1249,7 @@ void ASTStmtReader::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
|
|||
SourceRange Range = Reader.ReadSourceRange(Record, Idx);
|
||||
E->Loc = Range.getBegin();
|
||||
E->RParen = Range.getEnd();
|
||||
E->QueriedType = Reader.GetType(Record[Idx++]);
|
||||
E->QueriedType = Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx);
|
||||
}
|
||||
|
||||
Stmt *ASTReader::ReadStmt(llvm::BitstreamCursor &Cursor) {
|
||||
|
|
|
@ -1279,7 +1279,7 @@ void ASTStmtWriter::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
|
|||
VisitExpr(E);
|
||||
Record.push_back(E->getTrait());
|
||||
Writer.AddSourceRange(E->getSourceRange(), Record);
|
||||
Writer.AddTypeRef(E->getQueriedType(), Record);
|
||||
Writer.AddTypeSourceInfo(E->getQueriedTypeSourceInfo(), Record);
|
||||
Code = serialization::EXPR_CXX_UNARY_TYPE_TRAIT;
|
||||
}
|
||||
|
||||
|
|
|
@ -88,6 +88,7 @@ template<typename T>
|
|||
void test_even_more_dependent_exprs(T t, Y y) {
|
||||
typedef T type;
|
||||
(void)type(t, y);
|
||||
(void)__has_nothrow_assign(type);
|
||||
}
|
||||
|
||||
// RUN: c-index-test -test-load-source all %s | FileCheck %s
|
||||
|
@ -195,3 +196,5 @@ void test_even_more_dependent_exprs(T t, Y y) {
|
|||
// CHECK: load-stmts.cpp:90:9: TypeRef=type:89:13 Extent=[90:9 - 90:13]
|
||||
// CHECK: load-stmts.cpp:90:14: DeclRefExpr=t:88:39 Extent=[90:14 - 90:15]
|
||||
// CHECK: load-stmts.cpp:90:17: DeclRefExpr=y:88:44 Extent=[90:17 - 90:18]
|
||||
// CHECK: load-stmts.cpp:91:9: UnexposedExpr= Extent=[91:9 - 91:35]
|
||||
// CHECK: load-stmts.cpp:91:30: TypeRef=type:89:13 Extent=[91:30 - 91:34]
|
||||
|
|
|
@ -366,7 +366,6 @@ public:
|
|||
bool VisitCaseStmt(CaseStmt *S);
|
||||
bool VisitWhileStmt(WhileStmt *S);
|
||||
bool VisitForStmt(ForStmt *S);
|
||||
// bool VisitSwitchCase(SwitchCase *S);
|
||||
|
||||
// Expression visitors
|
||||
bool VisitDeclRefExpr(DeclRefExpr *E);
|
||||
|
@ -385,12 +384,13 @@ public:
|
|||
// FIXME: InitListExpr (for the designators)
|
||||
// FIXME: DesignatedInitExpr
|
||||
bool VisitCXXTypeidExpr(CXXTypeidExpr *E);
|
||||
bool VisitCXXUuidofExpr(CXXUuidofExpr *E);
|
||||
bool VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { return false; }
|
||||
bool VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E);
|
||||
bool VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E);
|
||||
bool VisitCXXNewExpr(CXXNewExpr *E);
|
||||
bool VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E);
|
||||
// FIXME: UnaryTypeTraitExpr has poor source-location information.
|
||||
bool VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E);
|
||||
bool VisitOverloadExpr(OverloadExpr *E);
|
||||
bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E);
|
||||
bool VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E);
|
||||
|
@ -1590,6 +1590,17 @@ bool CursorVisitor::VisitCXXTypeidExpr(CXXTypeidExpr *E) {
|
|||
return VisitExpr(E);
|
||||
}
|
||||
|
||||
bool CursorVisitor::VisitCXXUuidofExpr(CXXUuidofExpr *E) {
|
||||
if (E->isTypeOperand()) {
|
||||
if (TypeSourceInfo *TSInfo = E->getTypeOperandSourceInfo())
|
||||
return Visit(TSInfo->getTypeLoc());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return VisitExpr(E);
|
||||
}
|
||||
|
||||
bool CursorVisitor::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) {
|
||||
if (TypeSourceInfo *TSInfo = E->getTypeSourceInfo())
|
||||
return Visit(TSInfo->getTypeLoc());
|
||||
|
@ -1651,6 +1662,10 @@ bool CursorVisitor::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool CursorVisitor::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
|
||||
return Visit(E->getQueriedTypeSourceInfo()->getTypeLoc());
|
||||
}
|
||||
|
||||
bool CursorVisitor::VisitOverloadExpr(OverloadExpr *E) {
|
||||
// Visit the nested-name-specifier.
|
||||
if (NestedNameSpecifier *Qualifier = E->getQualifier())
|
||||
|
|
Loading…
Reference in New Issue