From: Douglas Gregor Date: Fri, 25 Feb 2011 18:19:59 +0000 (+0000) Subject: Push nested-name-specifier source-location information into X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f3db29fff6a583ecda823cf909ab7737d8d30129;p=clang Push nested-name-specifier source-location information into pseudo-destructor expressions. Also, clean up some template-instantiation and type-checking issues with pseudo-destructors. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126498 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 4a9a3d2cdf..5f4ab333a3 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -1331,13 +1331,9 @@ class CXXPseudoDestructorExpr : public Expr { /// \brief The location of the '.' or '->' operator. SourceLocation OperatorLoc; - + /// \brief The nested-name-specifier that follows the operator, if present. - NestedNameSpecifier *Qualifier; - - /// \brief The source range that covers the nested-name-specifier, if - /// present. - SourceRange QualifierRange; + NestedNameSpecifierLoc QualifierLoc; /// \brief The type that precedes the '::' in a qualified pseudo-destructor /// expression. @@ -1354,11 +1350,12 @@ class CXXPseudoDestructorExpr : public Expr { /// resolve the name. PseudoDestructorTypeStorage DestroyedType; + friend class ASTStmtReader; + public: CXXPseudoDestructorExpr(ASTContext &Context, Expr *Base, bool isArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, TypeSourceInfo *ScopeType, SourceLocation ColonColonLoc, SourceLocation TildeLoc, @@ -1366,36 +1363,32 @@ public: explicit CXXPseudoDestructorExpr(EmptyShell Shell) : Expr(CXXPseudoDestructorExprClass, Shell), - Base(0), IsArrow(false), Qualifier(0), ScopeType(0) { } + Base(0), IsArrow(false), QualifierLoc(), ScopeType(0) { } - void setBase(Expr *E) { Base = E; } Expr *getBase() const { return cast(Base); } /// \brief Determines whether this member expression actually had /// a C++ nested-name-specifier prior to the name of the member, e.g., /// x->Base::foo. - bool hasQualifier() const { return Qualifier != 0; } - - /// \brief If the member name was qualified, retrieves the source range of - /// the nested-name-specifier that precedes the member name. Otherwise, - /// returns an empty source range. - SourceRange getQualifierRange() const { return QualifierRange; } - void setQualifierRange(SourceRange R) { QualifierRange = R; } + bool hasQualifier() const { return QualifierLoc; } + /// \brief Retrieves the nested-name-specifier that qualifies the type name, + /// with source-location information. + NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } + /// \brief If the member name was qualified, retrieves the /// nested-name-specifier that precedes the member name. Otherwise, returns /// NULL. - NestedNameSpecifier *getQualifier() const { return Qualifier; } - void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; } + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); + } /// \brief Determine whether this pseudo-destructor expression was written /// using an '->' (otherwise, it used a '.'). bool isArrow() const { return IsArrow; } - void setArrow(bool A) { IsArrow = A; } /// \brief Retrieve the location of the '.' or '->' operator. SourceLocation getOperatorLoc() const { return OperatorLoc; } - void setOperatorLoc(SourceLocation L) { OperatorLoc = L; } /// \brief Retrieve the scope type in a qualified pseudo-destructor /// expression. @@ -1407,16 +1400,13 @@ public: /// nested-name-specifier. It is stored as the "scope type" of the pseudo- /// destructor expression. TypeSourceInfo *getScopeTypeInfo() const { return ScopeType; } - void setScopeTypeInfo(TypeSourceInfo *Info) { ScopeType = Info; } /// \brief Retrieve the location of the '::' in a qualified pseudo-destructor /// expression. SourceLocation getColonColonLoc() const { return ColonColonLoc; } - void setColonColonLoc(SourceLocation L) { ColonColonLoc = L; } /// \brief Retrieve the location of the '~'. SourceLocation getTildeLoc() const { return TildeLoc; } - void setTildeLoc(SourceLocation L) { TildeLoc = L; } /// \brief Retrieve the source location information for the type /// being destroyed. diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index ff59450b6a..8f9b3a0349 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -1846,7 +1846,7 @@ DEF_TRAVERSE_STMT(CXXDeleteExpr, { }) DEF_TRAVERSE_STMT(ExprWithCleanups, { }) DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, { }) DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, { - TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); if (TypeSourceInfo *ScopeInfo = S->getScopeTypeInfo()) TRY_TO(TraverseTypeLoc(ScopeInfo->getTypeLoc())); if (TypeSourceInfo *DestroyedTypeInfo = S->getDestroyedTypeInfo()) diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 0e83fac8be..fec7c249a7 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -128,10 +128,10 @@ PseudoDestructorTypeStorage::PseudoDestructorTypeStorage(TypeSourceInfo *Info) } CXXPseudoDestructorExpr::CXXPseudoDestructorExpr(ASTContext &Context, - Expr *Base, bool isArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, SourceRange QualifierRange, - TypeSourceInfo *ScopeType, SourceLocation ColonColonLoc, - SourceLocation TildeLoc, PseudoDestructorTypeStorage DestroyedType) + Expr *Base, bool isArrow, SourceLocation OperatorLoc, + NestedNameSpecifierLoc QualifierLoc, TypeSourceInfo *ScopeType, + SourceLocation ColonColonLoc, SourceLocation TildeLoc, + PseudoDestructorTypeStorage DestroyedType) : Expr(CXXPseudoDestructorExprClass, Context.getPointerType(Context.getFunctionType(Context.VoidTy, 0, 0, FunctionProtoType::ExtProtoInfo())), @@ -142,15 +142,16 @@ CXXPseudoDestructorExpr::CXXPseudoDestructorExpr(ASTContext &Context, /*isValueDependent=*/Base->isValueDependent(), // ContainsUnexpandedParameterPack (Base->containsUnexpandedParameterPack() || - (Qualifier && Qualifier->containsUnexpandedParameterPack()) || + (QualifierLoc && + QualifierLoc.getNestedNameSpecifier() + ->containsUnexpandedParameterPack()) || (ScopeType && ScopeType->getType()->containsUnexpandedParameterPack()) || (DestroyedType.getTypeSourceInfo() && DestroyedType.getTypeSourceInfo()->getType() ->containsUnexpandedParameterPack()))), Base(static_cast(Base)), IsArrow(isArrow), - OperatorLoc(OperatorLoc), Qualifier(Qualifier), - QualifierRange(QualifierRange), + OperatorLoc(OperatorLoc), QualifierLoc(QualifierLoc), ScopeType(ScopeType), ColonColonLoc(ColonColonLoc), TildeLoc(TildeLoc), DestroyedType(DestroyedType) { } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index d58a47ab45..4fa2adced4 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -3664,7 +3664,7 @@ ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base, Expr *Result = new (Context) CXXPseudoDestructorExpr(Context, Base, OpKind == tok::arrow, OpLoc, - SS.getScopeRep(), SS.getRange(), + SS.getWithLocInContext(Context), ScopeTypeInfo, CCLoc, TildeLoc, @@ -3786,7 +3786,7 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, if (FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) { ParsedType T = getTypeName(*FirstTypeName.Identifier, FirstTypeName.StartLocation, - S, &SS, false, false, ObjectTypePtrForLookup); + S, &SS, true, false, ObjectTypePtrForLookup); if (!T) { Diag(FirstTypeName.StartLocation, diag::err_pseudo_dtor_destructor_non_type) diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 641df425ad..4869ce6db6 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -1284,13 +1284,12 @@ public: /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. ExprResult RebuildCXXPseudoDestructorExpr(Expr *Base, - SourceLocation OperatorLoc, - bool isArrow, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, - TypeSourceInfo *ScopeType, - SourceLocation CCLoc, - SourceLocation TildeLoc, + SourceLocation OperatorLoc, + bool isArrow, + CXXScopeSpec &SS, + TypeSourceInfo *ScopeType, + SourceLocation CCLoc, + SourceLocation TildeLoc, PseudoDestructorTypeStorage Destroyed); /// \brief Build a new unary operator expression. @@ -2597,9 +2596,7 @@ TreeTransform::TransformNestedNameSpecifierLoc( } } - // The object type and qualifier-in-scope really apply to the - // leftmost entity. - ObjectType = QualType(); + // The qualifier-in-scope only applies to the leftmost entity. FirstQualifierInScope = 0; } @@ -6612,21 +6609,22 @@ TreeTransform::TransformCXXPseudoDestructorExpr( return ExprError(); QualType ObjectType = ObjectTypePtr.get(); - NestedNameSpecifier *Qualifier = E->getQualifier(); - if (Qualifier) { - Qualifier - = getDerived().TransformNestedNameSpecifier(E->getQualifier(), - E->getQualifierRange(), - ObjectType); - if (!Qualifier) + NestedNameSpecifierLoc QualifierLoc = E->getQualifierLoc(); + if (QualifierLoc) { + QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(QualifierLoc, ObjectType); + if (!QualifierLoc) return ExprError(); } + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); PseudoDestructorTypeStorage Destroyed; if (E->getDestroyedTypeInfo()) { TypeSourceInfo *DestroyedTypeInfo = getDerived().TransformTypeInObjectScope(E->getDestroyedTypeInfo(), - ObjectType, 0, Qualifier); + ObjectType, 0, + QualifierLoc.getNestedNameSpecifier()); if (!DestroyedTypeInfo) return ExprError(); Destroyed = DestroyedTypeInfo; @@ -6637,10 +6635,6 @@ TreeTransform::TransformCXXPseudoDestructorExpr( E->getDestroyedTypeLoc()); } else { // Look for a destructor known with the given name. - CXXScopeSpec SS; - if (Qualifier) - SS.MakeTrivial(SemaRef.Context, Qualifier, E->getQualifierRange()); - ParsedType T = SemaRef.getDestructorName(E->getTildeLoc(), *E->getDestroyedTypeIdentifier(), E->getDestroyedTypeLoc(), @@ -6665,8 +6659,7 @@ TreeTransform::TransformCXXPseudoDestructorExpr( return getDerived().RebuildCXXPseudoDestructorExpr(Base.get(), E->getOperatorLoc(), E->isArrow(), - Qualifier, - E->getQualifierRange(), + SS, ScopeTypeInfo, E->getColonColonLoc(), E->getTildeLoc(), @@ -7930,16 +7923,11 @@ ExprResult TreeTransform::RebuildCXXPseudoDestructorExpr(Expr *Base, SourceLocation OperatorLoc, bool isArrow, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + CXXScopeSpec &SS, TypeSourceInfo *ScopeType, SourceLocation CCLoc, SourceLocation TildeLoc, PseudoDestructorTypeStorage Destroyed) { - CXXScopeSpec SS; - if (Qualifier) - SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange); - QualType BaseType = Base->getType(); if (Base->isTypeDependent() || Destroyed.getIdentifier() || (!isArrow && !BaseType->getAs()) || diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 4e91c98926..34c37298d4 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -1167,14 +1167,13 @@ void ASTStmtReader::VisitCXXDeleteExpr(CXXDeleteExpr *E) { void ASTStmtReader::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) { VisitExpr(E); - E->setBase(Reader.ReadSubExpr()); - E->setArrow(Record[Idx++]); - E->setOperatorLoc(ReadSourceLocation(Record, Idx)); - E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx)); - E->setQualifierRange(ReadSourceRange(Record, Idx)); - E->setScopeTypeInfo(GetTypeSourceInfo(Record, Idx)); - E->setColonColonLoc(ReadSourceLocation(Record, Idx)); - E->setTildeLoc(ReadSourceLocation(Record, Idx)); + E->Base = Reader.ReadSubExpr(); + E->IsArrow = Record[Idx++]; + E->OperatorLoc = ReadSourceLocation(Record, Idx); + E->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); + E->ScopeType = GetTypeSourceInfo(Record, Idx); + E->ColonColonLoc = ReadSourceLocation(Record, Idx); + E->TildeLoc = ReadSourceLocation(Record, Idx); IdentifierInfo *II = Reader.GetIdentifierInfo(Record, Idx); if (II) diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index 8a5ffe96db..587b687cfb 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -1150,8 +1150,7 @@ void ASTStmtWriter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) { Writer.AddStmt(E->getBase()); Record.push_back(E->isArrow()); Writer.AddSourceLocation(E->getOperatorLoc(), Record); - Writer.AddNestedNameSpecifier(E->getQualifier(), Record); - Writer.AddSourceRange(E->getQualifierRange(), Record); + Writer.AddNestedNameSpecifierLoc(E->getQualifierLoc(), Record); Writer.AddTypeSourceInfo(E->getScopeTypeInfo(), Record); Writer.AddSourceLocation(E->getColonColonLoc(), Record); Writer.AddSourceLocation(E->getTildeLoc(), Record); diff --git a/test/Index/annotate-nested-name-specifier.cpp b/test/Index/annotate-nested-name-specifier.cpp index 216fc4ec9c..70d84889e9 100644 --- a/test/Index/annotate-nested-name-specifier.cpp +++ b/test/Index/annotate-nested-name-specifier.cpp @@ -51,7 +51,14 @@ namespace outer { using namespace outer_alias::inner::secret; namespace super_secret = outer_alias::inner::secret; -// RUN: c-index-test -test-annotate-tokens=%s:13:1:53:1 %s | FileCheck %s +template +struct X3 { + void f(T *t) { + t->::outer_alias::inner::template vector::~vector(); + } +}; + +// RUN: c-index-test -test-annotate-tokens=%s:13:1:60:1 %s | FileCheck %s // CHECK: Keyword: "using" [14:1 - 14:6] UsingDeclaration=vector[4:12] // CHECK: Identifier: "outer_alias" [14:7 - 14:18] NamespaceRef=outer_alias:10:11 @@ -120,3 +127,24 @@ namespace super_secret = outer_alias::inner::secret; // CHECK: Identifier: "secret" [52:46 - 52:52] NamespaceRef=secret:46:15 // CHECK: Punctuation: ";" [52:52 - 52:53] +// Pseudo-destructor +// CHECK: Identifier: "t" [57:5 - 57:6] DeclRefExpr=t:56:13 +// CHECK: Punctuation: "->" [57:6 - 57:8] UnexposedExpr= +// CHECK: Punctuation: "::" [57:8 - 57:10] UnexposedExpr= +// CHECK: Identifier: "outer_alias" [57:10 - 57:21] NamespaceRef=outer_alias:10:11 +// CHECK: Punctuation: "::" [57:21 - 57:23] UnexposedExpr= +// CHECK: Identifier: "inner" [57:23 - 57:28] NamespaceRef=inner:45:13 +// CHECK: Punctuation: "::" [57:28 - 57:30] UnexposedExpr= +// CHECK: Keyword: "template" [57:30 - 57:38] UnexposedExpr= +// CHECK: Identifier: "vector" [57:39 - 57:45] TemplateRef=vector:4:12 +// CHECK: Punctuation: "<" [57:45 - 57:46] UnexposedExpr= +// CHECK: Identifier: "T" [57:46 - 57:47] UnexposedExpr= +// CHECK: Punctuation: ">" [57:47 - 57:48] UnexposedExpr= +// CHECK: Punctuation: "::" [57:48 - 57:50] UnexposedExpr= +// CHECK: Punctuation: "~" [57:50 - 57:51] UnexposedExpr= +// CHECK: Identifier: "vector" [57:51 - 57:57] TemplateRef=vector:4:12 +// CHECK: Punctuation: "<" [57:57 - 57:58] UnexposedExpr= +// CHECK: Identifier: "T" [57:58 - 57:59] UnexposedExpr= +// CHECK: Punctuation: ">" [57:59 - 57:60] UnexposedExpr= +// CHECK: Punctuation: "(" [57:60 - 57:61] CallExpr= +// CHECK: Punctuation: ")" [57:61 - 57:62] CallExpr= diff --git a/test/SemaCXX/nested-name-spec-locations.cpp b/test/SemaCXX/nested-name-spec-locations.cpp index f0f42f754c..e4dd6cf986 100644 --- a/test/SemaCXX/nested-name-spec-locations.cpp +++ b/test/SemaCXX/nested-name-spec-locations.cpp @@ -40,3 +40,24 @@ struct UnresolvedUsingTypenameDeclTester { UnresolvedUsingTypenameDeclTester UnresolvedUsingTypenameDeclCheck; // expected-note{{in instantiation of template class}} + +template +struct PseudoDestructorExprTester { + void f(T *t) { + t->T::template Inner::type + * // expected-error{{as a pointer to a reference of type}} + >::Blarg::~Blarg(); + } +}; + +struct HasInnerTemplate { + template + struct Inner; + + typedef HasInnerTemplate T; +}; + +void PseudoDestructorExprCheck( + PseudoDestructorExprTester tester) { + tester.f(0); // expected-note{{in instantiation of member function}} +} diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index a09a737125..bddf3d82ff 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -140,6 +140,7 @@ public: DeclRefExprPartsKind, LabelRefVisitKind, ExplicitTemplateArgsVisitKind, NestedNameSpecifierVisitKind, + NestedNameSpecifierLocVisitKind, DeclarationNameInfoVisitKind, MemberRefVisitKind, SizeOfPackExprPartsKind }; protected: @@ -1615,6 +1616,24 @@ public: return SourceRange(A, B); } }; + +class NestedNameSpecifierLocVisit : public VisitorJob { +public: + NestedNameSpecifierLocVisit(NestedNameSpecifierLoc Qualifier, CXCursor parent) + : VisitorJob(parent, VisitorJob::NestedNameSpecifierLocVisitKind, + Qualifier.getNestedNameSpecifier(), + Qualifier.getOpaqueData()) { } + + static bool classof(const VisitorJob *VJ) { + return VJ->getKind() == VisitorJob::NestedNameSpecifierLocVisitKind; + } + + NestedNameSpecifierLoc get() const { + return NestedNameSpecifierLoc(static_cast(data[0]), + data[1]); + } +}; + class DeclarationNameInfoVisit : public VisitorJob { public: DeclarationNameInfoVisit(Stmt *S, CXCursor parent) @@ -1697,6 +1716,7 @@ public: private: void AddDeclarationNameInfo(Stmt *S); void AddNestedNameSpecifier(NestedNameSpecifier *NS, SourceRange R); + void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier); void AddExplicitTemplateArgs(const ExplicitTemplateArgumentList *A); void AddMemberRef(FieldDecl *D, SourceLocation L); void AddStmt(Stmt *S); @@ -1716,6 +1736,13 @@ void EnqueueVisitor::AddNestedNameSpecifier(NestedNameSpecifier *N, if (N) WL.push_back(NestedNameSpecifierVisit(N, R, Parent)); } + +void +EnqueueVisitor::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier) { + if (Qualifier) + WL.push_back(NestedNameSpecifierLocVisit(Qualifier, Parent)); +} + void EnqueueVisitor::AddStmt(Stmt *S) { if (S) WL.push_back(StmtVisit(S, Parent)); @@ -1800,8 +1827,8 @@ void EnqueueVisitor::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) { // but isn't. AddTypeLoc(E->getScopeTypeInfo()); // Visit the nested-name-specifier. - if (NestedNameSpecifier *Qualifier = E->getQualifier()) - AddNestedNameSpecifier(Qualifier, E->getQualifierRange()); + if (NestedNameSpecifierLoc QualifierLoc = E->getQualifierLoc()) + AddNestedNameSpecifierLoc(QualifierLoc); // Visit base expression. AddStmt(E->getBase()); } @@ -2048,12 +2075,21 @@ bool CursorVisitor::RunVisitorWorkList(VisitorWorkList &WL) { } continue; } + case VisitorJob::NestedNameSpecifierVisitKind: { NestedNameSpecifierVisit *V = cast(&LI); if (VisitNestedNameSpecifier(V->get(), V->getSourceRange())) return true; continue; } + + case VisitorJob::NestedNameSpecifierLocVisitKind: { + NestedNameSpecifierLocVisit *V = cast(&LI); + if (VisitNestedNameSpecifierLoc(V->get())) + return true; + continue; + } + case VisitorJob::DeclarationNameInfoVisitKind: { if (VisitDeclarationNameInfo(cast(&LI) ->get()))