Author: rsmith Date: Wed Feb 15 18:36:47 2017 New Revision: 295264 URL: http://llvm.org/viewvc/llvm-project?rev=295264&view=rev Log: [c++1z] Diagnose non-deducible template parameters in deduction guide templates, per [temp.param]p11.
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/lib/Sema/SemaTemplate.cpp cfe/trunk/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp cfe/trunk/www/cxx_status.html Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=295264&r1=295263&r2=295264&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Feb 15 18:36:47 2017 @@ -2002,6 +2002,10 @@ def err_deduction_guide_explicit_mismatc "previous declaration was%select{ not|}0">; def err_deduction_guide_specialized : Error<"deduction guide cannot be " "%select{explicitly instantiated|explicitly specialized}0">; +def err_deduction_guide_template_not_deducible : Error< + "deduction guide template contains " + "%select{a template parameter|template parameters}0 that cannot be " + "deduced">; // C++1y deduced return types def err_auto_fn_deduction_failure : Error< @@ -4146,7 +4150,7 @@ def ext_partial_specs_not_deducible : Ex "%select{a template parameter|template parameters}1 that cannot be " "deduced; this partial specialization will never be used">, DefaultError, InGroup<DiagGroup<"unusable-partial-specialization">>; -def note_partial_spec_unused_parameter : Note< +def note_non_deducible_parameter : Note< "non-deducible template parameter %0">; def err_partial_spec_ordering_ambiguous : Error< "ambiguous partial specializations of %0">; Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=295264&r1=295263&r2=295264&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Wed Feb 15 18:36:47 2017 @@ -5624,6 +5624,7 @@ public: Decl *ActOnConversionDeclarator(CXXConversionDecl *Conversion); void CheckDeductionGuideDeclarator(Declarator &D, QualType &R, StorageClass &SC); + void CheckDeductionGuideTemplate(FunctionTemplateDecl *TD); void CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD); void CheckExplicitlyDefaultedMemberExceptionSpec(CXXMethodDecl *MD, Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=295264&r1=295263&r2=295264&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Feb 15 18:36:47 2017 @@ -9152,13 +9152,15 @@ bool Sema::CheckFunctionDeclaration(Scop } else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(NewFD)) { ActOnConversionDeclarator(Conversion); - } else if (NewFD->isDeductionGuide() && - NewFD->getTemplateSpecializationKind() == - TSK_ExplicitSpecialization) { + } else if (NewFD->isDeductionGuide()) { + if (auto *TD = NewFD->getDescribedFunctionTemplate()) + CheckDeductionGuideTemplate(TD); + // A deduction guide is not on the list of entities that can be // explicitly specialized. - Diag(NewFD->getLocStart(), diag::err_deduction_guide_specialized) - << /*explicit specialization*/ 1; + if (NewFD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) + Diag(NewFD->getLocStart(), diag::err_deduction_guide_specialized) + << /*explicit specialization*/ 1; } // Find any virtual functions that this function overrides. Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=295264&r1=295263&r2=295264&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Feb 15 18:36:47 2017 @@ -3162,6 +3162,23 @@ static void checkMoreSpecializedThanPrim S.Diag(Template->getLocation(), diag::note_template_decl_here); } +static void +noteNonDeducibleParameters(Sema &S, TemplateParameterList *TemplateParams, + const llvm::SmallBitVector &DeducibleParams) { + for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I) { + if (!DeducibleParams[I]) { + NamedDecl *Param = cast<NamedDecl>(TemplateParams->getParam(I)); + if (Param->getDeclName()) + S.Diag(Param->getLocation(), diag::note_non_deducible_parameter) + << Param->getDeclName(); + else + S.Diag(Param->getLocation(), diag::note_non_deducible_parameter) + << "(anonymous)"; + } + } +} + + template<typename PartialSpecDecl> static void checkTemplatePartialSpecialization(Sema &S, PartialSpecDecl *Partial) { @@ -3189,19 +3206,7 @@ static void checkTemplatePartialSpeciali << (NumNonDeducible > 1) << SourceRange(Partial->getLocation(), Partial->getTemplateArgsAsWritten()->RAngleLoc); - for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I) { - if (!DeducibleParams[I]) { - NamedDecl *Param = cast<NamedDecl>(TemplateParams->getParam(I)); - if (Param->getDeclName()) - S.Diag(Param->getLocation(), - diag::note_partial_spec_unused_parameter) - << Param->getDeclName(); - else - S.Diag(Param->getLocation(), - diag::note_partial_spec_unused_parameter) - << "(anonymous)"; - } - } + noteNonDeducibleParameters(S, TemplateParams, DeducibleParams); } } @@ -3215,6 +3220,29 @@ void Sema::CheckTemplatePartialSpecializ checkTemplatePartialSpecialization(*this, Partial); } +void Sema::CheckDeductionGuideTemplate(FunctionTemplateDecl *TD) { + // C++1z [temp.param]p11: + // A template parameter of a deduction guide template that does not have a + // default-argument shall be deducible from the parameter-type-list of the + // deduction guide template. + auto *TemplateParams = TD->getTemplateParameters(); + llvm::SmallBitVector DeducibleParams(TemplateParams->size()); + MarkDeducedTemplateParameters(TD, DeducibleParams); + for (unsigned I = 0; I != TemplateParams->size(); ++I) { + // A parameter pack is deducible (to an empty pack). + auto *Param = TemplateParams->getParam(I); + if (Param->isParameterPack() || hasVisibleDefaultArgument(Param)) + DeducibleParams[I] = true; + } + + if (!DeducibleParams.all()) { + unsigned NumNonDeducible = DeducibleParams.size() - DeducibleParams.count(); + Diag(TD->getLocation(), diag::err_deduction_guide_template_not_deducible) + << (NumNonDeducible > 1); + noteNonDeducibleParameters(*this, TemplateParams, DeducibleParams); + } +} + DeclResult Sema::ActOnVarTemplateSpecialization( Scope *S, Declarator &D, TypeSourceInfo *DI, SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams, StorageClass SC, Modified: cfe/trunk/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp?rev=295264&r1=295263&r2=295264&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp (original) +++ cfe/trunk/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp Wed Feb 15 18:36:47 2017 @@ -150,3 +150,21 @@ namespace look_into_current_instantiatio C c = {1, 2}; } + +namespace nondeducible { + template<typename A, typename B> struct X {}; + + template<typename A> // expected-note {{non-deducible template parameter 'A'}} + X() -> X<A, int>; // expected-error {{deduction guide template contains a template parameter that cannot be deduced}} + + template<typename A> // expected-note {{non-deducible template parameter 'A'}} + X(typename X<A, int>::type) -> X<A, int>; // expected-error {{deduction guide template contains a template parameter that cannot be deduced}} + + template<typename A = int, + typename B> // expected-note {{non-deducible template parameter 'B'}} + X(int) -> X<A, B>; // expected-error {{deduction guide template contains a template parameter that cannot be deduced}} + + template<typename A = int, + typename ...B> + X(float) -> X<A, B...>; // ok +} Modified: cfe/trunk/www/cxx_status.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=295264&r1=295263&r2=295264&view=diff ============================================================================== --- cfe/trunk/www/cxx_status.html (original) +++ cfe/trunk/www/cxx_status.html Wed Feb 15 18:36:47 2017 @@ -684,11 +684,10 @@ as the draft C++1z standard evolves. <tr> <td rowspan="2">Template argument deduction for class templates</td> <td><a href="http://wg21.link/p0091r3">P0091R3</a></td> - <td class="svn" align="center">SVN</td> + <td rowspan="2" class="svn" align="center">SVN</td> </tr> <tr> <!-- from Issaquah --> <td><a href="http://wg21.link/p0512r0">P0512R0</a></td> - <td class="svn" align="center">SVN</td> </tr> <tr> <td>Non-type template parameters with <tt>auto</tt> type</td> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits