aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaTemplateInstantiateDecl.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2009-12-10 09:41:52 +0000
committerJohn McCall <rjmccall@apple.com>2009-12-10 09:41:52 +0000
commit9f54ad4381370c6b771424b53d219e661d6d6706 (patch)
treecf7e1c1bceaefab55c52fa3458005811e59d0185 /lib/Sema/SemaTemplateInstantiateDecl.cpp
parent153c33ed957b135a366178c61bbe22b6b1362a2a (diff)
Implement redeclaration checking and hiding semantics for using declarations. There
are a couple of O(n^2) operations in this, some analogous to the usual O(n^2) redeclaration problem and some not. In particular, retroactively removing shadow declarations when they're hidden by later decls is pretty unfortunate. I'm not yet convinced it's worse than the alternative, though. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91045 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp73
1 files changed, 53 insertions, 20 deletions
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 80dcfd4e6d..07e97117cb 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -708,7 +708,8 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
Previous.clear();
}
- SemaRef.CheckFunctionDeclaration(Function, Previous, false, Redeclaration,
+ SemaRef.CheckFunctionDeclaration(/*Scope*/ 0, Function, Previous,
+ false, Redeclaration,
/*FIXME:*/OverloadableAttrRequired);
// If the original function was part of a friend declaration,
@@ -868,7 +869,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
bool Redeclaration = false;
bool OverloadableAttrRequired = false;
- SemaRef.CheckFunctionDeclaration(Method, Previous, false, Redeclaration,
+ SemaRef.CheckFunctionDeclaration(0, Method, Previous, false, Redeclaration,
/*FIXME:*/OverloadableAttrRequired);
if (D->isPure())
@@ -1040,6 +1041,14 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
// The nested name specifier is non-dependent, so no transformation
// is required.
+ // We only need to do redeclaration lookups if we're in a class
+ // scope (in fact, it's not really even possible in non-class
+ // scopes).
+ bool CheckRedeclaration = Owner->isRecord();
+
+ LookupResult Prev(SemaRef, D->getDeclName(), D->getLocation(),
+ Sema::LookupUsingDeclName, Sema::ForRedeclaration);
+
UsingDecl *NewUD = UsingDecl::Create(SemaRef.Context, Owner,
D->getLocation(),
D->getNestedNameRange(),
@@ -1051,34 +1060,55 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
CXXScopeSpec SS;
SS.setScopeRep(D->getTargetNestedNameDecl());
SS.setRange(D->getNestedNameRange());
- if (SemaRef.CheckUsingDeclQualifier(D->getUsingLocation(), SS,
+
+ if (CheckRedeclaration) {
+ Prev.setHideTags(false);
+ SemaRef.LookupQualifiedName(Prev, Owner);
+
+ // Check for invalid redeclarations.
+ if (SemaRef.CheckUsingDeclRedeclaration(D->getUsingLocation(),
+ D->isTypeName(), SS,
+ D->getLocation(), Prev))
+ NewUD->setInvalidDecl();
+
+ }
+
+ if (!NewUD->isInvalidDecl() &&
+ SemaRef.CheckUsingDeclQualifier(D->getUsingLocation(), SS,
D->getLocation()))
NewUD->setInvalidDecl();
+
SemaRef.Context.setInstantiatedFromUsingDecl(NewUD, D);
NewUD->setAccess(D->getAccess());
Owner->addDecl(NewUD);
- // We'll transform the UsingShadowDecls as we reach them.
+ // Don't process the shadow decls for an invalid decl.
+ if (NewUD->isInvalidDecl())
+ return NewUD;
- return NewUD;
-}
+ // Process the shadow decls.
+ for (UsingDecl::shadow_iterator I = D->shadow_begin(), E = D->shadow_end();
+ I != E; ++I) {
+ UsingShadowDecl *Shadow = *I;
+ NamedDecl *InstTarget =
+ cast<NamedDecl>(SemaRef.FindInstantiatedDecl(Shadow->getTargetDecl(),
+ TemplateArgs));
-Decl *TemplateDeclInstantiator::VisitUsingShadowDecl(UsingShadowDecl *D) {
- UsingDecl *InstUsing =
- cast<UsingDecl>(SemaRef.FindInstantiatedDecl(D->getUsingDecl(),
- TemplateArgs));
- NamedDecl *InstTarget =
- cast<NamedDecl>(SemaRef.FindInstantiatedDecl(D->getTargetDecl(),
- TemplateArgs));
+ if (CheckRedeclaration &&
+ SemaRef.CheckUsingShadowDecl(NewUD, InstTarget, Prev))
+ continue;
- UsingShadowDecl *InstD = SemaRef.BuildUsingShadowDecl(/*Scope*/ 0,
- D->getAccess(),
- InstUsing,
- InstTarget);
+ UsingShadowDecl *InstShadow
+ = SemaRef.BuildUsingShadowDecl(/*Scope*/ 0, NewUD, InstTarget);
+ SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstShadow, Shadow);
+ }
- SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstD, D);
+ return NewUD;
+}
- return InstD;
+Decl *TemplateDeclInstantiator::VisitUsingShadowDecl(UsingShadowDecl *D) {
+ // Ignore these; we handle them in bulk when processing the UsingDecl.
+ return 0;
}
Decl * TemplateDeclInstantiator
@@ -2087,7 +2117,10 @@ NamedDecl *Sema::FindInstantiatedDecl(NamedDecl *D,
ParentDC->decls_end());
}
- assert(Result && "Unable to find instantiation of declaration!");
+ // UsingShadowDecls can instantiate to nothing because of using hiding.
+ assert((Result || isa<UsingShadowDecl>(D))
+ && "Unable to find instantiation of declaration!");
+
D = Result;
}