diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-09-28 00:47:05 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-09-28 00:47:05 +0000 |
commit | 2531c2d2f1e8ce35f2ce8e9539738ddf8dccb7cc (patch) | |
tree | 485e03397ececf4e424f9e50d48d2defb2ce8061 /lib/Sema/SemaDecl.cpp | |
parent | 182ddf0e5dc5667e6683a58b483a2e52564f4303 (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.cpp | 45 |
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) |