aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-09-28 00:47:05 +0000
committerDouglas Gregor <dgregor@apple.com>2009-09-28 00:47:05 +0000
commit2531c2d2f1e8ce35f2ce8e9539738ddf8dccb7cc (patch)
tree485e03397ececf4e424f9e50d48d2defb2ce8061 /lib/Sema/SemaDecl.cpp
parent182ddf0e5dc5667e6683a58b483a2e52564f4303 (diff)
Teach Sema::isDeclInScope to handle overload sets constructed from
functions that occur in multiple declaration contexts, e.g., because some were found via using declarations. Now, isDeclInScope will build a new overload set (when needed) containing only those declarations that are actually in scope. This eliminates a problem found with libstdc++'s <iostream>, where the presence of using In the longer term, I'd like to eliminate Sema::isDeclInScope in favor of better handling of the RedeclarationOnly flag in the name-lookup routines. That way, name lookup only returns the entities that matter, rather than taking the current two-pass approach of producing too many results and then filtering our the wrong results. It's not efficient, and I'm sure that we aren't filtering everywhere we should be. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82954 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r--lib/Sema/SemaDecl.cpp45
1 files changed, 41 insertions, 4 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index f8751fb9c9..d0463c658e 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -311,9 +311,10 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) {
IdentifierResolver::iterator
I = IdResolver.begin(TD->getDeclName()),
IEnd = IdResolver.end();
- if (I != IEnd && isDeclInScope(*I, CurContext, S)) {
+ NamedDecl *ID = *I;
+ if (I != IEnd && isDeclInScope(ID, CurContext, S)) {
NamedDecl *PrevDecl = *I;
- for (; I != IEnd && isDeclInScope(*I, CurContext, S);
+ for (; I != IEnd && isDeclInScope(ID, CurContext, S);
PrevDecl = *I, ++I) {
if (TD->declarationReplaces(*I)) {
// This is a redeclaration. Remove it from the chain and
@@ -374,6 +375,41 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) {
IdResolver.AddDecl(D);
}
+bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S) {
+ if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D)) {
+ // Look inside the overload set to determine if any of the declarations
+ // are in scope. (Possibly) build a new overload set containing only
+ // those declarations that are in scope.
+ OverloadedFunctionDecl *NewOvl = 0;
+ bool FoundInScope = false;
+ for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
+ FEnd = Ovl->function_end();
+ F != FEnd; ++F) {
+ NamedDecl *FD = F->get();
+ if (!isDeclInScope(FD, Ctx, S)) {
+ if (!NewOvl && F != Ovl->function_begin()) {
+ NewOvl = OverloadedFunctionDecl::Create(Context,
+ F->get()->getDeclContext(),
+ F->get()->getDeclName());
+ D = NewOvl;
+ for (OverloadedFunctionDecl::function_iterator
+ First = Ovl->function_begin();
+ First != F; ++First)
+ NewOvl->addOverload(*First);
+ }
+ } else {
+ FoundInScope = true;
+ if (NewOvl)
+ NewOvl->addOverload(*F);
+ }
+ }
+
+ return FoundInScope;
+ }
+
+ return IdResolver.isDeclInScope(D, Ctx, Context, S);
+}
+
void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
if (S->decl_empty()) return;
assert((S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) &&
@@ -1971,7 +2007,7 @@ void Sema::DiagnoseFunctionSpecifiers(Declarator& D) {
NamedDecl*
Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
QualType R, DeclaratorInfo *DInfo,
- Decl* PrevDecl, bool &Redeclaration) {
+ NamedDecl* PrevDecl, bool &Redeclaration) {
// Typedef declarators cannot be qualified (C++ [dcl.meaning]p1).
if (D.getCXXScopeSpec().isSet()) {
Diag(D.getIdentifierLoc(), diag::err_qualified_typedef_declarator)
@@ -4411,7 +4447,8 @@ CreateNewDecl:
if (Lookup.getKind() == LookupResult::Found)
PrevTypedef = dyn_cast<TypedefDecl>(Lookup.getAsDecl());
- if (PrevTypedef && isDeclInScope(PrevTypedef, SearchDC, S) &&
+ NamedDecl *PrevTypedefNamed = PrevTypedef;
+ if (PrevTypedef && isDeclInScope(PrevTypedefNamed, SearchDC, S) &&
Context.getCanonicalType(Context.getTypeDeclType(PrevTypedef)) !=
Context.getCanonicalType(Context.getTypeDeclType(New))) {
Diag(Loc, diag::err_tag_definition_of_typedef)