DR1902: if overload resolution recurses, and the inner overload resolution
selects a deleted function, the outer function is still a candidate even though the initialization sequence is "otherwise ill-formed". llvm-svn: 227169
This commit is contained in:
parent
9af09d758a
commit
48372b68fe
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue