diff options
| -rw-r--r-- | clang/include/clang/Sema/Overload.h | 61 | ||||
| -rw-r--r-- | clang/include/clang/Sema/Sema.h | 50 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 261 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateDeduction.cpp | 61 | ||||
| -rw-r--r-- | clang/test/CXX/drs/dr13xx.cpp | 78 | ||||
| -rw-r--r-- | clang/test/Misc/diag-template-diffing.cpp | 6 | ||||
| -rw-r--r-- | clang/test/SemaCXX/attr-mode-tmpl.cpp | 2 | ||||
| -rw-r--r-- | clang/test/SemaCXX/attr-noreturn.cpp | 10 | ||||
| -rw-r--r-- | clang/test/SemaCXX/overload-call.cpp | 2 | ||||
| -rw-r--r-- | clang/test/SemaCXX/overload-member-call.cpp | 2 | ||||
| -rw-r--r-- | clang/test/SemaTemplate/deduction.cpp | 4 | ||||
| -rw-r--r-- | clang/test/SemaTemplate/temp_arg_nontype.cpp | 8 | ||||
| -rw-r--r-- | clang/www/cxx_dr_status.html | 2 |
13 files changed, 400 insertions, 147 deletions
diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h index 14a9c319601..88fdc991f39 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -531,6 +531,13 @@ 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 { @@ -607,6 +614,11 @@ namespace clang { ovl_fail_inhctor_slice, }; + /// A list of implicit conversion sequences for the arguments of an + /// OverloadCandidate. + typedef llvm::MutableArrayRef<ImplicitConversionSequence> + ConversionSequenceList; + /// OverloadCandidate - A single candidate in an overload set (C++ 13.3). struct OverloadCandidate { /// Function - The actual function that this candidate @@ -631,18 +643,13 @@ namespace clang { /// is a surrogate, but only if IsSurrogate is true. CXXConversionDecl *Surrogate; - /// 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 conversion sequences used to convert the function arguments + /// to the function parameters. + ConversionSequenceList 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; @@ -701,9 +708,9 @@ namespace clang { /// hasAmbiguousConversion - Returns whether this overload /// candidate requires an ambiguous conversion or not. bool hasAmbiguousConversion() const { - for (unsigned i = 0, e = NumConversions; i != e; ++i) { - if (!Conversions[i].isInitialized()) return false; - if (Conversions[i].isAmbiguous()) return true; + for (auto &C : Conversions) { + if (!C.isInitialized()) return false; + if (C.isAmbiguous()) return true; } return false; } @@ -752,7 +759,7 @@ namespace clang { SmallVector<OverloadCandidate, 16> Candidates; llvm::SmallPtrSet<Decl *, 16> Functions; - // Allocator for OverloadCandidate::Conversions and DiagnoseIfAttr* arrays. + // Allocator for ConversionSequenceLists and DiagnoseIfAttr* arrays. // We store the first few of each of these inline to avoid allocation for // small sets. llvm::BumpPtrAllocator SlabAllocator; @@ -823,18 +830,32 @@ 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 = + slabAllocate<ImplicitConversionSequence>(NumConversions); + + // Construct the new objects. + for (unsigned I = 0; I != NumConversions; ++I) + new (&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) { + 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 = slabAllocate<ImplicitConversionSequence>(NumConversions); - // Construct the new objects. - for (unsigned i = 0; i != NumConversions; ++i) - new (&C.Conversions[i]) ImplicitConversionSequence(); - - C.NumConversions = NumConversions; + C.Conversions = Conversions.empty() + ? allocateConversionSequences(NumConversions) + : Conversions; return C; } diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 00e0b61f950..d5e4b069f8b 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -120,6 +120,7 @@ namespace clang { class FunctionProtoType; class FunctionTemplateDecl; class ImplicitConversionSequence; + typedef MutableArrayRef<ImplicitConversionSequence> ConversionSequenceList; class InitListExpr; class InitializationKind; class InitializationSequence; @@ -2518,10 +2519,11 @@ public: void AddOverloadCandidate(FunctionDecl *Function, DeclAccessPair FoundDecl, ArrayRef<Expr *> Args, - OverloadCandidateSet& CandidateSet, + OverloadCandidateSet &CandidateSet, bool SuppressUserConversions = false, bool PartialOverloading = false, - bool AllowExplicit = false); + bool AllowExplicit = false, + ConversionSequenceList EarlyConversions = None); void AddFunctionCandidates(const UnresolvedSetImpl &Functions, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, @@ -2541,7 +2543,8 @@ public: Expr *ThisArg, ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false, - bool PartialOverloading = false); + bool PartialOverloading = false, + ConversionSequenceList EarlyConversions = None); void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, @@ -2560,6 +2563,16 @@ public: OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false, bool PartialOverloading = false); + bool CheckNonDependentConversions(FunctionTemplateDecl *FunctionTemplate, + ArrayRef<QualType> ParamTypes, + ArrayRef<Expr *> Args, + OverloadCandidateSet &CandidateSet, + ConversionSequenceList &Conversions, + bool SuppressUserConversions, + CXXRecordDecl *ActingContext = nullptr, + QualType ObjectType = QualType(), + Expr::Classification + ObjectClassification = {}); void AddConversionCandidate(CXXConversionDecl *Conversion, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, @@ -6624,6 +6637,8 @@ public: /// \brief The explicitly-specified template arguments were not valid /// template arguments for the given template. TDK_InvalidExplicitArguments, + /// \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. @@ -6662,22 +6677,21 @@ public: QualType OriginalArgType; }; - TemplateDeductionResult - FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, - SmallVectorImpl<DeducedTemplateArgument> &Deduced, - unsigned NumExplicitlySpecified, - FunctionDecl *&Specialization, - sema::TemplateDeductionInfo &Info, - SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs = nullptr, - bool PartialOverloading = false); + TemplateDeductionResult FinishTemplateArgumentDeduction( + FunctionTemplateDecl *FunctionTemplate, + SmallVectorImpl<DeducedTemplateArgument> &Deduced, + unsigned NumExplicitlySpecified, FunctionDecl *&Specialization, + sema::TemplateDeductionInfo &Info, + SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs = nullptr, + bool PartialOverloading = false, + llvm::function_ref<bool()> CheckNonDependent = []{ return false; }); - TemplateDeductionResult - DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - TemplateArgumentListInfo *ExplicitTemplateArgs, - ArrayRef<Expr *> Args, - FunctionDecl *&Specialization, - sema::TemplateDeductionInfo &Info, - bool PartialOverloading = false); + TemplateDeductionResult DeduceTemplateArguments( + FunctionTemplateDecl *FunctionTemplate, + TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args, + FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info, + bool PartialOverloading, + llvm::function_ref<bool(ArrayRef<QualType>)> CheckNonDependent); TemplateDeductionResult DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index c0321d36a7c..41f4fa746fc 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -590,7 +590,6 @@ clang::MakeDeductionFailureInfo(ASTContext &Context, Result.Result = static_cast<unsigned>(TDK); Result.HasDiagnostic = false; switch (TDK) { - case Sema::TDK_Success: case Sema::TDK_Invalid: case Sema::TDK_InstantiationDepth: case Sema::TDK_TooManyArguments: @@ -646,6 +645,10 @@ clang::MakeDeductionFailureInfo(ASTContext &Context, Result.HasDiagnostic = true; } break; + + case Sema::TDK_Success: + case Sema::TDK_NonDependentConversionFailure: + llvm_unreachable("not a deduction failure"); } return Result; @@ -661,6 +664,7 @@ void DeductionFailureInfo::Destroy() { case Sema::TDK_TooFewArguments: case Sema::TDK_InvalidExplicitArguments: case Sema::TDK_CUDATargetMismatch: + case Sema::TDK_NonDependentConversionFailure: break; case Sema::TDK_Inconsistent: @@ -705,6 +709,7 @@ TemplateParameter DeductionFailureInfo::getTemplateParameter() { case Sema::TDK_DeducedMismatchNested: case Sema::TDK_NonDeducedMismatch: case Sema::TDK_CUDATargetMismatch: + case Sema::TDK_NonDependentConversionFailure: return TemplateParameter(); case Sema::TDK_Incomplete: @@ -736,6 +741,7 @@ TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() { case Sema::TDK_Underqualified: case Sema::TDK_NonDeducedMismatch: case Sema::TDK_CUDATargetMismatch: + case Sema::TDK_NonDependentConversionFailure: return nullptr; case Sema::TDK_DeducedMismatch: @@ -764,6 +770,7 @@ const TemplateArgument *DeductionFailureInfo::getFirstArg() { case Sema::TDK_InvalidExplicitArguments: case Sema::TDK_SubstitutionFailure: case Sema::TDK_CUDATargetMismatch: + case Sema::TDK_NonDependentConversionFailure: return nullptr; case Sema::TDK_Inconsistent: @@ -792,6 +799,7 @@ const TemplateArgument *DeductionFailureInfo::getSecondArg() { case Sema::TDK_InvalidExplicitArguments: case Sema::TDK_SubstitutionFailure: case Sema::TDK_CUDATargetMismatch: + case Sema::TDK_NonDependentConversionFailure: return nullptr; case Sema::TDK_Inconsistent: @@ -822,8 +830,8 @@ llvm::Optional<unsigned> DeductionFailureInfo::getCallArgIndex() { void OverloadCandidateSet::destroyCandidates() { for (iterator i = begin(), e = end(); i != e; ++i) { - for (unsigned ii = 0, ie = i->NumConversions; ii != ie; ++ii) - i->Conversions[ii].~ImplicitConversionSequence(); + for (auto &C : i->Conversions) + C.~ImplicitConversionSequence(); if (!i->Viable && i->FailureKind == ovl_fail_bad_deduction) i->DeductionFailure.Destroy(); } @@ -5860,7 +5868,8 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, bool PartialOverloading, - bool AllowExplicit) { + bool AllowExplicit, + ConversionSequenceList EarlyConversions) { const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>()); assert(Proto && "Functions without a prototype cannot be overloaded"); @@ -5876,10 +5885,11 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, // function, e.g., X::f(). We use an empty type for the implied // object argument (C++ [over.call.func]p3), and the acting context // is irrelevant. - AddMethodCandidate(Method, FoundDecl, Method->getParent(), - QualType(), Expr::Classification::makeSimpleLValue(), + AddMethodCandidate(Method, FoundDecl, Method->getParent(), QualType(), + Expr::Classification::makeSimpleLValue(), /*ThisArg=*/nullptr, Args, CandidateSet, - SuppressUserConversions, PartialOverloading); + SuppressUserConversions, PartialOverloading, + EarlyConversions); return; } // We treat a constructor like a non-member function, since its object @@ -5912,7 +5922,8 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); // Add this candidate - OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size()); + OverloadCandidate &Candidate = + CandidateSet.addCandidate(Args.size(), EarlyConversions); Candidate.FoundDecl = FoundDecl; Candidate.Function = Function; Candidate.Viable = true; @@ -5976,7 +5987,10 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, // Determine the implicit conversion sequences for each of the // arguments. for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) { - if (ArgIdx < NumParams) { + if (Candidate.Conversions[ArgIdx].isInitialized()) { + // We already formed a conversion sequence for this parameter during + // template argument deduction. + } else 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 @@ -6414,7 +6428,8 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, Expr *ThisArg, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, - bool PartialOverloading) { + bool PartialOverloading, + ConversionSequenceList EarlyConversions) { const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(Method->getType()->getAs<FunctionType>()); assert(Proto && "Methods without a prototype cannot be overloaded"); @@ -6435,7 +6450,8 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); // Add this candidate - OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size() + 1); + OverloadCandidate &Candidate = + CandidateSet.addCandidate(Args.size() + 1, EarlyConversions); Candidate.FoundDecl = FoundDecl; Candidate.Function = Method; Candidate.IsSurrogate = false; @@ -6497,7 +6513,10 @@ 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 (ArgIdx < NumParams) { + if (Candidate.Conversions[ArgIdx + 1].isInitialized()) { + // We already formed a conversion sequence for this parameter during + // template argument deduction. + } else 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 @@ -6562,19 +6581,30 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, // functions. TemplateDeductionInfo Info(CandidateSet.getLocation()); FunctionDecl *Specialization = nullptr; - if (TemplateDeductionResult Result - = DeduceTemplateArguments(MethodTmpl, ExplicitTemplateArgs, Args, - Specialization, Info, PartialOverloading)) { - OverloadCandidate &Candidate = CandidateSet.addCandidate(); + ConversionSequenceList Conversions; + if (TemplateDeductionResult Result = DeduceTemplateArguments( + MethodTmpl, ExplicitTemplateArgs, Args, Specialization, Info, + PartialOverloading, [&](ArrayRef<QualType> ParamTypes) { + return CheckNonDependentConversions( + MethodTmpl, ParamTypes, Args, CandidateSet, Conversions, + SuppressUserConversions, ActingContext, ObjectType, + ObjectClassification); + })) { + OverloadCandidate &Candidate = + CandidateSet.addCandidate(Conversions.size(), Conversions); 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(); - Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, - Info); + if (Result == TDK_NonDependentConversionFailure) + Candidate.FailureKind = ovl_fail_bad_conversion; + else { + Candidate.FailureKind = ovl_fail_bad_deduction; + Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, + Info); + } return; } @@ -6586,7 +6616,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, AddMethodCandidate(cast<CXXMethodDecl>(Specialization), FoundDecl, ActingContext, ObjectType, ObjectClassification, /*ThisArg=*/ThisArg, Args, CandidateSet, - SuppressUserConversions, PartialOverloading); + SuppressUserConversions, PartialOverloading, Conversions); } /// \brief Add a C++ function template specialization as a candidate @@ -6614,19 +6644,29 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, // functions. TemplateDeductionInfo Info(CandidateSet.getLocation()); FunctionDecl *Specialization = nullptr; - if (TemplateDeductionResult Result - = DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs, Args, - Specialization, Info, PartialOverloading)) { - OverloadCandidate &Candidate = CandidateSet.addCandidate(); + ConversionSequenceList Conversions; + if (TemplateDeductionResult Result = DeduceTemplateArguments( + FunctionTemplate, ExplicitTemplateArgs, Args, Specialization, Info, + PartialOverloading, [&](ArrayRef<QualType> ParamTypes) { + return CheckNonDependentConversions(FunctionTemplate, ParamTypes, + Args, CandidateSet, Conversions, + SuppressUserConversions); + })) { + OverloadCandidate &Candidate = + CandidateSet.addCandidate(Conversions.size(), Conversions); 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(); - Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, - Info); + if (Result == TDK_NonDependentConversionFailure) + Candidate.FailureKind = ovl_fail_bad_conversion; + else { + Candidate.FailureKind = ovl_fail_bad_deduction; + Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, + Info); + } return; } @@ -6634,7 +6674,64 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, // deduction as a candidate. assert(Specialization && "Missing function template specialization?"); AddOverloadCandidate(Specialization, FoundDecl, Args, CandidateSet, - SuppressUserConversions, PartialOverloading); + 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<QualType> ParamTypes, + ArrayRef<Expr *> 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<CXXMethodDecl>(FD); + bool HasThisConversion = Method && !isa<CXXConstructorDecl>(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<CXXMethodDecl>(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(ParamTypes.size(), Args.size()); I != N; + ++I) { + QualType ParamType = ParamTypes[I]; + 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; } /// Determine whether this is an allowable conversion from the result @@ -8875,8 +8972,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.NumConversions; - assert(Cand2.NumConversions == NumArgs && "Overload candidate mismatch"); + unsigned NumArgs = Cand1.Conversions.size(); + assert(Cand2.Conversions.size() == NumArgs && "Overload candidate mismatch"); bool HasBetterConversion = false; for (unsigned ArgIdx = StartArg; ArgIdx < NumArgs; ++ArgIdx) { bool Cand1Bad = IsIllFormedConversion(Cand1.Conversions[ArgIdx]); @@ -10099,7 +10196,7 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, case ovl_fail_bad_conversion: { unsigned I = (Cand->IgnoreObjectArgument ? 1 : 0); - for (unsigned N = Cand->NumConversions; I != N; ++I) + for (unsigned N = Cand->Conversions.size(); I != N; ++I) if (Cand->Conversions[I].isBad()) return DiagnoseBadConversion(S, Cand, I, TakingCandidateAddress); @@ -10168,12 +10265,12 @@ static void NoteSurrogateCandidate(Sema &S, OverloadCandidate *Cand) { static void NoteBuiltinOperatorCandidate(Sema &S, StringRef Opc, SourceLocation OpLoc, OverloadCandidate *Cand) { - assert(Cand->NumConversions <= 2 && "builtin operator is not binary"); + assert(Cand->Conversions.size() <= 2 && "builtin operator is not binary"); std::string TypeStr("operator"); TypeStr += Opc; TypeStr += "("; TypeStr += Cand->BuiltinTypes.ParamTypes[0].getAsString(); - if (Cand->NumConversions == 1) { + if (Cand->Conversions.size() == 1) { TypeStr += ")"; S.Diag(OpLoc, diag::note_ovl_builtin_unary_candidate) << TypeStr; } else { @@ -10186,9 +10283,7 @@ static void NoteBuiltinOperatorCandidate(Sema &S, StringRef Opc, static void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc, OverloadCandidate *Cand) { - unsigned NoOperands = Cand->NumConversions; - for (unsigned ArgIdx = 0; ArgIdx < NoOperands; ++ArgIdx) { - const ImplicitConversionSequence &ICS = Cand->Conversions[ArgIdx]; + for (const ImplicitConversionSequence &ICS : Cand->Conversions) { if (ICS.isBad()) break; // all meaningless after first invalid if (!ICS.isAmbiguous()) continue; @@ -10208,7 +10303,8 @@ static SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) { static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) { switch ((Sema::TemplateDeductionResult)DFI.Result) { case Sema::TDK_Success: - llvm_unreachable("TDK_success while diagnosing bad deduction"); + case Sema::TDK_NonDependentConversionFailure: + llvm_unreachable("non-deduction failure while diagnosing bad deduction"); case Sema::TDK_Invalid: case Sema::TDK_Incomplete: @@ -10311,11 +10407,11 @@ struct CompareOverloadCandidatesForDisplay { // If there's any ordering between the defined conversions... // FIXME: this might not be transitive. - assert(L->NumConversions == R->NumConversions); + assert(L->Conversions.size() == R->Conversions.size()); int leftBetter = 0; unsigned I = (L->IgnoreObjectArgument || R->IgnoreObjectArgument); - for (unsigned E = L->NumConversions; I != E; ++I) { + for (unsigned E = L->Conversions.size(); I != E; ++I) { switch (CompareImplicitConversionSequences(S, Loc, L->Conversions[I], R->Conversions[I])) { @@ -10364,7 +10460,8 @@ struct CompareOverloadCandidatesForDisplay { } /// CompleteNonViableCandidate - Normally, overload resolution only -/// computes up to the first. Produces the FixIt set if possible. +/// computes up to the first bad conversion. Produces the FixIt set if +/// possible. static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, ArrayRef<Expr *> Args) { assert(!Cand->Viable); @@ -10377,30 +10474,24 @@ static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, // Use a implicit copy initialization to check conversion fixes. Cand->Fix.setConversionChecker(TryCopyInitialization); - // Skip forward to the first bad conversion. - unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0); - unsigned ConvCount = Cand->NumConversions; - while (true) { + // Attempt to fix the bad conversion. + unsigned ConvCount = Cand->Conversions.size(); + for (unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0); /**/; + ++ConvIdx) { assert(ConvIdx != ConvCount && "no bad conversion in candidate"); - ConvIdx++; - if (Cand->Conversions[ConvIdx - 1].isBad()) { - Unfixable = !Cand->TryToFixBadConversion(ConvIdx - 1, S); + if (Cand->Conversions[ConvIdx].isInitialized() && + Cand->Conversions[ConvIdx].isBad()) { + Unfixable = !Cand->TryToFixBadConversion(ConvIdx, 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 = ConvIdx; + const FunctionProtoType *Proto; + unsigned ArgIdx = 0; if (Cand->IsSurrogate) { QualType ConvType @@ -10408,40 +10499,56 @@ static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>()) ConvType = ConvPtrType->getPointeeType(); Proto = ConvType->getAs<FunctionProtoType>(); - ArgIdx--; + ArgIdx = 1; } else if (Cand->Function) { Proto = Cand->Function->getType()->getAs<FunctionProtoType>(); if (isa<CXXMethodDecl>(Cand->Function) && !isa<CXXConstructorDecl>(Cand->Function)) - ArgIdx--; + ArgIdx = 1; } else { // Builtin binary operator with a bad first conversion. assert(ConvCount <= 3); - for (; ConvIdx != ConvCount; ++ConvIdx) - Cand->Conversions[ConvIdx] - = TryCopyInitialization(S, Args[ConvIdx], - Cand->BuiltinTypes.ParamTypes[ConvIdx], - SuppressUserConversions, - /*InOverloadResolution*/ true, - /*AllowObjCWritebackConversion=*/ - S.getLangOpts().ObjCAutoRefCount); + 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. + } return; } // Fill in the rest of the conversions. unsigned NumParams = Proto->getNumParams(); - 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 + 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 Cand->Conversions[ConvIdx].setEllipsis(); } } diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index a9fd8fd40ce..93e796ee966 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -2912,14 +2912,13 @@ static unsigned getPackIndexForParam(Sema &S, /// /// \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<DeducedTemplateArgument> &Deduced, - unsigned NumExplicitlySpecified, - FunctionDecl *&Specialization, - TemplateDeductionInfo &Info, - SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs, - bool PartialOverloading) { +Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( + FunctionTemplateDecl *FunctionTemplate, + SmallVectorImpl<DeducedTemplateArgument> &Deduced, + unsigned NumExplicitlySpecified, FunctionDecl *&Specialization, + TemplateDeductionInfo &Info, + SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs, + bool PartialOverloading, llvm::function_ref<bool()> CheckNonDependent) { // Unevaluated SFINAE context. EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); SFINAETrap Trap(*this); @@ -2946,6 +2945,18 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, 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); @@ -3392,12 +3403,19 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument( /// \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. The callback is passed the parameter +/// types (after substituting explicit template arguments). +/// /// \returns the result of template argument deduction. Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( FunctionTemplateDecl *FunctionTemplate, TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args, FunctionDecl *&Specialization, TemplateDeductionInfo &Info, - bool PartialOverloading) { + bool PartialOverloading, + llvm::function_ref<bool(ArrayRef<QualType>)> CheckNonDependent) { if (FunctionTemplate->isInvalidDecl()) return TDK_Invalid; @@ -3425,7 +3443,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( TemplateParameterList *TemplateParams = FunctionTemplate->getTemplateParameters(); SmallVector<DeducedTemplateArgument, 4> Deduced; - SmallVector<QualType, 4> ParamTypes; + SmallVector<QualType, 8> ParamTypes; unsigned NumExplicitlySpecified = 0; if (ExplicitTemplateArgs) { TemplateDeductionResult Result = @@ -3445,7 +3463,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( ParamTypes.push_back(Function->getParamDecl(I)->getType()); } - SmallVector<OriginalCallArg, 4> OriginalCallArgs; + SmallVector<OriginalCallArg, 8> OriginalCallArgs; // Deduce an argument of type ParamType from an expression with index ArgIdx. auto DeduceCallArgument = [&](QualType ParamType, unsigned ArgIdx) { @@ -3464,6 +3482,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( // Deduce template arguments from the function parameters. Deduced.resize(TemplateParams->size()); + SmallVector<QualType, 8> ParamTypesForArgChecking; for (unsigned ParamIdx = 0, NumParamTypes = ParamTypes.size(), ArgIdx = 0; ParamIdx != NumParamTypes; ++ParamIdx) { QualType ParamType = ParamTypes[ParamIdx]; @@ -3475,6 +3494,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( if (ArgIdx >= Args.size()) break; + ParamTypesForArgChecking.push_back(ParamType); if (auto Result = DeduceCallArgument(ParamType, ArgIdx++)) return Result; @@ -3502,20 +3522,25 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( // parameter pack and 0 otherwise, and we treat each deduction as a // non-deduced context. if (ParamIdx + 1 == NumParamTypes) { - for (; ArgIdx < Args.size(); PackScope.nextPackElement(), ++ArgIdx) + for (; ArgIdx < Args.size(); PackScope.nextPackElement(), ++ArgIdx) { + ParamTypesForArgChecking.push_back(ParamPattern); if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx)) return Result; + } } else { // If the parameter type contains an explicitly-specified pack that we // could not expand, skip the number of parameters notionally created // by the expansion. Optional<unsigned> NumExpansions = ParamExpansion->getNumExpansions(); - if (NumExpansions && !PackScope.isPartiallyExpanded()) + if (NumExpansions && !PackScope.isPartiallyExpanded()) { for (unsigned I = 0; I != *NumExpansions && ArgIdx < Args.size(); - ++I, ++ArgIdx) + ++I, ++ArgIdx) { + ParamTypesForArgChecking.push_back(ParamPattern); // FIXME: Should we add OriginalCallArgs for these? What if the // corresponding argument is a list? PackScope.nextPackElement(); + } + } } // Build argument packs for each of the parameter packs expanded by this @@ -3524,10 +3549,10 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( return Result; } - return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, - NumExplicitlySpecified, Specialization, - Info, &OriginalCallArgs, - PartialOverloading); + return FinishTemplateArgumentDeduction( + FunctionTemplate, Deduced, NumExplicitlySpecified, Specialization, Info, + &OriginalCallArgs, PartialOverloading, + [&]() { return CheckNonDependent(ParamTypesForArgChecking); }); } QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType, diff --git a/clang/test/CXX/drs/dr13xx.cpp b/clang/test/CXX/drs/dr13xx.cpp index 2c861ff5aeb..28e667f77f8 100644 --- a/clang/test/CXX/drs/dr13xx.cpp +++ b/clang/test/CXX/drs/dr13xx.cpp @@ -218,6 +218,84 @@ namespace dr1388 { // dr1388: 4.0 } } +namespace dr1391 { // dr1391: partial + struct A {}; struct B : A {}; + template<typename T> struct C { C(int); typename T::error error; }; // expected-error 2{{'::'}} + template<typename T> struct D {}; + + // No deduction is performed for parameters with no deducible template-parameters, therefore types do not need to match. + template<typename T> 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<typename T, typename U> void f(C<T>); + template<typename T> void f(D<T>); + + void g(D<int> d) { + f(d); // ok, first 'f' eliminated by deduction failure + f<int>(d); // ok, first 'f' eliminated because 'U' cannot be deduced + } + } + + namespace dr_example_2 { + template<typename T> typename C<T>::error f(int, T); + template<typename T> 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<typename T> struct Z { + typedef typename T::x xx; + }; + template<typename T> typename Z<T>::xx f(void *, T); + template<typename T> void f(int, T); + struct A {} a; + void g() { f(1, a); } + } + + template<typename T> void b(C<int> ci, T *p); + void b(...); + void test_b() { + b(0, 0); // ok, deduction fails prior to forming a conversion sequence and instantiating C<int> + // FIXME: The "while substituting" note should point at the overload candidate. + b<int>(0, 0); // expected-note {{instantiation of}} expected-note {{while substituting}} + } + + template<typename T> struct Id { typedef T type; }; + template<typename T> void c(T, typename Id<C<T> >::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<typename T> int a(T, short) = delete; // expected-error 0-1{{extension}} expected-note {{candidate}} + template<typename T> 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<typename T> int b(T, int) = delete; // expected-error 0-1{{extension}} expected-note {{candidate}} + template<typename T, typename U> 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<typename T> int c(int); + template<typename T> int c(T); + int test_c1 = c(0); // ok + int test_c2 = c<int>(0); // FIXME: apparently ambiguous + } +} + namespace dr1399 { // dr1399: dup 1388 template<typename ...T> void f(T..., int, T...) {} // expected-note {{candidate}} expected-error 0-1{{C++11}} void g() { diff --git a/clang/test/Misc/diag-template-diffing.cpp b/clang/test/Misc/diag-template-diffing.cpp index 78083989928..9006fc6f9ac 100644 --- a/clang/test/Misc/diag-template-diffing.cpp +++ b/clang/test/Misc/diag-template-diffing.cpp @@ -1265,7 +1265,7 @@ void test() { foo<BoolT<true>>(X); } // CHECK-ELIDE-NOTREE: no matching function for call to 'foo' -// CHECK-ELIDE-NOTREE: candidate function [with T = BoolArgumentBitExtended::BoolT<true>] not viable: no known conversion from 'BoolT<false>' to 'BoolT<true>' for 1st argument +// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'BoolT<false>' to 'BoolT<true>' for 1st argument } namespace DifferentIntegralTypes { @@ -1401,7 +1401,7 @@ void run() { f(1, integral_constant<bool, true>{}); } // CHECK-ELIDE-NOTREE: error: no matching function for call to 'f' -// 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 +// CHECK-ELIDE-NOTREE: note: candidate function not viable: no known conversion from 'integral_constant<[...], true>' to 'integral_constant<[...], false>' for 2nd argument } namespace ZeroArgs { @@ -1454,7 +1454,7 @@ void run() { D<X::X1>(VectorType<X::X2>()); } // CHECK-ELIDE-NOTREE: error: no matching function for call to 'D' -// CHECK-ELIDE-NOTREE: note: candidate function [with x = TypeAlias::X::X1] not viable: no known conversion from 'VectorType<X::X2>' to 'const VectorType<(TypeAlias::X)0>' for 1st argument +// CHECK-ELIDE-NOTREE: note: candidate function not viable: no known conversion from 'VectorType<X::X2>' to 'const VectorType<(TypeAlias::X)0>' for 1st argument } namespace TypeAlias2 { diff --git a/clang/test/SemaCXX/attr-mode-tmpl.cpp b/clang/test/SemaCXX/attr-mode-tmpl.cpp index 4e1489a8a5b..d83bb398905 100644 --- a/clang/test/SemaCXX/attr-mode-tmpl.cpp +++ b/clang/test/SemaCXX/attr-mode-tmpl.cpp @@ -45,7 +45,7 @@ void CheckMachineMode() { // Check attributes on function parameters. template <class T1, class T2> -void CheckParameters(T1 __attribute__((mode(SI))) paramSI, // expected-note2{{ignored: substitution failure}} +void CheckParameters(T1 __attribute__((mode(SI))) paramSI, // expected-note{{ignored: substitution failure}} expected-note-re{{not viable: no known conversion from '{{.*}}' (vector of 4 '{{.*}}' values) to 'EnumType' for 2nd argument}} T1 __attribute__((mode(V4DI))) paramV4DI, // expected-warning{{deprecated}} T2 __attribute__((mode(SF))) paramSF, T2 __attribute__((mode(V4DF))) paramV4DF) { // expected-warning{{deprecated}} diff --git a/clang/test/SemaCXX/attr-noreturn.cpp b/clang/test/SemaCXX/attr-noreturn.cpp index a8e71db7370..6edc86c43a7 100644 --- a/clang/test/SemaCXX/attr-noreturn.cpp +++ b/clang/test/SemaCXX/attr-noreturn.cpp @@ -244,11 +244,11 @@ namespace PR15291 { template <typename T> void qux(T) {} - // expected-note@+5 {{candidate function [with T = void (*)(int) __attribute__((noreturn))] not viable: no overload of 'baz' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}} - // expected-note@+4 {{candidate function [with T = void (*)(int) __attribute__((noreturn))] not viable: no overload of 'qux' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}} - // expected-note@+3 {{candidate function [with T = void (*)(int) __attribute__((noreturn))] not viable: no overload of 'bar' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}} - // expected-note@+2 {{candidate function [with T = void (*)(int)] not viable: no overload of 'bar' matching 'void (*)(int)' for 1st argument}} - // expected-note@+1 {{candidate function [with T = void (int)] not viable: no overload of 'bar' matching 'void (*)(int)' for 1st argument}} + // expected-note@+5 {{candidate function not viable: no overload of 'baz' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}} + // expected-note@+4 {{candidate function not viable: no overload of 'qux' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}} + // expected-note@+3 {{candidate function not viable: no overload of 'bar' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}} + // expected-note@+2 {{candidate function not viable: no overload of 'bar' matching 'void (*)(int)' for 1st argument}} + // expected-note@+1 {{candidate function not viable: no overload of 'bar' matching 'void (*)(int)' for 1st argument}} template <typename T> void accept_T(T) {} // expected-note@+1 {{candidate function not viable: no overload of 'bar' matching 'void (*)(int)' for 1st argument}} diff --git a/clang/test/SemaCXX/overload-call.cpp b/clang/test/SemaCXX/overload-call.cpp index 3a01bf24b31..0e3a9ee50bb 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 <class T> 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}} + template <class T> 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}} 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 e0f34d937f6..6e64b25d6b5 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 <class T> 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}} + template <class T> 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}} 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/SemaTemplate/deduction.cpp b/clang/test/SemaTemplate/deduction.cpp index 499b376855e..0c0e7d599cc 100644 --- a/clang/test/SemaTemplate/deduction.cpp +++ b/clang/test/SemaTemplate/deduction.cpp @@ -361,6 +361,10 @@ namespace deduction_after_explicit_pack { g<int, float&, double&>(a, b, c, &c); // ok } + template<class... ExtraArgs> + int test(ExtraArgs..., unsigned vla_size, const char *input); + int n = test(0, ""); + template <typename... T> void i(T..., int, T..., ...); // expected-note 5{{deduced conflicting}} void j() { i(0); diff --git a/clang/test/SemaTemplate/temp_arg_nontype.cpp b/clang/test/SemaTemplate/temp_arg_nontype.cpp index 93f11b5657d..27a0a03f84f 100644 --- a/clang/test/SemaTemplate/temp_arg_nontype.cpp +++ b/clang/test/SemaTemplate/temp_arg_nontype.cpp @@ -173,12 +173,16 @@ namespace pr6249 { } namespace PR6723 { - template<unsigned char C> void f(int (&a)[C]); // expected-note {{candidate template ignored}} \ - // expected-note{{substitution failure [with C = '\x00']}} + template<unsigned char C> void f(int (&a)[C]); // expected-note 3{{candidate template ignored: substitution failure [with C = '\x00']}} + // expected-note@-1 {{not viable: no known conversion from 'int [512]' to 'int (&)[0]'}} void g() { int arr512[512]; f(arr512); // expected-error{{no matching function for call}} f<512>(arr512); // expected-error{{no matching function for call}} + + int arr0[0]; + f(arr0); // expected-error{{no matching function for call}} + f<0>(arr0); // expected-error{{no matching function for call}} } } diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index 1ddbc00c410..c36adfdfad0 100644 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -8161,7 +8161,7 @@ and <I>POD class</I></td> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1391">1391</a></td> <td>DRWP</td> <td>Conversions to parameter types with non-deduced template arguments</td> - <td class="none" align="center">Unknown</td> + <td class="partial" align="center">Partial</td> </tr> <tr id="1392"> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1392">1392</a></td> |

