The way this code checks whether a pointer is null is wrong for other reasons; it doesn't actually check whether a null pointer constant is a "constant" in the C++ standard sense. But this fix at least makes sure we don't treat a non-null pointer as if it were null.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp | ||
---|---|---|
31 | It looks like in C++17 mode we catch this case: https://godbolt.org/z/s43oE5qWE |
clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp | ||
---|---|---|
31 | Another case to check for: IP<(int*)(1-1)> ip9; In C++11 the wording use to allow integer constant expressions |
It looks like in Sema::CheckTemplateArgument in C++17 mode we end up calling CheckConvertedConstantExpression which sees a IntegralToPointer cast which is basically an reintepret_cast and rejects it as ill-formed.
In the C++11 case we end up in CheckTemplateArgumentAddressOfObjectOrFunction.
Add release note. Add test coverage for C++17, since it uses a different codepath. (The C++17 codepath appears to work correctly without any changes.)
clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp | ||
---|---|---|
31 | The new diagnostic here is unfortunate. That 'does not refer to any declaration' doesn't really let me know that it is illegal because that isn't a NPE. The 'treat it as a null ptr' here is obviously awful, but I find myself wondering if we can do better on this diagnostic trivially enough? |
clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp | ||
---|---|---|
31 |
That's diagnosing the cast, not the template argument value. You can get around the cast diagnostic by forcing constant folding with a __builtin_constant_p conditional (example). Then we diagnose as
... which seems like a worse diagnostic than the C++11 one, because it's not even true. |
clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp | ||
---|---|---|
31 | It's easy enough to use a different message; we just need to detect the particular case we're considering, print an error, and return NPV_Error. But I'm not sure what a better diagnostic looks like. "standard C++ does not allow using '(int*)1' as a non-type template argument"? (The fact that null is allowed isn't really relevant here.) |
clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp | ||
---|---|---|
31 |
Great point, I missed that earlier. My point was that if we are catching this in C++17 mode maybe we can reuse the machinery to catch this other modes as well and fix the diagnostic quality as well. Although I realize that may not be easy but worth at least understanding. |
Any suggestions for what the error message should look like, if you aren't satisfied with the current messages?
clang/lib/Sema/SemaTemplate.cpp | ||
---|---|---|
6501–6502 | It's worth noting that the rules we follow changed slightly: http://eel.is/c++draft/temp.arg.nontype#2 so if we're making repairs in this area, are there broader changes we need to consider? (That's fine as a FIXME comment if the changes end up being unrelated to this specific fix.) | |
clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp | ||
31 | For comparison, ICC diagnoses this with: Either one of those diagnostics seems like an improvement over our status quo. |
clang/lib/Sema/SemaTemplate.cpp | ||
---|---|---|
6501–6502 | C++17 significantly revamped the rules for template arguments; we don't use this code at all for C++17 or later. (It might be worth considering re-unifying the codepaths to some extent; first evaluate under the C++17 rules, then verify if the argument is valid under the earlier standard's rules. But I really just wanted to write a quick bugfix for the obvious miscompile, not completely rewrite the code.) |
I would love it if the diagnostic had a little more info why it isn't, but this is probably good enough for now.
It's worth noting that the rules we follow changed slightly: http://eel.is/c++draft/temp.arg.nontype#2 so if we're making repairs in this area, are there broader changes we need to consider? (That's fine as a FIXME comment if the changes end up being unrelated to this specific fix.)