From: John McCall Date: Thu, 3 Dec 2009 00:58:24 +0000 (+0000) Subject: Stop stripping UnresolvedUsingDecls out of LookupResults that have other X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fda8e12774921e3cac3ebcba1148bcf4479ddd7a;p=clang Stop stripping UnresolvedUsingDecls out of LookupResults that have other results in them (which we were doing intentionally as a stopgap). Fix an DeclContext lookup-table ordering problem which was causing UsingDecls to show up incorrectly when looking for ordinary results. And oh hey Clang-Code-Syntax passes now. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90367 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h index c2b48cee36..9a38485745 100644 --- a/include/clang/AST/DeclContextInternals.h +++ b/include/clang/AST/DeclContextInternals.h @@ -200,11 +200,37 @@ public: } VectorTy &Vec = *getAsVector(); - if (isa(D) || - D->getIdentifierNamespace() == Decl::IDNS_Tag) + + // Using directives end up in a special entry which contains only + // other using directives, so all this logic is wasted for them. + // But avoiding the logic wastes time in the far-more-common case + // that we're *not* adding a new using directive. + + // Tag declarations always go at the end of the list so that an + // iterator which points at the first tag will start a span of + // decls that only contains tags. + if (D->getIdentifierNamespace() == Decl::IDNS_Tag) Vec.push_back(reinterpret_cast(D)); - else if (reinterpret_cast(Vec.back()) - ->getIdentifierNamespace() == Decl::IDNS_Tag) { + + // Resolved using declarations go at the front of the list so that + // they won't show up in other lookup results. Unresolved using + // declarations (which are always in IDNS_Using | IDNS_Ordinary) + // follow that so that the using declarations will be contiguous. + else if (D->getIdentifierNamespace() & Decl::IDNS_Using) { + VectorTy::iterator I = Vec.begin(); + if (D->getIdentifierNamespace() != Decl::IDNS_Using) { + while (I != Vec.end() && + reinterpret_cast(*I) + ->getIdentifierNamespace() == Decl::IDNS_Using) + ++I; + } + Vec.insert(I, reinterpret_cast(D)); + + // All other declarations go at the end of the list, but before any + // tag declarations. But we can be clever about tag declarations + // because there can only ever be one in a scope. + } else if (reinterpret_cast(Vec.back()) + ->getIdentifierNamespace() == Decl::IDNS_Tag) { uintptr_t TagD = Vec.back(); Vec.back() = reinterpret_cast(D); Vec.push_back(TagD); diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index f8cb5f037e..1ddfef839f 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -282,9 +282,6 @@ void LookupResult::resolveKind() { // If it's not unique, pull something off the back (and // continue at this index). Decls[I] = Decls[--N]; - } else if (isa(D)) { - // FIXME: support unresolved using value declarations - Decls[I] = Decls[--N]; } else { // Otherwise, do some decl type analysis and then continue. @@ -318,13 +315,13 @@ void LookupResult::resolveKind() { // wherever the object, function, or enumerator name is visible. // But it's still an error if there are distinct tag types found, // even if they're not visible. (ref?) - if (HideTags && HasTag && !Ambiguous && !HasUnresolved && - (HasFunction || HasNonFunction)) + if (HideTags && HasTag && !Ambiguous && + (HasFunction || HasNonFunction || HasUnresolved)) Decls[UniqueTagIndex] = Decls[--N]; Decls.set_size(N); - if (HasFunction && HasNonFunction) + if (HasNonFunction && (HasFunction || HasUnresolved)) Ambiguous = true; if (Ambiguous) diff --git a/test/SemaTemplate/instantiate-using-decl.cpp b/test/SemaTemplate/instantiate-using-decl.cpp index a1cf355c89..de66f79242 100644 --- a/test/SemaTemplate/instantiate-using-decl.cpp +++ b/test/SemaTemplate/instantiate-using-decl.cpp @@ -1,20 +1,49 @@ // RUN: clang-cc -fsyntax-only -verify %s -namespace N { } - -template -struct A { - void f(); -}; - -template -struct B : A { - using A::f; - - void g() { - using namespace N; - f(); - } -}; +namespace test0 { + namespace N { } + + template + struct A { + void f(); + }; + + template + struct B : A { + using A::f; + + void g() { + using namespace N; + f(); + } + }; + + template struct B; +} -template struct B; +namespace test1 { + template struct Visitor1 { + void Visit(struct Object1*); + }; + template struct Visitor2 { + void Visit(struct Object2*); // expected-note {{candidate function}} + }; + + template struct JoinVisitor + : Visitor1, Visitor2 { + typedef Visitor1 Base1; + typedef Visitor2 Base2; + + void Visit(struct Object1*); // expected-note {{candidate function}} + using Base2::Visit; + }; + + class Knot : JoinVisitor { + }; + + void test() { + Knot().Visit((struct Object1*) 0); + Knot().Visit((struct Object2*) 0); + Knot().Visit((struct Object3*) 0); // expected-error {{no matching member function for call}} + } +}