summaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaOverload.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaOverload.cpp')
-rw-r--r--clang/lib/Sema/SemaOverload.cpp1363
1 files changed, 924 insertions, 439 deletions
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 47c1e3cec0ea..0fd932fac970 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -60,14 +60,18 @@ CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, NamedDecl *FoundDecl,
// being used.
if (FoundDecl != Fn && S.DiagnoseUseOfDecl(Fn, Loc))
return ExprError();
- if (auto *FPT = Fn->getType()->getAs<FunctionProtoType>())
- S.ResolveExceptionSpec(Loc, FPT);
DeclRefExpr *DRE = new (S.Context)
DeclRefExpr(S.Context, Fn, false, Fn->getType(), VK_LValue, Loc, LocInfo);
if (HadMultipleCandidates)
DRE->setHadMultipleCandidates(true);
S.MarkDeclRefReferenced(DRE, Base);
+ if (auto *FPT = DRE->getType()->getAs<FunctionProtoType>()) {
+ if (isUnresolvedExceptionSpec(FPT->getExceptionSpecType())) {
+ S.ResolveExceptionSpec(Loc, FPT);
+ DRE->setType(Fn->getType());
+ }
+ }
return S.ImpCastExprToType(DRE, S.Context.getPointerType(DRE->getType()),
CK_FunctionToPointerDecay);
}
@@ -591,6 +595,12 @@ namespace {
TemplateArgumentList *TemplateArgs;
unsigned CallArgIndex;
};
+ // Structure used by DeductionFailureInfo to store information about
+ // unsatisfied constraints.
+ struct CNSInfo {
+ TemplateArgumentList *TemplateArgs;
+ ConstraintSatisfaction Satisfaction;
+ };
}
/// Convert from Sema's representation of template deduction information
@@ -661,6 +671,14 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
}
break;
+ case Sema::TDK_ConstraintsNotSatisfied: {
+ CNSInfo *Saved = new (Context) CNSInfo;
+ Saved->TemplateArgs = Info.take();
+ Saved->Satisfaction = Info.AssociatedConstraintsSatisfaction;
+ Result.Data = Saved;
+ break;
+ }
+
case Sema::TDK_Success:
case Sema::TDK_NonDependentConversionFailure:
llvm_unreachable("not a deduction failure");
@@ -701,6 +719,15 @@ void DeductionFailureInfo::Destroy() {
}
break;
+ case Sema::TDK_ConstraintsNotSatisfied:
+ // FIXME: Destroy the template argument list?
+ Data = nullptr;
+ if (PartialDiagnosticAt *Diag = getSFINAEDiagnostic()) {
+ Diag->~PartialDiagnosticAt();
+ HasDiagnostic = false;
+ }
+ break;
+
// Unhandled
case Sema::TDK_MiscellaneousDeductionFailure:
break;
@@ -726,6 +753,7 @@ TemplateParameter DeductionFailureInfo::getTemplateParameter() {
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_CUDATargetMismatch:
case Sema::TDK_NonDependentConversionFailure:
+ case Sema::TDK_ConstraintsNotSatisfied:
return TemplateParameter();
case Sema::TDK_Incomplete:
@@ -769,6 +797,9 @@ TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() {
case Sema::TDK_SubstitutionFailure:
return static_cast<TemplateArgumentList*>(Data);
+ case Sema::TDK_ConstraintsNotSatisfied:
+ return static_cast<CNSInfo*>(Data)->TemplateArgs;
+
// Unhandled
case Sema::TDK_MiscellaneousDeductionFailure:
break;
@@ -789,6 +820,7 @@ const TemplateArgument *DeductionFailureInfo::getFirstArg() {
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_CUDATargetMismatch:
case Sema::TDK_NonDependentConversionFailure:
+ case Sema::TDK_ConstraintsNotSatisfied:
return nullptr;
case Sema::TDK_IncompletePack:
@@ -820,6 +852,7 @@ const TemplateArgument *DeductionFailureInfo::getSecondArg() {
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_CUDATargetMismatch:
case Sema::TDK_NonDependentConversionFailure:
+ case Sema::TDK_ConstraintsNotSatisfied:
return nullptr;
case Sema::TDK_Inconsistent:
@@ -1104,7 +1137,8 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old,
}
bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
- bool UseMemberUsingDeclRules, bool ConsiderCudaAttrs) {
+ bool UseMemberUsingDeclRules, bool ConsiderCudaAttrs,
+ bool ConsiderRequiresClauses) {
// C++ [basic.start.main]p2: This function shall not be overloaded.
if (New->isMain())
return false;
@@ -1240,19 +1274,36 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
if (getLangOpts().CUDA && ConsiderCudaAttrs) {
// Don't allow overloading of destructors. (In theory we could, but it
// would be a giant change to clang.)
- if (isa<CXXDestructorDecl>(New))
- return false;
-
- CUDAFunctionTarget NewTarget = IdentifyCUDATarget(New),
- OldTarget = IdentifyCUDATarget(Old);
- if (NewTarget == CFT_InvalidTarget)
- return false;
+ if (!isa<CXXDestructorDecl>(New)) {
+ CUDAFunctionTarget NewTarget = IdentifyCUDATarget(New),
+ OldTarget = IdentifyCUDATarget(Old);
+ if (NewTarget != CFT_InvalidTarget) {
+ assert((OldTarget != CFT_InvalidTarget) &&
+ "Unexpected invalid target.");
+
+ // Allow overloading of functions with same signature and different CUDA
+ // target attributes.
+ if (NewTarget != OldTarget)
+ return true;
+ }
+ }
+ }
- assert((OldTarget != CFT_InvalidTarget) && "Unexpected invalid target.");
+ if (ConsiderRequiresClauses) {
+ Expr *NewRC = New->getTrailingRequiresClause(),
+ *OldRC = Old->getTrailingRequiresClause();
+ if ((NewRC != nullptr) != (OldRC != nullptr))
+ // RC are most certainly different - these are overloads.
+ return true;
- // Allow overloading of functions with same signature and different CUDA
- // target attributes.
- return NewTarget != OldTarget;
+ if (NewRC) {
+ llvm::FoldingSetNodeID NewID, OldID;
+ NewRC->Profile(NewID, Context, /*Canonical=*/true);
+ OldRC->Profile(OldID, Context, /*Canonical=*/true);
+ if (NewID != OldID)
+ // RCs are not equivalent - these are overloads.
+ return true;
+ }
}
// The signatures match; this is not an overload.
@@ -1326,7 +1377,7 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
ICS.Ambiguous.setToType(ToType);
for (OverloadCandidateSet::iterator Cand = Conversions.begin();
Cand != Conversions.end(); ++Cand)
- if (Cand->Viable)
+ if (Cand->Best)
ICS.Ambiguous.addConversion(Cand->FoundDecl, Cand->Function);
break;
@@ -2802,8 +2853,8 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
// Get the function type from the pointers.
if (FromType->isMemberPointerType() && ToType->isMemberPointerType()) {
- const MemberPointerType *FromMember = FromType->getAs<MemberPointerType>(),
- *ToMember = ToType->getAs<MemberPointerType>();
+ const auto *FromMember = FromType->castAs<MemberPointerType>(),
+ *ToMember = ToType->castAs<MemberPointerType>();
if (!Context.hasSameType(FromMember->getClass(), ToMember->getClass())) {
PDiag << ft_different_class << QualType(ToMember->getClass(), 0)
<< QualType(FromMember->getClass(), 0);
@@ -2898,8 +2949,12 @@ bool Sema::FunctionParamTypesAreEqual(const FunctionProtoType *OldType,
N = NewType->param_type_begin(),
E = OldType->param_type_end();
O && (O != E); ++O, ++N) {
- if (!Context.hasSameType(O->getUnqualifiedType(),
- N->getUnqualifiedType())) {
+ // Ignore address spaces in pointee type. This is to disallow overloading
+ // on __ptr32/__ptr64 address spaces.
+ QualType Old = Context.removePtrSizeAddrSpace(O->getUnqualifiedType());
+ QualType New = Context.removePtrSizeAddrSpace(N->getUnqualifiedType());
+
+ if (!Context.hasSameType(Old, New)) {
if (ArgPos)
*ArgPos = O - OldType->param_type_begin();
return false;
@@ -3114,6 +3169,70 @@ static bool isNonTrivialObjCLifetimeConversion(Qualifiers FromQuals,
return true;
}
+/// Perform a single iteration of the loop for checking if a qualification
+/// conversion is valid.
+///
+/// Specifically, check whether any change between the qualifiers of \p
+/// FromType and \p ToType is permissible, given knowledge about whether every
+/// outer layer is const-qualified.
+static bool isQualificationConversionStep(QualType FromType, QualType ToType,
+ bool CStyle,
+ bool &PreviousToQualsIncludeConst,
+ bool &ObjCLifetimeConversion) {
+ Qualifiers FromQuals = FromType.getQualifiers();
+ Qualifiers ToQuals = ToType.getQualifiers();
+
+ // Ignore __unaligned qualifier if this type is void.
+ if (ToType.getUnqualifiedType()->isVoidType())
+ FromQuals.removeUnaligned();
+
+ // Objective-C ARC:
+ // Check Objective-C lifetime conversions.
+ if (FromQuals.getObjCLifetime() != ToQuals.getObjCLifetime()) {
+ if (ToQuals.compatiblyIncludesObjCLifetime(FromQuals)) {
+ if (isNonTrivialObjCLifetimeConversion(FromQuals, ToQuals))
+ ObjCLifetimeConversion = true;
+ FromQuals.removeObjCLifetime();
+ ToQuals.removeObjCLifetime();
+ } else {
+ // Qualification conversions cannot cast between different
+ // Objective-C lifetime qualifiers.
+ return false;
+ }
+ }
+
+ // Allow addition/removal of GC attributes but not changing GC attributes.
+ if (FromQuals.getObjCGCAttr() != ToQuals.getObjCGCAttr() &&
+ (!FromQuals.hasObjCGCAttr() || !ToQuals.hasObjCGCAttr())) {
+ FromQuals.removeObjCGCAttr();
+ ToQuals.removeObjCGCAttr();
+ }
+
+ // -- for every j > 0, if const is in cv 1,j then const is in cv
+ // 2,j, and similarly for volatile.
+ if (!CStyle && !ToQuals.compatiblyIncludes(FromQuals))
+ return false;
+
+ // For a C-style cast, just require the address spaces to overlap.
+ // FIXME: Does "superset" also imply the representation of a pointer is the
+ // same? We're assuming that it does here and in compatiblyIncludes.
+ if (CStyle && !ToQuals.isAddressSpaceSupersetOf(FromQuals) &&
+ !FromQuals.isAddressSpaceSupersetOf(ToQuals))
+ return false;
+
+ // -- if the cv 1,j and cv 2,j are different, then const is in
+ // every cv for 0 < k < j.
+ if (!CStyle && FromQuals.getCVRQualifiers() != ToQuals.getCVRQualifiers() &&
+ !PreviousToQualsIncludeConst)
+ return false;
+
+ // Keep track of whether all prior cv-qualifiers in the "to" type
+ // include const.
+ PreviousToQualsIncludeConst =
+ PreviousToQualsIncludeConst && ToQuals.hasConst();
+ return true;
+}
+
/// IsQualificationConversion - Determines whether the conversion from
/// an rvalue of type FromType to ToType is a qualification conversion
/// (C++ 4.4).
@@ -3139,73 +3258,16 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType,
bool PreviousToQualsIncludeConst = true;
bool UnwrappedAnyPointer = false;
while (Context.UnwrapSimilarTypes(FromType, ToType)) {
- // Within each iteration of the loop, we check the qualifiers to
- // determine if this still looks like a qualification
- // conversion. Then, if all is well, we unwrap one more level of
- // pointers or pointers-to-members and do it all again
- // until there are no more pointers or pointers-to-members left to
- // unwrap.
- UnwrappedAnyPointer = true;
-
- Qualifiers FromQuals = FromType.getQualifiers();
- Qualifiers ToQuals = ToType.getQualifiers();
-
- // Ignore __unaligned qualifier if this type is void.
- if (ToType.getUnqualifiedType()->isVoidType())
- FromQuals.removeUnaligned();
-
- // Objective-C ARC:
- // Check Objective-C lifetime conversions.
- if (FromQuals.getObjCLifetime() != ToQuals.getObjCLifetime() &&
- UnwrappedAnyPointer) {
- if (ToQuals.compatiblyIncludesObjCLifetime(FromQuals)) {
- if (isNonTrivialObjCLifetimeConversion(FromQuals, ToQuals))
- ObjCLifetimeConversion = true;
- FromQuals.removeObjCLifetime();
- ToQuals.removeObjCLifetime();
- } else {
- // Qualification conversions cannot cast between different
- // Objective-C lifetime qualifiers.
- return false;
- }
- }
-
- // Allow addition/removal of GC attributes but not changing GC attributes.
- if (FromQuals.getObjCGCAttr() != ToQuals.getObjCGCAttr() &&
- (!FromQuals.hasObjCGCAttr() || !ToQuals.hasObjCGCAttr())) {
- FromQuals.removeObjCGCAttr();
- ToQuals.removeObjCGCAttr();
- }
-
- // -- for every j > 0, if const is in cv 1,j then const is in cv
- // 2,j, and similarly for volatile.
- if (!CStyle && !ToQuals.compatiblyIncludes(FromQuals))
- return false;
-
- // -- if the cv 1,j and cv 2,j are different, then const is in
- // every cv for 0 < k < j.
- if (!CStyle && FromQuals.getCVRQualifiers() != ToQuals.getCVRQualifiers()
- && !PreviousToQualsIncludeConst)
+ if (!isQualificationConversionStep(FromType, ToType, CStyle,
+ PreviousToQualsIncludeConst,
+ ObjCLifetimeConversion))
return false;
-
- // Keep track of whether all prior cv-qualifiers in the "to" type
- // include const.
- PreviousToQualsIncludeConst
- = PreviousToQualsIncludeConst && ToQuals.hasConst();
- }
-
- // Allows address space promotion by language rules implemented in
- // Type::Qualifiers::isAddressSpaceSupersetOf.
- Qualifiers FromQuals = FromType.getQualifiers();
- Qualifiers ToQuals = ToType.getQualifiers();
- if (!ToQuals.isAddressSpaceSupersetOf(FromQuals) &&
- !FromQuals.isAddressSpaceSupersetOf(ToQuals)) {
- return false;
+ UnwrappedAnyPointer = true;
}
// We are left with FromType and ToType being the pointee types
// after unwrapping the original FromType and ToType the same number
- // of types. If we unwrapped any pointers, and if FromType and
+ // of times. If we unwrapped any pointers, and if FromType and
// ToType have the same unqualified type (since we checked
// qualifiers above), then this is a qualification conversion.
return UnwrappedAnyPointer && Context.hasSameUnqualifiedType(FromType,ToType);
@@ -3242,8 +3304,7 @@ static bool tryAtomicConversion(Sema &S, Expr *From, QualType ToType,
static bool isFirstArgumentCompatibleWithType(ASTContext &Context,
CXXConstructorDecl *Constructor,
QualType Type) {
- const FunctionProtoType *CtorType =
- Constructor->getType()->getAs<FunctionProtoType>();
+ const auto *CtorType = Constructor->getType()->castAs<FunctionProtoType>();
if (CtorType->getNumParams() > 0) {
QualType FirstArg = CtorType->getParamType(0);
if (Context.hasSameUnqualifiedType(Type, FirstArg.getNonReferenceType()))
@@ -3265,8 +3326,7 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType,
continue;
bool Usable = !Info.Constructor->isInvalidDecl() &&
- S.isInitListConstructor(Info.Constructor) &&
- (AllowExplicit || !Info.Constructor->isExplicit());
+ S.isInitListConstructor(Info.Constructor);
if (Usable) {
// If the first argument is (a reference to) the target type,
// suppress conversions.
@@ -3388,11 +3448,9 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
continue;
bool Usable = !Info.Constructor->isInvalidDecl();
- if (ListInitializing)
- Usable = Usable && (AllowExplicit || !Info.Constructor->isExplicit());
- else
- Usable = Usable &&
- Info.Constructor->isConvertingConstructor(AllowExplicit);
+ if (!ListInitializing)
+ Usable = Usable && Info.Constructor->isConvertingConstructor(
+ /*AllowExplicit*/ true);
if (Usable) {
bool SuppressUserConversions = !ConstructorsOnly;
if (SuppressUserConversions && ListInitializing) {
@@ -3446,16 +3504,14 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
else
Conv = cast<CXXConversionDecl>(D);
- if (AllowExplicit || !Conv->isExplicit()) {
- if (ConvTemplate)
- S.AddTemplateConversionCandidate(
- ConvTemplate, FoundDecl, ActingContext, From, ToType,
- CandidateSet, AllowObjCConversionOnExplicit, AllowExplicit);
- else
- S.AddConversionCandidate(
- Conv, FoundDecl, ActingContext, From, ToType, CandidateSet,
- AllowObjCConversionOnExplicit, AllowExplicit);
- }
+ if (ConvTemplate)
+ S.AddTemplateConversionCandidate(
+ ConvTemplate, FoundDecl, ActingContext, From, ToType,
+ CandidateSet, AllowObjCConversionOnExplicit, AllowExplicit);
+ else
+ S.AddConversionCandidate(
+ Conv, FoundDecl, ActingContext, From, ToType, CandidateSet,
+ AllowObjCConversionOnExplicit, AllowExplicit);
}
}
}
@@ -3547,7 +3603,10 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) {
(OvResult == OR_No_Viable_Function && !CandidateSet.empty())))
return false;
- auto Cands = CandidateSet.CompleteCandidates(*this, OCD_AllCandidates, From);
+ auto Cands = CandidateSet.CompleteCandidates(
+ *this,
+ OvResult == OR_Ambiguous ? OCD_AmbiguousCandidates : OCD_AllCandidates,
+ From);
if (OvResult == OR_Ambiguous)
Diag(From->getBeginLoc(), diag::err_typecheck_ambiguous_condition)
<< From->getType() << ToType << From->getSourceRange();
@@ -3929,19 +3988,21 @@ CompareStandardConversionSequences(Sema &S, SourceLocation Loc,
}
}
- // Compare based on qualification conversions (C++ 13.3.3.2p3,
- // bullet 3).
- if (ImplicitConversionSequence::CompareKind QualCK
- = CompareQualificationConversions(S, SCS1, SCS2))
- return QualCK;
-
if (SCS1.ReferenceBinding && SCS2.ReferenceBinding) {
// Check for a better reference binding based on the kind of bindings.
if (isBetterReferenceBindingKind(SCS1, SCS2))
return ImplicitConversionSequence::Better;
else if (isBetterReferenceBindingKind(SCS2, SCS1))
return ImplicitConversionSequence::Worse;
+ }
+ // Compare based on qualification conversions (C++ 13.3.3.2p3,
+ // bullet 3).
+ if (ImplicitConversionSequence::CompareKind QualCK
+ = CompareQualificationConversions(S, SCS1, SCS2))
+ return QualCK;
+
+ if (SCS1.ReferenceBinding && SCS2.ReferenceBinding) {
// C++ [over.ics.rank]p3b4:
// -- S1 and S2 are reference bindings (8.5.3), and the types to
// which the references refer are the same type except for
@@ -3973,7 +4034,7 @@ CompareStandardConversionSequences(Sema &S, SourceLocation Loc,
T2 = S.Context.getQualifiedType(UnqualT2, T2Quals);
if (T2.isMoreQualifiedThan(T1))
return ImplicitConversionSequence::Better;
- else if (T1.isMoreQualifiedThan(T2))
+ if (T1.isMoreQualifiedThan(T2))
return ImplicitConversionSequence::Worse;
}
}
@@ -4047,22 +4108,16 @@ CompareQualificationConversions(Sema &S,
QualType T2 = SCS2.getToType(2);
T1 = S.Context.getCanonicalType(T1);
T2 = S.Context.getCanonicalType(T2);
+ assert(!T1->isReferenceType() && !T2->isReferenceType());
Qualifiers T1Quals, T2Quals;
QualType UnqualT1 = S.Context.getUnqualifiedArrayType(T1, T1Quals);
QualType UnqualT2 = S.Context.getUnqualifiedArrayType(T2, T2Quals);
- // If the types are the same, we won't learn anything by unwrapped
+ // If the types are the same, we won't learn anything by unwrapping
// them.
if (UnqualT1 == UnqualT2)
return ImplicitConversionSequence::Indistinguishable;
- // If the type is an array type, promote the element qualifiers to the type
- // for comparison.
- if (isa<ArrayType>(T1) && T1Quals)
- T1 = S.Context.getQualifiedType(UnqualT1, T1Quals);
- if (isa<ArrayType>(T2) && T2Quals)
- T2 = S.Context.getQualifiedType(UnqualT2, T2Quals);
-
ImplicitConversionSequence::CompareKind Result
= ImplicitConversionSequence::Indistinguishable;
@@ -4290,14 +4345,10 @@ CompareDerivedToBaseConversions(Sema &S, SourceLocation Loc,
if (SCS1.Second == ICK_Pointer_Member && SCS2.Second == ICK_Pointer_Member &&
FromType1->isMemberPointerType() && FromType2->isMemberPointerType() &&
ToType1->isMemberPointerType() && ToType2->isMemberPointerType()) {
- const MemberPointerType * FromMemPointer1 =
- FromType1->getAs<MemberPointerType>();
- const MemberPointerType * ToMemPointer1 =
- ToType1->getAs<MemberPointerType>();
- const MemberPointerType * FromMemPointer2 =
- FromType2->getAs<MemberPointerType>();
- const MemberPointerType * ToMemPointer2 =
- ToType2->getAs<MemberPointerType>();
+ const auto *FromMemPointer1 = FromType1->castAs<MemberPointerType>();
+ const auto *ToMemPointer1 = ToType1->castAs<MemberPointerType>();
+ const auto *FromMemPointer2 = FromType2->castAs<MemberPointerType>();
+ const auto *ToMemPointer2 = ToType2->castAs<MemberPointerType>();
const Type *FromPointeeType1 = FromMemPointer1->getClass();
const Type *ToPointeeType1 = ToMemPointer1->getClass();
const Type *FromPointeeType2 = FromMemPointer2->getClass();
@@ -4360,20 +4411,26 @@ static bool isTypeValid(QualType T) {
return true;
}
+static QualType withoutUnaligned(ASTContext &Ctx, QualType T) {
+ if (!T.getQualifiers().hasUnaligned())
+ return T;
+
+ Qualifiers Q;
+ T = Ctx.getUnqualifiedArrayType(T, Q);
+ Q.removeUnaligned();
+ return Ctx.getQualifiedType(T, Q);
+}
+
/// CompareReferenceRelationship - Compare the two types T1 and T2 to
-/// determine whether they are reference-related,
-/// reference-compatible, reference-compatible with added
-/// qualification, or incompatible, for use in C++ initialization by
+/// determine whether they are reference-compatible,
+/// reference-related, or incompatible, for use in C++ initialization by
/// reference (C++ [dcl.ref.init]p4). Neither type can be a reference
/// type, and the first type (T1) is the pointee type of the reference
/// type being initialized.
Sema::ReferenceCompareResult
Sema::CompareReferenceRelationship(SourceLocation Loc,
QualType OrigT1, QualType OrigT2,
- bool &DerivedToBase,
- bool &ObjCConversion,
- bool &ObjCLifetimeConversion,
- bool &FunctionConversion) {
+ ReferenceConversions *ConvOut) {
assert(!OrigT1->isReferenceType() &&
"T1 must be the pointee type of the reference type");
assert(!OrigT2->isReferenceType() && "T2 cannot be a reference type");
@@ -4384,76 +4441,84 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
QualType UnqualT1 = Context.getUnqualifiedArrayType(T1, T1Quals);
QualType UnqualT2 = Context.getUnqualifiedArrayType(T2, T2Quals);
- // C++ [dcl.init.ref]p4:
+ ReferenceConversions ConvTmp;
+ ReferenceConversions &Conv = ConvOut ? *ConvOut : ConvTmp;
+ Conv = ReferenceConversions();
+
+ // C++2a [dcl.init.ref]p4:
// Given types "cv1 T1" and "cv2 T2," "cv1 T1" is
- // reference-related to "cv2 T2" if T1 is the same type as T2, or
+ // reference-related to "cv2 T2" if T1 is similar to T2, or
// T1 is a base class of T2.
- DerivedToBase = false;
- ObjCConversion = false;
- ObjCLifetimeConversion = false;
+ // "cv1 T1" is reference-compatible with "cv2 T2" if
+ // a prvalue of type "pointer to cv2 T2" can be converted to the type
+ // "pointer to cv1 T1" via a standard conversion sequence.
+
+ // Check for standard conversions we can apply to pointers: derived-to-base
+ // conversions, ObjC pointer conversions, and function pointer conversions.
+ // (Qualification conversions are checked last.)
QualType ConvertedT2;
if (UnqualT1 == UnqualT2) {
// Nothing to do.
} else if (isCompleteType(Loc, OrigT2) &&
isTypeValid(UnqualT1) && isTypeValid(UnqualT2) &&
IsDerivedFrom(Loc, UnqualT2, UnqualT1))
- DerivedToBase = true;
+ Conv |= ReferenceConversions::DerivedToBase;
else if (UnqualT1->isObjCObjectOrInterfaceType() &&
UnqualT2->isObjCObjectOrInterfaceType() &&
Context.canBindObjCObjectType(UnqualT1, UnqualT2))
- ObjCConversion = true;
+ Conv |= ReferenceConversions::ObjC;
else if (UnqualT2->isFunctionType() &&
IsFunctionConversion(UnqualT2, UnqualT1, ConvertedT2)) {
- // C++1z [dcl.init.ref]p4:
- // cv1 T1" is reference-compatible with "cv2 T2" if [...] T2 is "noexcept
- // function" and T1 is "function"
- //
- // We extend this to also apply to 'noreturn', so allow any function
- // conversion between function types.
- FunctionConversion = true;
+ Conv |= ReferenceConversions::Function;
+ // No need to check qualifiers; function types don't have them.
return Ref_Compatible;
- } else
- return Ref_Incompatible;
-
- // At this point, we know that T1 and T2 are reference-related (at
- // least).
-
- // If the type is an array type, promote the element qualifiers to the type
- // for comparison.
- if (isa<ArrayType>(T1) && T1Quals)
- T1 = Context.getQualifiedType(UnqualT1, T1Quals);
- if (isa<ArrayType>(T2) && T2Quals)
- T2 = Context.getQualifiedType(UnqualT2, T2Quals);
-
- // C++ [dcl.init.ref]p4:
- // "cv1 T1" is reference-compatible with "cv2 T2" if T1 is
- // reference-related to T2 and cv1 is the same cv-qualification
- // as, or greater cv-qualification than, cv2. For purposes of
- // overload resolution, cases for which cv1 is greater
- // cv-qualification than cv2 are identified as
- // reference-compatible with added qualification (see 13.3.3.2).
- //
- // Note that we also require equivalence of Objective-C GC and address-space
- // qualifiers when performing these computations, so that e.g., an int in
- // address space 1 is not reference-compatible with an int in address
- // space 2.
- if (T1Quals.getObjCLifetime() != T2Quals.getObjCLifetime() &&
- T1Quals.compatiblyIncludesObjCLifetime(T2Quals)) {
- if (isNonTrivialObjCLifetimeConversion(T2Quals, T1Quals))
- ObjCLifetimeConversion = true;
-
- T1Quals.removeObjCLifetime();
- T2Quals.removeObjCLifetime();
}
+ bool ConvertedReferent = Conv != 0;
- // MS compiler ignores __unaligned qualifier for references; do the same.
- T1Quals.removeUnaligned();
- T2Quals.removeUnaligned();
+ // We can have a qualification conversion. Compute whether the types are
+ // similar at the same time.
+ bool PreviousToQualsIncludeConst = true;
+ bool TopLevel = true;
+ do {
+ if (T1 == T2)
+ break;
- if (T1Quals.compatiblyIncludes(T2Quals))
- return Ref_Compatible;
- else
- return Ref_Related;
+ // We will need a qualification conversion.
+ Conv |= ReferenceConversions::Qualification;
+
+ // Track whether we performed a qualification conversion anywhere other
+ // than the top level. This matters for ranking reference bindings in
+ // overload resolution.
+ if (!TopLevel)
+ Conv |= ReferenceConversions::NestedQualification;
+
+ // MS compiler ignores __unaligned qualifier for references; do the same.
+ T1 = withoutUnaligned(Context, T1);
+ T2 = withoutUnaligned(Context, T2);
+
+ // If we find a qualifier mismatch, the types are not reference-compatible,
+ // but are still be reference-related if they're similar.
+ bool ObjCLifetimeConversion = false;
+ if (!isQualificationConversionStep(T2, T1, /*CStyle=*/false,
+ PreviousToQualsIncludeConst,
+ ObjCLifetimeConversion))
+ return (ConvertedReferent || Context.hasSimilarType(T1, T2))
+ ? Ref_Related
+ : Ref_Incompatible;
+
+ // FIXME: Should we track this for any level other than the first?
+ if (ObjCLifetimeConversion)
+ Conv |= ReferenceConversions::ObjCLifetime;
+
+ TopLevel = false;
+ } while (Context.UnwrapSimilarTypes(T1, T2));
+
+ // At this point, if the types are reference-related, we must either have the
+ // same inner type (ignoring qualifiers), or must have already worked out how
+ // to convert the referent.
+ return (ConvertedReferent || Context.hasSameUnqualifiedType(T1, T2))
+ ? Ref_Compatible
+ : Ref_Incompatible;
}
/// Look for a user-defined conversion to a value reference-compatible
@@ -4464,8 +4529,7 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
Expr *Init, QualType T2, bool AllowRvalues,
bool AllowExplicit) {
assert(T2->isRecordType() && "Can only find conversions of record types.");
- CXXRecordDecl *T2RecordDecl
- = dyn_cast<CXXRecordDecl>(T2->castAs<RecordType>()->getDecl());
+ auto *T2RecordDecl = cast<CXXRecordDecl>(T2->castAs<RecordType>()->getDecl());
OverloadCandidateSet CandidateSet(
DeclLoc, OverloadCandidateSet::CSK_InitByUserDefinedConversion);
@@ -4484,17 +4548,7 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
else
Conv = cast<CXXConversionDecl>(D);
- // If this is an explicit conversion, and we're not allowed to consider
- // explicit conversions, skip it.
- if (!AllowExplicit && Conv->isExplicit())
- continue;
-
if (AllowRvalues) {
- bool DerivedToBase = false;
- bool ObjCConversion = false;
- bool ObjCLifetimeConversion = false;
- bool FunctionConversion = false;
-
// If we are initializing an rvalue reference, don't permit conversion
// functions that return lvalues.
if (!ConvTemplate && DeclType->isRValueReferenceType()) {
@@ -4510,9 +4564,8 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
Conv->getConversionType()
.getNonReferenceType()
.getUnqualifiedType(),
- DeclType.getNonReferenceType().getUnqualifiedType(),
- DerivedToBase, ObjCConversion, ObjCLifetimeConversion,
- FunctionConversion) == Sema::Ref_Incompatible)
+ DeclType.getNonReferenceType().getUnqualifiedType()) ==
+ Sema::Ref_Incompatible)
continue;
} else {
// If the conversion function doesn't return a reference type,
@@ -4571,7 +4624,7 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
ICS.setAmbiguous();
for (OverloadCandidateSet::iterator Cand = CandidateSet.begin();
Cand != CandidateSet.end(); ++Cand)
- if (Cand->Viable)
+ if (Cand->Best)
ICS.Ambiguous.addConversion(Cand->FoundDecl, Cand->Function);
return true;
@@ -4613,14 +4666,44 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
// Compute some basic properties of the types and the initializer.
bool isRValRef = DeclType->isRValueReferenceType();
- bool DerivedToBase = false;
- bool ObjCConversion = false;
- bool ObjCLifetimeConversion = false;
- bool FunctionConversion = false;
Expr::Classification InitCategory = Init->Classify(S.Context);
- Sema::ReferenceCompareResult RefRelationship = S.CompareReferenceRelationship(
- DeclLoc, T1, T2, DerivedToBase, ObjCConversion, ObjCLifetimeConversion,
- FunctionConversion);
+
+ Sema::ReferenceConversions RefConv;
+ Sema::ReferenceCompareResult RefRelationship =
+ S.CompareReferenceRelationship(DeclLoc, T1, T2, &RefConv);
+
+ auto SetAsReferenceBinding = [&](bool BindsDirectly) {
+ ICS.setStandard();
+ ICS.Standard.First = ICK_Identity;
+ // FIXME: A reference binding can be a function conversion too. We should
+ // consider that when ordering reference-to-function bindings.
+ ICS.Standard.Second = (RefConv & Sema::ReferenceConversions::DerivedToBase)
+ ? ICK_Derived_To_Base
+ : (RefConv & Sema::ReferenceConversions::ObjC)
+ ? ICK_Compatible_Conversion
+ : ICK_Identity;
+ // FIXME: As a speculative fix to a defect introduced by CWG2352, we rank
+ // a reference binding that performs a non-top-level qualification
+ // conversion as a qualification conversion, not as an identity conversion.
+ ICS.Standard.Third = (RefConv &
+ Sema::ReferenceConversions::NestedQualification)
+ ? ICK_Qualification
+ : ICK_Identity;
+ ICS.Standard.FromTypePtr = T2.getAsOpaquePtr();
+ ICS.Standard.setToType(0, T2);
+ ICS.Standard.setToType(1, T1);
+ ICS.Standard.setToType(2, T1);
+ ICS.Standard.ReferenceBinding = true;
+ ICS.Standard.DirectBinding = BindsDirectly;
+ ICS.Standard.IsLvalueReference = !isRValRef;
+ ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
+ ICS.Standard.BindsToRvalue = InitCategory.isRValue();
+ ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
+ ICS.Standard.ObjCLifetimeConversionBinding =
+ (RefConv & Sema::ReferenceConversions::ObjCLifetime) != 0;
+ ICS.Standard.CopyConstructor = nullptr;
+ ICS.Standard.DeprecatedStringLiteralToCharPtr = false;
+ };
// C++0x [dcl.init.ref]p5:
// A reference to type "cv1 T1" is initialized by an expression
@@ -4640,25 +4723,7 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
// has a type that is a derived class of the parameter type,
// in which case the implicit conversion sequence is a
// derived-to-base Conversion (13.3.3.1).
- ICS.setStandard();
- ICS.Standard.First = ICK_Identity;
- ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base
- : ObjCConversion? ICK_Compatible_Conversion
- : ICK_Identity;
- ICS.Standard.Third = ICK_Identity;
- ICS.Standard.FromTypePtr = T2.getAsOpaquePtr();
- ICS.Standard.setToType(0, T2);
- ICS.Standard.setToType(1, T1);
- ICS.Standard.setToType(2, T1);
- ICS.Standard.ReferenceBinding = true;
- ICS.Standard.DirectBinding = true;
- ICS.Standard.IsLvalueReference = !isRValRef;
- ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
- ICS.Standard.BindsToRvalue = false;
- ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
- ICS.Standard.ObjCLifetimeConversionBinding = ObjCLifetimeConversion;
- ICS.Standard.CopyConstructor = nullptr;
- ICS.Standard.DeprecatedStringLiteralToCharPtr = false;
+ SetAsReferenceBinding(/*BindsDirectly=*/true);
// Nothing more to do: the inaccessibility/ambiguity check for
// derived-to-base conversions is suppressed when we're
@@ -4696,34 +4761,16 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
// lvalue and "cv1 T1" is reference-compatible with "cv2 T2", or
if (RefRelationship == Sema::Ref_Compatible &&
(InitCategory.isXValue() ||
- (InitCategory.isPRValue() && (T2->isRecordType() || T2->isArrayType())) ||
+ (InitCategory.isPRValue() &&
+ (T2->isRecordType() || T2->isArrayType())) ||
(InitCategory.isLValue() && T2->isFunctionType()))) {
- ICS.setStandard();
- ICS.Standard.First = ICK_Identity;
- ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base
- : ObjCConversion? ICK_Compatible_Conversion
- : ICK_Identity;
- ICS.Standard.Third = ICK_Identity;
- ICS.Standard.FromTypePtr = T2.getAsOpaquePtr();
- ICS.Standard.setToType(0, T2);
- ICS.Standard.setToType(1, T1);
- ICS.Standard.setToType(2, T1);
- ICS.Standard.ReferenceBinding = true;
- // In C++0x, this is always a direct binding. In C++98/03, it's a direct
+ // In C++11, this is always a direct binding. In C++98/03, it's a direct
// binding unless we're binding to a class prvalue.
// Note: Although xvalues wouldn't normally show up in C++98/03 code, we
// allow the use of rvalue references in C++98/03 for the benefit of
// standard library implementors; therefore, we need the xvalue check here.
- ICS.Standard.DirectBinding =
- S.getLangOpts().CPlusPlus11 ||
- !(InitCategory.isPRValue() || T2->isRecordType());
- ICS.Standard.IsLvalueReference = !isRValRef;
- ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
- ICS.Standard.BindsToRvalue = InitCategory.isRValue();
- ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
- ICS.Standard.ObjCLifetimeConversionBinding = ObjCLifetimeConversion;
- ICS.Standard.CopyConstructor = nullptr;
- ICS.Standard.DeprecatedStringLiteralToCharPtr = false;
+ SetAsReferenceBinding(/*BindsDirectly=*/S.getLangOpts().CPlusPlus11 ||
+ !(InitCategory.isPRValue() || T2->isRecordType()));
return ICS;
}
@@ -5042,13 +5089,8 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
}
// Compute some basic properties of the types and the initializer.
- bool dummy1 = false;
- bool dummy2 = false;
- bool dummy3 = false;
- bool dummy4 = false;
Sema::ReferenceCompareResult RefRelationship =
- S.CompareReferenceRelationship(From->getBeginLoc(), T1, T2, dummy1,
- dummy2, dummy3, dummy4);
+ S.CompareReferenceRelationship(From->getBeginLoc(), T1, T2);
if (RefRelationship >= Sema::Ref_Related) {
return TryReferenceInit(S, Init, ToType, /*FIXME*/ From->getBeginLoc(),
@@ -5218,7 +5260,7 @@ TryObjectArgumentInitialization(Sema &S, SourceLocation Loc, QualType FromType,
return ICS;
}
- if (FromTypeCanon.getQualifiers().hasAddressSpace()) {
+ if (FromTypeCanon.hasAddressSpace()) {
Qualifiers QualsImplicitParamType = ImplicitParamType.getQualifiers();
Qualifiers QualsFromType = FromTypeCanon.getQualifiers();
if (!QualsImplicitParamType.isAddressSpaceSupersetOf(QualsFromType)) {
@@ -5367,7 +5409,10 @@ Sema::PerformObjectArgumentInitialization(Expr *From,
if (!Context.hasSameType(From->getType(), DestType)) {
CastKind CK;
- if (FromRecordType.getAddressSpace() != DestType.getAddressSpace())
+ QualType PteeTy = DestType->getPointeeType();
+ LangAS DestAS =
+ PteeTy.isNull() ? DestType.getAddressSpace() : PteeTy.getAddressSpace();
+ if (FromRecordType.getAddressSpace() != DestAS)
CK = CK_AddressSpaceConversion;
else
CK = CK_NoOp;
@@ -6046,7 +6091,7 @@ static bool IsAcceptableNonMemberOperatorCandidate(ASTContext &Context,
if (T1->isRecordType() || (!T2.isNull() && T2->isRecordType()))
return true;
- const FunctionProtoType *Proto = Fn->getType()->getAs<FunctionProtoType>();
+ const auto *Proto = Fn->getType()->castAs<FunctionProtoType>();
if (Proto->getNumParams() < 1)
return false;
@@ -6146,6 +6191,15 @@ void Sema::AddOverloadCandidate(
Candidate.IgnoreObjectArgument = false;
Candidate.ExplicitCallArguments = Args.size();
+ // Explicit functions are not actually candidates at all if we're not
+ // allowing them in this context, but keep them around so we can point
+ // to them in diagnostics.
+ if (!AllowExplicit && ExplicitSpecifier::getFromDecl(Function).isExplicit()) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_explicit;
+ return;
+ }
+
if (Function->isMultiVersion() && Function->hasAttr<TargetAttr>() &&
!Function->getAttr<TargetAttr>()->isDefaultVersion()) {
Candidate.Viable = false;
@@ -6237,6 +6291,16 @@ void Sema::AddOverloadCandidate(
return;
}
+ if (Expr *RequiresClause = Function->getTrailingRequiresClause()) {
+ ConstraintSatisfaction Satisfaction;
+ if (CheckConstraintSatisfaction(RequiresClause, Satisfaction) ||
+ !Satisfaction.IsSatisfied) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_constraints_not_satisfied;
+ return;
+ }
+ }
+
// Determine the implicit conversion sequences for each of the
// arguments.
for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) {
@@ -6269,15 +6333,6 @@ void Sema::AddOverloadCandidate(
}
}
- if (!AllowExplicit) {
- ExplicitSpecifier ES = ExplicitSpecifier::getFromDecl(Function);
- if (ES.getKind() != ExplicitSpecKind::ResolvedFalse) {
- Candidate.Viable = false;
- Candidate.FailureKind = ovl_fail_explicit_resolved;
- return;
- }
- }
-
if (EnableIfAttr *FailedAttr = CheckEnableIf(Function, Args)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_enable_if;
@@ -6753,6 +6808,16 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
return;
}
+ if (Expr *RequiresClause = Method->getTrailingRequiresClause()) {
+ ConstraintSatisfaction Satisfaction;
+ if (CheckConstraintSatisfaction(RequiresClause, Satisfaction) ||
+ !Satisfaction.IsSatisfied) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_constraints_not_satisfied;
+ return;
+ }
+ }
+
// Determine the implicit conversion sequences for each of the
// arguments.
for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) {
@@ -6866,6 +6931,12 @@ void Sema::AddMethodTemplateCandidate(
Conversions, PO);
}
+/// Determine whether a given function template has a simple explicit specifier
+/// or a non-value-dependent explicit-specification that evaluates to true.
+static bool isNonDependentlyExplicit(FunctionTemplateDecl *FTD) {
+ return ExplicitSpecifier::getFromDecl(FTD->getTemplatedDecl()).isExplicit();
+}
+
/// Add a C++ function template specialization as a candidate
/// in the candidate set, using template argument deduction to produce
/// an appropriate function template specialization.
@@ -6878,6 +6949,18 @@ void Sema::AddTemplateOverloadCandidate(
if (!CandidateSet.isNewCandidate(FunctionTemplate, PO))
return;
+ // If the function template has a non-dependent explicit specification,
+ // exclude it now if appropriate; we are not permitted to perform deduction
+ // and substitution in this case.
+ if (!AllowExplicit && isNonDependentlyExplicit(FunctionTemplate)) {
+ OverloadCandidate &Candidate = CandidateSet.addCandidate();
+ Candidate.FoundDecl = FoundDecl;
+ Candidate.Function = FunctionTemplate->getTemplatedDecl();
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_explicit;
+ return;
+ }
+
// C++ [over.match.funcs]p7:
// In each case where a candidate is a function template, candidate
// function template specializations are generated using template argument
@@ -7065,6 +7148,9 @@ void Sema::AddConversionCandidate(
// Per C++ [over.match.conv]p1, [over.match.ref]p1, an explicit conversion
// operator is only a candidate if its return type is the target type or
// can be converted to the target type with a qualification conversion.
+ //
+ // FIXME: Include such functions in the candidate list and explain why we
+ // can't select them.
if (Conversion->isExplicit() &&
!isAllowableExplicitConversion(*this, ConvType, ToType,
AllowObjCConversionOnExplicit))
@@ -7086,6 +7172,15 @@ void Sema::AddConversionCandidate(
Candidate.Viable = true;
Candidate.ExplicitCallArguments = 1;
+ // Explicit functions are not actually candidates at all if we're not
+ // allowing them in this context, but keep them around so we can point
+ // to them in diagnostics.
+ if (!AllowExplicit && Conversion->isExplicit()) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_explicit;
+ return;
+ }
+
// C++ [over.match.funcs]p4:
// For conversion functions, the function is considered to be a member of
// the class of the implicit implied object argument for the purpose of
@@ -7109,6 +7204,17 @@ void Sema::AddConversionCandidate(
return;
}
+ Expr *RequiresClause = Conversion->getTrailingRequiresClause();
+ if (RequiresClause) {
+ ConstraintSatisfaction Satisfaction;
+ if (CheckConstraintSatisfaction(RequiresClause, Satisfaction) ||
+ !Satisfaction.IsSatisfied) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_constraints_not_satisfied;
+ return;
+ }
+ }
+
// We won't go through a user-defined type conversion function to convert a
// derived to base as such conversions are given Conversion Rank. They only
// go through a copy constructor. 13.3.3.1.2-p4 [over.ics.user]
@@ -7199,13 +7305,6 @@ void Sema::AddConversionCandidate(
"Can only end up with a standard conversion sequence or failure");
}
- if (!AllowExplicit && Conversion->getExplicitSpecifier().getKind() !=
- ExplicitSpecKind::ResolvedFalse) {
- Candidate.Viable = false;
- Candidate.FailureKind = ovl_fail_explicit_resolved;
- return;
- }
-
if (EnableIfAttr *FailedAttr = CheckEnableIf(Conversion, None)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_enable_if;
@@ -7236,6 +7335,18 @@ void Sema::AddTemplateConversionCandidate(
if (!CandidateSet.isNewCandidate(FunctionTemplate))
return;
+ // If the function template has a non-dependent explicit specification,
+ // exclude it now if appropriate; we are not permitted to perform deduction
+ // and substitution in this case.
+ if (!AllowExplicit && isNonDependentlyExplicit(FunctionTemplate)) {
+ OverloadCandidate &Candidate = CandidateSet.addCandidate();
+ Candidate.FoundDecl = FoundDecl;
+ Candidate.Function = FunctionTemplate->getTemplatedDecl();
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_explicit;
+ return;
+ }
+
TemplateDeductionInfo Info(CandidateSet.getLocation());
CXXConversionDecl *Specialization = nullptr;
if (TemplateDeductionResult Result
@@ -9440,6 +9551,35 @@ bool clang::isBetterOverloadCandidate(
return BetterTemplate == Cand1.Function->getPrimaryTemplate();
}
+ // -— F1 and F2 are non-template functions with the same
+ // parameter-type-lists, and F1 is more constrained than F2 [...],
+ if (Cand1.Function && Cand2.Function && !Cand1IsSpecialization &&
+ !Cand2IsSpecialization && Cand1.Function->hasPrototype() &&
+ Cand2.Function->hasPrototype()) {
+ auto *PT1 = cast<FunctionProtoType>(Cand1.Function->getFunctionType());
+ auto *PT2 = cast<FunctionProtoType>(Cand2.Function->getFunctionType());
+ if (PT1->getNumParams() == PT2->getNumParams() &&
+ PT1->isVariadic() == PT2->isVariadic() &&
+ S.FunctionParamTypesAreEqual(PT1, PT2)) {
+ Expr *RC1 = Cand1.Function->getTrailingRequiresClause();
+ Expr *RC2 = Cand2.Function->getTrailingRequiresClause();
+ if (RC1 && RC2) {
+ bool AtLeastAsConstrained1, AtLeastAsConstrained2;
+ if (S.IsAtLeastAsConstrained(Cand1.Function, {RC1}, Cand2.Function,
+ {RC2}, AtLeastAsConstrained1))
+ return false;
+ if (!AtLeastAsConstrained1)
+ return false;
+ if (S.IsAtLeastAsConstrained(Cand2.Function, {RC2}, Cand1.Function,
+ {RC1}, AtLeastAsConstrained2))
+ return false;
+ if (!AtLeastAsConstrained2)
+ return true;
+ } else if (RC1 || RC2)
+ return RC1 != nullptr;
+ }
+ }
+
// -- F1 is a constructor for a class D, F2 is a constructor for a base
// class B of D, and for all arguments the corresponding parameters of
// F1 and F2 have the same type.
@@ -9527,8 +9667,7 @@ bool Sema::isEquivalentInternalLinkageDeclaration(const NamedDecl *A,
// entity in different modules.
if (!VA->getDeclContext()->getRedeclContext()->Equals(
VB->getDeclContext()->getRedeclContext()) ||
- getOwningModule(const_cast<ValueDecl *>(VA)) ==
- getOwningModule(const_cast<ValueDecl *>(VB)) ||
+ getOwningModule(VA) == getOwningModule(VB) ||
VA->isExternallyVisible() || VB->isExternallyVisible())
return false;
@@ -9565,12 +9704,12 @@ void Sema::diagnoseEquivalentInternalLinkageDeclarations(
SourceLocation Loc, const NamedDecl *D, ArrayRef<const NamedDecl *> Equiv) {
Diag(Loc, diag::ext_equivalent_internal_linkage_decl_in_modules) << D;
- Module *M = getOwningModule(const_cast<NamedDecl*>(D));
+ Module *M = getOwningModule(D);
Diag(D->getLocation(), diag::note_equivalent_internal_linkage_decl)
<< !M << (M ? M->getFullModuleName() : "");
for (auto *E : Equiv) {
- Module *M = getOwningModule(const_cast<NamedDecl*>(E));
+ Module *M = getOwningModule(E);
Diag(E->getLocation(), diag::note_equivalent_internal_linkage_decl)
<< !M << (M ? M->getFullModuleName() : "");
}
@@ -9622,11 +9761,13 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
// Find the best viable function.
Best = end();
- for (auto *Cand : Candidates)
+ for (auto *Cand : Candidates) {
+ Cand->Best = false;
if (Cand->Viable)
if (Best == end() ||
isBetterOverloadCandidate(S, *Cand, *Best, Loc, Kind))
Best = Cand;
+ }
// If we didn't find any viable functions, abort.
if (Best == end())
@@ -9634,22 +9775,33 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
llvm::SmallVector<const NamedDecl *, 4> EquivalentCands;
+ llvm::SmallVector<OverloadCandidate*, 4> PendingBest;
+ PendingBest.push_back(&*Best);
+ Best->Best = true;
+
// Make sure that this function is better than every other viable
// function. If not, we have an ambiguity.
- for (auto *Cand : Candidates) {
- if (Cand->Viable && Cand != Best &&
- !isBetterOverloadCandidate(S, *Best, *Cand, Loc, Kind)) {
- if (S.isEquivalentInternalLinkageDeclaration(Best->Function,
- Cand->Function)) {
- EquivalentCands.push_back(Cand->Function);
- continue;
+ while (!PendingBest.empty()) {
+ auto *Curr = PendingBest.pop_back_val();
+ for (auto *Cand : Candidates) {
+ if (Cand->Viable && !Cand->Best &&
+ !isBetterOverloadCandidate(S, *Curr, *Cand, Loc, Kind)) {
+ PendingBest.push_back(Cand);
+ Cand->Best = true;
+
+ if (S.isEquivalentInternalLinkageDeclaration(Cand->Function,
+ Curr->Function))
+ EquivalentCands.push_back(Cand->Function);
+ else
+ Best = end();
}
-
- Best = end();
- return OR_Ambiguous;
}
}
+ // If we found more than one best candidate, this is ambiguous.
+ if (Best == end())
+ return OR_Ambiguous;
+
// Best is the best viable function.
if (Best->Function && Best->Function->isDeleted())
return OR_Deleted;
@@ -9673,6 +9825,7 @@ enum OverloadCandidateKind {
oc_implicit_move_constructor,
oc_implicit_copy_assignment,
oc_implicit_move_assignment,
+ oc_implicit_equality_comparison,
oc_inherited_constructor
};
@@ -9701,6 +9854,9 @@ ClassifyOverloadCandidate(Sema &S, NamedDecl *Found, FunctionDecl *Fn,
}();
OverloadCandidateKind Kind = [&]() {
+ if (Fn->isImplicit() && Fn->getOverloadedOperator() == OO_EqualEqual)
+ return oc_implicit_equality_comparison;
+
if (CRK & CRK_Reversed)
return oc_reversed_binary_operator;
@@ -9791,6 +9947,24 @@ static bool checkAddressOfFunctionIsAvailable(Sema &S, const FunctionDecl *FD,
return false;
}
+ if (const Expr *RC = FD->getTrailingRequiresClause()) {
+ ConstraintSatisfaction Satisfaction;
+ if (S.CheckConstraintSatisfaction(RC, Satisfaction))
+ return false;
+ if (!Satisfaction.IsSatisfied) {
+ if (Complain) {
+ if (InOverloadResolution)
+ S.Diag(FD->getBeginLoc(),
+ diag::note_ovl_candidate_unsatisfied_constraints);
+ else
+ S.Diag(Loc, diag::err_addrof_function_constraints_not_satisfied)
+ << FD;
+ S.DiagnoseUnsatisfiedConstraint(Satisfaction);
+ }
+ return false;
+ }
+ }
+
auto I = llvm::find_if(FD->parameters(), [](const ParmVarDecl *P) {
return P->hasAttr<PassObjectSizeAttr>();
});
@@ -9848,6 +10022,55 @@ void Sema::NoteOverloadCandidate(NamedDecl *Found, FunctionDecl *Fn,
MaybeEmitInheritedConstructorNote(*this, Found);
}
+static void
+MaybeDiagnoseAmbiguousConstraints(Sema &S, ArrayRef<OverloadCandidate> Cands) {
+ // Perhaps the ambiguity was caused by two atomic constraints that are
+ // 'identical' but not equivalent:
+ //
+ // void foo() requires (sizeof(T) > 4) { } // #1
+ // void foo() requires (sizeof(T) > 4) && T::value { } // #2
+ //
+ // The 'sizeof(T) > 4' constraints are seemingly equivalent and should cause
+ // #2 to subsume #1, but these constraint are not considered equivalent
+ // according to the subsumption rules because they are not the same
+ // source-level construct. This behavior is quite confusing and we should try
+ // to help the user figure out what happened.
+
+ SmallVector<const Expr *, 3> FirstAC, SecondAC;
+ FunctionDecl *FirstCand = nullptr, *SecondCand = nullptr;
+ for (auto I = Cands.begin(), E = Cands.end(); I != E; ++I) {
+ if (!I->Function)
+ continue;
+ SmallVector<const Expr *, 3> AC;
+ if (auto *Template = I->Function->getPrimaryTemplate())
+ Template->getAssociatedConstraints(AC);
+ else
+ I->Function->getAssociatedConstraints(AC);
+ if (AC.empty())
+ continue;
+ if (FirstCand == nullptr) {
+ FirstCand = I->Function;
+ FirstAC = AC;
+ } else if (SecondCand == nullptr) {
+ SecondCand = I->Function;
+ SecondAC = AC;
+ } else {
+ // We have more than one pair of constrained functions - this check is
+ // expensive and we'd rather not try to diagnose it.
+ return;
+ }
+ }
+ if (!SecondCand)
+ return;
+ // The diagnostic can only happen if there are associated constraints on
+ // both sides (there needs to be some identical atomic constraint).
+ if (S.MaybeEmitAmbiguousAtomicConstraintsDiagnostic(FirstCand, FirstAC,
+ SecondCand, SecondAC))
+ // Just show the user one diagnostic, they'll probably figure it out
+ // from here.
+ return;
+}
+
// Notes the location of all overload candidates designated through
// OverloadedExpr
void Sema::NoteAllOverloadCandidates(Expr *OverloadedExpr, QualType DestType,
@@ -9916,7 +10139,7 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
std::string FnDesc;
std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair =
- ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn, Cand->RewriteKind,
+ ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn, Cand->getRewriteKind(),
FnDesc);
Expr *FromExpr = Conv.Bad.FromExpr;
@@ -9959,10 +10182,17 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
Qualifiers ToQs = CToTy.getQualifiers();
if (FromQs.getAddressSpace() != ToQs.getAddressSpace()) {
- S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_addrspace)
- << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
- << ToTy << (unsigned)isObjectArgument << I + 1;
+ if (isObjectArgument)
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_addrspace_this)
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second
+ << FnDesc << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+ << FromQs.getAddressSpace() << ToQs.getAddressSpace();
+ else
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_addrspace)
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second
+ << FnDesc << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+ << FromQs.getAddressSpace() << ToQs.getAddressSpace()
+ << ToTy->isReferenceType() << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
@@ -10167,7 +10397,7 @@ static void DiagnoseArityMismatch(Sema &S, NamedDecl *Found, Decl *D,
FunctionDecl *Fn = cast<FunctionDecl>(D);
// TODO: treat calls to a missing default constructor as a special case
- const FunctionProtoType *FnTy = Fn->getType()->getAs<FunctionProtoType>();
+ const auto *FnTy = Fn->getType()->castAs<FunctionProtoType>();
unsigned MinParams = Fn->getMinRequiredArguments();
// at least / at most / exactly
@@ -10303,6 +10533,16 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
which = 2;
}
+ // Tweak the diagnostic if the problem is that we deduced packs of
+ // different arities. We'll print the actual packs anyway in case that
+ // includes additional useful information.
+ if (DeductionFailure.getFirstArg()->getKind() == TemplateArgument::Pack &&
+ DeductionFailure.getSecondArg()->getKind() == TemplateArgument::Pack &&
+ DeductionFailure.getFirstArg()->pack_size() !=
+ DeductionFailure.getSecondArg()->pack_size()) {
+ which = 3;
+ }
+
S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_inconsistent_deduction)
<< which << ParamD->getDeclName() << *DeductionFailure.getFirstArg()
@@ -10333,6 +10573,23 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
MaybeEmitInheritedConstructorNote(S, Found);
return;
+ case Sema::TDK_ConstraintsNotSatisfied: {
+ // Format the template argument list into the argument string.
+ SmallString<128> TemplateArgString;
+ TemplateArgumentList *Args = DeductionFailure.getTemplateArgumentList();
+ TemplateArgString = " ";
+ TemplateArgString += S.getTemplateArgumentBindingsText(
+ getDescribedTemplate(Templated)->getTemplateParameters(), *Args);
+ if (TemplateArgString.size() == 1)
+ TemplateArgString.clear();
+ S.Diag(Templated->getLocation(),
+ diag::note_ovl_candidate_unsatisfied_constraints)
+ << TemplateArgString;
+
+ S.DiagnoseUnsatisfiedConstraint(
+ static_cast<CNSInfo*>(DeductionFailure.Data)->Satisfaction);
+ return;
+ }
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
DiagnoseArityMismatch(S, Found, Templated, NumArgs);
@@ -10352,6 +10609,8 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
TemplateArgString = " ";
TemplateArgString += S.getTemplateArgumentBindingsText(
getDescribedTemplate(Templated)->getTemplateParameters(), *Args);
+ if (TemplateArgString.size() == 1)
+ TemplateArgString.clear();
}
// If this candidate was disabled by enable_if, say so.
@@ -10401,6 +10660,8 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
TemplateArgString = " ";
TemplateArgString += S.getTemplateArgumentBindingsText(
getDescribedTemplate(Templated)->getTemplateParameters(), *Args);
+ if (TemplateArgString.size() == 1)
+ TemplateArgString.clear();
}
S.Diag(Templated->getLocation(), diag::note_ovl_candidate_deduced_mismatch)
@@ -10486,8 +10747,8 @@ static void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) {
std::string FnDesc;
std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair =
- ClassifyOverloadCandidate(S, Cand->FoundDecl, Callee, Cand->RewriteKind,
- FnDesc);
+ ClassifyOverloadCandidate(S, Cand->FoundDecl, Callee,
+ Cand->getRewriteKind(), FnDesc);
S.Diag(Callee->getLocation(), diag::note_ovl_candidate_bad_target)
<< (unsigned)FnKindPair.first << (unsigned)ocs_non_template
@@ -10545,30 +10806,36 @@ static void DiagnoseFailedEnableIfAttr(Sema &S, OverloadCandidate *Cand) {
}
static void DiagnoseFailedExplicitSpec(Sema &S, OverloadCandidate *Cand) {
- ExplicitSpecifier ES;
- const char *DeclName;
+ ExplicitSpecifier ES = ExplicitSpecifier::getFromDecl(Cand->Function);
+ assert(ES.isExplicit() && "not an explicit candidate");
+
+ unsigned Kind;
switch (Cand->Function->getDeclKind()) {
case Decl::Kind::CXXConstructor:
- ES = cast<CXXConstructorDecl>(Cand->Function)->getExplicitSpecifier();
- DeclName = "constructor";
+ Kind = 0;
break;
case Decl::Kind::CXXConversion:
- ES = cast<CXXConversionDecl>(Cand->Function)->getExplicitSpecifier();
- DeclName = "conversion operator";
+ Kind = 1;
break;
case Decl::Kind::CXXDeductionGuide:
- ES = cast<CXXDeductionGuideDecl>(Cand->Function)->getExplicitSpecifier();
- DeclName = "deductiong guide";
+ Kind = Cand->Function->isImplicit() ? 0 : 2;
break;
default:
llvm_unreachable("invalid Decl");
}
- assert(ES.getExpr() && "null expression should be handled before");
- S.Diag(Cand->Function->getLocation(),
- diag::note_ovl_candidate_explicit_forbidden)
- << DeclName;
- S.Diag(ES.getExpr()->getBeginLoc(),
- diag::note_explicit_bool_resolved_to_true);
+
+ // Note the location of the first (in-class) declaration; a redeclaration
+ // (particularly an out-of-class definition) will typically lack the
+ // 'explicit' specifier.
+ // FIXME: This is probably a good thing to do for all 'candidate' notes.
+ FunctionDecl *First = Cand->Function->getFirstDecl();
+ if (FunctionDecl *Pattern = First->getTemplateInstantiationPattern())
+ First = Pattern->getFirstDecl();
+
+ S.Diag(First->getLocation(),
+ diag::note_ovl_candidate_explicit)
+ << Kind << (ES.getExpr() ? 1 : 0)
+ << (ES.getExpr() ? ES.getExpr()->getSourceRange() : SourceRange());
}
static void DiagnoseOpenCLExtensionDisabled(Sema &S, OverloadCandidate *Cand) {
@@ -10605,8 +10872,8 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
if (Fn->isDeleted()) {
std::string FnDesc;
std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair =
- ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn, Cand->RewriteKind,
- FnDesc);
+ ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn,
+ Cand->getRewriteKind(), FnDesc);
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_deleted)
<< (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
@@ -10616,7 +10883,7 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
}
// We don't really have anything else to say about viable candidates.
- S.NoteOverloadCandidate(Cand->FoundDecl, Fn, Cand->RewriteKind);
+ S.NoteOverloadCandidate(Cand->FoundDecl, Fn, Cand->getRewriteKind());
return;
}
@@ -10649,7 +10916,7 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
case ovl_fail_trivial_conversion:
case ovl_fail_bad_final_conversion:
case ovl_fail_final_conversion_not_exact:
- return S.NoteOverloadCandidate(Cand->FoundDecl, Fn, Cand->RewriteKind);
+ return S.NoteOverloadCandidate(Cand->FoundDecl, Fn, Cand->getRewriteKind());
case ovl_fail_bad_conversion: {
unsigned I = (Cand->IgnoreObjectArgument ? 1 : 0);
@@ -10660,7 +10927,7 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
// FIXME: this currently happens when we're called from SemaInit
// when user-conversion overload fails. Figure out how to handle
// those conditions and diagnose them well.
- return S.NoteOverloadCandidate(Cand->FoundDecl, Fn, Cand->RewriteKind);
+ return S.NoteOverloadCandidate(Cand->FoundDecl, Fn, Cand->getRewriteKind());
}
case ovl_fail_bad_target:
@@ -10669,7 +10936,7 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
case ovl_fail_enable_if:
return DiagnoseFailedEnableIfAttr(S, Cand);
- case ovl_fail_explicit_resolved:
+ case ovl_fail_explicit:
return DiagnoseFailedExplicitSpec(S, Cand);
case ovl_fail_ext_disabled:
@@ -10695,6 +10962,23 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
case ovl_non_default_multiversion_function:
// Do nothing, these should simply be ignored.
break;
+
+ case ovl_fail_constraints_not_satisfied: {
+ std::string FnDesc;
+ std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair =
+ ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn,
+ Cand->getRewriteKind(), FnDesc);
+
+ S.Diag(Fn->getLocation(),
+ diag::note_ovl_candidate_constraints_not_satisfied)
+ << (unsigned)FnKindPair.first << (unsigned)ocs_non_template
+ << FnDesc /* Ignored */;
+ ConstraintSatisfaction Satisfaction;
+ if (S.CheckConstraintSatisfaction(Fn->getTrailingRequiresClause(),
+ Satisfaction))
+ break;
+ S.DiagnoseUnsatisfiedConstraint(Satisfaction);
+ }
}
}
@@ -10785,6 +11069,7 @@ static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) {
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_DeducedMismatch:
+ case Sema::TDK_ConstraintsNotSatisfied:
case Sema::TDK_DeducedMismatchNested:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_MiscellaneousDeductionFailure:
@@ -10816,6 +11101,23 @@ struct CompareOverloadCandidatesForDisplay {
OverloadCandidateSet::CandidateSetKind CSK)
: S(S), NumArgs(NArgs), CSK(CSK) {}
+ OverloadFailureKind EffectiveFailureKind(const OverloadCandidate *C) const {
+ // If there are too many or too few arguments, that's the high-order bit we
+ // want to sort by, even if the immediate failure kind was something else.
+ if (C->FailureKind == ovl_fail_too_many_arguments ||
+ C->FailureKind == ovl_fail_too_few_arguments)
+ return static_cast<OverloadFailureKind>(C->FailureKind);
+
+ if (C->Function) {
+ if (NumArgs > C->Function->getNumParams() && !C->Function->isVariadic())
+ return ovl_fail_too_many_arguments;
+ if (NumArgs < C->Function->getMinRequiredArguments())
+ return ovl_fail_too_few_arguments;
+ }
+
+ return static_cast<OverloadFailureKind>(C->FailureKind);
+ }
+
bool operator()(const OverloadCandidate *L,
const OverloadCandidate *R) {
// Fast-path this check.
@@ -10839,34 +11141,37 @@ struct CompareOverloadCandidatesForDisplay {
// Criteria by which we can sort non-viable candidates:
if (!L->Viable) {
+ OverloadFailureKind LFailureKind = EffectiveFailureKind(L);
+ OverloadFailureKind RFailureKind = EffectiveFailureKind(R);
+
// 1. Arity mismatches come after other candidates.
- if (L->FailureKind == ovl_fail_too_many_arguments ||
- L->FailureKind == ovl_fail_too_few_arguments) {
- if (R->FailureKind == ovl_fail_too_many_arguments ||
- R->FailureKind == ovl_fail_too_few_arguments) {
+ if (LFailureKind == ovl_fail_too_many_arguments ||
+ LFailureKind == ovl_fail_too_few_arguments) {
+ if (RFailureKind == ovl_fail_too_many_arguments ||
+ RFailureKind == ovl_fail_too_few_arguments) {
int LDist = std::abs((int)L->getNumParams() - (int)NumArgs);
int RDist = std::abs((int)R->getNumParams() - (int)NumArgs);
if (LDist == RDist) {
- if (L->FailureKind == R->FailureKind)
+ if (LFailureKind == RFailureKind)
// Sort non-surrogates before surrogates.
return !L->IsSurrogate && R->IsSurrogate;
// Sort candidates requiring fewer parameters than there were
// arguments given after candidates requiring more parameters
// than there were arguments given.
- return L->FailureKind == ovl_fail_too_many_arguments;
+ return LFailureKind == ovl_fail_too_many_arguments;
}
return LDist < RDist;
}
return false;
}
- if (R->FailureKind == ovl_fail_too_many_arguments ||
- R->FailureKind == ovl_fail_too_few_arguments)
+ if (RFailureKind == ovl_fail_too_many_arguments ||
+ RFailureKind == ovl_fail_too_few_arguments)
return true;
// 2. Bad conversions come first and are ordered by the number
// of bad conversions and quality of good conversions.
- if (L->FailureKind == ovl_fail_bad_conversion) {
- if (R->FailureKind != ovl_fail_bad_conversion)
+ if (LFailureKind == ovl_fail_bad_conversion) {
+ if (RFailureKind != ovl_fail_bad_conversion)
return true;
// The conversion that can be fixed with a smaller number of changes,
@@ -10904,17 +11209,17 @@ struct CompareOverloadCandidatesForDisplay {
if (leftBetter > 0) return true;
if (leftBetter < 0) return false;
- } else if (R->FailureKind == ovl_fail_bad_conversion)
+ } else if (RFailureKind == ovl_fail_bad_conversion)
return false;
- if (L->FailureKind == ovl_fail_bad_deduction) {
- if (R->FailureKind != ovl_fail_bad_deduction)
+ if (LFailureKind == ovl_fail_bad_deduction) {
+ if (RFailureKind != ovl_fail_bad_deduction)
return true;
if (L->DeductionFailure.Result != R->DeductionFailure.Result)
return RankDeductionFailure(L->DeductionFailure)
< RankDeductionFailure(R->DeductionFailure);
- } else if (R->FailureKind == ovl_fail_bad_deduction)
+ } else if (RFailureKind == ovl_fail_bad_deduction)
return false;
// TODO: others?
@@ -10943,7 +11248,8 @@ CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
assert(!Cand->Viable);
// Don't do anything on failures other than bad conversion.
- if (Cand->FailureKind != ovl_fail_bad_conversion) return;
+ if (Cand->FailureKind != ovl_fail_bad_conversion)
+ return;
// We only want the FixIts if all the arguments can be corrected.
bool Unfixable = false;
@@ -10969,6 +11275,7 @@ CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
unsigned ConvIdx = 0;
unsigned ArgIdx = 0;
ArrayRef<QualType> ParamTypes;
+ bool Reversed = Cand->RewriteKind & CRK_Reversed;
if (Cand->IsSurrogate) {
QualType ConvType
@@ -10982,10 +11289,11 @@ CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
ParamTypes =
Cand->Function->getType()->castAs<FunctionProtoType>()->getParamTypes();
if (isa<CXXMethodDecl>(Cand->Function) &&
- !isa<CXXConstructorDecl>(Cand->Function)) {
+ !isa<CXXConstructorDecl>(Cand->Function) && !Reversed) {
// Conversion 0 is 'this', which doesn't have a corresponding parameter.
ConvIdx = 1;
- if (CSK == OverloadCandidateSet::CSK_Operator)
+ if (CSK == OverloadCandidateSet::CSK_Operator &&
+ Cand->Function->getDeclName().getCXXOverloadedOperator() != OO_Call)
// Argument 0 is 'this', which doesn't have a corresponding parameter.
ArgIdx = 1;
}
@@ -10996,13 +11304,13 @@ CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
}
// Fill in the rest of the conversions.
- bool Reversed = Cand->RewriteKind & CRK_Reversed;
for (unsigned ParamIdx = Reversed ? ParamTypes.size() - 1 : 0;
ConvIdx != ConvCount;
++ConvIdx, ++ArgIdx, ParamIdx += (Reversed ? -1 : 1)) {
+ assert(ArgIdx < Args.size() && "no argument for this arg conversion");
if (Cand->Conversions[ConvIdx].isInitialized()) {
// We've already checked this conversion.
- } else if (ArgIdx < ParamTypes.size()) {
+ } else if (ParamIdx < ParamTypes.size()) {
if (ParamTypes[ParamIdx]->isDependentType())
Cand->Conversions[ConvIdx].setAsIdentityConversion(
Args[ArgIdx]->getType());
@@ -11033,15 +11341,30 @@ SmallVector<OverloadCandidate *, 32> OverloadCandidateSet::CompleteCandidates(
for (iterator Cand = begin(), LastCand = end(); Cand != LastCand; ++Cand) {
if (!Filter(*Cand))
continue;
- if (Cand->Viable)
- Cands.push_back(Cand);
- else if (OCD == OCD_AllCandidates) {
- CompleteNonViableCandidate(S, Cand, Args, Kind);
- if (Cand->Function || Cand->IsSurrogate)
- Cands.push_back(Cand);
- // Otherwise, this a non-viable builtin candidate. We do not, in general,
- // want to list every possible builtin candidate.
+ switch (OCD) {
+ case OCD_AllCandidates:
+ if (!Cand->Viable) {
+ if (!Cand->Function && !Cand->IsSurrogate) {
+ // This a non-viable builtin candidate. We do not, in general,
+ // want to list every possible builtin candidate.
+ continue;
+ }
+ CompleteNonViableCandidate(S, Cand, Args, Kind);
+ }
+ break;
+
+ case OCD_ViableCandidates:
+ if (!Cand->Viable)
+ continue;
+ break;
+
+ case OCD_AmbiguousCandidates:
+ if (!Cand->Best)
+ continue;
+ break;
}
+
+ Cands.push_back(Cand);
}
llvm::stable_sort(
@@ -11062,6 +11385,9 @@ void OverloadCandidateSet::NoteCandidates(PartialDiagnosticAt PD,
S.Diag(PD.first, PD.second);
NoteCandidates(S, Args, Cands, Opc, OpLoc);
+
+ if (OCD == OCD_AmbiguousCandidates)
+ MaybeDiagnoseAmbiguousConstraints(S, {begin(), end()});
}
void OverloadCandidateSet::NoteCandidates(Sema &S, ArrayRef<Expr *> Args,
@@ -11710,15 +12036,33 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr,
/// resolve that function to a single function that can have its address taken.
/// This will modify `Pair` iff it returns non-null.
///
-/// This routine can only realistically succeed if all but one candidates in the
-/// overload set for SrcExpr cannot have their addresses taken.
+/// This routine can only succeed if from all of the candidates in the overload
+/// set for SrcExpr that can have their addresses taken, there is one candidate
+/// that is more constrained than the rest.
FunctionDecl *
-Sema::resolveAddressOfOnlyViableOverloadCandidate(Expr *E,
- DeclAccessPair &Pair) {
+Sema::resolveAddressOfSingleOverloadCandidate(Expr *E, DeclAccessPair &Pair) {
OverloadExpr::FindResult R = OverloadExpr::find(E);
OverloadExpr *Ovl = R.Expression;
+ bool IsResultAmbiguous = false;
FunctionDecl *Result = nullptr;
DeclAccessPair DAP;
+ SmallVector<FunctionDecl *, 2> AmbiguousDecls;
+
+ auto CheckMoreConstrained =
+ [&] (FunctionDecl *FD1, FunctionDecl *FD2) -> Optional<bool> {
+ SmallVector<const Expr *, 1> AC1, AC2;
+ FD1->getAssociatedConstraints(AC1);
+ FD2->getAssociatedConstraints(AC2);
+ bool AtLeastAsConstrained1, AtLeastAsConstrained2;
+ if (IsAtLeastAsConstrained(FD1, AC1, FD2, AC2, AtLeastAsConstrained1))
+ return None;
+ if (IsAtLeastAsConstrained(FD2, AC2, FD1, AC1, AtLeastAsConstrained2))
+ return None;
+ if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
+ return None;
+ return AtLeastAsConstrained1;
+ };
+
// Don't use the AddressOfResolver because we're specifically looking for
// cases where we have one overload candidate that lacks
// enable_if/pass_object_size/...
@@ -11730,32 +12074,54 @@ Sema::resolveAddressOfOnlyViableOverloadCandidate(Expr *E,
if (!checkAddressOfFunctionIsAvailable(FD))
continue;
- // We have more than one result; quit.
- if (Result)
- return nullptr;
+ // We have more than one result - see if it is more constrained than the
+ // previous one.
+ if (Result) {
+ Optional<bool> MoreConstrainedThanPrevious = CheckMoreConstrained(FD,
+ Result);
+ if (!MoreConstrainedThanPrevious) {
+ IsResultAmbiguous = true;
+ AmbiguousDecls.push_back(FD);
+ continue;
+ }
+ if (!*MoreConstrainedThanPrevious)
+ continue;
+ // FD is more constrained - replace Result with it.
+ }
+ IsResultAmbiguous = false;
DAP = I.getPair();
Result = FD;
}
- if (Result)
+ if (IsResultAmbiguous)
+ return nullptr;
+
+ if (Result) {
+ SmallVector<const Expr *, 1> ResultAC;
+ // We skipped over some ambiguous declarations which might be ambiguous with
+ // the selected result.
+ for (FunctionDecl *Skipped : AmbiguousDecls)
+ if (!CheckMoreConstrained(Skipped, Result).hasValue())
+ return nullptr;
Pair = DAP;
+ }
return Result;
}
/// Given an overloaded function, tries to turn it into a non-overloaded
-/// function reference using resolveAddressOfOnlyViableOverloadCandidate. This
+/// function reference using resolveAddressOfSingleOverloadCandidate. This
/// will perform access checks, diagnose the use of the resultant decl, and, if
/// requested, potentially perform a function-to-pointer decay.
///
-/// Returns false if resolveAddressOfOnlyViableOverloadCandidate fails.
+/// Returns false if resolveAddressOfSingleOverloadCandidate fails.
/// Otherwise, returns true. This may emit diagnostics and return true.
-bool Sema::resolveAndFixAddressOfOnlyViableOverloadCandidate(
+bool Sema::resolveAndFixAddressOfSingleOverloadCandidate(
ExprResult &SrcExpr, bool DoFunctionPointerConverion) {
Expr *E = SrcExpr.get();
assert(E->getType() == Context.OverloadTy && "SrcExpr must be an overload");
DeclAccessPair DAP;
- FunctionDecl *Found = resolveAddressOfOnlyViableOverloadCandidate(E, DAP);
+ FunctionDecl *Found = resolveAddressOfSingleOverloadCandidate(E, DAP);
if (!Found || Found->isCPUDispatchMultiVersion() ||
Found->isCPUSpecificMultiVersion())
return false;
@@ -12406,7 +12772,7 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
PartialDiagnosticAt(Fn->getBeginLoc(),
SemaRef.PDiag(diag::err_ovl_ambiguous_call)
<< ULE->getName() << Fn->getSourceRange()),
- SemaRef, OCD_ViableCandidates, Args);
+ SemaRef, OCD_AmbiguousCandidates, Args);
break;
case OR_Deleted: {
@@ -12652,7 +13018,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
PDiag(diag::err_ovl_ambiguous_oper_unary)
<< UnaryOperator::getOpcodeStr(Opc)
<< Input->getType() << Input->getSourceRange()),
- *this, OCD_ViableCandidates, ArgsArray,
+ *this, OCD_AmbiguousCandidates, ArgsArray,
UnaryOperator::getOpcodeStr(Opc), OpLoc);
return ExprError();
@@ -12672,6 +13038,70 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
return CreateBuiltinUnaryOp(OpLoc, Opc, Input);
}
+/// Perform lookup for an overloaded binary operator.
+void Sema::LookupOverloadedBinOp(OverloadCandidateSet &CandidateSet,
+ OverloadedOperatorKind Op,
+ const UnresolvedSetImpl &Fns,
+ ArrayRef<Expr *> Args, bool PerformADL) {
+ SourceLocation OpLoc = CandidateSet.getLocation();
+
+ OverloadedOperatorKind ExtraOp =
+ CandidateSet.getRewriteInfo().AllowRewrittenCandidates
+ ? getRewrittenOverloadedOperator(Op)
+ : OO_None;
+
+ // Add the candidates from the given function set. This also adds the
+ // rewritten candidates using these functions if necessary.
+ AddNonMemberOperatorCandidates(Fns, Args, CandidateSet);
+
+ // Add operator candidates that are member functions.
+ AddMemberOperatorCandidates(Op, OpLoc, Args, CandidateSet);
+ if (CandidateSet.getRewriteInfo().shouldAddReversed(Op))
+ AddMemberOperatorCandidates(Op, OpLoc, {Args[1], Args[0]}, CandidateSet,
+ OverloadCandidateParamOrder::Reversed);
+
+ // In C++20, also add any rewritten member candidates.
+ if (ExtraOp) {
+ AddMemberOperatorCandidates(ExtraOp, OpLoc, Args, CandidateSet);
+ if (CandidateSet.getRewriteInfo().shouldAddReversed(ExtraOp))
+ AddMemberOperatorCandidates(ExtraOp, OpLoc, {Args[1], Args[0]},
+ CandidateSet,
+ OverloadCandidateParamOrder::Reversed);
+ }
+
+ // Add candidates from ADL. Per [over.match.oper]p2, this lookup is not
+ // performed for an assignment operator (nor for operator[] nor operator->,
+ // which don't get here).
+ if (Op != OO_Equal && PerformADL) {
+ DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
+ AddArgumentDependentLookupCandidates(OpName, OpLoc, Args,
+ /*ExplicitTemplateArgs*/ nullptr,
+ CandidateSet);
+ if (ExtraOp) {
+ DeclarationName ExtraOpName =
+ Context.DeclarationNames.getCXXOperatorName(ExtraOp);
+ AddArgumentDependentLookupCandidates(ExtraOpName, OpLoc, Args,
+ /*ExplicitTemplateArgs*/ nullptr,
+ CandidateSet);
+ }
+ }
+
+ // Add builtin operator candidates.
+ //
+ // FIXME: We don't add any rewritten candidates here. This is strictly
+ // incorrect; a builtin candidate could be hidden by a non-viable candidate,
+ // resulting in our selecting a rewritten builtin candidate. For example:
+ //
+ // enum class E { e };
+ // bool operator!=(E, E) requires false;
+ // bool k = E::e != E::e;
+ //
+ // ... should select the rewritten builtin candidate 'operator==(E, E)'. But
+ // it seems unreasonable to consider rewritten builtin candidates. A core
+ // issue has been filed proposing to removed this requirement.
+ AddBuiltinOperatorCandidates(Op, OpLoc, Args, CandidateSet);
+}
+
/// Create a binary operation that may resolve to an overloaded
/// operator.
///
@@ -12688,11 +13118,19 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
///
/// \param LHS Left-hand argument.
/// \param RHS Right-hand argument.
+/// \param PerformADL Whether to consider operator candidates found by ADL.
+/// \param AllowRewrittenCandidates Whether to consider candidates found by
+/// C++20 operator rewrites.
+/// \param DefaultedFn If we are synthesizing a defaulted operator function,
+/// the function in question. Such a function is never a candidate in
+/// our overload resolution. This also enables synthesizing a three-way
+/// comparison from < and == as described in C++20 [class.spaceship]p1.
ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
BinaryOperatorKind Opc,
const UnresolvedSetImpl &Fns, Expr *LHS,
Expr *RHS, bool PerformADL,
- bool AllowRewrittenCandidates) {
+ bool AllowRewrittenCandidates,
+ FunctionDecl *DefaultedFn) {
Expr *Args[2] = { LHS, RHS };
LHS=RHS=nullptr; // Please use only Args instead of LHS/RHS couple
@@ -12700,7 +13138,6 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
AllowRewrittenCandidates = false;
OverloadedOperatorKind Op = BinaryOperator::getOverloadedOperator(Opc);
- DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
// If either side is type-dependent, create an appropriate dependent
// expression.
@@ -12722,6 +13159,7 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// FIXME: save results of ADL from here?
CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators
// TODO: provide better source location info in DNLoc component.
+ DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
DeclarationNameInfo OpNameInfo(OpName, OpLoc);
UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create(
Context, NamingClass, NestedNameSpecifierLoc(), OpNameInfo,
@@ -12755,63 +13193,13 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
if (Opc == BO_PtrMemD)
return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
- // Build an empty overload set.
+ // Build the overload set.
OverloadCandidateSet CandidateSet(
OpLoc, OverloadCandidateSet::CSK_Operator,
OverloadCandidateSet::OperatorRewriteInfo(Op, AllowRewrittenCandidates));
-
- OverloadedOperatorKind ExtraOp =
- AllowRewrittenCandidates ? getRewrittenOverloadedOperator(Op) : OO_None;
-
- // Add the candidates from the given function set. This also adds the
- // rewritten candidates using these functions if necessary.
- AddNonMemberOperatorCandidates(Fns, Args, CandidateSet);
-
- // Add operator candidates that are member functions.
- AddMemberOperatorCandidates(Op, OpLoc, Args, CandidateSet);
- if (CandidateSet.getRewriteInfo().shouldAddReversed(Op))
- AddMemberOperatorCandidates(Op, OpLoc, {Args[1], Args[0]}, CandidateSet,
- OverloadCandidateParamOrder::Reversed);
-
- // In C++20, also add any rewritten member candidates.
- if (ExtraOp) {
- AddMemberOperatorCandidates(ExtraOp, OpLoc, Args, CandidateSet);
- if (CandidateSet.getRewriteInfo().shouldAddReversed(ExtraOp))
- AddMemberOperatorCandidates(ExtraOp, OpLoc, {Args[1], Args[0]},
- CandidateSet,
- OverloadCandidateParamOrder::Reversed);
- }
-
- // Add candidates from ADL. Per [over.match.oper]p2, this lookup is not
- // performed for an assignment operator (nor for operator[] nor operator->,
- // which don't get here).
- if (Opc != BO_Assign && PerformADL) {
- AddArgumentDependentLookupCandidates(OpName, OpLoc, Args,
- /*ExplicitTemplateArgs*/ nullptr,
- CandidateSet);
- if (ExtraOp) {
- DeclarationName ExtraOpName =
- Context.DeclarationNames.getCXXOperatorName(ExtraOp);
- AddArgumentDependentLookupCandidates(ExtraOpName, OpLoc, Args,
- /*ExplicitTemplateArgs*/ nullptr,
- CandidateSet);
- }
- }
-
- // Add builtin operator candidates.
- //
- // FIXME: We don't add any rewritten candidates here. This is strictly
- // incorrect; a builtin candidate could be hidden by a non-viable candidate,
- // resulting in our selecting a rewritten builtin candidate. For example:
- //
- // enum class E { e };
- // bool operator!=(E, E) requires false;
- // bool k = E::e != E::e;
- //
- // ... should select the rewritten builtin candidate 'operator==(E, E)'. But
- // it seems unreasonable to consider rewritten builtin candidates. A core
- // issue has been filed proposing to removed this requirement.
- AddBuiltinOperatorCandidates(Op, OpLoc, Args, CandidateSet);
+ if (DefaultedFn)
+ CandidateSet.exclude(DefaultedFn);
+ LookupOverloadedBinOp(CandidateSet, Op, Fns, Args, PerformADL);
bool HadMultipleCandidates = (CandidateSet.size() > 1);
@@ -13018,6 +13406,15 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
if (Opc == BO_Comma)
break;
+ // When defaulting an 'operator<=>', we can try to synthesize a three-way
+ // compare result using '==' and '<'.
+ if (DefaultedFn && Opc == BO_Cmp) {
+ ExprResult E = BuildSynthesizedThreeWayComparison(OpLoc, Fns, Args[0],
+ Args[1], DefaultedFn);
+ if (E.isInvalid() || E.isUsable())
+ return E;
+ }
+
// For class as left operand for assignment or compound assignment
// operator do not fall through to handling in built-in, but report that
// no overloaded assignment operator found
@@ -13061,20 +13458,26 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
<< Args[1]->getType()
<< Args[0]->getSourceRange()
<< Args[1]->getSourceRange()),
- *this, OCD_ViableCandidates, Args, BinaryOperator::getOpcodeStr(Opc),
+ *this, OCD_AmbiguousCandidates, Args, BinaryOperator::getOpcodeStr(Opc),
OpLoc);
return ExprError();
case OR_Deleted:
if (isImplicitlyDeleted(Best->Function)) {
- CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function);
- Diag(OpLoc, diag::err_ovl_deleted_special_oper)
- << Context.getRecordType(Method->getParent())
- << getSpecialMember(Method);
+ FunctionDecl *DeletedFD = Best->Function;
+ DefaultedFunctionKind DFK = getDefaultedFunctionKind(DeletedFD);
+ if (DFK.isSpecialMember()) {
+ Diag(OpLoc, diag::err_ovl_deleted_special_oper)
+ << Args[0]->getType() << DFK.asSpecialMember();
+ } else {
+ assert(DFK.isComparison());
+ Diag(OpLoc, diag::err_ovl_deleted_comparison)
+ << Args[0]->getType() << DeletedFD;
+ }
// The user probably meant to call this special member. Just
// explain why it's deleted.
- NoteDeletedFunction(Method);
+ NoteDeletedFunction(DeletedFD);
return ExprError();
}
CandidateSet.NoteCandidates(
@@ -13093,6 +13496,98 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
}
+ExprResult Sema::BuildSynthesizedThreeWayComparison(
+ SourceLocation OpLoc, const UnresolvedSetImpl &Fns, Expr *LHS, Expr *RHS,
+ FunctionDecl *DefaultedFn) {
+ const ComparisonCategoryInfo *Info =
+ Context.CompCategories.lookupInfoForType(DefaultedFn->getReturnType());
+ // If we're not producing a known comparison category type, we can't
+ // synthesize a three-way comparison. Let the caller diagnose this.
+ if (!Info)
+ return ExprResult((Expr*)nullptr);
+
+ // If we ever want to perform this synthesis more generally, we will need to
+ // apply the temporary materialization conversion to the operands.
+ assert(LHS->isGLValue() && RHS->isGLValue() &&
+ "cannot use prvalue expressions more than once");
+ Expr *OrigLHS = LHS;
+ Expr *OrigRHS = RHS;
+
+ // Replace the LHS and RHS with OpaqueValueExprs; we're going to refer to
+ // each of them multiple times below.
+ LHS = new (Context)
+ OpaqueValueExpr(LHS->getExprLoc(), LHS->getType(), LHS->getValueKind(),
+ LHS->getObjectKind(), LHS);
+ RHS = new (Context)
+ OpaqueValueExpr(RHS->getExprLoc(), RHS->getType(), RHS->getValueKind(),
+ RHS->getObjectKind(), RHS);
+
+ ExprResult Eq = CreateOverloadedBinOp(OpLoc, BO_EQ, Fns, LHS, RHS, true, true,
+ DefaultedFn);
+ if (Eq.isInvalid())
+ return ExprError();
+
+ ExprResult Less = CreateOverloadedBinOp(OpLoc, BO_LT, Fns, LHS, RHS, true,
+ true, DefaultedFn);
+ if (Less.isInvalid())
+ return ExprError();
+
+ ExprResult Greater;
+ if (Info->isPartial()) {
+ Greater = CreateOverloadedBinOp(OpLoc, BO_LT, Fns, RHS, LHS, true, true,
+ DefaultedFn);
+ if (Greater.isInvalid())
+ return ExprError();
+ }
+
+ // Form the list of comparisons we're going to perform.
+ struct Comparison {
+ ExprResult Cmp;
+ ComparisonCategoryResult Result;
+ } Comparisons[4] =
+ { {Eq, Info->isStrong() ? ComparisonCategoryResult::Equal
+ : ComparisonCategoryResult::Equivalent},
+ {Less, ComparisonCategoryResult::Less},
+ {Greater, ComparisonCategoryResult::Greater},
+ {ExprResult(), ComparisonCategoryResult::Unordered},
+ };
+
+ int I = Info->isPartial() ? 3 : 2;
+
+ // Combine the comparisons with suitable conditional expressions.
+ ExprResult Result;
+ for (; I >= 0; --I) {
+ // Build a reference to the comparison category constant.
+ auto *VI = Info->lookupValueInfo(Comparisons[I].Result);
+ // FIXME: Missing a constant for a comparison category. Diagnose this?
+ if (!VI)
+ return ExprResult((Expr*)nullptr);
+ ExprResult ThisResult =
+ BuildDeclarationNameExpr(CXXScopeSpec(), DeclarationNameInfo(), VI->VD);
+ if (ThisResult.isInvalid())
+ return ExprError();
+
+ // Build a conditional unless this is the final case.
+ if (Result.get()) {
+ Result = ActOnConditionalOp(OpLoc, OpLoc, Comparisons[I].Cmp.get(),
+ ThisResult.get(), Result.get());
+ if (Result.isInvalid())
+ return ExprError();
+ } else {
+ Result = ThisResult;
+ }
+ }
+
+ // Build a PseudoObjectExpr to model the rewriting of an <=> operator, and to
+ // bind the OpaqueValueExprs before they're (repeatedly) used.
+ Expr *SyntacticForm = new (Context)
+ BinaryOperator(OrigLHS, OrigRHS, BO_Cmp, Result.get()->getType(),
+ Result.get()->getValueKind(),
+ Result.get()->getObjectKind(), OpLoc, FPFeatures);
+ Expr *SemanticForm[] = {LHS, RHS, Result.get()};
+ return PseudoObjectExpr::Create(Context, SyntacticForm, SemanticForm, 2);
+}
+
ExprResult
Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
SourceLocation RLoc,
@@ -13246,7 +13741,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
<< Args[1]->getType()
<< Args[0]->getSourceRange()
<< Args[1]->getSourceRange()),
- *this, OCD_ViableCandidates, Args, "[]", LLoc);
+ *this, OCD_AmbiguousCandidates, Args, "[]", LLoc);
return ExprError();
case OR_Deleted:
@@ -13438,7 +13933,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
PartialDiagnosticAt(UnresExpr->getMemberLoc(),
PDiag(diag::err_ovl_ambiguous_member_call)
<< DeclName << MemExprE->getSourceRange()),
- *this, OCD_AllCandidates, Args);
+ *this, OCD_AmbiguousCandidates, Args);
// FIXME: Leaking incoming expressions!
return ExprError();
@@ -13469,7 +13964,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
ResultType = ResultType.getNonLValueExprType(Context);
assert(Method && "Member call to something that isn't a method?");
- const auto *Proto = Method->getType()->getAs<FunctionProtoType>();
+ const auto *Proto = Method->getType()->castAs<FunctionProtoType>();
CXXMemberCallExpr *TheCall =
CXXMemberCallExpr::Create(Context, MemExprE, Args, ResultType, VK,
RParenLoc, Proto->getNumParams());
@@ -13566,7 +14061,6 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
assert(Object.get()->getType()->isRecordType() &&
"Requires object type argument");
- const RecordType *Record = Object.get()->getType()->getAs<RecordType>();
// C++ [over.call.object]p1:
// If the primary-expression E in the function call syntax
@@ -13583,6 +14077,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
diag::err_incomplete_object_call, Object.get()))
return true;
+ const auto *Record = Object.get()->getType()->castAs<RecordType>();
LookupResult R(*this, OpName, LParenLoc, LookupOrdinaryName);
LookupQualifiedName(R, Record->getDecl());
R.suppressDiagnostics();
@@ -13670,7 +14165,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
PDiag(diag::err_ovl_ambiguous_object_call)
<< Object.get()->getType()
<< Object.get()->getSourceRange()),
- *this, OCD_ViableCandidates, Args);
+ *this, OCD_AmbiguousCandidates, Args);
break;
case OR_Deleted:
@@ -13730,9 +14225,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
if (Method->isInvalidDecl())
return ExprError();
- const FunctionProtoType *Proto =
- Method->getType()->getAs<FunctionProtoType>();
-
+ const auto *Proto = Method->getType()->castAs<FunctionProtoType>();
unsigned NumParams = Proto->getNumParams();
DeclarationNameInfo OpLocInfo(
@@ -13853,14 +14346,13 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
DeclarationName OpName =
Context.DeclarationNames.getCXXOperatorName(OO_Arrow);
OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Operator);
- const RecordType *BaseRecord = Base->getType()->getAs<RecordType>();
if (RequireCompleteType(Loc, Base->getType(),
diag::err_typecheck_incomplete_tag, Base))
return ExprError();
LookupResult R(*this, OpName, OpLoc, LookupOrdinaryName);
- LookupQualifiedName(R, BaseRecord->getDecl());
+ LookupQualifiedName(R, Base->getType()->castAs<RecordType>()->getDecl());
R.suppressDiagnostics();
for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
@@ -13905,7 +14397,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
PartialDiagnosticAt(OpLoc, PDiag(diag::err_ovl_ambiguous_oper_unary)
<< "->" << Base->getType()
<< Base->getSourceRange()),
- *this, OCD_ViableCandidates, Base);
+ *this, OCD_AmbiguousCandidates, Base);
return ExprError();
case OR_Deleted:
@@ -13985,7 +14477,7 @@ ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R,
CandidateSet.NoteCandidates(
PartialDiagnosticAt(R.getNameLoc(), PDiag(diag::err_ovl_ambiguous_call)
<< R.getLookupName()),
- *this, OCD_ViableCandidates, Args);
+ *this, OCD_AmbiguousCandidates, Args);
return ExprError();
}
@@ -14200,13 +14692,6 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
UnOp->getOperatorLoc(), false);
}
- // C++ [except.spec]p17:
- // An exception-specification is considered to be needed when:
- // - in an expression the function is the unique lookup result or the
- // selected member of a set of overloaded functions
- if (auto *FPT = Fn->getType()->getAs<FunctionProtoType>())
- ResolveExceptionSpec(E->getExprLoc(), FPT);
-
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
// FIXME: avoid copy.
TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;