Issue |
146272
|
Summary |
[clang] ICE and corrupted values of non-type template parameters that include padding
|
Labels |
clang
|
Assignees |
|
Reporter |
tttapa
|
Accessing members of a non-type template parameter of struct type sometimes results in incorrect values or internal compiler errors if the struct has padding.
In particular, reading members after the padding returns the bits of other members. Accessing the last member seems to raise an out-of-bounds error in the compiler.
Reproducible on Clang 18, 19, 20 and trunk (3cc78a8067788e9aad2bee8ffa95c03ea2f17b04), both on Compiler Explorer and locally (using the releases from https://apt.llvm.org).
https://godbolt.org/z/Y8rf46Gvv
```cpp
// clang++ -std=c++20
#include <fmt/format.h>
struct Config {
unsigned char a = 0xAA;
unsigned int b = 0xBBBBBBBB;
unsigned char c = 0xCC;
unsigned char d = 0xDD;
unsigned char e = 0xEE;
};
template <Config Conf>
void foo() {
fmt::print("Conf.a = {:02X} ", Conf.a);
fmt::print("Conf.b = {:08X} ", Conf.b);
fmt::print("Conf.c = {:02X} ", Conf.c);
fmt::print("Conf.d = {:02X} ", Conf.d);
#ifndef __clang__ // fatal error: error in backend: Invalid size request on a scalable vector.
fmt::print("Conf.e = {:02X} ", Conf.e);
#endif
fmt::println("");
auto &conf = Conf;
fmt::print("conf.a = {:02X} ", conf.a);
fmt::print("conf.b = {:08X} ", conf.b);
fmt::print("conf.c = {:02X} ", conf.c);
fmt::print("conf.d = {:02X} ", conf.d);
fmt::print("conf.e = {:02X} ", conf.e);
fmt::println("");
}
int main() { foo<{}>(); }
```
```
Conf.a = AA Conf.b = 00EEDDCC Conf.c = DD Conf.d = EE
conf.a = AA conf.b = BBBBBBBB conf.c = CC conf.d = DD conf.e = EE
```
Note how `Conf.b` contains the bits of `Conf.{c,d,e}`, and the values of `Conf.{c,d}` are also offset by one byte. Trying to print `Conf.e` crashes the compiler.
The behavior seems to be sensitive to minor changes to the code. For example, storing `Conf` in a constexpr variable before printing does not trigger the bug. In the code base where I originally encountered the issue, passing `Conf.b` as a template argument to another function `template <int I> void bar();` would actually call `bar<0x00EEDDCC>()`, but I'm having trouble reproducing this in a standalone program.
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs