Author: rsmith Date: Fri Feb 10 13:49:50 2017 New Revision: 294773 URL: http://llvm.org/viewvc/llvm-project?rev=294773&view=rev Log: [c++1z] Disallow deduction guides with deduced types that don't syntactically match the template being deduced.
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/Sema/SemaDeclCXX.cpp cfe/trunk/test/CXX/temp/temp.deduct.guide/p3.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=294773&r1=294772&r2=294773&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Feb 10 13:49:50 2017 @@ -1981,6 +1981,9 @@ def err_deduced_class_template_explicit "%select{constructor|deduction guide}1 for copy-list-initialization">; def err_deduction_guide_no_trailing_return_type : Error< "deduction guide declaration without trailing return type">; +def err_deduction_guide_bad_trailing_return_type : Error< + "deduced type %1 of deduction guide is not %select{|written as }2" + "a specialization of template %0">; def err_deduction_guide_with_complex_decl : Error< "cannot specify any part of a return type in the " "declaration of a deduction guide">; Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=294773&r1=294772&r2=294773&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Feb 10 13:49:50 2017 @@ -8192,12 +8192,46 @@ void Sema::CheckDeductionGuideDeclarator diag::err_deduction_guide_no_trailing_return_type); break; } + + // Check that the return type is written as a specialization of + // the template specified as the deduction-guide's name. + ParsedType TrailingReturnType = Chunk.Fun.getTrailingReturnType(); + TemplateName GuidedTemplate = D.getName().TemplateName.get().get(); + TypeSourceInfo *TSI = nullptr; + QualType RetTy = GetTypeFromParser(TrailingReturnType, &TSI); + assert(TSI && "deduction guide has valid type but invalid return type?"); + bool AcceptableReturnType = false; + bool MightInstantiateToSpecialization = false; + if (auto RetTST = + TSI->getTypeLoc().getAs<TemplateSpecializationTypeLoc>()) { + TemplateName SpecifiedName = RetTST.getTypePtr()->getTemplateName(); + bool TemplateMatches = + Context.hasSameTemplateName(SpecifiedName, GuidedTemplate); + if (SpecifiedName.getKind() == TemplateName::Template && TemplateMatches) + AcceptableReturnType = true; + else { + // This could still instantiate to the right type, unless we know it + // names the wrong class template. + auto *TD = SpecifiedName.getAsTemplateDecl(); + MightInstantiateToSpecialization = !(TD && isa<ClassTemplateDecl>(TD) && + !TemplateMatches); + } + } else if (!RetTy.hasQualifiers() && RetTy->isDependentType()) { + MightInstantiateToSpecialization = true; + } + + if (!AcceptableReturnType) { + Diag(TSI->getTypeLoc().getLocStart(), + diag::err_deduction_guide_bad_trailing_return_type) + << GuidedTemplate << TSI->getType() << MightInstantiateToSpecialization + << TSI->getTypeLoc().getSourceRange(); + } + + // Keep going to check that we don't have any inner declarator pieces (we + // could still have a function returning a pointer to a function). FoundFunction = true; } - // FIXME: Check that the return type can instantiate to a specialization of - // the template specified as the deduction-guide's name. - if (D.isFunctionDefinition()) Diag(D.getIdentifierLoc(), diag::err_deduction_guide_defines_function); } Modified: cfe/trunk/test/CXX/temp/temp.deduct.guide/p3.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.deduct.guide/p3.cpp?rev=294773&r1=294772&r2=294773&view=diff ============================================================================== --- cfe/trunk/test/CXX/temp/temp.deduct.guide/p3.cpp (original) +++ cfe/trunk/test/CXX/temp/temp.deduct.guide/p3.cpp Fri Feb 10 13:49:50 2017 @@ -32,11 +32,9 @@ template<template<typename> typename TT> TT(int) -> TT<int>; // expected-error 2{{cannot specify deduction guide for template template parameter 'TT'}} expected-error {{requires an identifier}} }; -// FIXME: Even if the DR is applied as we hope, we should still warn if the -// trailing-return-type can obviously never produce a specialization of the -// named template. -A(int) -> int; -template<typename T> A(T) -> T*; +A(int) -> int; // expected-error {{deduced type 'int' of deduction guide is not a specialization of template 'A'}} +template<typename T> A(T) -> B<T>; // expected-error {{deduced type 'B<T>' (aka 'A<type-parameter-0-0>') of deduction guide is not written as a specialization of template 'A'}} +template<typename T> A(T*) -> const A<T>; // expected-error {{deduced type 'const A<T>' of deduction guide is not a specialization of template 'A'}} // A deduction-guide shall be declared in the same scope as the corresponding // class template. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits