-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[clang] check constant template parameters in dependent contexts #159463
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clang Author: Matheus Izvekov (mizvekov) ChangesThis 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. Full diff: https://github.com/llvm/llvm-project/pull/159463.diff 3 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 51e5973098c14..0eadc1c773597 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -241,7 +241,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 d6b25c2d83613..faeba6ada0c6b 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..763ca629eae3e 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,12 @@ 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'}}
+ };
}
namespace PR32185 {
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this makes sense, it seems to do as described at least. I'm not sure WHAT, but it feels like we could/should do a better job with some demonstrative tests though.
I am open to suggestions, I can't think of anything which would demonstrate this better or show some interesting corner case not shown in the current test changes already. |
I couldn't come up with anything either... lets hold this off to give @cor3ntin a chance to take a look (or others?) to see if anyone else has a more demonstrative/canonical example for the tests, else this LGTM. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this looks neat
Though I don't have a demonstrative test either...
Alright, I guess I was dreaming about a better test. Ship it. |
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.
614e4a7
to
f0e3578
Compare
Alright, I just thought of a new test case, which my patch doesn't actually change anything. |
Note @mizvekov : we observed on an internal test (I am going to have someone work on minimizing it) that this causes an assertion. As you can see, it is all in boost, so a reduction might take a while, but was hoping you might see something obvious in advance:
|
I actually repro'd off the stack trace :)
AS this is a part of Boost/major libraries and is a pretty simple bit of valid code, if you can't get a fix reasonably fast, please consider a revert. |
This fixes a regression reported here: #159463 (comment) Since this regression was never released, there are no release notes.
…159819) This fixes a regression reported here: #159463 (comment) Since this regression was never released, there are no release notes.
… operators (#159819) This fixes a regression reported here: llvm/llvm-project#159463 (comment) Since this regression was never released, there are no release notes.
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.