зеркало из https://github.com/microsoft/clang-1.git
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
This commit is contained in:
Родитель
74635d8cd3
Коммит
fda8e12774
|
@ -200,11 +200,37 @@ public:
|
|||
}
|
||||
|
||||
VectorTy &Vec = *getAsVector();
|
||||
if (isa<UsingDirectiveDecl>(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<uintptr_t>(D));
|
||||
else if (reinterpret_cast<NamedDecl *>(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<NamedDecl *>(*I)
|
||||
->getIdentifierNamespace() == Decl::IDNS_Using)
|
||||
++I;
|
||||
}
|
||||
Vec.insert(I, reinterpret_cast<uintptr_t>(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<NamedDecl *>(Vec.back())
|
||||
->getIdentifierNamespace() == Decl::IDNS_Tag) {
|
||||
uintptr_t TagD = Vec.back();
|
||||
Vec.back() = reinterpret_cast<uintptr_t>(D);
|
||||
Vec.push_back(TagD);
|
||||
|
|
|
@ -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<UnresolvedUsingValueDecl>(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)
|
||||
|
|
|
@ -1,20 +1,49 @@
|
|||
// RUN: clang-cc -fsyntax-only -verify %s
|
||||
|
||||
namespace N { }
|
||||
namespace test0 {
|
||||
namespace N { }
|
||||
|
||||
template<typename T>
|
||||
struct A {
|
||||
void f();
|
||||
};
|
||||
template<typename T>
|
||||
struct A {
|
||||
void f();
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct B : A<T> {
|
||||
using A<T>::f;
|
||||
|
||||
void g() {
|
||||
using namespace N;
|
||||
f();
|
||||
template<typename T>
|
||||
struct B : A<T> {
|
||||
using A<T>::f;
|
||||
|
||||
void g() {
|
||||
using namespace N;
|
||||
f();
|
||||
}
|
||||
};
|
||||
|
||||
template struct B<int>;
|
||||
}
|
||||
|
||||
namespace test1 {
|
||||
template <class Derived> struct Visitor1 {
|
||||
void Visit(struct Object1*);
|
||||
};
|
||||
template <class Derived> struct Visitor2 {
|
||||
void Visit(struct Object2*); // expected-note {{candidate function}}
|
||||
};
|
||||
|
||||
template <class Derived> struct JoinVisitor
|
||||
: Visitor1<Derived>, Visitor2<Derived> {
|
||||
typedef Visitor1<Derived> Base1;
|
||||
typedef Visitor2<Derived> Base2;
|
||||
|
||||
void Visit(struct Object1*); // expected-note {{candidate function}}
|
||||
using Base2::Visit;
|
||||
};
|
||||
|
||||
class Knot : JoinVisitor<Knot> {
|
||||
};
|
||||
|
||||
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}}
|
||||
}
|
||||
};
|
||||
|
||||
template struct B<int>;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче