diff options
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 47 | ||||
-rw-r--r-- | clang/test/CXX/drs/dr19xx.cpp | 38 | ||||
-rw-r--r-- | clang/www/cxx_dr_status.html | 2 |
3 files changed, 66 insertions, 21 deletions
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index c244d7e5306..7c34f43d270 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -1098,11 +1098,11 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType, // Attempt user-defined conversion. OverloadCandidateSet Conversions(From->getExprLoc(), OverloadCandidateSet::CSK_Normal); - OverloadingResult UserDefResult - = IsUserDefinedConversion(S, From, ToType, ICS.UserDefined, Conversions, - AllowExplicit, AllowObjCConversionOnExplicit); - - if (UserDefResult == OR_Success) { + switch (IsUserDefinedConversion(S, From, ToType, ICS.UserDefined, + Conversions, AllowExplicit, + AllowObjCConversionOnExplicit)) { + case OR_Success: + case OR_Deleted: ICS.setUserDefined(); ICS.UserDefined.Before.setAsIdentityConversion(); // C++ [over.ics.user]p4: @@ -1131,16 +1131,24 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType, ICS.Standard.Second = ICK_Derived_To_Base; } } - } else if (UserDefResult == OR_Ambiguous && !SuppressUserConversions) { - ICS.setAmbiguous(); - ICS.Ambiguous.setFromType(From->getType()); - ICS.Ambiguous.setToType(ToType); - for (OverloadCandidateSet::iterator Cand = Conversions.begin(); - Cand != Conversions.end(); ++Cand) - if (Cand->Viable) - ICS.Ambiguous.addConversion(Cand->Function); - } else { + break; + + case OR_Ambiguous: + if (!SuppressUserConversions) { + ICS.setAmbiguous(); + ICS.Ambiguous.setFromType(From->getType()); + ICS.Ambiguous.setToType(ToType); + for (OverloadCandidateSet::iterator Cand = Conversions.begin(); + Cand != Conversions.end(); ++Cand) + if (Cand->Viable) + ICS.Ambiguous.addConversion(Cand->Function); + break; + } + + // Fall through. + case OR_No_Viable_Function: ICS.setBad(BadConversionSequence::no_conversion, From, ToType); + break; } return ICS; @@ -3129,8 +3137,10 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, bool HadMultipleCandidates = (CandidateSet.size() > 1); OverloadCandidateSet::iterator Best; - switch (CandidateSet.BestViableFunction(S, From->getLocStart(), Best, true)) { + switch (auto Result = CandidateSet.BestViableFunction(S, From->getLocStart(), + Best, true)) { case OR_Success: + case OR_Deleted: // Record the standard conversion we used and the conversion function. if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Best->Function)) { @@ -3158,7 +3168,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, User.After.setAsIdentityConversion(); User.After.setFromType(ThisType->getAs<PointerType>()->getPointeeType()); User.After.setAllToTypes(ToType); - return OR_Success; + return Result; } if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(Best->Function)) { @@ -3184,15 +3194,12 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, // user-defined conversion sequence (see 13.3.3 and // 13.3.3.1). User.After = Best->FinalConversion; - return OR_Success; + return Result; } llvm_unreachable("Not a constructor or conversion function?"); case OR_No_Viable_Function: return OR_No_Viable_Function; - case OR_Deleted: - // No conversion here! We're done. - return OR_Deleted; case OR_Ambiguous: return OR_Ambiguous; diff --git a/clang/test/CXX/drs/dr19xx.cpp b/clang/test/CXX/drs/dr19xx.cpp new file mode 100644 index 00000000000..e2108aaa127 --- /dev/null +++ b/clang/test/CXX/drs/dr19xx.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++1z %s -verify -fexceptions -fcxx-exceptions -pedantic-errors + +namespace dr1902 { // dr1902: 3.7 + struct A {}; + struct B { + B(A); +#if __cplusplus >= 201103L + // expected-note@-2 {{candidate}} +#endif + + B() = delete; +#if __cplusplus < 201103L + // expected-error@-2 {{extension}} +#endif + + B(const B&) // expected-note {{deleted here}} +#if __cplusplus >= 201103L + // expected-note@-2 {{candidate}} +#else + // expected-error@+2 {{extension}} +#endif + = delete; + + operator A(); + }; + + extern B b1; + B b2(b1); // expected-error {{call to deleted}} + +#if __cplusplus >= 201103L + // This is ambiguous, even though calling the B(const B&) constructor would + // both directly and indirectly call a deleted function. + B b({}); // expected-error {{ambiguous}} +#endif +} diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index 1a4f4f2939f..ed066f3aa8f 100644 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -11227,7 +11227,7 @@ and <I>POD class</I></td> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1902">1902</a></td> <td>DR</td> <td>What makes a conversion “otherwise ill-formed”?</td> - <td class="none" align="center">Unknown</td> + <td class="svn" align="center">SVN</td> </tr> <tr class="open" id="1903"> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1903">1903</a></td> |