diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-02-25 02:25:35 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-02-25 02:25:35 +0000 |
commit | c22b5fff39a7520207f165fb16a27a34b944bd9c (patch) | |
tree | c79ab64b51bd9c1b5fe807aa689003dc23d2f128 | |
parent | 7decebfc7b9dc841f228c93cc2e41e3e62911ff8 (diff) |
Use NestedNameSpecifierLoc within out-of-line variables, function, and
tag definitions. Also, add support for template instantiation of
NestedNameSpecifierLocs.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126470 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/ASTImporter.h | 9 | ||||
-rw-r--r-- | include/clang/AST/Decl.h | 44 | ||||
-rw-r--r-- | include/clang/AST/NestedNameSpecifier.h | 12 | ||||
-rw-r--r-- | include/clang/Sema/DeclSpec.h | 2 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 5 | ||||
-rw-r--r-- | lib/AST/ASTImporter.cpp | 48 | ||||
-rw-r--r-- | lib/AST/Decl.cpp | 20 | ||||
-rw-r--r-- | lib/Sema/DeclSpec.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 7 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 11 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 102 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 176 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 3 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 3 | ||||
-rw-r--r-- | test/Index/annotate-nested-name-specifier.cpp | 19 | ||||
-rw-r--r-- | tools/libclang/CIndex.cpp | 18 |
18 files changed, 350 insertions, 139 deletions
diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h index b659ce74bb..e1535965b1 100644 --- a/include/clang/AST/ASTImporter.h +++ b/include/clang/AST/ASTImporter.h @@ -145,7 +145,14 @@ namespace clang { /// \returns the equivalent nested-name-specifier in the "to" /// context, or NULL if an error occurred. NestedNameSpecifier *Import(NestedNameSpecifier *FromNNS); - + + /// \brief Import the given nested-name-specifier from the "from" + /// context into the "to" context. + /// + /// \returns the equivalent nested-name-specifier in the "to" + /// context. + NestedNameSpecifierLoc Import(NestedNameSpecifierLoc FromNNS); + /// \brief Import the goven template name from the "from" context into the /// "to" context. TemplateName Import(TemplateName From); diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 1d5d0fe68b..ec379c3707 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -475,10 +475,7 @@ public: /// QualifierInfo - A struct with extended info about a syntactic /// name qualifier, to be used for the case of out-of-line declarations. struct QualifierInfo { - /// NNS - The syntactic name qualifier. - NestedNameSpecifier *NNS; - /// NNSRange - The source range for the qualifier. - SourceRange NNSRange; + NestedNameSpecifierLoc QualifierLoc; /// NumTemplParamLists - The number of template parameter lists /// that were matched against the template-ids occurring into the NNS. unsigned NumTemplParamLists; @@ -487,8 +484,7 @@ struct QualifierInfo { TemplateParameterList** TemplParamLists; /// Default constructor. - QualifierInfo() - : NNS(0), NNSRange(), NumTemplParamLists(0), TemplParamLists(0) {} + QualifierInfo() : QualifierLoc(), NumTemplParamLists(0), TemplParamLists(0) {} /// setTemplateParameterListsInfo - Sets info about matched template /// parameter lists. void setTemplateParameterListsInfo(ASTContext &Context, @@ -545,14 +541,22 @@ public: return SourceRange(getOuterLocStart(), getLocation()); } + /// \brief Retrieve the nested-name-specifier that qualifies the name of this + /// declaration, if it was present in the source. NestedNameSpecifier *getQualifier() const { - return hasExtInfo() ? getExtInfo()->NNS : 0; + return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier() + : 0; } - SourceRange getQualifierRange() const { - return hasExtInfo() ? getExtInfo()->NNSRange : SourceRange(); + + /// \brief Retrieve the nested-name-specifier (with source-location + /// information) that qualifies the name of this declaration, if it was + /// present in the source. + NestedNameSpecifierLoc getQualifierLoc() const { + return hasExtInfo() ? getExtInfo()->QualifierLoc + : NestedNameSpecifierLoc(); } - void setQualifierInfo(NestedNameSpecifier *Qualifier, - SourceRange QualifierRange); + + void setQualifierInfo(NestedNameSpecifierLoc QualifierLoc); unsigned getNumTemplateParameterLists() const { return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0; @@ -2140,14 +2144,22 @@ public: void setTypedefForAnonDecl(TypedefDecl *TDD); + /// \brief Retrieve the nested-name-specifier that qualifies the name of this + /// declaration, if it was present in the source. NestedNameSpecifier *getQualifier() const { - return hasExtInfo() ? getExtInfo()->NNS : 0; + return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier() + : 0; } - SourceRange getQualifierRange() const { - return hasExtInfo() ? getExtInfo()->NNSRange : SourceRange(); + + /// \brief Retrieve the nested-name-specifier (with source-location + /// information) that qualifies the name of this declaration, if it was + /// present in the source. + NestedNameSpecifierLoc getQualifierLoc() const { + return hasExtInfo() ? getExtInfo()->QualifierLoc + : NestedNameSpecifierLoc(); } - void setQualifierInfo(NestedNameSpecifier *Qualifier, - SourceRange QualifierRange); + + void setQualifierInfo(NestedNameSpecifierLoc QualifierLoc); unsigned getNumTemplateParameterLists() const { return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0; diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h index 2803f51951..5e9adfccc4 100644 --- a/include/clang/AST/NestedNameSpecifier.h +++ b/include/clang/AST/NestedNameSpecifier.h @@ -268,6 +268,18 @@ public: return getSourceRange().getEnd(); } + /// \brief Retrieve the location of the beginning of this + /// component of the nested-name-specifier. + SourceLocation getLocalBeginLoc() const { + return getLocalSourceRange().getBegin(); + } + + /// \brief Retrieve the location of the end of this component of the + /// nested-name-specifier. + SourceLocation getLocalEndLoc() const { + return getLocalSourceRange().getEnd(); + } + /// \brief Return the prefix of this nested-name-specifier. /// /// For example, if this instance refers to a nested-name-specifier diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 9386d35873..64126bd4d8 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -168,7 +168,7 @@ public: /// /// \param Context The context into which this nested-name-specifier will be /// copied. - NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context); + NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const; /// No scope specifier. bool isEmpty() const { return !Range.isValid(); } diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 8573f1dbfc..a93739892c 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -4293,6 +4293,11 @@ public: SubstNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range, const MultiLevelTemplateArgumentList &TemplateArgs); + + NestedNameSpecifierLoc + SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, + const MultiLevelTemplateArgumentList &TemplateArgs); + DeclarationNameInfo SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo, const MultiLevelTemplateArgumentList &TemplateArgs); diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 65c0a3bb61..21f10fb7ad 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -2097,11 +2097,7 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { D->isScoped(), D->isScopedUsingClassTag(), D->isFixed()); // Import the qualifier, if any. - if (D->getQualifier()) { - NestedNameSpecifier *NNS = Importer.Import(D->getQualifier()); - SourceRange NNSRange = Importer.Import(D->getQualifierRange()); - D2->setQualifierInfo(NNS, NNSRange); - } + D2->setQualifierInfo(Importer.Import(D->getQualifierLoc())); D2->setAccess(D->getAccess()); D2->setLexicalDeclContext(LexicalDC); Importer.Imported(D, D2); @@ -2225,12 +2221,8 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { Name.getAsIdentifierInfo(), Importer.Import(D->getTagKeywordLoc())); } - // Import the qualifier, if any. - if (D->getQualifier()) { - NestedNameSpecifier *NNS = Importer.Import(D->getQualifier()); - SourceRange NNSRange = Importer.Import(D->getQualifierRange()); - D2->setQualifierInfo(NNS, NNSRange); - } + + D2->setQualifierInfo(Importer.Import(D->getQualifierLoc())); D2->setLexicalDeclContext(LexicalDC); LexicalDC->addDecl(D2); } @@ -2408,11 +2400,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { } // Import the qualifier, if any. - if (D->getQualifier()) { - NestedNameSpecifier *NNS = Importer.Import(D->getQualifier()); - SourceRange NNSRange = Importer.Import(D->getQualifierRange()); - ToFunction->setQualifierInfo(NNS, NNSRange); - } + ToFunction->setQualifierInfo(Importer.Import(D->getQualifierLoc())); ToFunction->setAccess(D->getAccess()); ToFunction->setLexicalDeclContext(LexicalDC); ToFunction->setVirtualAsWritten(D->isVirtualAsWritten()); @@ -2666,12 +2654,7 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { Name.getAsIdentifierInfo(), T, TInfo, D->getStorageClass(), D->getStorageClassAsWritten()); - // Import the qualifier, if any. - if (D->getQualifier()) { - NestedNameSpecifier *NNS = Importer.Import(D->getQualifier()); - SourceRange NNSRange = Importer.Import(D->getQualifierRange()); - ToVar->setQualifierInfo(NNS, NNSRange); - } + ToVar->setQualifierInfo(Importer.Import(D->getQualifierLoc())); ToVar->setAccess(D->getAccess()); ToVar->setLexicalDeclContext(LexicalDC); Importer.Imported(D, ToVar); @@ -3591,14 +3574,7 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { Name.getAsIdentifierInfo(), Importer.Import(DTemplated->getTagKeywordLoc())); D2Templated->setAccess(DTemplated->getAccess()); - - - // Import the qualifier, if any. - if (DTemplated->getQualifier()) { - NestedNameSpecifier *NNS = Importer.Import(DTemplated->getQualifier()); - SourceRange NNSRange = Importer.Import(DTemplated->getQualifierRange()); - D2Templated->setQualifierInfo(NNS, NNSRange); - } + D2Templated->setQualifierInfo(Importer.Import(DTemplated->getQualifierLoc())); D2Templated->setLexicalDeclContext(LexicalDC); // Create the class template declaration itself. @@ -3703,12 +3679,7 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( ClassTemplate->AddSpecialization(D2, InsertPos); // Import the qualifier, if any. - if (D->getQualifier()) { - NestedNameSpecifier *NNS = Importer.Import(D->getQualifier()); - SourceRange NNSRange = Importer.Import(D->getQualifierRange()); - D2->setQualifierInfo(NNS, NNSRange); - } - + D2->setQualifierInfo(Importer.Import(D->getQualifierLoc())); // Add the specialization to this context. D2->setLexicalDeclContext(LexicalDC); @@ -4067,6 +4038,11 @@ NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) { return 0; } +NestedNameSpecifierLoc ASTImporter::Import(NestedNameSpecifierLoc FromNNS) { + // FIXME: Implement! + return NestedNameSpecifierLoc(); +} + TemplateName ASTImporter::Import(TemplateName From) { switch (From.getKind()) { case TemplateName::Template: diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index ccc883e944..d7e389e616 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -935,9 +935,8 @@ SourceLocation DeclaratorDecl::getTypeSpecStartLoc() const { return SourceLocation(); } -void DeclaratorDecl::setQualifierInfo(NestedNameSpecifier *Qualifier, - SourceRange QualifierRange) { - if (Qualifier) { +void DeclaratorDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { + if (QualifierLoc) { // Make sure the extended decl info is allocated. if (!hasExtInfo()) { // Save (non-extended) type source info pointer. @@ -948,12 +947,10 @@ void DeclaratorDecl::setQualifierInfo(NestedNameSpecifier *Qualifier, getExtInfo()->TInfo = savedTInfo; } // Set qualifier info. - getExtInfo()->NNS = Qualifier; - getExtInfo()->NNSRange = QualifierRange; + getExtInfo()->QualifierLoc = QualifierLoc; } else { // Here Qualifier == 0, i.e., we are removing the qualifier (if any). - assert(QualifierRange.isInvalid()); if (hasExtInfo()) { // Save type source info pointer. TypeSourceInfo *savedTInfo = getExtInfo()->TInfo; @@ -975,7 +972,7 @@ QualifierInfo::setTemplateParameterListsInfo(ASTContext &Context, TemplateParameterList **TPLists) { assert((NumTPLists == 0 || TPLists != 0) && "Empty array of template parameters with positive size!"); - assert((NumTPLists == 0 || NNS) && + assert((NumTPLists == 0 || QualifierLoc) && "Nonempty array of template parameters with no qualifier!"); // Free previous template parameters (if any). @@ -2027,19 +2024,16 @@ TagDecl* TagDecl::getDefinition() const { return 0; } -void TagDecl::setQualifierInfo(NestedNameSpecifier *Qualifier, - SourceRange QualifierRange) { - if (Qualifier) { +void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { + if (QualifierLoc) { // Make sure the extended qualifier info is allocated. if (!hasExtInfo()) TypedefDeclOrQualifier = new (getASTContext()) ExtInfo; // Set qualifier info. - getExtInfo()->NNS = Qualifier; - getExtInfo()->NNSRange = QualifierRange; + getExtInfo()->QualifierLoc = QualifierLoc; } else { // Here Qualifier == 0, i.e., we are removing the qualifier (if any). - assert(QualifierRange.isInvalid()); if (hasExtInfo()) { getASTContext().Deallocate(getExtInfo()); TypedefDeclOrQualifier = (TypedefDecl*) 0; diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp index 2d85374280..037594a44a 100644 --- a/lib/Sema/DeclSpec.cpp +++ b/lib/Sema/DeclSpec.cpp @@ -265,7 +265,8 @@ void CXXScopeSpec::Adopt(NestedNameSpecifierLoc Other) { BufferCapacity = 0; } -NestedNameSpecifierLoc CXXScopeSpec::getWithLocInContext(ASTContext &Context) { +NestedNameSpecifierLoc +CXXScopeSpec::getWithLocInContext(ASTContext &Context) const { if (isEmpty() || isInvalid()) return NestedNameSpecifierLoc(); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 75e7c6f2d9..d6efd7a6c9 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2895,8 +2895,7 @@ isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC, static void SetNestedNameSpecifier(DeclaratorDecl *DD, Declarator &D) { CXXScopeSpec &SS = D.getCXXScopeSpec(); if (!SS.isSet()) return; - DD->setQualifierInfo(static_cast<NestedNameSpecifier*>(SS.getScopeRep()), - SS.getRange()); + DD->setQualifierInfo(SS.getWithLocInContext(DD->getASTContext())); } NamedDecl* @@ -6445,9 +6444,7 @@ CreateNewDecl: // Maybe add qualifier info. if (SS.isNotEmpty()) { if (SS.isSet()) { - NestedNameSpecifier *NNS - = static_cast<NestedNameSpecifier*>(SS.getScopeRep()); - New->setQualifierInfo(NNS, SS.getRange()); + New->setQualifierInfo(SS.getWithLocInContext(Context)); if (NumMatchedTemplateParamLists > 0) { New->setTemplateParameterListsInfo(Context, NumMatchedTemplateParamLists, diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index bef1bb451f..893cf6ac26 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -2841,7 +2841,7 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II) { FD->getType(), FD->getTypeSourceInfo()); if (FD->getQualifier()) { FunctionDecl *NewFD = cast<FunctionDecl>(NewD); - NewFD->setQualifierInfo(FD->getQualifier(), FD->getQualifierRange()); + NewFD->setQualifierInfo(FD->getQualifierLoc()); } } else if (VarDecl *VD = dyn_cast<VarDecl>(ND)) { NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(), @@ -2851,7 +2851,7 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II) { VD->getStorageClassAsWritten()); if (VD->getQualifier()) { VarDecl *NewVD = cast<VarDecl>(NewD); - NewVD->setQualifierInfo(VD->getQualifier(), VD->getQualifierRange()); + NewVD->setQualifierInfo(VD->getQualifierLoc()); } } return NewD; diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 8f7b7da6f3..5b09dfcee1 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -783,8 +783,7 @@ Sema::ActOnTemplateParameterList(unsigned Depth, static void SetNestedNameSpecifier(TagDecl *T, const CXXScopeSpec &SS) { if (SS.isSet()) - T->setQualifierInfo(static_cast<NestedNameSpecifier*>(SS.getScopeRep()), - SS.getRange()); + T->setQualifierInfo(SS.getWithLocInContext(T->getASTContext())); } DeclResult diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 44f5913d55..ae0ac9cbe3 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -2140,6 +2140,17 @@ Sema::SubstNestedNameSpecifier(NestedNameSpecifier *NNS, return Instantiator.TransformNestedNameSpecifier(NNS, Range); } +NestedNameSpecifierLoc +Sema::SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, + const MultiLevelTemplateArgumentList &TemplateArgs) { + if (!NNS) + return NestedNameSpecifierLoc(); + + TemplateInstantiator Instantiator(*this, TemplateArgs, NNS.getBeginLoc(), + DeclarationName()); + return Instantiator.TransformNestedNameSpecifierLoc(NNS); +} + /// \brief Do template substitution on declaration name info. DeclarationNameInfo Sema::SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo, diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index e1a7065197..f437cd3092 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -27,33 +27,33 @@ using namespace clang; bool TemplateDeclInstantiator::SubstQualifier(const DeclaratorDecl *OldDecl, DeclaratorDecl *NewDecl) { - NestedNameSpecifier *OldQual = OldDecl->getQualifier(); - if (!OldQual) return false; - - SourceRange QualRange = OldDecl->getQualifierRange(); - - NestedNameSpecifier *NewQual - = SemaRef.SubstNestedNameSpecifier(OldQual, QualRange, TemplateArgs); - if (!NewQual) + if (!OldDecl->getQualifierLoc()) + return false; + + NestedNameSpecifierLoc NewQualifierLoc + = SemaRef.SubstNestedNameSpecifierLoc(OldDecl->getQualifierLoc(), + TemplateArgs); + + if (!NewQualifierLoc) return true; - - NewDecl->setQualifierInfo(NewQual, QualRange); + + NewDecl->setQualifierInfo(NewQualifierLoc); return false; } bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl, TagDecl *NewDecl) { - NestedNameSpecifier *OldQual = OldDecl->getQualifier(); - if (!OldQual) return false; - - SourceRange QualRange = OldDecl->getQualifierRange(); - - NestedNameSpecifier *NewQual - = SemaRef.SubstNestedNameSpecifier(OldQual, QualRange, TemplateArgs); - if (!NewQual) + if (!OldDecl->getQualifierLoc()) + return false; + + NestedNameSpecifierLoc NewQualifierLoc + = SemaRef.SubstNestedNameSpecifierLoc(OldDecl->getQualifierLoc(), + TemplateArgs); + + if (!NewQualifierLoc) return true; - - NewDecl->setQualifierInfo(NewQual, QualRange); + + NewDecl->setQualifierInfo(NewQualifierLoc); return false; } @@ -642,12 +642,12 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { // Instantiate the qualifier. We have to do this first in case // we're a friend declaration, because if we are then we need to put // the new declaration in the appropriate context. - NestedNameSpecifier *Qualifier = Pattern->getQualifier(); - if (Qualifier) { - Qualifier = SemaRef.SubstNestedNameSpecifier(Qualifier, - Pattern->getQualifierRange(), - TemplateArgs); - if (!Qualifier) return 0; + NestedNameSpecifierLoc QualifierLoc = Pattern->getQualifierLoc(); + if (QualifierLoc) { + QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, + TemplateArgs); + if (!QualifierLoc) + return 0; } CXXRecordDecl *PrevDecl = 0; @@ -668,9 +668,9 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { // the appropriate context. DeclContext *DC = Owner; if (isFriend) { - if (Qualifier) { + if (QualifierLoc) { CXXScopeSpec SS; - SS.MakeTrivial(SemaRef.Context, Qualifier, Pattern->getQualifierRange()); + SS.Adopt(QualifierLoc); DC = SemaRef.computeDeclContext(SS); if (!DC) return 0; } else { @@ -691,10 +691,10 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { PrevDecl = PrevClassTemplate->getTemplatedDecl(); } - if (!PrevClassTemplate && Qualifier) { + if (!PrevClassTemplate && QualifierLoc) { SemaRef.Diag(Pattern->getLocation(), diag::err_not_tag_in_scope) << D->getTemplatedDecl()->getTagKind() << Pattern->getDeclName() << DC - << Pattern->getQualifierRange(); + << QualifierLoc.getSourceRange(); return 0; } @@ -755,8 +755,8 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { Pattern->getTagKeywordLoc(), PrevDecl, /*DelayTypeCreation=*/true); - if (Qualifier) - RecordInst->setQualifierInfo(Qualifier, Pattern->getQualifierRange()); + if (QualifierLoc) + RecordInst->setQualifierInfo(QualifierLoc); ClassTemplateDecl *Inst = ClassTemplateDecl::Create(SemaRef.Context, DC, D->getLocation(), @@ -968,12 +968,12 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, return 0; QualType T = TInfo->getType(); - NestedNameSpecifier *Qualifier = D->getQualifier(); - if (Qualifier) { - Qualifier = SemaRef.SubstNestedNameSpecifier(Qualifier, - D->getQualifierRange(), - TemplateArgs); - if (!Qualifier) return 0; + NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc(); + if (QualifierLoc) { + QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, + TemplateArgs); + if (!QualifierLoc) + return 0; } // If we're instantiating a local function declaration, put the result @@ -981,9 +981,9 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, DeclContext *DC; if (D->getDeclContext()->isFunctionOrMethod()) DC = Owner; - else if (isFriend && Qualifier) { + else if (isFriend && QualifierLoc) { CXXScopeSpec SS; - SS.MakeTrivial(SemaRef.Context, Qualifier, D->getQualifierRange()); + SS.Adopt(QualifierLoc); DC = SemaRef.computeDeclContext(SS); if (!DC) return 0; } else { @@ -997,8 +997,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, D->getStorageClass(), D->getStorageClassAsWritten(), D->isInlineSpecified(), D->hasWrittenPrototype()); - if (Qualifier) - Function->setQualifierInfo(Qualifier, D->getQualifierRange()); + if (QualifierLoc) + Function->setQualifierInfo(QualifierLoc); DeclContext *LexicalDC = Owner; if (!isFriend && D->isOutOfLine()) { @@ -1260,19 +1260,19 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, return 0; } - NestedNameSpecifier *Qualifier = D->getQualifier(); - if (Qualifier) { - Qualifier = SemaRef.SubstNestedNameSpecifier(Qualifier, - D->getQualifierRange(), + NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc(); + if (QualifierLoc) { + QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, TemplateArgs); - if (!Qualifier) return 0; + if (!QualifierLoc) + return 0; } DeclContext *DC = Owner; if (isFriend) { - if (Qualifier) { + if (QualifierLoc) { CXXScopeSpec SS; - SS.MakeTrivial(SemaRef.Context, Qualifier, D->getQualifierRange()); + SS.Adopt(QualifierLoc); DC = SemaRef.computeDeclContext(SS); if (DC && SemaRef.RequireCompleteDeclContext(SS, DC)) @@ -1315,8 +1315,8 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, D->isInlineSpecified()); } - if (Qualifier) - Method->setQualifierInfo(Qualifier, D->getQualifierRange()); + if (QualifierLoc) + Method->setQualifierInfo(QualifierLoc); if (TemplateParams) { // Our resulting instantiation is actually a function template, since we diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index fa0c2b97d4..641df425ad 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -385,6 +385,17 @@ public: QualType ObjectType = QualType(), NamedDecl *FirstQualifierInScope = 0); + /// \brief Transform the given nested-name-specifier with source-location + /// information. + /// + /// By default, transforms all of the types and declarations within the + /// nested-name-specifier. Subclasses may override this function to provide + /// alternate behavior. + NestedNameSpecifierLoc TransformNestedNameSpecifierLoc( + NestedNameSpecifierLoc NNS, + QualType ObjectType = QualType(), + NamedDecl *FirstQualifierInScope = 0); + /// \brief Transform the given declaration name. /// /// By default, transforms the types of conversion function, constructor, @@ -2264,6 +2275,11 @@ private: QualType ObjectType, NamedDecl *FirstQualifierInScope, NestedNameSpecifier *Prefix); + + TypeLoc TransformTypeInObjectScope(TypeLoc TL, + QualType ObjectType, + NamedDecl *FirstQualifierInScope, + CXXScopeSpec &SS); }; template<typename Derived> @@ -2504,6 +2520,105 @@ TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS, } template<typename Derived> +NestedNameSpecifierLoc +TreeTransform<Derived>::TransformNestedNameSpecifierLoc( + NestedNameSpecifierLoc NNS, + QualType ObjectType, + NamedDecl *FirstQualifierInScope) { + llvm::SmallVector<NestedNameSpecifierLoc, 4> Qualifiers; + for (NestedNameSpecifierLoc Qualifier = NNS; Qualifier; + Qualifier = Qualifier.getPrefix()) + Qualifiers.push_back(Qualifier); + + CXXScopeSpec SS; + while (!Qualifiers.empty()) { + NestedNameSpecifierLoc Q = Qualifiers.pop_back_val(); + NestedNameSpecifier *QNNS = Q.getNestedNameSpecifier(); + + switch (QNNS->getKind()) { + case NestedNameSpecifier::Identifier: + if (SemaRef.BuildCXXNestedNameSpecifier(/*Scope=*/0, + *QNNS->getAsIdentifier(), + Q.getLocalBeginLoc(), + Q.getLocalEndLoc(), + ObjectType, false, SS, + FirstQualifierInScope, false)) + return NestedNameSpecifierLoc(); + + break; + + case NestedNameSpecifier::Namespace: { + NamespaceDecl *NS + = cast_or_null<NamespaceDecl>( + getDerived().TransformDecl( + Q.getLocalBeginLoc(), + QNNS->getAsNamespace())); + SS.Extend(SemaRef.Context, NS, Q.getLocalBeginLoc(), Q.getLocalEndLoc()); + break; + } + + case NestedNameSpecifier::NamespaceAlias: { + NamespaceAliasDecl *Alias + = cast_or_null<NamespaceAliasDecl>( + getDerived().TransformDecl(Q.getLocalBeginLoc(), + QNNS->getAsNamespaceAlias())); + SS.Extend(SemaRef.Context, Alias, Q.getLocalBeginLoc(), + Q.getLocalEndLoc()); + break; + } + + case NestedNameSpecifier::Global: + // There is no meaningful transformation that one could perform on the + // global scope. + SS.MakeGlobal(SemaRef.Context, Q.getBeginLoc()); + break; + + case NestedNameSpecifier::TypeSpecWithTemplate: + case NestedNameSpecifier::TypeSpec: { + TypeLoc TL = TransformTypeInObjectScope(Q.getTypeLoc(), ObjectType, + FirstQualifierInScope, SS); + + if (!TL) + return NestedNameSpecifierLoc(); + + if (TL.getType()->isDependentType() || TL.getType()->isRecordType() || + (SemaRef.getLangOptions().CPlusPlus0x && + TL.getType()->isEnumeralType())) { + assert(!TL.getType().hasLocalQualifiers() && + "Can't get cv-qualifiers here"); + SS.Extend(SemaRef.Context, /*FIXME:*/SourceLocation(), TL, + Q.getLocalEndLoc()); + break; + } + + SemaRef.Diag(TL.getBeginLoc(), diag::err_nested_name_spec_non_tag) + << TL.getType() << SS.getRange(); + return NestedNameSpecifierLoc(); + } + } + + // The object type and qualifier-in-scope really apply to the + // leftmost entity. + ObjectType = QualType(); + FirstQualifierInScope = 0; + } + + // Don't rebuild the nested-name-specifier if we don't have to. + if (SS.getScopeRep() == NNS.getNestedNameSpecifier() && + !getDerived().AlwaysRebuild()) + return NNS; + + // If we can re-use the source-location data from the original + // nested-name-specifier, do so. + if (SS.location_size() == NNS.getDataLength() && + memcmp(SS.location_data(), NNS.getOpaqueData(), SS.location_size()) == 0) + return NestedNameSpecifierLoc(SS.getScopeRep(), NNS.getOpaqueData()); + + // Allocate new nested-name-specifier location information. + return SS.getWithLocInContext(SemaRef.Context); +} + +template<typename Derived> DeclarationNameInfo TreeTransform<Derived> ::TransformDeclarationNameInfo(const DeclarationNameInfo &NameInfo) { @@ -3099,7 +3214,7 @@ TreeTransform<Derived>::TransformTypeInObjectScope(TypeSourceInfo *TSI, QualType ObjectType, NamedDecl *UnqualLookup, NestedNameSpecifier *Prefix) { - // TODO: in some cases, we might be some verification to do here. + // TODO: in some cases, we might have some verification to do here. if (ObjectType.isNull()) return getDerived().TransformType(TSI); @@ -3136,6 +3251,62 @@ TreeTransform<Derived>::TransformTypeInObjectScope(TypeSourceInfo *TSI, return TLB.getTypeSourceInfo(SemaRef.Context, Result); } +template<typename Derived> +TypeLoc +TreeTransform<Derived>::TransformTypeInObjectScope(TypeLoc TL, + QualType ObjectType, + |