// 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:
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;
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)) {
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)) {
// 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;
--- /dev/null
+// 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
+}