Open DimitryAndric opened 2 years ago
@llvm/issue-subscribers-clang-frontend
@llvm/issue-subscribers-c-20
@llvm/issue-subscribers-clang-codegen
works without template, ICEs with template:
// clang++ -cc1 -triple x86_64-- -S -std=c++20 54831.cc
// non-template, ok
struct CLS {
static constexpr char hex_digits[] = "";
};
void Ok(bool upper) {
void (upper ? "" : CLS::hex_digits);
}
// ICE with template
template<typename = void>
struct TPL {
static constexpr char hex_digits[] = "";
};
void Bad(bool upper) {
void (upper ? "" : TPL<>::hex_digits);
}
Updating to today's HEAD (55b6a3186cfa) fixes the ICE
@urnathan any idea which specific commit fixes it? I'd like to backport it to 14.0.1.
I do not know. I last updated on Friday, to 26b3a1ea3483, so somewhere between those two commits? None of the [clang] fixes between those leap out (from their titles, not looked in detail). It could be the opaque pointer enablement patch: 702d5de4380b 2022-04-07 | [Clang] Enable opaque pointers by default [Nikita Popov] but if so, that smells coincidental
ETA: indeed, today adding -no-opaque-pointers is also needed to tickle the bug. so no magic happened over the weekend.
ETA: for some reason the TPL<>::hex_chars access gets a const char []
declrefexpr, which doesn't happen in the CLS::hex_chars case:
gdb) call RHSExpr->dump()
DeclRefExpr 0xd28c6c0 'const char[]' lvalue Var 0xd28c600 'hex_digits' 'const char[1]'
However, I think there's also a p388-related defect in order to get to the ICE.
I suppose I own this bug now.
yeah, we totally mess up the types of static members of template instantiations with incomplete array types:
template<typename = void> struct TPL
{
static constexpr char CEAry[] = "abc";
static char Ary[];
};
template<typename T> char TPL<T>::Ary[] = {0, 0};
void Use (const void *);
void Bob ()
{
Use(&typeid(TPL<>::CEAry)); // unbounded
Use(&typeid(TPL<>::Ary)); // unbounded
(void)(TPL<>::CEAry[0] + TPL<>::Ary[0]);
Use(&typeid(TPL<>::CEAry)); // bound[4]
Use(&typeid(TPL<>::Ary)); // unbounded!
}
The intializer should only be instantiated if the variable is used in such a way that it's needed. But we appear to be forgetting that the initializer can complete the array type. Excitingly the VarDecl's type is mutated after creation, depending no how it is used, that's never a good thing.
Ah yes, it looks like 702d5de4380b1e1554e5b90863093c3a57f76f70 papered over this bug, as the test case didn't assert anymore after that. However, if you run it with -no-opaque-pointers
, it still asserts in the same fashion.
After dcd74716f9d ("[clang] p0388 conversion to incomplete array", by @urnathan, reviewed by @AaronBallman), compiling the FreeBSD editors/imhex port (see https://github.com/WerWolv/ImHex), which uses C++20, results in assertion failures:
Assertion failed: (getType() == V->getType() && "All operands to PHI node must be the same type as the PHI node!"), function setIncomingValue, file /poudriere/jails/mainamd64PR261742/usr/src/contrib/llvm-project/llvm/include/llvm/IR/Instructions.h, line 2756.
Minimized test case (mostly parts of
std::format
):Backtrace: