Author: Matheus Izvekov Date: 2025-09-18T17:07:21-03:00 New Revision: 3fe85ca4e024df9330f263a99a2552952a5520bc
URL: https://github.com/llvm/llvm-project/commit/3fe85ca4e024df9330f263a99a2552952a5520bc DIFF: https://github.com/llvm/llvm-project/commit/3fe85ca4e024df9330f263a99a2552952a5520bc.diff LOG: [clang] check constant template parameters in dependent contexts (#159463) This patch makes sure constant template parameters are checked even in dependent contexts. This can for example diagnose narrowings earlier, but this is permitted as these templates would have no valid instantiations. Added: Modified: clang/docs/ReleaseNotes.rst clang/lib/Sema/SemaTemplate.cpp clang/test/SemaTemplate/temp_arg_template.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 95bbc39fd3860..c898784b3f93e 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -265,7 +265,8 @@ Improvements to Clang's diagnostics - Fixed fix-it hint for fold expressions. Clang now correctly places the suggested right parenthesis when diagnosing malformed fold expressions. (#GH151787) - Added fix-it hint for when scoped enumerations require explicit conversions for binary operations. (#GH24265) - +- Constant template parameters are now type checked in template definitions, + including template template parameters. - Fixed an issue where emitted format-signedness diagnostics were not associated with an appropriate diagnostic id. Besides being incorrect from an API standpoint, this was user visible, e.g.: "format specifies type 'unsigned int' but the argument has type 'int' [-Wformat]" diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index e1b1269e0d4d8..f051a246f954f 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -5482,9 +5482,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &ArgLoc, if (NTTP->isParameterPack() && NTTP->isExpandedParameterPack()) NTTPType = NTTP->getExpansionType(ArgumentPackIndex); - if (NTTPType->isInstantiationDependentType() && - !isa<TemplateTemplateParmDecl>(Template) && - !Template->getDeclContext()->isDependentContext()) { + if (NTTPType->isInstantiationDependentType()) { // Do substitution on the type of the non-type template parameter. InstantiatingTemplate Inst(*this, TemplateLoc, Template, NTTP, CTAI.SugaredConverted, @@ -5494,6 +5492,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &ArgLoc, MultiLevelTemplateArgumentList MLTAL(Template, CTAI.SugaredConverted, /*Final=*/true); + MLTAL.addOuterRetainedLevels(NTTP->getDepth()); // If the parameter is a pack expansion, expand this slice of the pack. if (auto *PET = NTTPType->getAs<PackExpansionType>()) { Sema::ArgPackSubstIndexRAII SubstIndex(*this, ArgumentPackIndex); diff --git a/clang/test/SemaTemplate/temp_arg_template.cpp b/clang/test/SemaTemplate/temp_arg_template.cpp index aa53dba652050..431e19741ece9 100644 --- a/clang/test/SemaTemplate/temp_arg_template.cpp +++ b/clang/test/SemaTemplate/temp_arg_template.cpp @@ -117,16 +117,8 @@ namespace CheckDependentNonTypeParamTypes { X<int, long, 3> x; } void h() { - // FIXME: If we accept A<B> at all, it's not obvious what should happen - // here. While parsing the template, we form - // X<unsigned char, int, (unsigned char)1234> - // but in the final instantiation do we get - // B<unsigned char, int, (int)1234> - // or - // B<unsigned char, int, (int)(unsigned char)1234> - // ? X<unsigned char, int, 1234> x; - int check[x.value == 1234 ? 1 : -1]; + // expected-error@-1 {{evaluates to 1234, which cannot be narrowed to type 'unsigned char'}} } }; @@ -143,6 +135,20 @@ namespace CheckDependentNonTypeParamTypes { ab.g(); ab.h(); } + + template<class> struct C { + template<class T, T V> struct D {}; + using T = D<char, 1234>; + // expected-error@-1 {{evaluates to 1234, which cannot be narrowed to type 'char'}} + }; + + template<class T> struct E { + template <template <T V> class TT> struct F { + using X = TT<1234>; + }; + }; + // FIXME: This should be rejected, as there are no valid instantiations for E<char>::F + template struct E<char>; } namespace PR32185 { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
