llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.86k stars 11.92k forks source link

clang-cl rejects "extern const __declspec(selectany)" variable as having "non-external linkage" when variable definition includes a struct definition #110208

Open dunhor opened 1 month ago

dunhor commented 1 month ago

Wow that title is a mouthful. Here's a concrete example:

extern const __declspec(selectany) struct { int x; } foo = { 42 };

clang-cl gives the error:

> clang-cl main.cpp
main.cpp(2,25): error: 'selectany' can only be applied to data items with external linkage
    2 | extern const __declspec(selectany) struct { int x; } foo = { 42 };
      |                         ^
1 error generated.

> clang -v
clang version 19.1.0
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: C:\Program Files\LLVM\bin

Of course, if you give the struct its own definition, the code compiles fine:

struct bar { int x; };
extern const __declspec(selectany) bar foo = { 42 };

MSVC compiles both without issue.

llvmbot commented 1 month ago

@llvm/issue-subscribers-clang-frontend

Author: Duncan Horn (dunhor)

Wow that title is a mouthful. Here's a concrete example: ```c++ extern const __declspec(selectany) struct { int x; } foo = { 42 }; ``` clang-cl gives the error: ``` > clang-cl main.cpp main.cpp(2,25): error: 'selectany' can only be applied to data items with external linkage 2 | extern const __declspec(selectany) struct { int x; } foo = { 42 }; | ^ 1 error generated. > clang -v clang version 19.1.0 Target: x86_64-pc-windows-msvc Thread model: posix InstalledDir: C:\Program Files\LLVM\bin ``` Of course, if you give the struct its own definition, the code compiles fine: ```c++ struct bar { int x; }; extern const __declspec(selectany) bar foo = { 42 }; ``` MSVC compiles both without issue.
efriedma-quic commented 1 month ago

Under C++ rules for type definitions, there isn't any way to actually declare the variable in question outside the current translation unit. (The type has no linkage, so any other declaration would have a different type, which violates ODR.) So marking it selectany is, at best, useless.

Probably the diagnostics here could be improved.