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
Pointer template parameters have the wrong value in some situations #57883
Comments
Could you please try 15 or |
I get the same result for both programs with clang 15. |
Compiling with clang trunk causes the following compilation error (for the first program, the only different things for the second program are line numbers and
Which is weird since the template argument is a compile-time constant. |
Not sure why the compiler accepts the code with -std=c++14 or earlier. Probably the check for a null template argument is wrong somehow. |
My point is that the program wouldn't have compiled if the initializer of
The |
I've done additional tests with clang trunk and #include <cstdio>
template<typename To, typename From>
inline constexpr To constexpr_reinterpret_cast(From from) {
return __builtin_constant_p( reinterpret_cast<To>(from) ) ? reinterpret_cast<To>(from) : reinterpret_cast<To>(from);
}
constexpr int* test = constexpr_reinterpret_cast<int*>(42UL);
constexpr int* test2(int* param) {
return param + 1;
}
constexpr int* test3 = test2(test);
int main(int argc, char* argv[]) {
std::printf("In main function: %p\n", test3);
} Output:
Likewise, the assembly code for this program contains |
Oh, right, __builtin_constant_p lets you violate the normal constexpr rules a bit. Template arguments in particular have extra restrictions according to the standard, though; __builtin_constant_p can't be used to get around those. We have to ensure standard-compliant code works correctly, and we print the correct diagnostics for invalid code, before we can consider any non-standard extensions. (I'm not sure a non-standard extension is really warranted here; it's a bit obscure.) |
Thank you for your answer. In that case, I'll try to program a compiler plugin to support this (or just replace pointer template arguments with |
Posted https://reviews.llvm.org/D134928 .
We could consider it. We mostly weigh this sort of thing by practical compatibility impact (and to some extent, how difficult it is to implement). Please file a new bug report for this; please describe as much as you can how widespread the breakage is, and how hard it is to fix the code to avoid this construct. (Let's keep this bug report just about the miscompile.) |
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. Fixes llvm#57883 Differential Revision: https://reviews.llvm.org/D134928
I'm using clang 14.0.6-2 which I've installed with pacman on Arch Linux.
I'm currently trying to cross-compile LunaLua on Linux with clang. This project makes extensive use of casts from integers to pointers in
constexpr
contexts in order to reference static variables fromsmbx.exe
. Such casts are allowed in Visual C++ 2015 but not in clang. To overcome this restrictions, I used the following workarounds:__builtin_constant_p
GCC builtin:unsigned long
literal:Both codes compile successfully and the compiler doesn't raise warnings when using
-fsanitize=undefined,address
. Furthermore,test
or&test
have the correct value when passed to a function or assigned to a variable. The problem arises when passingtest
or&test
as a template parameter. In that case, they inexplicably take the valuenullptr
. Here's the output of both programs when compiled and executed:The text was updated successfully, but these errors were encountered: