diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h index 0d74816dfd06..376db92d03bd 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -531,13 +531,6 @@ namespace clang { Ambiguous.construct(); } - void setAsIdentityConversion(QualType T) { - setStandard(); - Standard.setAsIdentityConversion(); - Standard.setFromType(T); - Standard.setAllToTypes(T); - } - /// \brief Whether the target is really a std::initializer_list, and the /// sequence only represents the worst element conversion. bool isStdInitializerListElement() const { @@ -610,11 +603,6 @@ namespace clang { ovl_fail_ext_disabled, }; - /// A list of implicit conversion sequences for the arguments of an - /// OverloadCandidate. - typedef llvm::MutableArrayRef - ConversionSequenceList; - /// OverloadCandidate - A single candidate in an overload set (C++ 13.3). struct OverloadCandidate { /// Function - The actual function that this candidate @@ -639,13 +627,18 @@ namespace clang { /// is a surrogate, but only if IsSurrogate is true. CXXConversionDecl *Surrogate; - /// The conversion sequences used to convert the function arguments - /// to the function parameters. - ConversionSequenceList Conversions; + /// Conversions - The conversion sequences used to convert the + /// function arguments to the function parameters, the pointer points to a + /// fixed size array with NumConversions elements. The memory is owned by + /// the OverloadCandidateSet. + ImplicitConversionSequence *Conversions; /// The FixIt hints which can be used to fix the Bad candidate. ConversionFixItGenerator Fix; + /// NumConversions - The number of elements in the Conversions array. + unsigned NumConversions; + /// Viable - True to indicate that this overload candidate is viable. bool Viable; @@ -684,9 +677,9 @@ namespace clang { /// hasAmbiguousConversion - Returns whether this overload /// candidate requires an ambiguous conversion or not. bool hasAmbiguousConversion() const { - for (auto &C : Conversions) { - if (!C.isInitialized()) return false; - if (C.isAmbiguous()) return true; + for (unsigned i = 0, e = NumConversions; i != e; ++i) { + if (!Conversions[i].isInitialized()) return false; + if (Conversions[i].isAmbiguous()) return true; } return false; } @@ -735,7 +728,7 @@ namespace clang { SmallVector Candidates; llvm::SmallPtrSet Functions; - // Allocator for ConversionSequenceLists. We store the first few + // Allocator for OverloadCandidate::Conversions. We store the first few // elements inline to avoid allocation for small sets. llvm::BumpPtrAllocator ConversionSequenceAllocator; @@ -776,45 +769,30 @@ namespace clang { size_t size() const { return Candidates.size(); } bool empty() const { return Candidates.empty(); } - /// \brief Allocate storage for conversion sequences for NumConversions - /// conversions. - ConversionSequenceList - allocateConversionSequences(unsigned NumConversions) { - ImplicitConversionSequence *Conversions; + /// \brief Add a new candidate with NumConversions conversion sequence slots + /// to the overload set. + OverloadCandidate &addCandidate(unsigned NumConversions = 0) { + Candidates.push_back(OverloadCandidate()); + OverloadCandidate &C = Candidates.back(); // Assign space from the inline array if there are enough free slots // available. if (NumConversions + NumInlineSequences <= 16) { ImplicitConversionSequence *I = (ImplicitConversionSequence *)InlineSpace.buffer; - Conversions = &I[NumInlineSequences]; + C.Conversions = &I[NumInlineSequences]; NumInlineSequences += NumConversions; } else { // Otherwise get memory from the allocator. - Conversions = - ConversionSequenceAllocator.Allocate( - NumConversions); + C.Conversions = ConversionSequenceAllocator + .Allocate(NumConversions); } // Construct the new objects. - for (unsigned I = 0; I != NumConversions; ++I) - new (&Conversions[I]) ImplicitConversionSequence(); + for (unsigned i = 0; i != NumConversions; ++i) + new (&C.Conversions[i]) ImplicitConversionSequence(); - return ConversionSequenceList(Conversions, NumConversions); - } - - /// \brief Add a new candidate with NumConversions conversion sequence slots - /// to the overload set. - OverloadCandidate &addCandidate(unsigned NumConversions = 0, - ConversionSequenceList Conversions = None) { - assert((Conversions.empty() || Conversions.size() == NumConversions) && - "preallocated conversion sequence has wrong length"); - - Candidates.push_back(OverloadCandidate()); - OverloadCandidate &C = Candidates.back(); - C.Conversions = Conversions.empty() - ? allocateConversionSequences(NumConversions) - : Conversions; + C.NumConversions = NumConversions; return C; } diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index a7e563d3b86b..82caaeb24ae7 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -119,7 +119,6 @@ namespace clang { class FunctionProtoType; class FunctionTemplateDecl; class ImplicitConversionSequence; - typedef MutableArrayRef ConversionSequenceList; class InitListExpr; class InitializationKind; class InitializationSequence; @@ -2511,11 +2510,10 @@ public: void AddOverloadCandidate(FunctionDecl *Function, DeclAccessPair FoundDecl, ArrayRef Args, - OverloadCandidateSet &CandidateSet, + OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false, bool PartialOverloading = false, - bool AllowExplicit = false, - ConversionSequenceList EarlyConversions = None); + bool AllowExplicit = false); void AddFunctionCandidates(const UnresolvedSetImpl &Functions, ArrayRef Args, OverloadCandidateSet &CandidateSet, @@ -2535,8 +2533,7 @@ public: ArrayRef Args, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false, - bool PartialOverloading = false, - ConversionSequenceList EarlyConversions = None); + bool PartialOverloading = false); void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, @@ -2554,15 +2551,6 @@ public: OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false, bool PartialOverloading = false); - bool CheckNonDependentConversions(FunctionTemplateDecl *FunctionTemplate, - ArrayRef Args, - OverloadCandidateSet &CandidateSet, - ConversionSequenceList &Conversions, - bool SuppressUserConversions, - CXXRecordDecl *ActingContext = nullptr, - QualType ObjectType = QualType(), - Expr::Classification - ObjectClassification = {}); void AddConversionCandidate(CXXConversionDecl *Conversion, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, @@ -6591,8 +6579,6 @@ public: /// \brief The arguments included an overloaded function name that could /// not be resolved to a suitable function. TDK_FailedOverloadResolution, - /// \brief Checking non-dependent argument conversions failed. - TDK_NonDependentConversionFailure, /// \brief Deduction failed; that's all we know. TDK_MiscellaneousDeductionFailure, /// \brief CUDA Target attributes do not match. @@ -6630,14 +6616,14 @@ public: QualType OriginalArgType; }; - TemplateDeductionResult FinishTemplateArgumentDeduction( - FunctionTemplateDecl *FunctionTemplate, - SmallVectorImpl &Deduced, - unsigned NumExplicitlySpecified, FunctionDecl *&Specialization, - sema::TemplateDeductionInfo &Info, - SmallVectorImpl const *OriginalCallArgs = nullptr, - bool PartialOverloading = false, - llvm::function_ref CheckNonDependent = []{ return false; }); + TemplateDeductionResult + FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, + SmallVectorImpl &Deduced, + unsigned NumExplicitlySpecified, + FunctionDecl *&Specialization, + sema::TemplateDeductionInfo &Info, + SmallVectorImpl const *OriginalCallArgs = nullptr, + bool PartialOverloading = false); TemplateDeductionResult DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, @@ -6645,8 +6631,7 @@ public: ArrayRef Args, FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info, - bool PartialOverloading, - llvm::function_ref CheckNonDependent); + bool PartialOverloading = false); TemplateDeductionResult DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index a2ee2b00ecfc..47e3df20d911 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -589,6 +589,7 @@ clang::MakeDeductionFailureInfo(ASTContext &Context, Result.Result = static_cast(TDK); Result.HasDiagnostic = false; switch (TDK) { + case Sema::TDK_Success: case Sema::TDK_Invalid: case Sema::TDK_InstantiationDepth: case Sema::TDK_TooManyArguments: @@ -647,10 +648,6 @@ clang::MakeDeductionFailureInfo(ASTContext &Context, case Sema::TDK_FailedOverloadResolution: Result.Data = Info.Expression; break; - - case Sema::TDK_Success: - case Sema::TDK_NonDependentConversionFailure: - llvm_unreachable("not a deduction failure"); } return Result; @@ -667,7 +664,6 @@ void DeductionFailureInfo::Destroy() { case Sema::TDK_InvalidExplicitArguments: case Sema::TDK_FailedOverloadResolution: case Sema::TDK_CUDATargetMismatch: - case Sema::TDK_NonDependentConversionFailure: break; case Sema::TDK_Inconsistent: @@ -711,7 +707,6 @@ TemplateParameter DeductionFailureInfo::getTemplateParameter() { case Sema::TDK_NonDeducedMismatch: case Sema::TDK_FailedOverloadResolution: case Sema::TDK_CUDATargetMismatch: - case Sema::TDK_NonDependentConversionFailure: return TemplateParameter(); case Sema::TDK_Incomplete: @@ -744,7 +739,6 @@ TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() { case Sema::TDK_NonDeducedMismatch: case Sema::TDK_FailedOverloadResolution: case Sema::TDK_CUDATargetMismatch: - case Sema::TDK_NonDependentConversionFailure: return nullptr; case Sema::TDK_DeducedMismatch: @@ -773,7 +767,6 @@ const TemplateArgument *DeductionFailureInfo::getFirstArg() { case Sema::TDK_SubstitutionFailure: case Sema::TDK_FailedOverloadResolution: case Sema::TDK_CUDATargetMismatch: - case Sema::TDK_NonDependentConversionFailure: return nullptr; case Sema::TDK_Inconsistent: @@ -802,7 +795,6 @@ const TemplateArgument *DeductionFailureInfo::getSecondArg() { case Sema::TDK_SubstitutionFailure: case Sema::TDK_FailedOverloadResolution: case Sema::TDK_CUDATargetMismatch: - case Sema::TDK_NonDependentConversionFailure: return nullptr; case Sema::TDK_Inconsistent: @@ -837,8 +829,8 @@ llvm::Optional DeductionFailureInfo::getCallArgIndex() { void OverloadCandidateSet::destroyCandidates() { for (iterator i = begin(), e = end(); i != e; ++i) { - for (auto &C : i->Conversions) - C.~ImplicitConversionSequence(); + for (unsigned ii = 0, ie = i->NumConversions; ii != ie; ++ii) + i->Conversions[ii].~ImplicitConversionSequence(); if (!i->Viable && i->FailureKind == ovl_fail_bad_deduction) i->DeductionFailure.Destroy(); } @@ -5845,8 +5837,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, bool PartialOverloading, - bool AllowExplicit, - ConversionSequenceList EarlyConversions) { + bool AllowExplicit) { const FunctionProtoType *Proto = dyn_cast(Function->getType()->getAs()); assert(Proto && "Functions without a prototype cannot be overloaded"); @@ -5865,7 +5856,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, AddMethodCandidate(Method, FoundDecl, Method->getParent(), QualType(), Expr::Classification::makeSimpleLValue(), Args, CandidateSet, SuppressUserConversions, - PartialOverloading, EarlyConversions); + PartialOverloading); return; } // We treat a constructor like a non-member function, since its object @@ -5898,8 +5889,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); // Add this candidate - OverloadCandidate &Candidate = - CandidateSet.addCandidate(Args.size(), EarlyConversions); + OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size()); Candidate.FoundDecl = FoundDecl; Candidate.Function = Function; Candidate.Viable = true; @@ -5963,10 +5953,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, // Determine the implicit conversion sequences for each of the // arguments. for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) { - if (Candidate.Conversions[ArgIdx].isInitialized()) { - // We already formed a conversion sequence for this parameter during - // template argument deduction. - } else if (ArgIdx < NumParams) { + if (ArgIdx < NumParams) { // (C++ 13.3.2p3): for F to be a viable function, there shall // exist for each argument an implicit conversion sequence // (13.3.3.1) that converts that argument to the corresponding @@ -6275,8 +6262,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, ArrayRef Args, OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, - bool PartialOverloading, - ConversionSequenceList EarlyConversions) { + bool PartialOverloading) { const FunctionProtoType *Proto = dyn_cast(Method->getType()->getAs()); assert(Proto && "Methods without a prototype cannot be overloaded"); @@ -6297,8 +6283,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); // Add this candidate - OverloadCandidate &Candidate = - CandidateSet.addCandidate(Args.size() + 1, EarlyConversions); + OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size() + 1); Candidate.FoundDecl = FoundDecl; Candidate.Function = Method; Candidate.IsSurrogate = false; @@ -6360,10 +6345,7 @@ 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()) { - // We already formed a conversion sequence for this parameter during - // template argument deduction. - } else if (ArgIdx < NumParams) { + if (ArgIdx < NumParams) { // (C++ 13.3.2p3): for F to be a viable function, there shall // exist for each argument an implicit conversion sequence // (13.3.3.1) that converts that argument to the corresponding @@ -6424,30 +6406,19 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, // functions. TemplateDeductionInfo Info(CandidateSet.getLocation()); FunctionDecl *Specialization = nullptr; - ConversionSequenceList Conversions; - if (TemplateDeductionResult Result = DeduceTemplateArguments( - MethodTmpl, ExplicitTemplateArgs, Args, Specialization, Info, - PartialOverloading, [&]() { - return CheckNonDependentConversions( - MethodTmpl, Args, CandidateSet, Conversions, - SuppressUserConversions, ActingContext, ObjectType, - ObjectClassification); - })) { - OverloadCandidate &Candidate = - CandidateSet.addCandidate(Conversions.size(), Conversions); + if (TemplateDeductionResult Result + = DeduceTemplateArguments(MethodTmpl, ExplicitTemplateArgs, Args, + Specialization, Info, PartialOverloading)) { + OverloadCandidate &Candidate = CandidateSet.addCandidate(); Candidate.FoundDecl = FoundDecl; Candidate.Function = MethodTmpl->getTemplatedDecl(); Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_deduction; Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = false; Candidate.ExplicitCallArguments = Args.size(); - if (Result == TDK_NonDependentConversionFailure) - Candidate.FailureKind = ovl_fail_bad_conversion; - else { - Candidate.FailureKind = ovl_fail_bad_deduction; - Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, - Info); - } + Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, + Info); return; } @@ -6458,8 +6429,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, "Specialization is not a member function?"); AddMethodCandidate(cast(Specialization), FoundDecl, ActingContext, ObjectType, ObjectClassification, Args, - CandidateSet, SuppressUserConversions, PartialOverloading, - Conversions); + CandidateSet, SuppressUserConversions, PartialOverloading); } /// \brief Add a C++ function template specialization as a candidate @@ -6487,29 +6457,19 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, // functions. TemplateDeductionInfo Info(CandidateSet.getLocation()); FunctionDecl *Specialization = nullptr; - ConversionSequenceList Conversions; - if (TemplateDeductionResult Result = DeduceTemplateArguments( - FunctionTemplate, ExplicitTemplateArgs, Args, Specialization, Info, - PartialOverloading, [&]() { - return CheckNonDependentConversions(FunctionTemplate, Args, - CandidateSet, Conversions, - SuppressUserConversions); - })) { - OverloadCandidate &Candidate = - CandidateSet.addCandidate(Conversions.size(), Conversions); + if (TemplateDeductionResult Result + = DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs, Args, + Specialization, Info, PartialOverloading)) { + OverloadCandidate &Candidate = CandidateSet.addCandidate(); Candidate.FoundDecl = FoundDecl; Candidate.Function = FunctionTemplate->getTemplatedDecl(); Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_deduction; Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = false; Candidate.ExplicitCallArguments = Args.size(); - if (Result == TDK_NonDependentConversionFailure) - Candidate.FailureKind = ovl_fail_bad_conversion; - else { - Candidate.FailureKind = ovl_fail_bad_deduction; - Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, - Info); - } + Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, + Info); return; } @@ -6517,64 +6477,7 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, // deduction as a candidate. assert(Specialization && "Missing function template specialization?"); AddOverloadCandidate(Specialization, FoundDecl, Args, CandidateSet, - SuppressUserConversions, PartialOverloading, - /*AllowExplicit*/false, Conversions); -} - -/// Check that implicit conversion sequences can be formed for each argument -/// whose corresponding parameter has a non-dependent type, per DR1391's -/// [temp.deduct.call]p10. -bool Sema::CheckNonDependentConversions( - FunctionTemplateDecl *FunctionTemplate, ArrayRef Args, - OverloadCandidateSet &CandidateSet, ConversionSequenceList &Conversions, - bool SuppressUserConversions, CXXRecordDecl *ActingContext, - QualType ObjectType, Expr::Classification ObjectClassification) { - // 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. - const bool AllowExplicit = false; - - auto *FD = FunctionTemplate->getTemplatedDecl(); - auto *Method = dyn_cast(FD); - bool HasThisConversion = Method && !isa(Method); - unsigned ThisConversions = HasThisConversion ? 1 : 0; - - Conversions = - CandidateSet.allocateConversionSequences(ThisConversions + Args.size()); - - // Overload resolution is always an unevaluated context. - EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); - - // For a method call, check the 'this' conversion here too. DR1391 doesn't - // require that, but this check should never result in a hard error, and - // overload resolution is permitted to sidestep instantiations. - if (HasThisConversion && !cast(FD)->isStatic() && - !ObjectType.isNull()) { - Conversions[0] = TryObjectArgumentInitialization( - *this, CandidateSet.getLocation(), ObjectType, ObjectClassification, - Method, ActingContext); - if (Conversions[0].isBad()) - return true; - } - - - for (unsigned I = 0, N = std::min(FD->getNumParams(), Args.size()); - I != N; ++I) { - QualType ParamType = FD->getParamDecl(I)->getType(); - if (!ParamType->isDependentType()) { - Conversions[ThisConversions + I] - = TryCopyInitialization(*this, Args[I], ParamType, - SuppressUserConversions, - /*InOverloadResolution=*/true, - /*AllowObjCWritebackConversion=*/ - getLangOpts().ObjCAutoRefCount, - AllowExplicit); - if (Conversions[ThisConversions + I].isBad()) - return true; - } - } - - return false; + SuppressUserConversions, PartialOverloading); } /// Determine whether this is an allowable conversion from the result @@ -8813,8 +8716,8 @@ bool clang::isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1, // Define functions that don't require ill-formed conversions for a given // argument to be better candidates than functions that do. - unsigned NumArgs = Cand1.Conversions.size(); - assert(Cand2.Conversions.size() == NumArgs && "Overload candidate mismatch"); + unsigned NumArgs = Cand1.NumConversions; + assert(Cand2.NumConversions == NumArgs && "Overload candidate mismatch"); bool HasBetterConversion = false; for (unsigned ArgIdx = StartArg; ArgIdx < NumArgs; ++ArgIdx) { bool Cand1Bad = IsIllFormedConversion(Cand1.Conversions[ArgIdx]); @@ -10021,7 +9924,7 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, case ovl_fail_bad_conversion: { unsigned I = (Cand->IgnoreObjectArgument ? 1 : 0); - for (unsigned N = Cand->Conversions.size(); I != N; ++I) + for (unsigned N = Cand->NumConversions; I != N; ++I) if (Cand->Conversions[I].isBad()) return DiagnoseBadConversion(S, Cand, I, TakingCandidateAddress); @@ -10084,12 +9987,12 @@ static void NoteSurrogateCandidate(Sema &S, OverloadCandidate *Cand) { static void NoteBuiltinOperatorCandidate(Sema &S, StringRef Opc, SourceLocation OpLoc, OverloadCandidate *Cand) { - assert(Cand->Conversions.size() <= 2 && "builtin operator is not binary"); + assert(Cand->NumConversions <= 2 && "builtin operator is not binary"); std::string TypeStr("operator"); TypeStr += Opc; TypeStr += "("; TypeStr += Cand->BuiltinTypes.ParamTypes[0].getAsString(); - if (Cand->Conversions.size() == 1) { + if (Cand->NumConversions == 1) { TypeStr += ")"; S.Diag(OpLoc, diag::note_ovl_builtin_unary_candidate) << TypeStr; } else { @@ -10102,7 +10005,9 @@ static void NoteBuiltinOperatorCandidate(Sema &S, StringRef Opc, static void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc, OverloadCandidate *Cand) { - for (const ImplicitConversionSequence &ICS : Cand->Conversions) { + unsigned NoOperands = Cand->NumConversions; + for (unsigned ArgIdx = 0; ArgIdx < NoOperands; ++ArgIdx) { + const ImplicitConversionSequence &ICS = Cand->Conversions[ArgIdx]; if (ICS.isBad()) break; // all meaningless after first invalid if (!ICS.isAmbiguous()) continue; @@ -10122,8 +10027,7 @@ static SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) { static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) { switch ((Sema::TemplateDeductionResult)DFI.Result) { case Sema::TDK_Success: - case Sema::TDK_NonDependentConversionFailure: - llvm_unreachable("non-deduction failure while diagnosing bad deduction"); + llvm_unreachable("TDK_success while diagnosing bad deduction"); case Sema::TDK_Invalid: case Sema::TDK_Incomplete: @@ -10226,11 +10130,11 @@ struct CompareOverloadCandidatesForDisplay { // If there's any ordering between the defined conversions... // FIXME: this might not be transitive. - assert(L->Conversions.size() == R->Conversions.size()); + assert(L->NumConversions == R->NumConversions); int leftBetter = 0; unsigned I = (L->IgnoreObjectArgument || R->IgnoreObjectArgument); - for (unsigned E = L->Conversions.size(); I != E; ++I) { + for (unsigned E = L->NumConversions; I != E; ++I) { switch (CompareImplicitConversionSequences(S, Loc, L->Conversions[I], R->Conversions[I])) { @@ -10279,8 +10183,7 @@ struct CompareOverloadCandidatesForDisplay { } /// CompleteNonViableCandidate - Normally, overload resolution only -/// computes up to the first bad conversion. Produces the FixIt set if -/// possible. +/// computes up to the first. Produces the FixIt set if possible. static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, ArrayRef Args) { assert(!Cand->Viable); @@ -10293,24 +10196,30 @@ static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, // Use a implicit copy initialization to check conversion fixes. Cand->Fix.setConversionChecker(TryCopyInitialization); - // Attempt to fix the bad conversion. - unsigned ConvCount = Cand->Conversions.size(); - for (unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0); /**/; - ++ConvIdx) { + // Skip forward to the first bad conversion. + unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0); + unsigned ConvCount = Cand->NumConversions; + while (true) { assert(ConvIdx != ConvCount && "no bad conversion in candidate"); - if (Cand->Conversions[ConvIdx].isInitialized() && - Cand->Conversions[ConvIdx].isBad()) { - Unfixable = !Cand->TryToFixBadConversion(ConvIdx, S); + ConvIdx++; + if (Cand->Conversions[ConvIdx - 1].isBad()) { + Unfixable = !Cand->TryToFixBadConversion(ConvIdx - 1, S); break; } } + if (ConvIdx == ConvCount) + return; + + assert(!Cand->Conversions[ConvIdx].isInitialized() && + "remaining conversion is initialized?"); + // FIXME: this should probably be preserved from the overload // operation somehow. bool SuppressUserConversions = false; - const FunctionProtoType *Proto; - unsigned ArgIdx = 0; + const FunctionProtoType* Proto; + unsigned ArgIdx = ConvIdx; if (Cand->IsSurrogate) { QualType ConvType @@ -10318,56 +10227,40 @@ static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, if (const PointerType *ConvPtrType = ConvType->getAs()) ConvType = ConvPtrType->getPointeeType(); Proto = ConvType->getAs(); - ArgIdx = 1; + ArgIdx--; } else if (Cand->Function) { Proto = Cand->Function->getType()->getAs(); if (isa(Cand->Function) && !isa(Cand->Function)) - ArgIdx = 1; + ArgIdx--; } else { // Builtin binary operator with a bad first conversion. assert(ConvCount <= 3); - for (unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0); - ConvIdx != ConvCount; ++ConvIdx) { - if (Cand->Conversions[ConvIdx].isInitialized()) - continue; - if (Cand->BuiltinTypes.ParamTypes[ConvIdx]->isDependentType()) - Cand->Conversions[ConvIdx].setAsIdentityConversion( - Args[ConvIdx]->getType()); - else - Cand->Conversions[ConvIdx] = TryCopyInitialization( - S, Args[ConvIdx], Cand->BuiltinTypes.ParamTypes[ConvIdx], - SuppressUserConversions, - /*InOverloadResolution*/ true, - /*AllowObjCWritebackConversion=*/ - S.getLangOpts().ObjCAutoRefCount); - // FIXME: If the conversion is bad, try to fix it. - } + for (; ConvIdx != ConvCount; ++ConvIdx) + Cand->Conversions[ConvIdx] + = TryCopyInitialization(S, Args[ConvIdx], + Cand->BuiltinTypes.ParamTypes[ConvIdx], + SuppressUserConversions, + /*InOverloadResolution*/ true, + /*AllowObjCWritebackConversion=*/ + S.getLangOpts().ObjCAutoRefCount); return; } // Fill in the rest of the conversions. unsigned NumParams = Proto->getNumParams(); - for (unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0); - ConvIdx != ConvCount; ++ConvIdx, ++ArgIdx) { - if (Cand->Conversions[ConvIdx].isInitialized()) { - // Found the bad conversion. - } else if (ArgIdx < NumParams) { - if (Proto->getParamType(ArgIdx)->isDependentType()) - Cand->Conversions[ConvIdx].setAsIdentityConversion( - Args[ArgIdx]->getType()); - else { - Cand->Conversions[ConvIdx] = - TryCopyInitialization(S, Args[ArgIdx], Proto->getParamType(ArgIdx), - SuppressUserConversions, - /*InOverloadResolution=*/true, - /*AllowObjCWritebackConversion=*/ - S.getLangOpts().ObjCAutoRefCount); - // Store the FixIt in the candidate if it exists. - if (!Unfixable && Cand->Conversions[ConvIdx].isBad()) - Unfixable = !Cand->TryToFixBadConversion(ConvIdx, S); - } - } else + for (; ConvIdx != ConvCount; ++ConvIdx, ++ArgIdx) { + if (ArgIdx < NumParams) { + Cand->Conversions[ConvIdx] = TryCopyInitialization( + S, Args[ArgIdx], Proto->getParamType(ArgIdx), SuppressUserConversions, + /*InOverloadResolution=*/true, + /*AllowObjCWritebackConversion=*/ + S.getLangOpts().ObjCAutoRefCount); + // Store the FixIt in the candidate if it exists. + if (!Unfixable && Cand->Conversions[ConvIdx].isBad()) + Unfixable = !Cand->TryToFixBadConversion(ConvIdx, S); + } + else Cand->Conversions[ConvIdx].setEllipsis(); } } diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index dc291836fb94..0bc85a2f2635 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -2849,13 +2849,14 @@ CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg, /// /// \param OriginalCallArgs If non-NULL, the original call arguments against /// which the deduced argument types should be compared. -Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( - FunctionTemplateDecl *FunctionTemplate, - SmallVectorImpl &Deduced, - unsigned NumExplicitlySpecified, FunctionDecl *&Specialization, - TemplateDeductionInfo &Info, - SmallVectorImpl const *OriginalCallArgs, - bool PartialOverloading, llvm::function_ref CheckNonDependent) { +Sema::TemplateDeductionResult +Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, + SmallVectorImpl &Deduced, + unsigned NumExplicitlySpecified, + FunctionDecl *&Specialization, + TemplateDeductionInfo &Info, + SmallVectorImpl const *OriginalCallArgs, + bool PartialOverloading) { // Unevaluated SFINAE context. EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); SFINAETrap Trap(*this); @@ -2882,18 +2883,6 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( PartialOverloading)) return Result; - // C++ [temp.deduct.call]p10: [DR1391] - // If deduction succeeds for all parameters that contain - // template-parameters that participate in template argument deduction, - // and all template arguments are explicitly specified, deduced, or - // obtained from default template arguments, remaining parameters are then - // compared with the corresponding arguments. For each remaining parameter - // P with a type that was non-dependent before substitution of any - // explicitly-specified template arguments, if the corresponding argument - // A cannot be implicitly converted to P, deduction fails. - if (CheckNonDependent()) - return TDK_NonDependentConversionFailure; - // Form the template argument list from the deduced template arguments. TemplateArgumentList *DeducedArgumentList = TemplateArgumentList::CreateCopy(Context, Builder); @@ -3318,17 +3307,12 @@ DeduceTemplateArgumentByListElement(Sema &S, /// \param Info the argument will be updated to provide additional information /// about template argument deduction. /// -/// \param CheckNonDependent A callback to invoke to check conversions for -/// non-dependent parameters, between deduction and substitution, per DR1391. -/// If this returns true, substitution will be skipped and we return -/// TDK_NonDependentConversionFailure. -/// /// \returns the result of template argument deduction. Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( FunctionTemplateDecl *FunctionTemplate, TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef Args, FunctionDecl *&Specialization, TemplateDeductionInfo &Info, - bool PartialOverloading, llvm::function_ref CheckNonDependent) { + bool PartialOverloading) { if (FunctionTemplate->isInvalidDecl()) return TDK_Invalid; @@ -3512,7 +3496,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, NumExplicitlySpecified, Specialization, Info, &OriginalCallArgs, - PartialOverloading, CheckNonDependent); + PartialOverloading); } QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType, diff --git a/clang/test/CXX/drs/dr13xx.cpp b/clang/test/CXX/drs/dr13xx.cpp index b9be5ca821c5..28bebcbb607e 100644 --- a/clang/test/CXX/drs/dr13xx.cpp +++ b/clang/test/CXX/drs/dr13xx.cpp @@ -174,81 +174,3 @@ namespace dr1359 { // dr1359: 3.5 constexpr Y y = Y(); // expected-error {{no matching}} #endif } - -namespace dr1391 { // dr1391: partial - struct A {}; struct B : A {}; - template struct C { C(int); typename T::error error; }; // expected-error 2{{'::'}} - template struct D {}; - - // No deduction is performed for parameters with no deducible template-parameters, therefore types do not need to match. - template void a(T, int T::*); - void test_a(int A::*p) { a(A(), p); } // ok, type of second parameter does not need to match - - namespace dr_example_1 { - template void f(C); - template void f(D); - - void g(D d) { - f(d); // ok, first 'f' eliminated by deduction failure - f(d); // ok, first 'f' eliminated because 'U' cannot be deduced - } - } - - namespace dr_example_2 { - template typename C::error f(int, T); - template T f(T, T); - - void g(A a) { - f(a, a); // ok, no conversion from A to int for first parameter of first candidate - } - } - - namespace std_example { - template struct Z { - typedef typename T::x xx; - }; - template typename Z::xx f(void *, T); - template void f(int, T); - struct A {} a; - void g() { f(1, a); } - } - - template void b(C ci, T *p); - void b(...); - void test_b() { - b(0, 0); // ok, deduction fails prior to forming a conversion sequence and instantiating C - // FIXME: The "while substituting" note should point at the overload candidate. - b(0, 0); // expected-note {{instantiation of}} expected-note {{while substituting}} - } - - template struct Id { typedef T type; }; - template void c(T, typename Id >::type); - void test_c() { - // Implicit conversion sequences for dependent types are checked later. - c(0.0, 0); // expected-note {{instantiation of}} - } - - namespace partial_ordering { - // FIXME: Second template should be considered more specialized because non-dependent parameter is ignored. - template int a(T, short) = delete; // expected-error 0-1{{extension}} expected-note {{candidate}} - template int a(T*, char); // expected-note {{candidate}} - int test_a = a((int*)0, 0); // FIXME: expected-error {{ambiguous}} - - // FIXME: Second template should be considered more specialized: - // deducing #1 from #2 ignores the second P/A pair, so deduction succeeds, - // deducing #2 from #1 fails to deduce T, so deduction fails. - template int b(T, int) = delete; // expected-error 0-1{{extension}} expected-note {{candidate}} - template int b(T*, U); // expected-note {{candidate}} - int test_b = b((int*)0, 0); // FIXME: expected-error {{ambiguous}} - - // Unintended consequences: because partial ordering does not consider - // explicit template arguments, and deduction from a non-dependent type - // vacuously succeeds, a non-dependent template is less specialized than - // anything else! - // According to DR1391, this is ambiguous! - template int c(int); - template int c(T); - int test_c1 = c(0); // ok - int test_c2 = c(0); // FIXME: apparently ambiguous - } -} diff --git a/clang/test/Misc/diag-template-diffing.cpp b/clang/test/Misc/diag-template-diffing.cpp index 2192223191bb..780839899282 100644 --- a/clang/test/Misc/diag-template-diffing.cpp +++ b/clang/test/Misc/diag-template-diffing.cpp @@ -1401,7 +1401,7 @@ void run() { f(1, integral_constant{}); } // CHECK-ELIDE-NOTREE: error: no matching function for call to 'f' -// CHECK-ELIDE-NOTREE: note: candidate function not viable: no known conversion from 'integral_constant<[...], true>' to 'integral_constant<[...], false>' for 2nd argument +// CHECK-ELIDE-NOTREE: note: candidate function [with T = int] not viable: no known conversion from 'integral_constant<[...], true>' to 'integral_constant<[...], false>' for 2nd argument } namespace ZeroArgs { diff --git a/clang/test/SemaCXX/overload-call.cpp b/clang/test/SemaCXX/overload-call.cpp index 0e3a9ee50bb2..3a01bf24b31a 100644 --- a/clang/test/SemaCXX/overload-call.cpp +++ b/clang/test/SemaCXX/overload-call.cpp @@ -338,7 +338,7 @@ namespace PR5756 { // Tests the exact text used to note the candidates namespace test1 { - template void foo(T t, unsigned N); // expected-note {{candidate function not viable: no known conversion from 'const char [6]' to 'unsigned int' for 2nd argument}} + template void foo(T t, unsigned N); // expected-note {{candidate function [with T = int] not viable: no known conversion from 'const char [6]' to 'unsigned int' for 2nd argument}} void foo(int n, char N); // expected-note {{candidate function not viable: no known conversion from 'const char [6]' to 'char' for 2nd argument}} void foo(int n, const char *s, int t); // expected-note {{candidate function not viable: requires 3 arguments, but 2 were provided}} void foo(int n, const char *s, int t, ...); // expected-note {{candidate function not viable: requires at least 3 arguments, but 2 were provided}} diff --git a/clang/test/SemaCXX/overload-member-call.cpp b/clang/test/SemaCXX/overload-member-call.cpp index 6e64b25d6b53..e0f34d937f6f 100644 --- a/clang/test/SemaCXX/overload-member-call.cpp +++ b/clang/test/SemaCXX/overload-member-call.cpp @@ -70,7 +70,7 @@ void test_X2(X2 *x2p, const X2 *cx2p) { // Tests the exact text used to note the candidates namespace test1 { class A { - template void foo(T t, unsigned N); // expected-note {{candidate function not viable: no known conversion from 'const char [6]' to 'unsigned int' for 2nd argument}} + template void foo(T t, unsigned N); // expected-note {{candidate function [with T = int] not viable: no known conversion from 'const char [6]' to 'unsigned int' for 2nd argument}} void foo(int n, char N); // expected-note {{candidate function not viable: no known conversion from 'const char [6]' to 'char' for 2nd argument}} void foo(int n, const char *s, int t); // expected-note {{candidate function not viable: requires 3 arguments, but 2 were provided}} void foo(int n, const char *s, int t, ...); // expected-note {{candidate function not viable: requires at least 3 arguments, but 2 were provided}} diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index 90176314403f..b4936eed3b35 100644 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -8161,7 +8161,7 @@ and POD class 1391 DRWP Conversions to parameter types with non-deduced template arguments - Partial + Unknown 1392