summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Sema/Lookup.h28
-rw-r--r--clang/include/clang/Sema/Sema.h4
-rw-r--r--clang/lib/Sema/SemaLookup.cpp4
-rw-r--r--clang/test/SemaCXX/diagnostic-order.cpp20
4 files changed, 35 insertions, 21 deletions
diff --git a/clang/include/clang/Sema/Lookup.h b/clang/include/clang/Sema/Lookup.h
index 81fc5a5e159..2ed9548b593 100644
--- a/clang/include/clang/Sema/Lookup.h
+++ b/clang/include/clang/Sema/Lookup.h
@@ -769,7 +769,13 @@ public:
class ADLResult {
private:
/// A map from canonical decls to the 'most recent' decl.
- llvm::DenseMap<NamedDecl*, NamedDecl*> Decls;
+ llvm::MapVector<NamedDecl*, NamedDecl*> Decls;
+
+ struct select_second {
+ NamedDecl *operator()(std::pair<NamedDecl*, NamedDecl*> P) const {
+ return P.second;
+ }
+ };
public:
/// Adds a new ADL candidate to this map.
@@ -780,23 +786,11 @@ public:
Decls.erase(cast<NamedDecl>(D->getCanonicalDecl()));
}
- class iterator
- : public llvm::iterator_adaptor_base<
- iterator, llvm::DenseMap<NamedDecl *, NamedDecl *>::iterator,
- std::forward_iterator_tag, NamedDecl *> {
- friend class ADLResult;
-
- iterator(llvm::DenseMap<NamedDecl *, NamedDecl *>::iterator Iter)
- : iterator_adaptor_base(std::move(Iter)) {}
-
- public:
- iterator() {}
-
- value_type operator*() const { return I->second; }
- };
+ typedef llvm::mapped_iterator<decltype(Decls)::iterator, select_second>
+ iterator;
- iterator begin() { return iterator(Decls.begin()); }
- iterator end() { return iterator(Decls.end()); }
+ iterator begin() { return iterator(Decls.begin(), select_second()); }
+ iterator end() { return iterator(Decls.end(), select_second()); }
};
}
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 34fedd2160e..377fb182a4f 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2385,8 +2385,8 @@ public:
// Members have to be NamespaceDecl* or TranslationUnitDecl*.
// TODO: make this is a typesafe union.
- typedef llvm::SmallPtrSet<DeclContext *, 16> AssociatedNamespaceSet;
- typedef llvm::SmallPtrSet<CXXRecordDecl *, 16> AssociatedClassSet;
+ typedef llvm::SmallSetVector<DeclContext *, 16> AssociatedNamespaceSet;
+ typedef llvm::SmallSetVector<CXXRecordDecl *, 16> AssociatedClassSet;
void AddOverloadCandidate(FunctionDecl *Function,
DeclAccessPair FoundDecl,
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 00379336251..08133d68899 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -2446,7 +2446,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
// FIXME: That's not correct, we may have added this class only because it
// was the enclosing class of another class, and in that case we won't have
// added its base classes yet.
- if (!Result.Classes.insert(Class).second)
+ if (!Result.Classes.insert(Class))
return;
// -- If T is a template-id, its associated namespaces and classes are
@@ -2496,7 +2496,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
if (!BaseType)
continue;
CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(BaseType->getDecl());
- if (Result.Classes.insert(BaseDecl).second) {
+ if (Result.Classes.insert(BaseDecl)) {
// Find the associated namespace for this base class.
DeclContext *BaseCtx = BaseDecl->getDeclContext();
CollectEnclosingNamespace(Result.Namespaces, BaseCtx);
diff --git a/clang/test/SemaCXX/diagnostic-order.cpp b/clang/test/SemaCXX/diagnostic-order.cpp
new file mode 100644
index 00000000000..f0899018f7f
--- /dev/null
+++ b/clang/test/SemaCXX/diagnostic-order.cpp
@@ -0,0 +1,20 @@
+// RUN: not %clang_cc1 %s -fsyntax-only 2>&1 | FileCheck %s
+
+// Ensure that the diagnostics we produce for this situation appear in a
+// deterministic order. This requires ADL to provide lookup results in a
+// deterministic order.
+template<typename T> struct Error { typedef typename T::error error; };
+struct X { template<typename T> friend typename Error<T>::error f(X, T); };
+struct Y { template<typename T> friend typename Error<T>::error f(T, Y); };
+
+void g() {
+ f(X(), Y());
+}
+
+// We don't really care which order these two diagnostics appear (although the
+// order below is source order, which seems best). The crucial fact is that
+// there is one single order that is stable across multiple runs of clang.
+//
+// CHECK: no type named 'error' in 'Y'
+// CHECK: no type named 'error' in 'X'
+// CHECK: no matching function for call to 'f'
OpenPOWER on IntegriCloud