diff options
Diffstat (limited to 'lib/Sema/SemaOverload.cpp')
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 653 |
1 files changed, 490 insertions, 163 deletions
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index f632a4d3bd1a..47c1e3cec0ea 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -257,8 +257,18 @@ isPointerConversionToVoidPointer(ASTContext& Context) const { /// Skip any implicit casts which could be either part of a narrowing conversion /// or after one in an implicit conversion. -static const Expr *IgnoreNarrowingConversion(const Expr *Converted) { - while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Converted)) { +static const Expr *IgnoreNarrowingConversion(ASTContext &Ctx, + const Expr *Converted) { + // We can have cleanups wrapping the converted expression; these need to be + // preserved so that destructors run if necessary. + if (auto *EWC = dyn_cast<ExprWithCleanups>(Converted)) { + Expr *Inner = + const_cast<Expr *>(IgnoreNarrowingConversion(Ctx, EWC->getSubExpr())); + return ExprWithCleanups::Create(Ctx, Inner, EWC->cleanupsHaveSideEffects(), + EWC->getObjects()); + } + + while (auto *ICE = dyn_cast<ImplicitCastExpr>(Converted)) { switch (ICE->getCastKind()) { case CK_NoOp: case CK_IntegralCast: @@ -332,7 +342,7 @@ NarrowingKind StandardConversionSequence::getNarrowingKind( if (IgnoreFloatToIntegralConversion) return NK_Not_Narrowing; llvm::APSInt IntConstantValue; - const Expr *Initializer = IgnoreNarrowingConversion(Converted); + const Expr *Initializer = IgnoreNarrowingConversion(Ctx, Converted); assert(Initializer && "Unknown conversion expression"); // If it's value-dependent, we can't tell whether it's narrowing. @@ -370,7 +380,7 @@ NarrowingKind StandardConversionSequence::getNarrowingKind( if (FromType->isRealFloatingType() && ToType->isRealFloatingType() && Ctx.getFloatingTypeOrder(FromType, ToType) == 1) { // FromType is larger than ToType. - const Expr *Initializer = IgnoreNarrowingConversion(Converted); + const Expr *Initializer = IgnoreNarrowingConversion(Ctx, Converted); // If it's value-dependent, we can't tell whether it's narrowing. if (Initializer->isValueDependent()) @@ -416,7 +426,7 @@ NarrowingKind StandardConversionSequence::getNarrowingKind( (FromSigned && !ToSigned)) { // Not all values of FromType can be represented in ToType. llvm::APSInt InitializerValue; - const Expr *Initializer = IgnoreNarrowingConversion(Converted); + const Expr *Initializer = IgnoreNarrowingConversion(Ctx, Converted); // If it's value-dependent, we can't tell whether it's narrowing. if (Initializer->isValueDependent()) @@ -838,6 +848,25 @@ llvm::Optional<unsigned> DeductionFailureInfo::getCallArgIndex() { } } +bool OverloadCandidateSet::OperatorRewriteInfo::shouldAddReversed( + OverloadedOperatorKind Op) { + if (!AllowRewrittenCandidates) + return false; + return Op == OO_EqualEqual || Op == OO_Spaceship; +} + +bool OverloadCandidateSet::OperatorRewriteInfo::shouldAddReversed( + ASTContext &Ctx, const FunctionDecl *FD) { + if (!shouldAddReversed(FD->getDeclName().getCXXOverloadedOperator())) + return false; + // Don't bother adding a reversed candidate that can never be a better + // match than the non-reversed version. + return FD->getNumParams() != 2 || + !Ctx.hasSameUnqualifiedType(FD->getParamDecl(0)->getType(), + FD->getParamDecl(1)->getType()) || + FD->hasAttr<EnableIfAttr>(); +} + void OverloadCandidateSet::destroyCandidates() { for (iterator i = begin(), e = end(); i != e; ++i) { for (auto &C : i->Conversions) @@ -1463,14 +1492,14 @@ bool Sema::IsFunctionConversion(QualType FromType, QualType ToType, if (TyClass != CanFrom->getTypeClass()) return false; if (TyClass != Type::FunctionProto && TyClass != Type::FunctionNoProto) { if (TyClass == Type::Pointer) { - CanTo = CanTo.getAs<PointerType>()->getPointeeType(); - CanFrom = CanFrom.getAs<PointerType>()->getPointeeType(); + CanTo = CanTo.castAs<PointerType>()->getPointeeType(); + CanFrom = CanFrom.castAs<PointerType>()->getPointeeType(); } else if (TyClass == Type::BlockPointer) { - CanTo = CanTo.getAs<BlockPointerType>()->getPointeeType(); - CanFrom = CanFrom.getAs<BlockPointerType>()->getPointeeType(); + CanTo = CanTo.castAs<BlockPointerType>()->getPointeeType(); + CanFrom = CanFrom.castAs<BlockPointerType>()->getPointeeType(); } else if (TyClass == Type::MemberPointer) { - auto ToMPT = CanTo.getAs<MemberPointerType>(); - auto FromMPT = CanFrom.getAs<MemberPointerType>(); + auto ToMPT = CanTo.castAs<MemberPointerType>(); + auto FromMPT = CanFrom.castAs<MemberPointerType>(); // A function pointer conversion cannot change the class of the function. if (ToMPT->getClass() != FromMPT->getClass()) return false; @@ -2273,7 +2302,7 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType, // Blocks: Block pointers can be converted to void*. if (FromType->isBlockPointerType() && ToType->isPointerType() && - ToType->getAs<PointerType>()->getPointeeType()->isVoidType()) { + ToType->castAs<PointerType>()->getPointeeType()->isVoidType()) { ConvertedType = ToType; return true; } @@ -3272,7 +3301,7 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType, User.ConversionFunction = Constructor; User.FoundConversionFunction = Best->FoundDecl; User.After.setAsIdentityConversion(); - User.After.setFromType(ThisType->getAs<PointerType>()->getPointeeType()); + User.After.setFromType(ThisType->castAs<PointerType>()->getPointeeType()); User.After.setAllToTypes(ToType); return Result; } @@ -3463,7 +3492,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, User.ConversionFunction = Constructor; User.FoundConversionFunction = Best->FoundDecl; User.After.setAsIdentityConversion(); - User.After.setFromType(ThisType->getAs<PointerType>()->getPointeeType()); + User.After.setFromType(ThisType->castAs<PointerType>()->getPointeeType()); User.After.setAllToTypes(ToType); return Result; } @@ -3755,6 +3784,34 @@ isBetterReferenceBindingKind(const StandardConversionSequence &SCS1, !SCS2.IsLvalueReference && SCS2.BindsToFunctionLvalue); } +enum class FixedEnumPromotion { + None, + ToUnderlyingType, + ToPromotedUnderlyingType +}; + +/// Returns kind of fixed enum promotion the \a SCS uses. +static FixedEnumPromotion +getFixedEnumPromtion(Sema &S, const StandardConversionSequence &SCS) { + + if (SCS.Second != ICK_Integral_Promotion) + return FixedEnumPromotion::None; + + QualType FromType = SCS.getFromType(); + if (!FromType->isEnumeralType()) + return FixedEnumPromotion::None; + + EnumDecl *Enum = FromType->getAs<EnumType>()->getDecl(); + if (!Enum->isFixed()) + return FixedEnumPromotion::None; + + QualType UnderlyingType = Enum->getIntegerType(); + if (S.Context.hasSameType(SCS.getToType(1), UnderlyingType)) + return FixedEnumPromotion::ToUnderlyingType; + + return FixedEnumPromotion::ToPromotedUnderlyingType; +} + /// CompareStandardConversionSequences - Compare two standard /// conversion sequences to determine whether one is better than the /// other or if they are indistinguishable (C++ 13.3.3.2p3). @@ -3796,6 +3853,20 @@ CompareStandardConversionSequences(Sema &S, SourceLocation Loc, ? ImplicitConversionSequence::Better : ImplicitConversionSequence::Worse; + // C++14 [over.ics.rank]p4b2: + // This is retroactively applied to C++11 by CWG 1601. + // + // A conversion that promotes an enumeration whose underlying type is fixed + // to its underlying type is better than one that promotes to the promoted + // underlying type, if the two are different. + FixedEnumPromotion FEP1 = getFixedEnumPromtion(S, SCS1); + FixedEnumPromotion FEP2 = getFixedEnumPromtion(S, SCS2); + if (FEP1 != FixedEnumPromotion::None && FEP2 != FixedEnumPromotion::None && + FEP1 != FEP2) + return FEP1 == FixedEnumPromotion::ToUnderlyingType + ? ImplicitConversionSequence::Better + : ImplicitConversionSequence::Worse; + // C++ [over.ics.rank]p4b2: // // If class B is derived directly or indirectly from class A, @@ -4105,14 +4176,14 @@ CompareDerivedToBaseConversions(Sema &S, SourceLocation Loc, /*FIXME: Remove if Objective-C id conversions get their own rank*/ FromType1->isPointerType() && FromType2->isPointerType() && ToType1->isPointerType() && ToType2->isPointerType()) { - QualType FromPointee1 - = FromType1->getAs<PointerType>()->getPointeeType().getUnqualifiedType(); - QualType ToPointee1 - = ToType1->getAs<PointerType>()->getPointeeType().getUnqualifiedType(); - QualType FromPointee2 - = FromType2->getAs<PointerType>()->getPointeeType().getUnqualifiedType(); - QualType ToPointee2 - = ToType2->getAs<PointerType>()->getPointeeType().getUnqualifiedType(); + QualType FromPointee1 = + FromType1->castAs<PointerType>()->getPointeeType().getUnqualifiedType(); + QualType ToPointee1 = + ToType1->castAs<PointerType>()->getPointeeType().getUnqualifiedType(); + QualType FromPointee2 = + FromType2->castAs<PointerType>()->getPointeeType().getUnqualifiedType(); + QualType ToPointee2 = + ToType2->castAs<PointerType>()->getPointeeType().getUnqualifiedType(); // -- conversion of C* to B* is better than conversion of C* to A*, if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) { @@ -4301,7 +4372,8 @@ Sema::CompareReferenceRelationship(SourceLocation Loc, QualType OrigT1, QualType OrigT2, bool &DerivedToBase, bool &ObjCConversion, - bool &ObjCLifetimeConversion) { + bool &ObjCLifetimeConversion, + bool &FunctionConversion) { assert(!OrigT1->isReferenceType() && "T1 must be the pointee type of the reference type"); assert(!OrigT2->isReferenceType() && "T2 cannot be a reference type"); @@ -4331,15 +4403,16 @@ Sema::CompareReferenceRelationship(SourceLocation Loc, Context.canBindObjCObjectType(UnqualT1, UnqualT2)) ObjCConversion = true; else if (UnqualT2->isFunctionType() && - IsFunctionConversion(UnqualT2, UnqualT1, ConvertedT2)) + 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; return Ref_Compatible; - else + } else return Ref_Incompatible; // At this point, we know that T1 and T2 are reference-related (at @@ -4392,7 +4465,7 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, bool AllowExplicit) { assert(T2->isRecordType() && "Can only find conversions of record types."); CXXRecordDecl *T2RecordDecl - = dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl()); + = dyn_cast<CXXRecordDecl>(T2->castAs<RecordType>()->getDecl()); OverloadCandidateSet CandidateSet( DeclLoc, OverloadCandidateSet::CSK_InitByUserDefinedConversion); @@ -4420,6 +4493,7 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, 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. @@ -4432,12 +4506,13 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, if (!ConvTemplate && S.CompareReferenceRelationship( - DeclLoc, - Conv->getConversionType().getNonReferenceType() - .getUnqualifiedType(), - DeclType.getNonReferenceType().getUnqualifiedType(), - DerivedToBase, ObjCConversion, ObjCLifetimeConversion) == - Sema::Ref_Incompatible) + DeclLoc, + Conv->getConversionType() + .getNonReferenceType() + .getUnqualifiedType(), + DeclType.getNonReferenceType().getUnqualifiedType(), + DerivedToBase, ObjCConversion, ObjCLifetimeConversion, + FunctionConversion) == Sema::Ref_Incompatible) continue; } else { // If the conversion function doesn't return a reference type, @@ -4523,7 +4598,7 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, ImplicitConversionSequence ICS; ICS.setBad(BadConversionSequence::no_conversion, Init, DeclType); - QualType T1 = DeclType->getAs<ReferenceType>()->getPointeeType(); + QualType T1 = DeclType->castAs<ReferenceType>()->getPointeeType(); QualType T2 = Init->getType(); // If the initializer is the address of an overloaded function, try @@ -4541,11 +4616,11 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, 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); - + Sema::ReferenceCompareResult RefRelationship = S.CompareReferenceRelationship( + DeclLoc, T1, T2, DerivedToBase, ObjCConversion, ObjCLifetimeConversion, + FunctionConversion); // C++0x [dcl.init.ref]p5: // A reference to type "cv1 T1" is initialized by an expression @@ -4920,13 +4995,11 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, // Type is an aggregate, argument is an init list. At this point it comes // down to checking whether the initialization works. // FIXME: Find out whether this parameter is consumed or not. - // FIXME: Expose SemaInit's aggregate initialization code so that we don't - // need to call into the initialization code here; overload resolution - // should not be doing that. InitializedEntity Entity = InitializedEntity::InitializeParameter(S.Context, ToType, /*Consumed=*/false); - if (S.CanPerformCopyInitialization(Entity, From)) { + if (S.CanPerformAggregateInitializationForOverloadResolution(Entity, + From)) { Result.setUserDefined(); Result.UserDefined.Before.setAsIdentityConversion(); // Initializer lists don't have a type. @@ -4949,7 +5022,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, // mention initializer lists in any way. So we go by what list- // initialization would do and try to extrapolate from that. - QualType T1 = ToType->getAs<ReferenceType>()->getPointeeType(); + QualType T1 = ToType->castAs<ReferenceType>()->getPointeeType(); // If the initializer list has a single element that is reference-related // to the parameter type, we initialize the reference from that. @@ -4972,9 +5045,10 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, bool dummy1 = false; bool dummy2 = false; bool dummy3 = false; + bool dummy4 = false; Sema::ReferenceCompareResult RefRelationship = S.CompareReferenceRelationship(From->getBeginLoc(), T1, T2, dummy1, - dummy2, dummy3); + dummy2, dummy3, dummy4); if (RefRelationship >= Sema::Ref_Related) { return TryReferenceInit(S, Init, ToType, /*FIXME*/ From->getBeginLoc(), @@ -5219,7 +5293,7 @@ Sema::PerformObjectArgumentInitialization(Expr *From, CXXMethodDecl *Method) { QualType FromRecordType, DestType; QualType ImplicitParamRecordType = - Method->getThisType()->getAs<PointerType>()->getPointeeType(); + Method->getThisType()->castAs<PointerType>()->getPointeeType(); Expr::Classification FromClassification; if (const PointerType *PT = From->getType()->getAs<PointerType>()) { @@ -5467,6 +5541,14 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From, if (Result.isInvalid()) return Result; + // C++2a [intro.execution]p5: + // A full-expression is [...] a constant-expression [...] + Result = + S.ActOnFinishFullExpr(Result.get(), From->getExprLoc(), + /*DiscardedValue=*/false, /*IsConstexpr=*/true); + if (Result.isInvalid()) + return Result; + // Check for a narrowing implicit conversion. APValue PreNarrowingValue; QualType PreNarrowingType; @@ -5998,7 +6080,8 @@ void Sema::AddOverloadCandidate( FunctionDecl *Function, DeclAccessPair FoundDecl, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, bool PartialOverloading, bool AllowExplicit, bool AllowExplicitConversions, - ADLCallKind IsADLCandidate, ConversionSequenceList EarlyConversions) { + ADLCallKind IsADLCandidate, ConversionSequenceList EarlyConversions, + OverloadCandidateParamOrder PO) { const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>()); assert(Proto && "Functions without a prototype cannot be overloaded"); @@ -6017,25 +6100,14 @@ void Sema::AddOverloadCandidate( AddMethodCandidate(Method, FoundDecl, Method->getParent(), QualType(), Expr::Classification::makeSimpleLValue(), Args, CandidateSet, SuppressUserConversions, - PartialOverloading, EarlyConversions); + PartialOverloading, EarlyConversions, PO); return; } // We treat a constructor like a non-member function, since its object // argument doesn't participate in overload resolution. } - if (!CandidateSet.isNewCandidate(Function)) - return; - - // C++ [over.match.oper]p3: - // if no operand has a class type, only those non-member functions in the - // lookup set that have a first parameter of type T1 or "reference to - // (possibly cv-qualified) T1", when T1 is an enumeration type, or (if there - // is a right operand) a second parameter of type T2 or "reference to - // (possibly cv-qualified) T2", when T2 is an enumeration type, are - // candidate functions. - if (CandidateSet.getKind() == OverloadCandidateSet::CSK_Operator && - !IsAcceptableNonMemberOperatorCandidate(Context, Function, Args)) + if (!CandidateSet.isNewCandidate(Function, PO)) return; // C++11 [class.copy]p11: [DR1402] @@ -6050,12 +6122,25 @@ void Sema::AddOverloadCandidate( EnterExpressionEvaluationContext Unevaluated( *this, Sema::ExpressionEvaluationContext::Unevaluated); + // C++ [over.match.oper]p3: + // if no operand has a class type, only those non-member functions in the + // lookup set that have a first parameter of type T1 or "reference to + // (possibly cv-qualified) T1", when T1 is an enumeration type, or (if there + // is a right operand) a second parameter of type T2 or "reference to + // (possibly cv-qualified) T2", when T2 is an enumeration type, are + // candidate functions. + if (CandidateSet.getKind() == OverloadCandidateSet::CSK_Operator && + !IsAcceptableNonMemberOperatorCandidate(Context, Function, Args)) + return; + // Add this candidate OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size(), EarlyConversions); Candidate.FoundDecl = FoundDecl; Candidate.Function = Function; Candidate.Viable = true; + Candidate.RewriteKind = + CandidateSet.getRewriteInfo().getRewriteKind(Function, PO); Candidate.IsSurrogate = false; Candidate.IsADLCandidate = IsADLCandidate; Candidate.IgnoreObjectArgument = false; @@ -6155,7 +6240,9 @@ void Sema::AddOverloadCandidate( // Determine the implicit conversion sequences for each of the // arguments. for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) { - if (Candidate.Conversions[ArgIdx].isInitialized()) { + unsigned ConvIdx = + PO == OverloadCandidateParamOrder::Reversed ? 1 - ArgIdx : ArgIdx; + if (Candidate.Conversions[ConvIdx].isInitialized()) { // We already formed a conversion sequence for this parameter during // template argument deduction. } else if (ArgIdx < NumParams) { @@ -6164,12 +6251,12 @@ void Sema::AddOverloadCandidate( // (13.3.3.1) that converts that argument to the corresponding // parameter of F. QualType ParamType = Proto->getParamType(ArgIdx); - Candidate.Conversions[ArgIdx] = TryCopyInitialization( + Candidate.Conversions[ConvIdx] = TryCopyInitialization( *this, Args[ArgIdx], ParamType, SuppressUserConversions, /*InOverloadResolution=*/true, /*AllowObjCWritebackConversion=*/ getLangOpts().ObjCAutoRefCount, AllowExplicitConversions); - if (Candidate.Conversions[ArgIdx].isBad()) { + if (Candidate.Conversions[ConvIdx].isBad()) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_conversion; return; @@ -6178,7 +6265,7 @@ void Sema::AddOverloadCandidate( // (C++ 13.3.2p2): For the purposes of overload resolution, any // argument for which there is no corresponding parameter is // considered to ""match the ellipsis" (C+ 13.3.3.1.3). - Candidate.Conversions[ArgIdx].setEllipsis(); + Candidate.Conversions[ConvIdx].setEllipsis(); } } @@ -6525,9 +6612,10 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, FunctionArgs = Args.slice(1); } if (FunTmpl) { - AddTemplateOverloadCandidate( - FunTmpl, F.getPair(), ExplicitTemplateArgs, FunctionArgs, - CandidateSet, SuppressUserConversions, PartialOverloading); + AddTemplateOverloadCandidate(FunTmpl, F.getPair(), + ExplicitTemplateArgs, FunctionArgs, + CandidateSet, SuppressUserConversions, + PartialOverloading); } else { AddOverloadCandidate(FD, F.getPair(), FunctionArgs, CandidateSet, SuppressUserConversions, PartialOverloading); @@ -6538,12 +6626,12 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, /// AddMethodCandidate - Adds a named decl (which is some kind of /// method) as a method candidate to the given overload set. -void Sema::AddMethodCandidate(DeclAccessPair FoundDecl, - QualType ObjectType, +void Sema::AddMethodCandidate(DeclAccessPair FoundDecl, QualType ObjectType, Expr::Classification ObjectClassification, ArrayRef<Expr *> Args, - OverloadCandidateSet& CandidateSet, - bool SuppressUserConversions) { + OverloadCandidateSet &CandidateSet, + bool SuppressUserConversions, + OverloadCandidateParamOrder PO) { NamedDecl *Decl = FoundDecl.getDecl(); CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(Decl->getDeclContext()); @@ -6556,11 +6644,11 @@ void Sema::AddMethodCandidate(DeclAccessPair FoundDecl, AddMethodTemplateCandidate(TD, FoundDecl, ActingContext, /*ExplicitArgs*/ nullptr, ObjectType, ObjectClassification, Args, CandidateSet, - SuppressUserConversions); + SuppressUserConversions, false, PO); } else { AddMethodCandidate(cast<CXXMethodDecl>(Decl), FoundDecl, ActingContext, ObjectType, ObjectClassification, Args, CandidateSet, - SuppressUserConversions); + SuppressUserConversions, false, None, PO); } } @@ -6579,14 +6667,15 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, bool PartialOverloading, - ConversionSequenceList EarlyConversions) { + ConversionSequenceList EarlyConversions, + OverloadCandidateParamOrder PO) { const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(Method->getType()->getAs<FunctionType>()); assert(Proto && "Methods without a prototype cannot be overloaded"); assert(!isa<CXXConstructorDecl>(Method) && "Use AddOverloadCandidate for constructors"); - if (!CandidateSet.isNewCandidate(Method)) + if (!CandidateSet.isNewCandidate(Method, PO)) return; // C++11 [class.copy]p23: [DR1402] @@ -6605,6 +6694,8 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, CandidateSet.addCandidate(Args.size() + 1, EarlyConversions); Candidate.FoundDecl = FoundDecl; Candidate.Function = Method; + Candidate.RewriteKind = + CandidateSet.getRewriteInfo().getRewriteKind(Method, PO); Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = false; Candidate.ExplicitCallArguments = Args.size(); @@ -6640,12 +6731,13 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, // The implicit object argument is ignored. Candidate.IgnoreObjectArgument = true; else { + unsigned ConvIdx = PO == OverloadCandidateParamOrder::Reversed ? 1 : 0; // Determine the implicit conversion sequence for the object // parameter. - Candidate.Conversions[0] = TryObjectArgumentInitialization( + Candidate.Conversions[ConvIdx] = TryObjectArgumentInitialization( *this, CandidateSet.getLocation(), ObjectType, ObjectClassification, Method, ActingContext); - if (Candidate.Conversions[0].isBad()) { + if (Candidate.Conversions[ConvIdx].isBad()) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_conversion; return; @@ -6664,7 +6756,9 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, // Determine the implicit conversion sequences for each of the // arguments. for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) { - if (Candidate.Conversions[ArgIdx + 1].isInitialized()) { + unsigned ConvIdx = + PO == OverloadCandidateParamOrder::Reversed ? 0 : (ArgIdx + 1); + if (Candidate.Conversions[ConvIdx].isInitialized()) { // We already formed a conversion sequence for this parameter during // template argument deduction. } else if (ArgIdx < NumParams) { @@ -6673,13 +6767,13 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, // (13.3.3.1) that converts that argument to the corresponding // parameter of F. QualType ParamType = Proto->getParamType(ArgIdx); - Candidate.Conversions[ArgIdx + 1] + Candidate.Conversions[ConvIdx] = TryCopyInitialization(*this, Args[ArgIdx], ParamType, SuppressUserConversions, /*InOverloadResolution=*/true, /*AllowObjCWritebackConversion=*/ getLangOpts().ObjCAutoRefCount); - if (Candidate.Conversions[ArgIdx + 1].isBad()) { + if (Candidate.Conversions[ConvIdx].isBad()) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_conversion; return; @@ -6688,7 +6782,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, // (C++ 13.3.2p2): For the purposes of overload resolution, any // argument for which there is no corresponding parameter is // considered to "match the ellipsis" (C+ 13.3.3.1.3). - Candidate.Conversions[ArgIdx + 1].setEllipsis(); + Candidate.Conversions[ConvIdx].setEllipsis(); } } @@ -6709,18 +6803,14 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, /// Add a C++ member function template as a candidate to the candidate /// set, using template argument deduction to produce an appropriate member /// function template specialization. -void -Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, - DeclAccessPair FoundDecl, - CXXRecordDecl *ActingContext, - TemplateArgumentListInfo *ExplicitTemplateArgs, - QualType ObjectType, - Expr::Classification ObjectClassification, - ArrayRef<Expr *> Args, - OverloadCandidateSet& CandidateSet, - bool SuppressUserConversions, - bool PartialOverloading) { - if (!CandidateSet.isNewCandidate(MethodTmpl)) +void Sema::AddMethodTemplateCandidate( + FunctionTemplateDecl *MethodTmpl, DeclAccessPair FoundDecl, + CXXRecordDecl *ActingContext, + TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ObjectType, + Expr::Classification ObjectClassification, ArrayRef<Expr *> Args, + OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, + bool PartialOverloading, OverloadCandidateParamOrder PO) { + if (!CandidateSet.isNewCandidate(MethodTmpl, PO)) return; // C++ [over.match.funcs]p7: @@ -6741,13 +6831,15 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, return CheckNonDependentConversions( MethodTmpl, ParamTypes, Args, CandidateSet, Conversions, SuppressUserConversions, ActingContext, ObjectType, - ObjectClassification); + ObjectClassification, PO); })) { OverloadCandidate &Candidate = CandidateSet.addCandidate(Conversions.size(), Conversions); Candidate.FoundDecl = FoundDecl; Candidate.Function = MethodTmpl->getTemplatedDecl(); Candidate.Viable = false; + Candidate.RewriteKind = + CandidateSet.getRewriteInfo().getRewriteKind(Candidate.Function, PO); Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = cast<CXXMethodDecl>(Candidate.Function)->isStatic() || @@ -6771,7 +6863,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, AddMethodCandidate(cast<CXXMethodDecl>(Specialization), FoundDecl, ActingContext, ObjectType, ObjectClassification, Args, CandidateSet, SuppressUserConversions, PartialOverloading, - Conversions); + Conversions, PO); } /// Add a C++ function template specialization as a candidate @@ -6781,8 +6873,9 @@ void Sema::AddTemplateOverloadCandidate( FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, - bool PartialOverloading, bool AllowExplicit, ADLCallKind IsADLCandidate) { - if (!CandidateSet.isNewCandidate(FunctionTemplate)) + bool PartialOverloading, bool AllowExplicit, ADLCallKind IsADLCandidate, + OverloadCandidateParamOrder PO) { + if (!CandidateSet.isNewCandidate(FunctionTemplate, PO)) return; // C++ [over.match.funcs]p7: @@ -6800,15 +6893,17 @@ void Sema::AddTemplateOverloadCandidate( if (TemplateDeductionResult Result = DeduceTemplateArguments( FunctionTemplate, ExplicitTemplateArgs, Args, Specialization, Info, PartialOverloading, [&](ArrayRef<QualType> ParamTypes) { - return CheckNonDependentConversions(FunctionTemplate, ParamTypes, - Args, CandidateSet, Conversions, - SuppressUserConversions); + return CheckNonDependentConversions( + FunctionTemplate, ParamTypes, Args, CandidateSet, Conversions, + SuppressUserConversions, nullptr, QualType(), {}, PO); })) { OverloadCandidate &Candidate = CandidateSet.addCandidate(Conversions.size(), Conversions); Candidate.FoundDecl = FoundDecl; Candidate.Function = FunctionTemplate->getTemplatedDecl(); Candidate.Viable = false; + Candidate.RewriteKind = + CandidateSet.getRewriteInfo().getRewriteKind(Candidate.Function, PO); Candidate.IsSurrogate = false; Candidate.IsADLCandidate = IsADLCandidate; // Ignore the object argument if there is one, since we don't have an object @@ -6833,7 +6928,7 @@ void Sema::AddTemplateOverloadCandidate( AddOverloadCandidate( Specialization, FoundDecl, Args, CandidateSet, SuppressUserConversions, PartialOverloading, AllowExplicit, - /*AllowExplicitConversions*/ false, IsADLCandidate, Conversions); + /*AllowExplicitConversions*/ false, IsADLCandidate, Conversions, PO); } /// Check that implicit conversion sequences can be formed for each argument @@ -6844,7 +6939,7 @@ bool Sema::CheckNonDependentConversions( ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, ConversionSequenceList &Conversions, bool SuppressUserConversions, CXXRecordDecl *ActingContext, QualType ObjectType, - Expr::Classification ObjectClassification) { + Expr::Classification ObjectClassification, OverloadCandidateParamOrder PO) { // FIXME: The cases in which we allow explicit conversions for constructor // arguments never consider calling a constructor template. It's not clear // that is correct. @@ -6867,10 +6962,11 @@ bool Sema::CheckNonDependentConversions( // overload resolution is permitted to sidestep instantiations. if (HasThisConversion && !cast<CXXMethodDecl>(FD)->isStatic() && !ObjectType.isNull()) { - Conversions[0] = TryObjectArgumentInitialization( + unsigned ConvIdx = PO == OverloadCandidateParamOrder::Reversed ? 1 : 0; + Conversions[ConvIdx] = TryObjectArgumentInitialization( *this, CandidateSet.getLocation(), ObjectType, ObjectClassification, Method, ActingContext); - if (Conversions[0].isBad()) + if (Conversions[ConvIdx].isBad()) return true; } @@ -6878,14 +6974,17 @@ bool Sema::CheckNonDependentConversions( ++I) { QualType ParamType = ParamTypes[I]; if (!ParamType->isDependentType()) { - Conversions[ThisConversions + I] + unsigned ConvIdx = PO == OverloadCandidateParamOrder::Reversed + ? 0 + : (ThisConversions + I); + Conversions[ConvIdx] = TryCopyInitialization(*this, Args[I], ParamType, SuppressUserConversions, /*InOverloadResolution=*/true, /*AllowObjCWritebackConversion=*/ getLangOpts().ObjCAutoRefCount, AllowExplicit); - if (Conversions[ThisConversions + I].isBad()) + if (Conversions[ConvIdx].isBad()) return true; } } @@ -6998,7 +7097,7 @@ void Sema::AddConversionCandidate( if (const PointerType *FromPtrType = ImplicitParamType->getAs<PointerType>()) ImplicitParamType = FromPtrType->getPointeeType(); CXXRecordDecl *ConversionContext - = cast<CXXRecordDecl>(ImplicitParamType->getAs<RecordType>()->getDecl()); + = cast<CXXRecordDecl>(ImplicitParamType->castAs<RecordType>()->getDecl()); Candidate.Conversions[0] = TryObjectArgumentInitialization( *this, CandidateSet.getLocation(), From->getType(), @@ -7052,10 +7151,9 @@ void Sema::AddConversionCandidate( // allocator). QualType CallResultType = ConversionType.getNonLValueExprType(Context); - llvm::AlignedCharArray<alignof(CallExpr), sizeof(CallExpr) + sizeof(Stmt *)> - Buffer; + alignas(CallExpr) char Buffer[sizeof(CallExpr) + sizeof(Stmt *)]; CallExpr *TheTemporaryCall = CallExpr::CreateTemporary( - Buffer.buffer, &ConversionFn, CallResultType, VK, From->getBeginLoc()); + Buffer, &ConversionFn, CallResultType, VK, From->getBeginLoc()); ImplicitConversionSequence ICS = TryCopyInitialization(*this, TheTemporaryCall, ToType, @@ -7274,6 +7372,48 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, } } +/// Add all of the non-member operator function declarations in the given +/// function set to the overload candidate set. +void Sema::AddNonMemberOperatorCandidates( + const UnresolvedSetImpl &Fns, ArrayRef<Expr *> Args, + OverloadCandidateSet &CandidateSet, + TemplateArgumentListInfo *ExplicitTemplateArgs) { + for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) { + NamedDecl *D = F.getDecl()->getUnderlyingDecl(); + ArrayRef<Expr *> FunctionArgs = Args; + + FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D); + FunctionDecl *FD = + FunTmpl ? FunTmpl->getTemplatedDecl() : cast<FunctionDecl>(D); + + // Don't consider rewritten functions if we're not rewriting. + if (!CandidateSet.getRewriteInfo().isAcceptableCandidate(FD)) + continue; + + assert(!isa<CXXMethodDecl>(FD) && + "unqualified operator lookup found a member function"); + + if (FunTmpl) { + AddTemplateOverloadCandidate(FunTmpl, F.getPair(), ExplicitTemplateArgs, + FunctionArgs, CandidateSet); + if (CandidateSet.getRewriteInfo().shouldAddReversed(Context, FD)) + AddTemplateOverloadCandidate( + FunTmpl, F.getPair(), ExplicitTemplateArgs, + {FunctionArgs[1], FunctionArgs[0]}, CandidateSet, false, false, + true, ADLCallKind::NotADL, OverloadCandidateParamOrder::Reversed); + } else { + if (ExplicitTemplateArgs) + continue; + AddOverloadCandidate(FD, F.getPair(), FunctionArgs, CandidateSet); + if (CandidateSet.getRewriteInfo().shouldAddReversed(Context, FD)) + AddOverloadCandidate(FD, F.getPair(), + {FunctionArgs[1], FunctionArgs[0]}, CandidateSet, + false, false, true, false, ADLCallKind::NotADL, + None, OverloadCandidateParamOrder::Reversed); + } + } +} + /// Add overload candidates for overloaded operators that are /// member functions. /// @@ -7285,8 +7425,8 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op, SourceLocation OpLoc, ArrayRef<Expr *> Args, - OverloadCandidateSet& CandidateSet, - SourceRange OpRange) { + OverloadCandidateSet &CandidateSet, + OverloadCandidateParamOrder PO) { DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op); // C++ [over.match.oper]p3: @@ -7321,7 +7461,7 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op, ++Oper) AddMethodCandidate(Oper.getPair(), Args[0]->getType(), Args[0]->Classify(Context), Args.slice(1), - CandidateSet, /*SuppressUserConversion=*/false); + CandidateSet, /*SuppressUserConversion=*/false, PO); } } @@ -7776,7 +7916,7 @@ class BuiltinOperatorOverloadBuilder { static constexpr int ArithmeticTypesCap = 24; SmallVector<CanQualType, ArithmeticTypesCap> ArithmeticTypes; - // Define some indices used to iterate over the arithemetic types in + // Define some indices used to iterate over the arithmetic types in // ArithmeticTypes. The "promoted arithmetic types" are the arithmetic // types are that preserved by promotion (C++ [over.built]p2). unsigned FirstIntegralType, @@ -8126,10 +8266,16 @@ public: if (C->Function->isFunctionTemplateSpecialization()) continue; - QualType FirstParamType = - C->Function->getParamDecl(0)->getType().getUnqualifiedType(); - QualType SecondParamType = - C->Function->getParamDecl(1)->getType().getUnqualifiedType(); + // We interpret "same parameter-type-list" as applying to the + // "synthesized candidate, with the order of the two parameters + // reversed", not to the original function. + bool Reversed = C->RewriteKind & CRK_Reversed; + QualType FirstParamType = C->Function->getParamDecl(Reversed ? 1 : 0) + ->getType() + .getUnqualifiedType(); + QualType SecondParamType = C->Function->getParamDecl(Reversed ? 0 : 1) + ->getType() + .getUnqualifiedType(); // Skip if either parameter isn't of enumeral type. if (!FirstParamType->isEnumeralType() || @@ -8759,7 +8905,7 @@ public: Enum = CandidateTypes[ArgIdx].enumeration_begin(), EnumEnd = CandidateTypes[ArgIdx].enumeration_end(); Enum != EnumEnd; ++Enum) { - if (!(*Enum)->getAs<EnumType>()->getDecl()->isScoped()) + if (!(*Enum)->castAs<EnumType>()->getDecl()->isScoped()) continue; if (!AddedTypes.insert(S.Context.getCanonicalType(*Enum)).second) @@ -9183,6 +9329,7 @@ bool clang::isBetterOverloadCandidate( // A viable function F1 is defined to be a better function than another // viable function F2 if for all arguments i, ICSi(F1) is not a worse // conversion sequence than ICSi(F2), and then... + bool HasWorseConversion = false; for (unsigned ArgIdx = StartArg; ArgIdx < NumArgs; ++ArgIdx) { switch (CompareImplicitConversionSequences(S, Loc, Cand1.Conversions[ArgIdx], @@ -9193,6 +9340,24 @@ bool clang::isBetterOverloadCandidate( break; case ImplicitConversionSequence::Worse: + if (Cand1.Function && Cand1.Function == Cand2.Function && + (Cand2.RewriteKind & CRK_Reversed) != 0) { + // Work around large-scale breakage caused by considering reversed + // forms of operator== in C++20: + // + // When comparing a function against its reversed form, if we have a + // better conversion for one argument and a worse conversion for the + // other, we prefer the non-reversed form. + // + // This prevents a conversion function from being considered ambiguous + // with its own reversed form in various where it's only incidentally + // heterogeneous. + // + // We diagnose this as an extension from CreateOverloadedBinOp. + HasWorseConversion = true; + break; + } + // Cand1 can't be better than Cand2. return false; @@ -9206,6 +9371,8 @@ bool clang::isBetterOverloadCandidate( // ICSj(F2), or, if not that, if (HasBetterConversion) return true; + if (HasWorseConversion) + return false; // -- the context is an initialization by user-defined conversion // (see 8.5, 13.3.1.5) and the standard conversion sequence @@ -9273,8 +9440,10 @@ bool clang::isBetterOverloadCandidate( return BetterTemplate == Cand1.Function->getPrimaryTemplate(); } - // FIXME: Work around a defect in the C++17 inheriting constructor wording. - // A derived-class constructor beats an (inherited) base class constructor. + // -- 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. + // FIXME: Implement the "all parameters have the same type" check. bool Cand1IsInherited = dyn_cast_or_null<ConstructorUsingShadowDecl>(Cand1.FoundDecl.getDecl()); bool Cand2IsInherited = @@ -9292,6 +9461,16 @@ bool clang::isBetterOverloadCandidate( // Inherited from sibling base classes: still ambiguous. } + // -- F2 is a rewritten candidate (12.4.1.2) and F1 is not + // -- F1 and F2 are rewritten candidates, and F2 is a synthesized candidate + // with reversed order of parameters and F1 is not + // + // We rank reversed + different operator as worse than just reversed, but + // that comparison can never happen, because we only consider reversing for + // the maximally-rewritten operator (== or <=>). + if (Cand1.RewriteKind != Cand2.RewriteKind) + return Cand1.RewriteKind < Cand2.RewriteKind; + // Check C++17 tie-breakers for deduction guides. { auto *Guide1 = dyn_cast_or_null<CXXDeductionGuideDecl>(Cand1.Function); @@ -9425,13 +9604,15 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc, const FunctionDecl *Caller = dyn_cast<FunctionDecl>(S.CurContext); bool ContainsSameSideCandidate = llvm::any_of(Candidates, [&](OverloadCandidate *Cand) { - return Cand->Function && + // Check viable function only. + return Cand->Viable && Cand->Function && S.IdentifyCUDAPreference(Caller, Cand->Function) == Sema::CFP_SameSide; }); if (ContainsSameSideCandidate) { auto IsWrongSideCandidate = [&](OverloadCandidate *Cand) { - return Cand->Function && + // Check viable function only to avoid unnecessary data copying/moving. + return Cand->Viable && Cand->Function && S.IdentifyCUDAPreference(Caller, Cand->Function) == Sema::CFP_WrongSide; }; @@ -9485,6 +9666,7 @@ namespace { enum OverloadCandidateKind { oc_function, oc_method, + oc_reversed_binary_operator, oc_constructor, oc_implicit_default_constructor, oc_implicit_copy_constructor, @@ -9502,6 +9684,7 @@ enum OverloadCandidateSelect { static std::pair<OverloadCandidateKind, OverloadCandidateSelect> ClassifyOverloadCandidate(Sema &S, NamedDecl *Found, FunctionDecl *Fn, + OverloadCandidateRewriteKind CRK, std::string &Description) { bool isTemplate = Fn->isTemplateDecl() || Found->isTemplateDecl(); @@ -9518,6 +9701,9 @@ ClassifyOverloadCandidate(Sema &S, NamedDecl *Found, FunctionDecl *Fn, }(); OverloadCandidateKind Kind = [&]() { + if (CRK & CRK_Reversed) + return oc_reversed_binary_operator; + if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn)) { if (!Ctor->isImplicit()) { if (isa<ConstructorUsingShadowDecl>(Found)) @@ -9642,6 +9828,7 @@ bool Sema::checkAddressOfFunctionIsAvailable(const FunctionDecl *Function, // Notes the location of an overload candidate. void Sema::NoteOverloadCandidate(NamedDecl *Found, FunctionDecl *Fn, + OverloadCandidateRewriteKind RewriteKind, QualType DestType, bool TakingAddress) { if (TakingAddress && !checkAddressOfCandidateIsAvailable(*this, Fn)) return; @@ -9651,7 +9838,7 @@ void Sema::NoteOverloadCandidate(NamedDecl *Found, FunctionDecl *Fn, std::string FnDesc; std::pair<OverloadCandidateKind, OverloadCandidateSelect> KSPair = - ClassifyOverloadCandidate(*this, Found, Fn, FnDesc); + ClassifyOverloadCandidate(*this, Found, Fn, RewriteKind, FnDesc); PartialDiagnostic PD = PDiag(diag::note_ovl_candidate) << (unsigned)KSPair.first << (unsigned)KSPair.second << Fn << FnDesc; @@ -9675,11 +9862,11 @@ void Sema::NoteAllOverloadCandidates(Expr *OverloadedExpr, QualType DestType, I != IEnd; ++I) { if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>((*I)->getUnderlyingDecl()) ) { - NoteOverloadCandidate(*I, FunTmpl->getTemplatedDecl(), DestType, + NoteOverloadCandidate(*I, FunTmpl->getTemplatedDecl(), CRK_None, DestType, TakingAddress); } else if (FunctionDecl *Fun = dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl()) ) { - NoteOverloadCandidate(*I, Fun, DestType, TakingAddress); + NoteOverloadCandidate(*I, Fun, CRK_None, DestType, TakingAddress); } } } @@ -9729,7 +9916,8 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, std::string FnDesc; std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair = - ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn, FnDesc); + ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn, Cand->RewriteKind, + FnDesc); Expr *FromExpr = Conv.Bad.FromExpr; QualType FromTy = Conv.Bad.getFromType(); @@ -10001,7 +10189,7 @@ static void DiagnoseArityMismatch(Sema &S, NamedDecl *Found, Decl *D, std::string Description; std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair = - ClassifyOverloadCandidate(S, Found, Fn, Description); + ClassifyOverloadCandidate(S, Found, Fn, CRK_None, Description); if (modeCount == 1 && Fn->getParamDecl(0)->getDeclName()) S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity_one) @@ -10298,7 +10486,8 @@ static void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) { std::string FnDesc; std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair = - ClassifyOverloadCandidate(S, Cand->FoundDecl, Callee, FnDesc); + ClassifyOverloadCandidate(S, Cand->FoundDecl, Callee, Cand->RewriteKind, + FnDesc); S.Diag(Callee->getLocation(), diag::note_ovl_candidate_bad_target) << (unsigned)FnKindPair.first << (unsigned)ocs_non_template @@ -10416,7 +10605,8 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, if (Fn->isDeleted()) { std::string FnDesc; std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair = - ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn, FnDesc); + ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn, Cand->RewriteKind, + FnDesc); S.Diag(Fn->getLocation(), diag::note_ovl_candidate_deleted) << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc @@ -10426,7 +10616,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); + S.NoteOverloadCandidate(Cand->FoundDecl, Fn, Cand->RewriteKind); return; } @@ -10459,7 +10649,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); + return S.NoteOverloadCandidate(Cand->FoundDecl, Fn, Cand->RewriteKind); case ovl_fail_bad_conversion: { unsigned I = (Cand->IgnoreObjectArgument ? 1 : 0); @@ -10470,7 +10660,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); + return S.NoteOverloadCandidate(Cand->FoundDecl, Fn, Cand->RewriteKind); } case ovl_fail_bad_target: @@ -10550,12 +10740,12 @@ static void NoteBuiltinOperatorCandidate(Sema &S, StringRef Opc, TypeStr += Cand->BuiltinParamTypes[0].getAsString(); if (Cand->Conversions.size() == 1) { TypeStr += ")"; - S.Diag(OpLoc, diag::note_ovl_builtin_unary_candidate) << TypeStr; + S.Diag(OpLoc, diag::note_ovl_builtin_candidate) << TypeStr; } else { TypeStr += ", "; TypeStr += Cand->BuiltinParamTypes[1].getAsString(); TypeStr += ")"; - S.Diag(OpLoc, diag::note_ovl_builtin_binary_candidate) << TypeStr; + S.Diag(OpLoc, diag::note_ovl_builtin_candidate) << TypeStr; } } @@ -10746,8 +10936,10 @@ struct CompareOverloadCandidatesForDisplay { /// CompleteNonViableCandidate - Normally, overload resolution only /// computes up to the first bad conversion. Produces the FixIt set if /// possible. -static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, - ArrayRef<Expr *> Args) { +static void +CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, + ArrayRef<Expr *> Args, + OverloadCandidateSet::CandidateSetKind CSK) { assert(!Cand->Viable); // Don't do anything on failures other than bad conversion. @@ -10775,6 +10967,7 @@ static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, bool SuppressUserConversions = false; unsigned ConvIdx = 0; + unsigned ArgIdx = 0; ArrayRef<QualType> ParamTypes; if (Cand->IsSurrogate) { @@ -10782,16 +10975,19 @@ static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, = Cand->Surrogate->getConversionType().getNonReferenceType(); if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>()) ConvType = ConvPtrType->getPointeeType(); - ParamTypes = ConvType->getAs<FunctionProtoType>()->getParamTypes(); - // Conversion 0 is 'this', which doesn't have a corresponding argument. + ParamTypes = ConvType->castAs<FunctionProtoType>()->getParamTypes(); + // Conversion 0 is 'this', which doesn't have a corresponding parameter. ConvIdx = 1; } else if (Cand->Function) { ParamTypes = - Cand->Function->getType()->getAs<FunctionProtoType>()->getParamTypes(); + Cand->Function->getType()->castAs<FunctionProtoType>()->getParamTypes(); if (isa<CXXMethodDecl>(Cand->Function) && !isa<CXXConstructorDecl>(Cand->Function)) { - // Conversion 0 is 'this', which doesn't have a corresponding argument. + // Conversion 0 is 'this', which doesn't have a corresponding parameter. ConvIdx = 1; + if (CSK == OverloadCandidateSet::CSK_Operator) + // Argument 0 is 'this', which doesn't have a corresponding parameter. + ArgIdx = 1; } } else { // Builtin operator. @@ -10800,16 +10996,19 @@ static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, } // Fill in the rest of the conversions. - for (unsigned ArgIdx = 0; ConvIdx != ConvCount; ++ConvIdx, ++ArgIdx) { + bool Reversed = Cand->RewriteKind & CRK_Reversed; + for (unsigned ParamIdx = Reversed ? ParamTypes.size() - 1 : 0; + ConvIdx != ConvCount; + ++ConvIdx, ++ArgIdx, ParamIdx += (Reversed ? -1 : 1)) { if (Cand->Conversions[ConvIdx].isInitialized()) { // We've already checked this conversion. } else if (ArgIdx < ParamTypes.size()) { - if (ParamTypes[ArgIdx]->isDependentType()) + if (ParamTypes[ParamIdx]->isDependentType()) Cand->Conversions[ConvIdx].setAsIdentityConversion( Args[ArgIdx]->getType()); else { Cand->Conversions[ConvIdx] = - TryCopyInitialization(S, Args[ArgIdx], ParamTypes[ArgIdx], + TryCopyInitialization(S, Args[ArgIdx], ParamTypes[ParamIdx], SuppressUserConversions, /*InOverloadResolution=*/true, /*AllowObjCWritebackConversion=*/ @@ -10837,7 +11036,7 @@ SmallVector<OverloadCandidate *, 32> OverloadCandidateSet::CompleteCandidates( if (Cand->Viable) Cands.push_back(Cand); else if (OCD == OCD_AllCandidates) { - CompleteNonViableCandidate(S, Cand, Args); + 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, @@ -11394,7 +11593,7 @@ public: if (FunctionDecl *Fun = dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl())) if (!functionHasPassObjectSizeParams(Fun)) - S.NoteOverloadCandidate(*I, Fun, TargetFunctionType, + S.NoteOverloadCandidate(*I, Fun, CRK_None, TargetFunctionType, /*TakingAddress=*/true); FailedCandidates.NoteCandidates(S, OvlExpr->getBeginLoc()); } @@ -12344,7 +12543,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, OverloadCandidateSet CandidateSet(OpLoc, OverloadCandidateSet::CSK_Operator); // Add the candidates from the given function set. - AddFunctionCandidates(Fns, ArgsArray, CandidateSet); + AddNonMemberOperatorCandidates(Fns, ArgsArray, CandidateSet); // Add operator candidates that are member functions. AddMemberOperatorCandidates(Op, OpLoc, ArgsArray, CandidateSet); @@ -12489,14 +12688,17 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, /// /// \param LHS Left-hand argument. /// \param RHS Right-hand argument. -ExprResult -Sema::CreateOverloadedBinOp(SourceLocation OpLoc, - BinaryOperatorKind Opc, - const UnresolvedSetImpl &Fns, - Expr *LHS, Expr *RHS, bool PerformADL) { +ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc, + BinaryOperatorKind Opc, + const UnresolvedSetImpl &Fns, Expr *LHS, + Expr *RHS, bool PerformADL, + bool AllowRewrittenCandidates) { Expr *Args[2] = { LHS, RHS }; LHS=RHS=nullptr; // Please use only Args instead of LHS/RHS couple + if (!getLangOpts().CPlusPlus2a) + AllowRewrittenCandidates = false; + OverloadedOperatorKind Op = BinaryOperator::getOverloadedOperator(Opc); DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op); @@ -12554,23 +12756,61 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]); // Build an empty overload set. - OverloadCandidateSet CandidateSet(OpLoc, OverloadCandidateSet::CSK_Operator); + OverloadCandidateSet CandidateSet( + OpLoc, OverloadCandidateSet::CSK_Operator, + OverloadCandidateSet::OperatorRewriteInfo(Op, AllowRewrittenCandidates)); - // Add the candidates from the given function set. - AddFunctionCandidates(Fns, Args, CandidateSet); + 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) + 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); bool HadMultipleCandidates = (CandidateSet.size() > 1); @@ -12582,11 +12822,57 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // We found a built-in operator or an overloaded operator. FunctionDecl *FnDecl = Best->Function; + bool IsReversed = (Best->RewriteKind & CRK_Reversed); + if (IsReversed) + std::swap(Args[0], Args[1]); + if (FnDecl) { Expr *Base = nullptr; // We matched an overloaded operator. Build a call to that // operator. + OverloadedOperatorKind ChosenOp = + FnDecl->getDeclName().getCXXOverloadedOperator(); + + // C++2a [over.match.oper]p9: + // If a rewritten operator== candidate is selected by overload + // resolution for an operator@, its return type shall be cv bool + if (Best->RewriteKind && ChosenOp == OO_EqualEqual && + !FnDecl->getReturnType()->isBooleanType()) { + Diag(OpLoc, diag::err_ovl_rewrite_equalequal_not_bool) + << FnDecl->getReturnType() << BinaryOperator::getOpcodeStr(Opc) + << Args[0]->getSourceRange() << Args[1]->getSourceRange(); + Diag(FnDecl->getLocation(), diag::note_declared_at); + return ExprError(); + } + + if (AllowRewrittenCandidates && !IsReversed && + CandidateSet.getRewriteInfo().shouldAddReversed(ChosenOp)) { + // We could have reversed this operator, but didn't. Check if the + // reversed form was a viable candidate, and if so, if it had a + // better conversion for either parameter. If so, this call is + // formally ambiguous, and allowing it is an extension. + for (OverloadCandidate &Cand : CandidateSet) { + if (Cand.Viable && Cand.Function == FnDecl && + Cand.RewriteKind & CRK_Reversed) { + for (unsigned ArgIdx = 0; ArgIdx < 2; ++ArgIdx) { + if (CompareImplicitConversionSequences( + *this, OpLoc, Cand.Conversions[ArgIdx], + Best->Conversions[ArgIdx]) == + ImplicitConversionSequence::Better) { + Diag(OpLoc, diag::ext_ovl_ambiguous_oper_binary_reversed) + << BinaryOperator::getOpcodeStr(Opc) + << Args[0]->getType() << Args[1]->getType() + << Args[0]->getSourceRange() << Args[1]->getSourceRange(); + Diag(FnDecl->getLocation(), + diag::note_ovl_ambiguous_oper_binary_reversed_candidate); + } + } + break; + } + } + } + // Convert the arguments. if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) { // Best->Access is only meaningful for class members. @@ -12640,8 +12926,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, ResultTy = ResultTy.getNonLValueExprType(Context); CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create( - Context, Op, FnExpr.get(), Args, ResultTy, VK, OpLoc, FPFeatures, - Best->IsADLCandidate); + Context, ChosenOp, FnExpr.get(), Args, ResultTy, VK, OpLoc, + FPFeatures, Best->IsADLCandidate); if (CheckCallReturnType(FnDecl->getReturnType(), OpLoc, TheCall, FnDecl)) @@ -12663,7 +12949,46 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, isa<CXXMethodDecl>(FnDecl), OpLoc, TheCall->getSourceRange(), VariadicDoesNotApply); - return MaybeBindToTemporary(TheCall); + ExprResult R = MaybeBindToTemporary(TheCall); + if (R.isInvalid()) + return ExprError(); + + // For a rewritten candidate, we've already reversed the arguments + // if needed. Perform the rest of the rewrite now. + if ((Best->RewriteKind & CRK_DifferentOperator) || + (Op == OO_Spaceship && IsReversed)) { + if (Op == OO_ExclaimEqual) { + assert(ChosenOp == OO_EqualEqual && "unexpected operator name"); + R = CreateBuiltinUnaryOp(OpLoc, UO_LNot, R.get()); + } else { + assert(ChosenOp == OO_Spaceship && "unexpected operator name"); + llvm::APSInt Zero(Context.getTypeSize(Context.IntTy), false); + Expr *ZeroLiteral = + IntegerLiteral::Create(Context, Zero, Context.IntTy, OpLoc); + + Sema::CodeSynthesisContext Ctx; + Ctx.Kind = Sema::CodeSynthesisContext::RewritingOperatorAsSpaceship; + Ctx.Entity = FnDecl; + pushCodeSynthesisContext(Ctx); + + R = CreateOverloadedBinOp( + OpLoc, Opc, Fns, IsReversed ? ZeroLiteral : R.get(), + IsReversed ? R.get() : ZeroLiteral, PerformADL, + /*AllowRewrittenCandidates=*/false); + + popCodeSynthesisContext(); + } + if (R.isInvalid()) + return ExprError(); + } else { + assert(ChosenOp == Op && "unexpected operator name"); + } + + // Make a note in the AST if we did any rewriting. + if (Best->RewriteKind != CRK_None) + R = new (Context) CXXRewrittenBinaryOperator(R.get(), IsReversed); + + return R; } else { // We matched a built-in operator. Convert the arguments, then // break out so that we will build the appropriate built-in @@ -12753,10 +13078,12 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, return ExprError(); } CandidateSet.NoteCandidates( - PartialDiagnosticAt(OpLoc, PDiag(diag::err_ovl_deleted_oper) - << BinaryOperator::getOpcodeStr(Opc) - << Args[0]->getSourceRange() - << Args[1]->getSourceRange()), + PartialDiagnosticAt( + OpLoc, PDiag(diag::err_ovl_deleted_oper) + << getOperatorSpelling(Best->Function->getDeclName() + .getCXXOverloadedOperator()) + << Args[0]->getSourceRange() + << Args[1]->getSourceRange()), *this, OCD_AllCandidates, Args, BinaryOperator::getOpcodeStr(Opc), OpLoc); return ExprError(); @@ -13633,8 +13960,8 @@ ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R, OverloadCandidateSet CandidateSet(UDSuffixLoc, OverloadCandidateSet::CSK_Normal); - AddFunctionCandidates(R.asUnresolvedSet(), Args, CandidateSet, TemplateArgs, - /*SuppressUserConversions=*/true); + AddNonMemberOperatorCandidates(R.asUnresolvedSet(), Args, CandidateSet, + TemplateArgs); bool HadMultipleCandidates = (CandidateSet.size() > 1); |