summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-03-15 10:12:16 +0000
committerJohn McCall <rjmccall@apple.com>2010-03-15 10:12:16 +0000
commit3e11ebebc83643747f15bcafa28b3b7e232f6cc1 (patch)
tree5bc9d793fb1e75fccc7da56e4314642242d497d7 /clang/lib/Sema
parent1e3a1a7eff8549fbb5295e4c2014f9b9a7a7b30f (diff)
downloadbcm5719-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.cpp18
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp8
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp10
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiateDecl.cpp64
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);
OpenPOWER on IntegriCloud