From dc355713be51fcb4ee52d9fd6b4548ceff47fadf Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Fri, 25 Feb 2011 00:36:19 +0000 Subject: [PATCH] Update UsingDecl, UnresolvedUsingTypenameDecl, and UnresolvedUsingValueDecl to use NestedNameSpecifierLoc rather than the extremely-lossy NestedNameSpecifier/SourceRange pair it used to use, improving source-location information. Various infrastructure updates to support NestedNameSpecifierLoc: - AST/PCH (de-)serialization - Recursive AST visitor - libclang traversal (including the first tests of this functionality) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126459 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/DeclCXX.h | 140 ++++++++---------- include/clang/AST/NestedNameSpecifier.h | 23 ++- include/clang/AST/RecursiveASTVisitor.h | 37 ++++- include/clang/Frontend/DeclXML.def | 2 +- include/clang/Serialization/ASTReader.h | 4 + include/clang/Serialization/ASTWriter.h | 7 + lib/AST/Decl.cpp | 10 +- lib/AST/DeclCXX.cpp | 18 +-- lib/AST/DeclPrinter.cpp | 6 +- lib/AST/NestedNameSpecifier.cpp | 15 +- lib/AST/StmtDumper.cpp | 4 +- lib/Sema/SemaDeclCXX.cpp | 31 ++-- lib/Sema/SemaTemplate.cpp | 2 +- lib/Sema/SemaTemplateInstantiateDecl.cpp | 32 ++-- lib/Serialization/ASTReader.cpp | 103 +++++++++++++ lib/Serialization/ASTReaderDecl.cpp | 21 ++- lib/Serialization/ASTWriter.cpp | 61 +++++++- lib/Serialization/ASTWriterDecl.cpp | 9 +- test/Index/annotate-nested-name-specifier.cpp | 42 ++++++ tools/libclang/CIndex.cpp | 57 ++++++- 20 files changed, 461 insertions(+), 163 deletions(-) create mode 100644 test/Index/annotate-nested-name-specifier.cpp diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index d11ee8f7fd..7e8bc44396 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -2002,15 +2002,11 @@ public: /// UsingDecl - Represents a C++ using-declaration. For example: /// using someNameSpace::someIdentifier; class UsingDecl : public NamedDecl { - /// \brief The source range that covers the nested-name-specifier - /// preceding the declaration name. - SourceRange NestedNameRange; - /// \brief The source location of the "using" location itself. SourceLocation UsingLocation; - /// \brief Target nested name specifier. - NestedNameSpecifier* TargetNestedName; + /// \brief The nested-name-specifier that precedes the name. + NestedNameSpecifierLoc QualifierLoc; /// DNLoc - Provides source/type location info for the /// declaration name embedded in the ValueDecl base class. @@ -2023,37 +2019,34 @@ class UsingDecl : public NamedDecl { // \brief Has 'typename' keyword. bool IsTypeName; - UsingDecl(DeclContext *DC, SourceRange NNR, - SourceLocation UL, NestedNameSpecifier* TargetNNS, + UsingDecl(DeclContext *DC, SourceLocation UL, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool IsTypeNameArg) : NamedDecl(Using, DC, NameInfo.getLoc(), NameInfo.getName()), - NestedNameRange(NNR), UsingLocation(UL), TargetNestedName(TargetNNS), + UsingLocation(UL), QualifierLoc(QualifierLoc), DNLoc(NameInfo.getInfo()), FirstUsingShadow(0),IsTypeName(IsTypeNameArg) { } public: - /// \brief Returns the source range that covers the nested-name-specifier - /// preceding the namespace name. - SourceRange getNestedNameRange() const { return NestedNameRange; } - - /// \brief Set the source range of the nested-name-specifier. - void setNestedNameRange(SourceRange R) { NestedNameRange = R; } - - // FIXME: Naming is inconsistent with other get*Loc functions. /// \brief Returns the source location of the "using" keyword. SourceLocation getUsingLocation() const { return UsingLocation; } /// \brief Set the source location of the 'using' keyword. void setUsingLocation(SourceLocation L) { UsingLocation = L; } - /// \brief Get the target nested name declaration. - NestedNameSpecifier* getTargetNestedNameDecl() const { - return TargetNestedName; + /// \brief Retrieve the nested-name-specifier that qualifies the name, + /// with source-location information. + NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } + + /// \brief Retrieve the nested-name-specifier that qualifies the name. + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); } - /// \brief Set the target nested name declaration. - void setTargetNestedNameDecl(NestedNameSpecifier *NNS) { - TargetNestedName = NNS; + /// \brief Retrieve the source range of the nested-name-specifier + /// that qualifies the name. + SourceRange getQualifierRange() const { + return QualifierLoc.getSourceRange(); } DeclarationNameInfo getNameInfo() const { @@ -2119,8 +2112,8 @@ public: void removeShadowDecl(UsingShadowDecl *S); static UsingDecl *Create(ASTContext &C, DeclContext *DC, - SourceRange NNR, SourceLocation UsingL, - NestedNameSpecifier* TargetNNS, + SourceLocation UsingL, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool IsTypeNameArg); @@ -2145,61 +2138,55 @@ public: /// using Base::foo; /// }; class UnresolvedUsingValueDecl : public ValueDecl { - /// \brief The source range that covers the nested-name-specifier - /// preceding the declaration name. - SourceRange TargetNestedNameRange; - /// \brief The source location of the 'using' keyword SourceLocation UsingLocation; - NestedNameSpecifier *TargetNestedNameSpecifier; + /// \brief The nested-name-specifier that precedes the name. + NestedNameSpecifierLoc QualifierLoc; /// DNLoc - Provides source/type location info for the /// declaration name embedded in the ValueDecl base class. DeclarationNameLoc DNLoc; UnresolvedUsingValueDecl(DeclContext *DC, QualType Ty, - SourceLocation UsingLoc, SourceRange TargetNNR, - NestedNameSpecifier *TargetNNS, + SourceLocation UsingLoc, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo) : ValueDecl(UnresolvedUsingValue, DC, NameInfo.getLoc(), NameInfo.getName(), Ty), - TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc), - TargetNestedNameSpecifier(TargetNNS), DNLoc(NameInfo.getInfo()) + UsingLocation(UsingLoc), QualifierLoc(QualifierLoc), + DNLoc(NameInfo.getInfo()) { } public: - /// \brief Returns the source range that covers the nested-name-specifier - /// preceding the namespace name. - SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; } - - /// \brief Set the source range coverting the nested-name-specifier preceding - /// the namespace name. - void setTargetNestedNameRange(SourceRange R) { TargetNestedNameRange = R; } - - /// \brief Get target nested name declaration. - NestedNameSpecifier* getTargetNestedNameSpecifier() const { - return TargetNestedNameSpecifier; - } - - /// \brief Set the nested name declaration. - void setTargetNestedNameSpecifier(NestedNameSpecifier* NNS) { - TargetNestedNameSpecifier = NNS; - } - /// \brief Returns the source location of the 'using' keyword. SourceLocation getUsingLoc() const { return UsingLocation; } /// \brief Set the source location of the 'using' keyword. void setUsingLoc(SourceLocation L) { UsingLocation = L; } + /// \brief Retrieve the nested-name-specifier that qualifies the name, + /// with source-location information. + NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } + + /// \brief Retrieve the nested-name-specifier that qualifies the name. + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); + } + + /// \brief Retrieve the source range of the nested-name-specifier + /// that qualifies the name. + SourceRange getQualifierRange() const { + return QualifierLoc.getSourceRange(); + } + DeclarationNameInfo getNameInfo() const { return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); } static UnresolvedUsingValueDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, - SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo); SourceRange getSourceRange() const { @@ -2224,49 +2211,52 @@ public: /// The type associated with a unresolved using typename decl is /// currently always a typename type. class UnresolvedUsingTypenameDecl : public TypeDecl { - /// \brief The source range that covers the nested-name-specifier - /// preceding the declaration name. - SourceRange TargetNestedNameRange; - /// \brief The source location of the 'using' keyword SourceLocation UsingLocation; /// \brief The source location of the 'typename' keyword SourceLocation TypenameLocation; - NestedNameSpecifier *TargetNestedNameSpecifier; + /// \brief The nested-name-specifier that precedes the name. + NestedNameSpecifierLoc QualifierLoc; UnresolvedUsingTypenameDecl(DeclContext *DC, SourceLocation UsingLoc, - SourceLocation TypenameLoc, - SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, - SourceLocation TargetNameLoc, IdentifierInfo *TargetName) + SourceLocation TypenameLoc, + NestedNameSpecifierLoc QualifierLoc, + SourceLocation TargetNameLoc, + IdentifierInfo *TargetName) : TypeDecl(UnresolvedUsingTypename, DC, TargetNameLoc, TargetName), - TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc), - TypenameLocation(TypenameLoc), TargetNestedNameSpecifier(TargetNNS) - { } + UsingLocation(UsingLoc), TypenameLocation(TypenameLoc), + QualifierLoc(QualifierLoc) { } friend class ASTDeclReader; public: - /// \brief Returns the source range that covers the nested-name-specifier - /// preceding the namespace name. - SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; } - - /// \brief Get target nested name declaration. - NestedNameSpecifier* getTargetNestedNameSpecifier() { - return TargetNestedNameSpecifier; - } - /// \brief Returns the source location of the 'using' keyword. SourceLocation getUsingLoc() const { return UsingLocation; } /// \brief Returns the source location of the 'typename' keyword. SourceLocation getTypenameLoc() const { return TypenameLocation; } + /// \brief Retrieve the nested-name-specifier that qualifies the name, + /// with source-location information. + NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } + + /// \brief Retrieve the nested-name-specifier that qualifies the name. + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); + } + + /// \brief Retrieve the source range of the nested-name-specifier + /// that qualifies the name. + SourceRange getQualifierRange() const { + return QualifierLoc.getSourceRange(); + } + + // FIXME: DeclarationNameInfo static UnresolvedUsingTypenameDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, - SourceLocation TypenameLoc, - SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, + SourceLocation TypenameLoc, NestedNameSpecifierLoc QualifierLoc, SourceLocation TargetNameLoc, DeclarationName TargetName); SourceRange getSourceRange() const { diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h index 6d1798c168..2803f51951 100644 --- a/include/clang/AST/NestedNameSpecifier.h +++ b/include/clang/AST/NestedNameSpecifier.h @@ -30,6 +30,7 @@ class NamespaceDecl; class IdentifierInfo; struct PrintingPolicy; class Type; +class TypeLoc; class LangOptions; /// \brief Represents a C++ nested name specifier, such as @@ -245,7 +246,7 @@ public: /// For example, if this instance refers to a nested-name-specifier /// \c ::std::vector::, the returned source range would cover /// from the initial '::' to the last '::'. - SourceRange getSourceRange(); + SourceRange getSourceRange() const; /// \brief Retrieve the source range covering just the last part of /// this nested-name-specifier, not including the prefix. @@ -253,7 +254,19 @@ public: /// For example, if this instance refers to a nested-name-specifier /// \c ::std::vector::, the returned source range would cover /// from "vector" to the last '::'. - SourceRange getLocalSourceRange(); + SourceRange getLocalSourceRange() const; + + /// \brief Retrieve the location of the beginning of this + /// nested-name-specifier. + SourceLocation getBeginLoc() const { + return getSourceRange().getBegin(); + } + + /// \brief Retrieve the location of the end of this + /// nested-name-specifier. + SourceLocation getEndLoc() const { + return getSourceRange().getEnd(); + } /// \brief Return the prefix of this nested-name-specifier. /// @@ -267,7 +280,11 @@ public: return NestedNameSpecifierLoc(Qualifier->getPrefix(), Data); } - + + /// \brief For a nested-name-specifier that refers to a type, + /// retrieve the type with source-location information. + TypeLoc getTypeLoc() const; + /// \brief Determines the data length for the entire /// nested-name-specifier. unsigned getDataLength() const { return getDataLength(Qualifier); } diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 328a737747..6359241660 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -181,6 +181,12 @@ public: /// \returns false if the visitation was terminated early, true otherwise. bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS); + /// \brief Recursively visit a C++ nested-name-specifier with location + /// information. + /// + /// \returns false if the visitation was terminated early, true otherwise. + bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS); + /// \brief Recursively visit a template name and dispatch to the /// appropriate method. /// @@ -514,6 +520,31 @@ bool RecursiveASTVisitor::TraverseNestedNameSpecifier( return true; } +template +bool RecursiveASTVisitor::TraverseNestedNameSpecifierLoc( + NestedNameSpecifierLoc NNS) { + if (!NNS) + return true; + + if (NestedNameSpecifierLoc Prefix = NNS.getPrefix()) + TRY_TO(TraverseNestedNameSpecifierLoc(Prefix)); + + switch (NNS.getNestedNameSpecifier()->getKind()) { + case NestedNameSpecifier::Identifier: + case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: + case NestedNameSpecifier::Global: + return true; + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + TRY_TO(TraverseTypeLoc(NNS.getTypeLoc())); + break; + } + + return true; +} + template bool RecursiveASTVisitor::TraverseTemplateName(TemplateName Template) { if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) @@ -1143,7 +1174,7 @@ DEF_TRAVERSE_DECL(ObjCPropertyDecl, { }) DEF_TRAVERSE_DECL(UsingDecl, { - TRY_TO(TraverseNestedNameSpecifier(D->getTargetNestedNameDecl())); + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); }) DEF_TRAVERSE_DECL(UsingDirectiveDecl, { @@ -1313,7 +1344,7 @@ DEF_TRAVERSE_DECL(TypedefDecl, { DEF_TRAVERSE_DECL(UnresolvedUsingTypenameDecl, { // A dependent using declaration which was marked with 'typename'. // template class A : public B { using typename B::foo; }; - TRY_TO(TraverseNestedNameSpecifier(D->getTargetNestedNameSpecifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); // We shouldn't traverse D->getTypeForDecl(); it's a result of // declaring the type, not something that was written in the // source. @@ -1426,7 +1457,7 @@ DEF_TRAVERSE_DECL(EnumConstantDecl, { DEF_TRAVERSE_DECL(UnresolvedUsingValueDecl, { // Like UnresolvedUsingTypenameDecl, but without the 'typename': // template Class A : public Base { using Base::foo; }; - TRY_TO(TraverseNestedNameSpecifier(D->getTargetNestedNameSpecifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); }) DEF_TRAVERSE_DECL(IndirectFieldDecl, {}) diff --git a/include/clang/Frontend/DeclXML.def b/include/clang/Frontend/DeclXML.def index 1b158fdfaf..58f7e55fbe 100644 --- a/include/clang/Frontend/DeclXML.def +++ b/include/clang/Frontend/DeclXML.def @@ -349,7 +349,7 @@ NODE_XML(UsingDecl, "Using") ID_ATTRIBUTE_XML ATTRIBUTE_FILE_LOCATION_XML ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getTargetNestedNameDecl(), "target_nested_namespace_decl") + ATTRIBUTE_XML(getQualifier(), "target_nested_namespace_decl") ATTRIBUTE_XML(isTypeName(), "is_typename") END_NODE_XML diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index 94b65cc299..424e78c391 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -1133,6 +1133,10 @@ public: NestedNameSpecifier *ReadNestedNameSpecifier(const RecordData &Record, unsigned &Idx); + NestedNameSpecifierLoc ReadNestedNameSpecifierLoc(PerFileData &F, + const RecordData &Record, + unsigned &Idx); + /// \brief Read a template name. TemplateName ReadTemplateName(PerFileData &F, const RecordData &Record, unsigned &Idx); diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index beb493625e..04ad93fa7c 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -443,6 +443,9 @@ public: /// \brief Emits a reference to a declarator info. void AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordDataImpl &Record); + /// \brief Emits a type with source-location information. + void AddTypeLoc(TypeLoc TL, RecordDataImpl &Record); + /// \brief Emits a template argument location info. void AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, const TemplateArgumentLocInfo &Arg, @@ -474,6 +477,10 @@ public: /// \brief Emit a nested name specifier. void AddNestedNameSpecifier(NestedNameSpecifier *NNS, RecordDataImpl &Record); + + /// \brief Emit a nested name specifier with source-location information. + void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, + RecordDataImpl &Record); /// \brief Emit a template name. void AddTemplateName(TemplateName Name, RecordDataImpl &Record); diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index c0300c50cd..ccc883e944 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -868,9 +868,13 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const { return cast(this)->getTargetDecl() == cast(OldD)->getTargetDecl(); - if (isa(this) && isa(OldD)) - return cast(this)->getTargetNestedNameDecl() == - cast(OldD)->getTargetNestedNameDecl(); + if (isa(this) && isa(OldD)) { + ASTContext &Context = getASTContext(); + return Context.getCanonicalNestedNameSpecifier( + cast(this)->getQualifier()) == + Context.getCanonicalNestedNameSpecifier( + cast(OldD)->getQualifier()); + } // For non-function declarations, if the declarations are of the // same kind then this must be a redeclaration, or semantic analysis diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index fba73f59d5..a1d6cc369e 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -1337,35 +1337,31 @@ void UsingDecl::removeShadowDecl(UsingShadowDecl *S) { S->UsingOrNextShadow = this; } -UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC, - SourceRange NNR, SourceLocation UL, - NestedNameSpecifier* TargetNNS, +UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UL, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool IsTypeNameArg) { - return new (C) UsingDecl(DC, NNR, UL, TargetNNS, NameInfo, IsTypeNameArg); + return new (C) UsingDecl(DC, UL, QualifierLoc, NameInfo, IsTypeNameArg); } UnresolvedUsingValueDecl * UnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, - SourceRange TargetNNR, - NestedNameSpecifier *TargetNNS, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo) { return new (C) UnresolvedUsingValueDecl(DC, C.DependentTy, UsingLoc, - TargetNNR, TargetNNS, NameInfo); + QualifierLoc, NameInfo); } UnresolvedUsingTypenameDecl * UnresolvedUsingTypenameDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, SourceLocation TypenameLoc, - SourceRange TargetNNR, - NestedNameSpecifier *TargetNNS, + NestedNameSpecifierLoc QualifierLoc, SourceLocation TargetNameLoc, DeclarationName TargetName) { return new (C) UnresolvedUsingTypenameDecl(DC, UsingLoc, TypenameLoc, - TargetNNR, TargetNNS, - TargetNameLoc, + QualifierLoc, TargetNameLoc, TargetName.getAsIdentifierInfo()); } diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index 77b4257470..c6ae128e42 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -918,20 +918,20 @@ void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) { void DeclPrinter::VisitUsingDecl(UsingDecl *D) { Out << "using "; - D->getTargetNestedNameDecl()->print(Out, Policy); + D->getQualifier()->print(Out, Policy); Out << D; } void DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) { Out << "using typename "; - D->getTargetNestedNameSpecifier()->print(Out, Policy); + D->getQualifier()->print(Out, Policy); Out << D->getDeclName(); } void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { Out << "using "; - D->getTargetNestedNameSpecifier()->print(Out, Policy); + D->getQualifier()->print(Out, Policy); Out << D->getDeclName(); } diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp index da12aa77dd..0689ae1c88 100644 --- a/lib/AST/NestedNameSpecifier.cpp +++ b/lib/AST/NestedNameSpecifier.cpp @@ -320,7 +320,7 @@ namespace { } } -SourceRange NestedNameSpecifierLoc::getSourceRange() { +SourceRange NestedNameSpecifierLoc::getSourceRange() const { NestedNameSpecifierLoc First = *this; while (NestedNameSpecifierLoc Prefix= First.getPrefix()) First = Prefix; @@ -329,7 +329,7 @@ SourceRange NestedNameSpecifierLoc::getSourceRange() { getLocalSourceRange().getEnd()); } -SourceRange NestedNameSpecifierLoc::getLocalSourceRange() { +SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const { unsigned Offset = getDataLength(Qualifier->getPrefix()); switch (Qualifier->getKind()) { case NestedNameSpecifier::Global: @@ -354,3 +354,14 @@ SourceRange NestedNameSpecifierLoc::getLocalSourceRange() { return SourceRange(); } + +TypeLoc NestedNameSpecifierLoc::getTypeLoc() const { + assert((Qualifier->getKind() == NestedNameSpecifier::TypeSpec || + Qualifier->getKind() == NestedNameSpecifier::TypeSpecWithTemplate) && + "Nested-name-specifier location is not a type"); + + // The "void*" that points at the TypeLoc data. + unsigned Offset = getDataLength(Qualifier->getPrefix()); + void *TypeData = LoadPointer(Data, Offset); + return TypeLoc(Qualifier->getAsType(), TypeData); +} diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp index 846bd4ce14..5c7dbb3ed9 100644 --- a/lib/AST/StmtDumper.cpp +++ b/lib/AST/StmtDumper.cpp @@ -279,8 +279,8 @@ void StmtDumper::DumpDeclarator(Decl *D) { // print using decl (e.g. "using std::string;") const char *tn = UD->isTypeName() ? "typename " : ""; OS << '"' << UD->getDeclKindName() << tn; - UD->getTargetNestedNameDecl()->print(OS, - PrintingPolicy(UD->getASTContext().getLangOptions())); + UD->getQualifier()->print(OS, + PrintingPolicy(UD->getASTContext().getLangOptions())); OS << ";\""; } else if (LabelDecl *LD = dyn_cast(D)) { OS << "label " << LD->getNameAsString(); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 8e1792bf1d..89b2263329 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -3919,16 +3919,16 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, if (OrigDC == CurContext) { Diag(Using->getLocation(), diag::err_using_decl_nested_name_specifier_is_current_class) - << Using->getNestedNameRange(); + << Using->getQualifierLoc().getSourceRange(); Diag(Orig->getLocation(), diag::note_using_decl_target); return true; } - Diag(Using->getNestedNameRange().getBegin(), + Diag(Using->getQualifierLoc().getBeginLoc(), diag::err_using_decl_nested_name_specifier_is_not_base_class) - << Using->getTargetNestedNameDecl() + << Using->getQualifier() << cast(CurContext) - << Using->getNestedNameRange(); + << Using->getQualifierLoc().getSourceRange(); Diag(Orig->getLocation(), diag::note_using_decl_target); return true; } @@ -4134,8 +4134,6 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, LookupQualifiedName(Previous, CurContext); } - NestedNameSpecifier *NNS = SS.getScopeRep(); - // Check for invalid redeclarations. if (CheckUsingDeclRedeclaration(UsingLoc, IsTypeName, SS, IdentLoc, Previous)) return 0; @@ -4146,22 +4144,21 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, DeclContext *LookupContext = computeDeclContext(SS); NamedDecl *D; + NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); if (!LookupContext) { if (IsTypeName) { // FIXME: not all declaration name kinds are legal here D = UnresolvedUsingTypenameDecl::Create(Context, CurContext, UsingLoc, TypenameLoc, - SS.getRange(), NNS, + QualifierLoc, IdentLoc, NameInfo.getName()); } else { - D = UnresolvedUsingValueDecl::Create(Context, CurContext, - UsingLoc, SS.getRange(), - NNS, NameInfo); + D = UnresolvedUsingValueDecl::Create(Context, CurContext, UsingLoc, + QualifierLoc, NameInfo); } } else { - D = UsingDecl::Create(Context, CurContext, - SS.getRange(), UsingLoc, NNS, NameInfo, - IsTypeName); + D = UsingDecl::Create(Context, CurContext, UsingLoc, QualifierLoc, + NameInfo, IsTypeName); } D->setAccess(AS); CurContext->addDecl(D); @@ -4252,7 +4249,7 @@ bool Sema::CheckInheritedConstructorUsingDecl(UsingDecl *UD) { return true; } - const Type *SourceType = UD->getTargetNestedNameDecl()->getAsType(); + const Type *SourceType = UD->getQualifier()->getAsType(); assert(SourceType && "Using decl naming constructor doesn't have type in scope spec."); CXXRecordDecl *TargetClass = cast(CurContext); @@ -4309,15 +4306,15 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc, NestedNameSpecifier *DQual; if (UsingDecl *UD = dyn_cast(D)) { DTypename = UD->isTypeName(); - DQual = UD->getTargetNestedNameDecl(); + DQual = UD->getQualifier(); } else if (UnresolvedUsingValueDecl *UD = dyn_cast(D)) { DTypename = false; - DQual = UD->getTargetNestedNameSpecifier(); + DQual = UD->getQualifier(); } else if (UnresolvedUsingTypenameDecl *UD = dyn_cast(D)) { DTypename = true; - DQual = UD->getTargetNestedNameSpecifier(); + DQual = UD->getQualifier(); } else continue; // using decls differ if one says 'typename' and the other doesn't. diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 474a18df7f..8f7b7da6f3 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -6036,7 +6036,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, << Name << Ctx << FullRange; if (UnresolvedUsingValueDecl *Using = dyn_cast(Result.getRepresentativeDecl())){ - SourceLocation Loc = Using->getTargetNestedNameRange().getBegin(); + SourceLocation Loc = Using->getQualifierLoc().getBeginLoc(); Diag(Loc, diag::note_using_value_decl_missing_typename) << FixItHint::CreateInsertion(Loc, "typename "); } diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index de4cd46e7a..e1a7065197 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1661,12 +1661,12 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { // template struct t; // Here, in using s1::f1, s1 refers to t::s1; // we need to substitute for t::s1. - NestedNameSpecifier *NNS = - SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameDecl(), - D->getNestedNameRange(), - TemplateArgs); + NestedNameSpecifier *NNS + = SemaRef.SubstNestedNameSpecifier(D->getQualifier(), + D->getQualifierRange(), + TemplateArgs); if (!NNS) - return 0; + return 0; // The name info is non-dependent, so no transformation // is required. @@ -1680,16 +1680,18 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { LookupResult Prev(SemaRef, NameInfo, Sema::LookupUsingDeclName, Sema::ForRedeclaration); + CXXScopeSpec SS; + if (NNS == D->getQualifier()) + SS.Adopt(D->getQualifierLoc()); + else + SS.MakeTrivial(SemaRef.Context, NNS, D->getQualifierRange()); + UsingDecl *NewUD = UsingDecl::Create(SemaRef.Context, Owner, - D->getNestedNameRange(), D->getUsingLocation(), - NNS, + SS.getWithLocInContext(SemaRef.Context), NameInfo, D->isTypeName()); - CXXScopeSpec SS; - SS.MakeTrivial(SemaRef.Context, NNS, D->getNestedNameRange()); - if (CheckRedeclaration) { Prev.setHideTags(false); SemaRef.LookupQualifiedName(Prev, Owner); @@ -1749,14 +1751,13 @@ Decl *TemplateDeclInstantiator::VisitUsingShadowDecl(UsingShadowDecl *D) { Decl * TemplateDeclInstantiator ::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) { NestedNameSpecifier *NNS = - SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameSpecifier(), - D->getTargetNestedNameRange(), + SemaRef.SubstNestedNameSpecifier(D->getQualifier(), D->getQualifierRange(), TemplateArgs); if (!NNS) return 0; CXXScopeSpec SS; - SS.MakeTrivial(SemaRef.Context, NNS, D->getTargetNestedNameRange()); + SS.MakeTrivial(SemaRef.Context, NNS, D->getQualifierRange()); // Since NameInfo refers to a typename, it cannot be a C++ special name. // Hence, no tranformation is required for it. @@ -1775,14 +1776,13 @@ Decl * TemplateDeclInstantiator Decl * TemplateDeclInstantiator ::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { NestedNameSpecifier *NNS = - SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameSpecifier(), - D->getTargetNestedNameRange(), + SemaRef.SubstNestedNameSpecifier(D->getQualifier(), D->getQualifierRange(), TemplateArgs); if (!NNS) return 0; CXXScopeSpec SS; - SS.MakeTrivial(SemaRef.Context, NNS, D->getTargetNestedNameRange()); + SS.MakeTrivial(SemaRef.Context, NNS, D->getQualifierRange()); DeclarationNameInfo NameInfo = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs); diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 6f8856cd8d..93e3606942 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -4759,6 +4759,109 @@ ASTReader::ReadNestedNameSpecifier(const RecordData &Record, unsigned &Idx) { return NNS; } +NestedNameSpecifierLoc +ASTReader::ReadNestedNameSpecifierLoc(PerFileData &F, const RecordData &Record, + unsigned &Idx) { + unsigned N = Record[Idx++]; + NestedNameSpecifier *NNS = 0, *Prev = 0; + llvm::SmallVector LocationData; + for (unsigned I = 0; I != N; ++I) { + NestedNameSpecifier::SpecifierKind Kind + = (NestedNameSpecifier::SpecifierKind)Record[Idx++]; + switch (Kind) { + case NestedNameSpecifier::Identifier: { + // Nested-name-specifier + IdentifierInfo *II = GetIdentifierInfo(Record, Idx); + NNS = NestedNameSpecifier::Create(*Context, Prev, II); + + // Location information + SourceRange Range = ReadSourceRange(F, Record, Idx); + unsigned RawStart = Range.getBegin().getRawEncoding(); + unsigned RawEnd = Range.getEnd().getRawEncoding(); + LocationData.append(reinterpret_cast(&RawStart), + reinterpret_cast(&RawStart) +sizeof(unsigned)); + LocationData.append(reinterpret_cast(&RawEnd), + reinterpret_cast(&RawEnd) + sizeof(unsigned)); + break; + } + + case NestedNameSpecifier::Namespace: { + // Nested-name-specifier + NamespaceDecl *NS = cast(GetDecl(Record[Idx++])); + NNS = NestedNameSpecifier::Create(*Context, Prev, NS); + + // Location information + SourceRange Range = ReadSourceRange(F, Record, Idx); + unsigned RawStart = Range.getBegin().getRawEncoding(); + unsigned RawEnd = Range.getEnd().getRawEncoding(); + LocationData.append(reinterpret_cast(&RawStart), + reinterpret_cast(&RawStart) +sizeof(unsigned)); + LocationData.append(reinterpret_cast(&RawEnd), + reinterpret_cast(&RawEnd) + sizeof(unsigned)); + break; + } + + case NestedNameSpecifier::NamespaceAlias: { + // Nested-name-specifier + NamespaceAliasDecl *Alias + = cast(GetDecl(Record[Idx++])); + NNS = NestedNameSpecifier::Create(*Context, Prev, Alias); + + // Location information + SourceRange Range = ReadSourceRange(F, Record, Idx); + unsigned RawStart = Range.getBegin().getRawEncoding(); + unsigned RawEnd = Range.getEnd().getRawEncoding(); + LocationData.append(reinterpret_cast(&RawStart), + reinterpret_cast(&RawStart) +sizeof(unsigned)); + LocationData.append(reinterpret_cast(&RawEnd), + reinterpret_cast(&RawEnd) + sizeof(unsigned)); + + break; + } + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: { + // Nested-name-specifier + bool Template = Record[Idx++]; + TypeSourceInfo *T = GetTypeSourceInfo(F, Record, Idx); + if (!T) + return NestedNameSpecifierLoc(); + NNS = NestedNameSpecifier::Create(*Context, Prev, Template, + T->getType().getTypePtr()); + + // Location information. + SourceLocation ColonColonLoc = ReadSourceLocation(F, Record, Idx); + unsigned RawLocation = ColonColonLoc.getRawEncoding(); + void *OpaqueTypeData = T->getTypeLoc().getOpaqueData(); + LocationData.append(reinterpret_cast(&OpaqueTypeData), + (reinterpret_cast(&OpaqueTypeData) + + sizeof(void *))); + LocationData.append(reinterpret_cast(&RawLocation), + (reinterpret_cast(&RawLocation) + + sizeof(unsigned))); + break; + } + + case NestedNameSpecifier::Global: { + // Nested-name-specifier + NNS = NestedNameSpecifier::GlobalSpecifier(*Context); + + SourceLocation ColonColonLoc = ReadSourceLocation(F, Record, Idx); + unsigned RawLocation = ColonColonLoc.getRawEncoding(); + LocationData.append(reinterpret_cast(&RawLocation), + (reinterpret_cast(&RawLocation) + + sizeof(unsigned))); + break; + } + } + Prev = NNS; + } + + void *Mem = Context->Allocate(LocationData.size(), llvm::alignOf()); + memcpy(Mem, LocationData.data(), LocationData.size()); + return NestedNameSpecifierLoc(NNS, Mem); +} + SourceRange ASTReader::ReadSourceRange(PerFileData &F, const RecordData &Record, unsigned &Idx) { diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index dec15dd694..caa5132473 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -753,8 +753,7 @@ void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { void ASTDeclReader::VisitUsingDecl(UsingDecl *D) { VisitNamedDecl(D); D->setUsingLocation(ReadSourceLocation(Record, Idx)); - D->setNestedNameRange(ReadSourceRange(Record, Idx)); - D->setTargetNestedNameDecl(Reader.ReadNestedNameSpecifier(Record, Idx)); + D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); ReadDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record, Idx); D->FirstUsingShadow = cast_or_null(Reader.GetDecl(Record[Idx++])); D->setTypeName(Record[Idx++]); @@ -785,19 +784,17 @@ void ASTDeclReader::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { void ASTDeclReader::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { VisitValueDecl(D); - D->setTargetNestedNameRange(ReadSourceRange(Record, Idx)); D->setUsingLoc(ReadSourceLocation(Record, Idx)); - D->setTargetNestedNameSpecifier(Reader.ReadNestedNameSpecifier(Record, Idx)); + D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); ReadDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record, Idx); } void ASTDeclReader::VisitUnresolvedUsingTypenameDecl( UnresolvedUsingTypenameDecl *D) { VisitTypeDecl(D); - D->TargetNestedNameRange = ReadSourceRange(Record, Idx); D->UsingLocation = ReadSourceLocation(Record, Idx); D->TypenameLocation = ReadSourceLocation(Record, Idx); - D->TargetNestedNameSpecifier = Reader.ReadNestedNameSpecifier(Record, Idx); + D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); } void ASTDeclReader::ReadCXXDefinitionData( @@ -1436,8 +1433,9 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) { SourceLocation(), 0); break; case DECL_USING: - D = UsingDecl::Create(*Context, 0, SourceRange(), SourceLocation(), - 0, DeclarationNameInfo(), false); + D = UsingDecl::Create(*Context, 0, SourceLocation(), + NestedNameSpecifierLoc(), DeclarationNameInfo(), + false); break; case DECL_USING_SHADOW: D = UsingShadowDecl::Create(*Context, 0, SourceLocation(), 0, 0); @@ -1449,13 +1447,14 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) { break; case DECL_UNRESOLVED_USING_VALUE: D = UnresolvedUsingValueDecl::Create(*Context, 0, SourceLocation(), - SourceRange(), 0, + NestedNameSpecifierLoc(), DeclarationNameInfo()); break; case DECL_UNRESOLVED_USING_TYPENAME: D = UnresolvedUsingTypenameDecl::Create(*Context, 0, SourceLocation(), - SourceLocation(), SourceRange(), - 0, SourceLocation(), + SourceLocation(), + NestedNameSpecifierLoc(), + SourceLocation(), DeclarationName()); break; case DECL_CXX_RECORD: diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 42ca293932..ba2494b5c5 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -3276,15 +3276,21 @@ void ASTWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg, Record); } -void ASTWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordDataImpl &Record) { +void ASTWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo, + RecordDataImpl &Record) { if (TInfo == 0) { AddTypeRef(QualType(), Record); return; } - AddTypeRef(TInfo->getType(), Record); + AddTypeLoc(TInfo->getTypeLoc(), Record); +} + +void ASTWriter::AddTypeLoc(TypeLoc TL, RecordDataImpl &Record) { + AddTypeRef(TL.getType(), Record); + TypeLocWriter TLW(*this, Record); - for (TypeLoc TL = TInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc()) + for (; !TL.isNull(); TL = TL.getNextTypeLoc()) TLW.Visit(TL); } @@ -3487,6 +3493,55 @@ void ASTWriter::AddNestedNameSpecifier(NestedNameSpecifier *NNS, } } +void ASTWriter::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, + RecordDataImpl &Record) { + // Nested name specifiers usually aren't too long. I think that 8 would + // typically accomodate the vast majority. + llvm::SmallVector NestedNames; + + // Push each of the nested-name-specifiers's onto a stack for + // serialization in reverse order. + while (NNS) { + NestedNames.push_back(NNS); + NNS = NNS.getPrefix(); + } + + Record.push_back(NestedNames.size()); + while(!NestedNames.empty()) { + NNS = NestedNames.pop_back_val(); + NestedNameSpecifier::SpecifierKind Kind + = NNS.getNestedNameSpecifier()->getKind(); + Record.push_back(Kind); + switch (Kind) { + case NestedNameSpecifier::Identifier: + AddIdentifierRef(NNS.getNestedNameSpecifier()->getAsIdentifier(), Record); + AddSourceRange(NNS.getLocalSourceRange(), Record); + break; + + case NestedNameSpecifier::Namespace: + AddDeclRef(NNS.getNestedNameSpecifier()->getAsNamespace(), Record); + AddSourceRange(NNS.getLocalSourceRange(), Record); + break; + + case NestedNameSpecifier::NamespaceAlias: + AddDeclRef(NNS.getNestedNameSpecifier()->getAsNamespaceAlias(), Record); + AddSourceRange(NNS.getLocalSourceRange(), Record); + break; + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + Record.push_back(Kind == NestedNameSpecifier::TypeSpecWithTemplate); + AddTypeLoc(NNS.getTypeLoc(), Record); + AddSourceLocation(NNS.getLocalSourceRange().getEnd(), Record); + break; + + case NestedNameSpecifier::Global: + AddSourceLocation(NNS.getLocalSourceRange().getEnd(), Record); + break; + } + } +} + void ASTWriter::AddTemplateName(TemplateName Name, RecordDataImpl &Record) { TemplateName::NameKind Kind = Name.getKind(); Record.push_back(Kind); diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index ce07e1389b..5d0514fca2 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -706,9 +706,8 @@ void ASTDeclWriter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { void ASTDeclWriter::VisitUsingDecl(UsingDecl *D) { VisitNamedDecl(D); - Writer.AddSourceRange(D->getNestedNameRange(), Record); Writer.AddSourceLocation(D->getUsingLocation(), Record); - Writer.AddNestedNameSpecifier(D->getTargetNestedNameDecl(), Record); + Writer.AddNestedNameSpecifierLoc(D->getQualifierLoc(), Record); Writer.AddDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record); Writer.AddDeclRef(D->FirstUsingShadow, Record); Record.push_back(D->isTypeName()); @@ -737,9 +736,8 @@ void ASTDeclWriter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { void ASTDeclWriter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { VisitValueDecl(D); - Writer.AddSourceRange(D->getTargetNestedNameRange(), Record); Writer.AddSourceLocation(D->getUsingLoc(), Record); - Writer.AddNestedNameSpecifier(D->getTargetNestedNameSpecifier(), Record); + Writer.AddNestedNameSpecifierLoc(D->getQualifierLoc(), Record); Writer.AddDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record); Code = serialization::DECL_UNRESOLVED_USING_VALUE; } @@ -747,10 +745,9 @@ void ASTDeclWriter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { void ASTDeclWriter::VisitUnresolvedUsingTypenameDecl( UnresolvedUsingTypenameDecl *D) { VisitTypeDecl(D); - Writer.AddSourceRange(D->getTargetNestedNameRange(), Record); Writer.AddSourceLocation(D->getUsingLoc(), Record); Writer.AddSourceLocation(D->getTypenameLoc(), Record); - Writer.AddNestedNameSpecifier(D->getTargetNestedNameSpecifier(), Record); + Writer.AddNestedNameSpecifierLoc(D->getQualifierLoc(), Record); Code = serialization::DECL_UNRESOLVED_USING_TYPENAME; } diff --git a/test/Index/annotate-nested-name-specifier.cpp b/test/Index/annotate-nested-name-specifier.cpp new file mode 100644 index 0000000000..13bcc98db5 --- /dev/null +++ b/test/Index/annotate-nested-name-specifier.cpp @@ -0,0 +1,42 @@ +namespace outer { + namespace inner { + template + struct vector { + typedef T* iterator; + }; + } +} + +namespace outer_alias = outer; + +struct X { }; + +using outer_alias::inner::vector; + +struct X_vector : outer_alias::inner::vector { + using outer_alias::inner::vector::iterator; +}; + + + +// RUN: c-index-test -test-annotate-tokens=%s:13:1:19: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 +// CHECK: Punctuation: "::" [14:18 - 14:20] UsingDeclaration=vector[4:12] +// CHECK: Identifier: "inner" [14:20 - 14:25] NamespaceRef=inner:2:13 +// CHECK: Punctuation: "::" [14:25 - 14:27] UsingDeclaration=vector[4:12] +// CHECK: Identifier: "vector" [14:27 - 14:33] OverloadedDeclRef=vector[4:12] +// CHECK: Punctuation: ";" [14:33 - 14:34] +// FIXME: Base specifiers, too +// CHECK: Keyword: "using" [17:3 - 17:8] UsingDeclaration=iterator[5:18] +// CHECK: Identifier: "outer_alias" [17:9 - 17:20] NamespaceRef=outer_alias:10:11 +// CHECK: Punctuation: "::" [17:20 - 17:22] UsingDeclaration=iterator[5:18] +// CHECK: Identifier: "inner" [17:22 - 17:27] NamespaceRef=inner:2:13 +// CHECK: Punctuation: "::" [17:27 - 17:29] UsingDeclaration=iterator[5:18] +// CHECK: Identifier: "vector" [17:29 - 17:35] TemplateRef=vector:4:12 +// CHECK: Punctuation: "<" [17:35 - 17:36] UsingDeclaration=iterator[5:18] +// CHECK: Identifier: "X" [17:36 - 17:37] TypeRef=struct X:12:8 +// CHECK: Punctuation: ">" [17:37 - 17:38] UsingDeclaration=iterator[5:18] +// CHECK: Punctuation: "::" [17:38 - 17:40] UsingDeclaration=iterator[5:18] +// CHECK: Identifier: "iterator" [17:40 - 17:48] OverloadedDeclRef=iterator[5:18] diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index c57a489d7d..dfcf220ff4 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -310,6 +310,7 @@ public: // Name visitor bool VisitDeclarationNameInfo(DeclarationNameInfo Name); bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range); + bool VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS); // Template visitors bool VisitTemplateParameters(const TemplateParameterList *Params); @@ -1084,9 +1085,10 @@ bool CursorVisitor::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { bool CursorVisitor::VisitUsingDecl(UsingDecl *D) { // Visit nested-name-specifier. - if (NestedNameSpecifier *Qualifier = D->getTargetNestedNameDecl()) - if (VisitNestedNameSpecifier(Qualifier, D->getNestedNameRange())) + if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc()) { + if (VisitNestedNameSpecifierLoc(QualifierLoc)) return true; + } if (Visit(MakeCursorOverloadedDeclRef(D, D->getLocation(), TU))) return true; @@ -1106,9 +1108,10 @@ bool CursorVisitor::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { bool CursorVisitor::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { // Visit nested-name-specifier. - if (NestedNameSpecifier *Qualifier = D->getTargetNestedNameSpecifier()) - if (VisitNestedNameSpecifier(Qualifier, D->getTargetNestedNameRange())) + if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc()) { + if (VisitNestedNameSpecifierLoc(QualifierLoc)) return true; + } return VisitDeclarationNameInfo(D->getNameInfo()); } @@ -1116,8 +1119,8 @@ bool CursorVisitor::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { bool CursorVisitor::VisitUnresolvedUsingTypenameDecl( UnresolvedUsingTypenameDecl *D) { // Visit nested-name-specifier. - if (NestedNameSpecifier *Qualifier = D->getTargetNestedNameSpecifier()) - if (VisitNestedNameSpecifier(Qualifier, D->getTargetNestedNameRange())) + if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc()) + if (VisitNestedNameSpecifierLoc(QualifierLoc)) return true; return false; @@ -1194,6 +1197,48 @@ bool CursorVisitor::VisitNestedNameSpecifier(NestedNameSpecifier *NNS, return false; } +bool +CursorVisitor::VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier) { + llvm::SmallVector Qualifiers; + for (; Qualifier; Qualifier = Qualifier.getPrefix()) + Qualifiers.push_back(Qualifier); + + while (!Qualifiers.empty()) { + NestedNameSpecifierLoc Q = Qualifiers.pop_back_val(); + NestedNameSpecifier *NNS = Q.getNestedNameSpecifier(); + switch (NNS->getKind()) { + case NestedNameSpecifier::Namespace: + if (Visit(MakeCursorNamespaceRef(NNS->getAsNamespace(), + Q.getLocalSourceRange().getBegin(), + TU))) + return true; + + break; + + case NestedNameSpecifier::NamespaceAlias: + if (Visit(MakeCursorNamespaceRef(NNS->getAsNamespaceAlias(), + Q.getLocalSourceRange().getBegin(), + TU))) + return true; + + break; + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + if (Visit(Q.getTypeLoc())) + return true; + + break; + + case NestedNameSpecifier::Global: + case NestedNameSpecifier::Identifier: + break; + } + } + + return false; +} + bool CursorVisitor::VisitTemplateParameters( const TemplateParameterList *Params) { if (!Params)