llvm-project
5dcd3816 - [clang][ExprConstant] Fix error on static constexpr symbol in dllimport function (#171628)

Commit
5 days ago
[clang][ExprConstant] Fix error on static constexpr symbol in dllimport function (#171628) Consider the following: ``` struct A { __declspec(dllimport) __forceinline static const int* foo() { static constexpr int var = 42; static constexpr const int* p = &var; static_assert(*p == 42, ""); return p; } }; const int* (*pfoo)() = &A::foo; int main() { return pfoo() == A::foo(); } ``` With clang-cl, this generates an error: ``` > clang-cl /c C:\src\git\test\test.cpp C:\src\git\test\test.cpp(5,37): error: constexpr variable 'p' must be initialized by a constant expression 5 | static constexpr const int* p = &var; | ^ ~~~~ C:\src\git\test\test.cpp(6,23): error: static assertion expression is not an integral constant expression 6 | static_assert(*p == 42, ""); | ^~~~~~~~ C:\src\git\test\test.cpp(6,24): note: initializer of 'p' is not a constant expression 6 | static_assert(*p == 42, ""); | ^ C:\src\git\test\test.cpp(5,37): note: declared here 5 | static constexpr const int* p = &var; | ^ 2 errors generated. ``` MSVC cl.exe does not generate such error with the same snippet. The problem here is that the static variable 'var' inherits the dllimport attribute, and the const-init evaluation for 'p' is rejected because of the dllimport attribute. I think it's fine to accept the example above since the body of the function will be discarded anyway; and the inlined version of the function will contain a reference to the imported function-static symbol, like MSVC does: ``` > cl.exe /c test.cpp /Ox ... > dumpbin /disasm test.obj Microsoft (R) COFF/PE Dumper Version 14.44.35222.0 Copyright (C) Microsoft Corporation. All rights reserved. Dump of file test.obj File Type: COFF OBJECT main: 0000000000000000: 48 83 EC 28 sub rsp,28h 0000000000000004: FF 15 00 00 00 00 call qword ptr [?pfoo@@3P6APEBHXZEA] 000000000000000A: 48 8B 0D 00 00 00 mov rcx,qword ptr [__imp_?p@?1??foo@A@@SAPEBHXZ@4QEBHEB] 00 0000000000000011: 33 D2 xor edx,edx 0000000000000013: 48 3B 01 cmp rax,qword ptr [rcx] 0000000000000016: 0F 94 C2 sete dl 0000000000000019: 8B C2 mov eax,edx 000000000000001B: 48 83 C4 28 add rsp,28h 000000000000001F: C3 ret ??__Epfoo@@YAXXZ (void __cdecl `dynamic initializer for 'pfoo''(void)): 0000000000000000: 48 8B 05 00 00 00 mov rax,qword ptr [__imp_?foo@A@@SAPEBHXZ] 00 0000000000000007: 48 89 05 00 00 00 mov qword ptr [?pfoo@@3P6APEBHXZEA],rax 00 000000000000000E: C3 ret > clang-cl.exe /c test.cpp /Ox > dumpbin /disasm test.obj Microsoft (R) COFF/PE Dumper Version 14.44.35222.0 Copyright (C) Microsoft Corporation. All rights reserved. Dump of file test.obj File Type: COFF OBJECT main: 0000000000000000: 48 83 EC 28 sub rsp,28h 0000000000000004: FF 15 00 00 00 00 call qword ptr [?pfoo@@3P6APEBHXZEA] 000000000000000A: 31 C9 xor ecx,ecx 000000000000000C: 48 3B 05 00 00 00 cmp rax,qword ptr [__imp_?var@?1??foo@A@@SAPEBHXZ@4HB] 00 0000000000000013: 0F 94 C1 sete cl 0000000000000016: 89 C8 mov eax,ecx 0000000000000018: 48 83 C4 28 add rsp,28h 000000000000001C: C3 ret 000000000000001D: 0F 1F 00 nop dword ptr [rax] _GLOBAL__sub_I_test.cpp: 0000000000000020: 48 8B 05 00 00 00 mov rax,qword ptr [__imp_?foo@A@@SAPEBHXZ] 00 0000000000000027: 48 89 05 00 00 00 mov qword ptr [?pfoo@@3P6APEBHXZEA],rax 00 000000000000002E: C3 ret ``` Thanks to @jfmarquis for crafting a reproducer.
Author
Parents
Loading