[clang] 3fe85ca - [clang] check constant template parameters in dependent contexts (#159463)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 18 13:07:25 PDT 2025
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 at -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 at -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 {
More information about the cfe-commits
mailing list