diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index c244d7e5306d..7c34f43d270d 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(Best->Function)) { @@ -3158,7 +3168,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, User.After.setAsIdentityConversion(); User.After.setFromType(ThisType->getAs()->getPointeeType()); User.After.setAllToTypes(ToType); - return OR_Success; + return Result; } if (CXXConversionDecl *Conversion = dyn_cast(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 000000000000..e2108aaa127b --- /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 1a4f4f2939fb..ed066f3aa8f1 100644 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -11227,7 +11227,7 @@ and POD class 1902 DR What makes a conversion “otherwise ill-formed”? - Unknown + SVN 1903