summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
authorGeorge Burgess IV <george.burgess.iv@gmail.com>2016-09-07 20:03:19 +0000
committerGeorge Burgess IV <george.burgess.iv@gmail.com>2016-09-07 20:03:19 +0000
commitfbad5b2f1b7dfd1c7e16252315e63c6b3ebb1cc3 (patch)
tree974503dcf05fc04741e6be1c22e250f035f7cb9f /clang/lib/Sema
parent14f382065fd183bd5e4d78fa2d41f4faf9c7d576 (diff)
downloadbcm5719-llvm-fbad5b2f1b7dfd1c7e16252315e63c6b3ebb1cc3.tar.gz
bcm5719-llvm-fbad5b2f1b7dfd1c7e16252315e63c6b3ebb1cc3.zip
[Sema] Compare bad conversions in overload resolution.
r280553 introduced an issue where we'd emit ambiguity errors for code like: ``` void foo(int *, int); void foo(unsigned int *, unsigned int); void callFoo() { unsigned int i; foo(&i, 0); // ambiguous: int->unsigned int is worse than int->int, // but unsigned int*->unsigned int* is better than // int*->int*. } ``` This patch fixes this issue by changing how we handle ill-formed (but valid) implicit conversions. Candidates with said conversions now always rank worse than candidates without them, and two candidates are considered to be equally bad if they both have these conversions for the same argument. Additionally, this fixes a case in C++11 where we'd complain about an ambiguity in a case like: ``` void f(char *, int); void f(const char *, unsigned); void g() { f("abc", 0); } ``` ...Since conversion to char* from a string literal is considered ill-formed in C++11 (and deprecated in C++03), but we accept it as an extension. llvm-svn: 280847
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/SemaOverload.cpp33
1 files changed, 30 insertions, 3 deletions
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 183fdf4272e..10aa9977459 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -8600,13 +8600,40 @@ bool clang::isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1,
if (Cand1.IgnoreObjectArgument || Cand2.IgnoreObjectArgument)
StartArg = 1;
+ auto IsIllFormedConversion = [&](const ImplicitConversionSequence &ICS) {
+ // We don't allow incompatible pointer conversions in C++.
+ if (!S.getLangOpts().CPlusPlus)
+ return ICS.isStandard() &&
+ ICS.Standard.Second == ICK_Incompatible_Pointer_Conversion;
+
+ // The only ill-formed conversion we allow in C++ is the string literal to
+ // char* conversion, which is only considered ill-formed after C++11.
+ return S.getLangOpts().CPlusPlus11 && !S.getLangOpts().WritableStrings &&
+ hasDeprecatedStringLiteralToCharPtrConversion(ICS);
+ };
+
+ // Define functions that don't require ill-formed conversions for a given
+ // argument to be better candidates than functions that do.
+ unsigned NumArgs = Cand1.NumConversions;
+ assert(Cand2.NumConversions == NumArgs && "Overload candidate mismatch");
+ bool HasBetterConversion = false;
+ for (unsigned ArgIdx = StartArg; ArgIdx < NumArgs; ++ArgIdx) {
+ bool Cand1Bad = IsIllFormedConversion(Cand1.Conversions[ArgIdx]);
+ bool Cand2Bad = IsIllFormedConversion(Cand2.Conversions[ArgIdx]);
+ if (Cand1Bad != Cand2Bad) {
+ if (Cand1Bad)
+ return false;
+ HasBetterConversion = true;
+ }
+ }
+
+ if (HasBetterConversion)
+ return true;
+
// C++ [over.match.best]p1:
// A viable function F1 is defined to be a better function than another
// viable function F2 if for all arguments i, ICSi(F1) is not a worse
// conversion sequence than ICSi(F2), and then...
- unsigned NumArgs = Cand1.NumConversions;
- assert(Cand2.NumConversions == NumArgs && "Overload candidate mismatch");
- bool HasBetterConversion = false;
for (unsigned ArgIdx = StartArg; ArgIdx < NumArgs; ++ArgIdx) {
switch (CompareImplicitConversionSequences(S, Loc,
Cand1.Conversions[ArgIdx],
OpenPOWER on IntegriCloud