diff options
| author | John McCall <rjmccall@apple.com> | 2010-03-15 10:12:16 +0000 |
|---|---|---|
| committer | John McCall <rjmccall@apple.com> | 2010-03-15 10:12:16 +0000 |
| commit | 3e11ebebc83643747f15bcafa28b3b7e232f6cc1 (patch) | |
| tree | 5bc9d793fb1e75fccc7da56e4314642242d497d7 /clang/lib/Sema | |
| parent | 1e3a1a7eff8549fbb5295e4c2014f9b9a7a7b30f (diff) | |
| download | bcm5719-llvm-3e11ebebc83643747f15bcafa28b3b7e232f6cc1.tar.gz bcm5719-llvm-3e11ebebc83643747f15bcafa28b3b7e232f6cc1.zip | |
Remember declaration scope qualifiers in the AST. Imposes no memory overhead
on unqualified declarations.
Patch by Enea Zaffanella! Minimal adjustments: allocate the ExtInfo nodes
with the ASTContext and delete them during Destroy(). I audited a bunch of
Destroy methods at the same time, to ensure that the correct teardown was
being done.
llvm-svn: 98540
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 18 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 8 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 10 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 64 |
4 files changed, 100 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 7179f4bc6bb..dab7d883a1d 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2262,6 +2262,13 @@ isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC, return true; } +static void SetNestedNameSpecifier(DeclaratorDecl *DD, Declarator &D) { + CXXScopeSpec &SS = D.getCXXScopeSpec(); + if (!SS.isSet()) return; + DD->setQualifierInfo(static_cast<NestedNameSpecifier*>(SS.getScopeRep()), + SS.getRange()); +} + NamedDecl* Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, QualType R, TypeSourceInfo *TInfo, @@ -2371,6 +2378,8 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (D.isInvalidType()) NewVD->setInvalidDecl(); + SetNestedNameSpecifier(NewVD, D); + if (D.getDeclSpec().isThreadSpecified()) { if (NewVD->hasLocalStorage()) Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_thread_non_global); @@ -2799,6 +2808,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (D.isInvalidType()) NewFD->setInvalidDecl(); + SetNestedNameSpecifier(NewFD, D); + // Set the lexical context. If the declarator has a C++ // scope specifier, or is the object of a friend declaration, the // lexical context will be different from the semantic context. @@ -4847,6 +4858,13 @@ CreateNewDecl: cast_or_null<RecordDecl>(PrevDecl)); } + // Maybe add qualifier info. + if (SS.isNotEmpty()) { + NestedNameSpecifier *NNS + = static_cast<NestedNameSpecifier*>(SS.getScopeRep()); + New->setQualifierInfo(NNS, SS.getRange()); + } + if (Kind != TagDecl::TK_enum) { // Handle #pragma pack: if the #pragma pack stack has non-default // alignment, make up a packed attribute for this decl. These diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 242d66fa521..d369b773e8d 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -1945,11 +1945,19 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II) { NewD = FunctionDecl::Create(FD->getASTContext(), FD->getDeclContext(), FD->getLocation(), DeclarationName(II), FD->getType(), FD->getTypeSourceInfo()); + if (FD->getQualifier()) { + FunctionDecl *NewFD = cast<FunctionDecl>(NewD); + NewFD->setQualifierInfo(FD->getQualifier(), FD->getQualifierRange()); + } } else if (VarDecl *VD = dyn_cast<VarDecl>(ND)) { NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(), VD->getLocation(), II, VD->getType(), VD->getTypeSourceInfo(), VD->getStorageClass()); + if (VD->getQualifier()) { + VarDecl *NewVD = cast<VarDecl>(NewD); + NewVD->setQualifierInfo(VD->getQualifier(), VD->getQualifierRange()); + } } return NewD; } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 79298acc229..434d5563e1b 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -697,6 +697,12 @@ Sema::ActOnTemplateParameterList(unsigned Depth, RAngleLoc); } +static void SetNestedNameSpecifier(TagDecl *T, const CXXScopeSpec &SS) { + if (SS.isSet()) + T->setQualifierInfo(static_cast<NestedNameSpecifier*>(SS.getScopeRep()), + SS.getRange()); +} + Sema::DeclResult Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, const CXXScopeSpec &SS, @@ -864,6 +870,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, PrevClassTemplate? PrevClassTemplate->getTemplatedDecl() : 0, /*DelayTypeCreation=*/true); + SetNestedNameSpecifier(NewClass, SS); ClassTemplateDecl *NewTemplate = ClassTemplateDecl::Create(Context, SemanticContext, NameLoc, @@ -3491,6 +3498,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TemplateArgs, CanonType, PrevPartial); + SetNestedNameSpecifier(Partial, SS); if (PrevPartial) { ClassTemplate->getPartialSpecializations().RemoveNode(PrevPartial); @@ -3547,6 +3555,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, ClassTemplate, Converted, PrevDecl); + SetNestedNameSpecifier(Specialization, SS); if (PrevDecl) { ClassTemplate->getSpecializations().RemoveNode(PrevDecl); @@ -4328,6 +4337,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, TemplateNameLoc, ClassTemplate, Converted, PrevDecl); + SetNestedNameSpecifier(Specialization, SS); if (PrevDecl) { // Remove the previous declaration from the folding set, since we want diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index e8bcb8be89b..dbe041c4aad 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -97,6 +97,11 @@ namespace { TemplateParameterList * SubstTemplateParams(TemplateParameterList *List); + + bool SubstQualifier(const DeclaratorDecl *OldDecl, + DeclaratorDecl *NewDecl); + bool SubstQualifier(const TagDecl *OldDecl, + TagDecl *NewDecl); bool InstantiateClassTemplatePartialSpecialization( ClassTemplateDecl *ClassTemplate, @@ -104,6 +109,38 @@ namespace { }; } +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) + return true; + + NewDecl->setQualifierInfo(NewQual, QualRange); + 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) + return true; + + NewDecl->setQualifierInfo(NewQual, QualRange); + return false; +} + // FIXME: Is this too simple? void TemplateDeclInstantiator::InstantiateAttrs(Decl *Tmpl, Decl *New) { for (const Attr *TmplAttr = Tmpl->getAttrs(); TmplAttr; @@ -287,6 +324,10 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { Var->setCXXDirectInitializer(D->hasCXXDirectInitializer()); Var->setDeclaredInCondition(D->isDeclaredInCondition()); + // Substitute the nested name specifier, if any. + if (SubstQualifier(D, Var)) + return 0; + // If we are instantiating a static data member defined // out-of-line, the instantiation will have the same lexical // context (which will be a namespace scope) as the template. @@ -511,6 +552,7 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { /*PrevDecl=*/0); Enum->setInstantiationOfMemberEnum(D); Enum->setAccess(D->getAccess()); + if (SubstQualifier(D, Enum)) return 0; Owner->addDecl(Enum); Enum->startDefinition(); @@ -611,6 +653,10 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { Pattern->getTagKeywordLoc(), /*PrevDecl=*/ NULL, /*DelayTypeCreation=*/true); + // Substitute the nested name specifier, if any. + if (SubstQualifier(Pattern, RecordInst)) + return 0; + ClassTemplateDecl *Inst = ClassTemplateDecl::Create(SemaRef.Context, Owner, D->getLocation(), D->getIdentifier(), InstParams, RecordInst, 0); @@ -745,6 +791,11 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { = CXXRecordDecl::Create(SemaRef.Context, D->getTagKind(), Owner, D->getLocation(), D->getIdentifier(), D->getTagKeywordLoc(), PrevDecl); + + // Substitute the nested name specifier, if any. + if (SubstQualifier(D, Record)) + return 0; + Record->setImplicit(D->isImplicit()); // FIXME: Check against AS_none is an ugly hack to work around the issue that // the tag decls introduced by friend class declarations don't have an access @@ -818,6 +869,11 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, D->getDeclName(), T, TInfo, D->getStorageClass(), D->isInlineSpecified(), D->hasWrittenPrototype()); + + // Substitute the nested name specifier, if any. + if (SubstQualifier(D, Function)) + return 0; + Function->setLexicalDeclContext(Owner); // Attach the parameters @@ -979,6 +1035,10 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, D->isStatic(), D->isInlineSpecified()); } + // Substitute the nested name specifier, if any. + if (SubstQualifier(D, Method)) + return 0; + if (TemplateParams) { // Our resulting instantiation is actually a function template, since we // are substituting only the outer template parameters. For example, given @@ -1508,6 +1568,10 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( InstTemplateArgs, CanonType, 0); + // Substitute the nested name specifier, if any. + if (SubstQualifier(PartialSpec, InstPartialSpec)) + return 0; + InstPartialSpec->setInstantiatedFromMember(PartialSpec); InstPartialSpec->setTypeAsWritten(WrittenTy); |

