summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2015-10-21 07:13:52 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2015-10-21 07:13:52 +0000
commit896c66ecc64e9f8fa80b08b8d9d7eecfce5c3acd (patch)
tree495d1a16c5c55d9c63c4a537b467fb9f7245213c /clang/lib
parent4215236621357cb4b21dfbcfc6e87bc3c222e9f1 (diff)
downloadbcm5719-llvm-896c66ecc64e9f8fa80b08b8d9d7eecfce5c3acd.tar.gz
bcm5719-llvm-896c66ecc64e9f8fa80b08b8d9d7eecfce5c3acd.zip
[modules] libstdc++ defines some static inline functions in its internal
headers. If those headers end up being textually included twice into the same module, we get ambiguity errors. Work around this by downgrading the ambiguity error to a warning if multiple identical internal-linkage functions appear in an overload set, and just pick one of those functions as the lookup result. llvm-svn: 250884
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Sema/SemaOverload.cpp36
1 files changed, 36 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 1ad43a35925..743ca680427 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -8565,6 +8565,27 @@ bool clang::isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1,
return false;
}
+/// Determine whether two function declarations are "equivalent" for overload
+/// resolution purposes. This applies when the same internal linkage function
+/// is defined by two modules (textually including the same header). In such
+/// a case, we don't consider the declarations to declare the same entity, but
+/// we also don't want lookups with both declarations visible to be ambiguous
+/// in some cases (this happens when using a modularized libstdc++).
+static bool isEquivalentCompatibleOverload(Sema &S,
+ const OverloadCandidate &Best,
+ const OverloadCandidate &Cand) {
+ return Best.Function && Cand.Function &&
+ Best.Function->getDeclContext()->getRedeclContext()->Equals(
+ Cand.Function->getDeclContext()->getRedeclContext()) &&
+ S.getOwningModule(Best.Function) != S.getOwningModule(Cand.Function) &&
+ !Best.Function->isExternallyVisible() &&
+ !Cand.Function->isExternallyVisible() &&
+ !S.IsOverload(Best.Function, Cand.Function, /*UsingDecl*/false);
+}
+
+static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
+ unsigned NumArgs);
+
/// \brief Computes the best viable function (C++ 13.3.3)
/// within an overload candidate set.
///
@@ -8592,6 +8613,8 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
if (Best == end())
return OR_No_Viable_Function;
+ llvm::SmallVector<const OverloadCandidate *, 4> EquivalentCands;
+
// Make sure that this function is better than every other viable
// function. If not, we have an ambiguity.
for (iterator Cand = begin(); Cand != end(); ++Cand) {
@@ -8599,6 +8622,11 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
Cand != Best &&
!isBetterOverloadCandidate(S, *Best, *Cand, Loc,
UserDefinedConversion)) {
+ if (isEquivalentCompatibleOverload(S, *Best, *Cand)) {
+ EquivalentCands.push_back(Cand);
+ continue;
+ }
+
Best = end();
return OR_Ambiguous;
}
@@ -8610,6 +8638,14 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
S.isFunctionConsideredUnavailable(Best->Function)))
return OR_Deleted;
+ if (!EquivalentCands.empty()) {
+ S.Diag(Loc, diag::ext_ovl_equivalent_internal_linkage_functions_in_modules)
+ << Best->Function;
+ S.NoteOverloadCandidate(Best->Function);
+ for (auto *Cand : EquivalentCands)
+ S.NoteOverloadCandidate(Cand->Function);
+ }
+
return OR_Success;
}
OpenPOWER on IntegriCloud