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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@98540 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index e8bcb8b..dbe041c 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -97,6 +97,11 @@
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 @@
};
}
+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 @@
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 @@
/*PrevDecl=*/0);
Enum->setInstantiationOfMemberEnum(D);
Enum->setAccess(D->getAccess());
+ if (SubstQualifier(D, Enum)) return 0;
Owner->addDecl(Enum);
Enum->startDefinition();
@@ -611,6 +653,10 @@
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 @@
= 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 @@
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 @@
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 @@
InstTemplateArgs,
CanonType,
0);
+ // Substitute the nested name specifier, if any.
+ if (SubstQualifier(PartialSpec, InstPartialSpec))
+ return 0;
+
InstPartialSpec->setInstantiatedFromMember(PartialSpec);
InstPartialSpec->setTypeAsWritten(WrittenTy);