[clang] [clang] Prevent duplicated instantiation of enumerators of unscoped member enumerations (PR #124407)
André Brand via cfe-commits
cfe-commits at lists.llvm.org
Sat Jan 25 05:43:35 PST 2025
thebrandre wrote:
Here are some details why I think this is a valid fix:
If you take a look at the generated AST you can see that the EnumConstantDecl for `X 'S<int>::E'` appears twice in the instantiation in the AST for the following example.
```cpp
template <typename T>
struct S {
enum E : T;
enum E : T { X = 5 };
};
auto x = S<char>::X;
```
```
`-ClassTemplateSpecializationDecl <line:1:1, line:5:1> line:2:8 struct S definition implicit_instantiation
| |-DefinitionData [...]
| |-TemplateArgument type 'int'
| | `-BuiltinType 'int'
| |-CXXRecordDecl <col:1, col:8> col:8 implicit struct S
| |-EnumDecl <line:3:5, col:14> line:4:10 E 'int'
| | `-EnumConstantDecl <col:18, col:22> col:18 X 'S<int>::E'
| | `-ConstantExpr <col:22> 'int'
| | |-value: Int 5
| | `-IntegerLiteral <col:22> 'int' 5
| `-EnumDecl prev 0x1b3d5d90 <col:5, col:14> col:10 E 'int'
| `-EnumConstantDecl <col:18, col:22> col:18 X 'S<int>::E'
| `-ConstantExpr <col:22> 'int'
| |-value: Int 5
| `-IntegerLiteral <col:22> 'int' 5
```
If you compare it with analog cases with member classes and scoped member enumerations such as the following ...
```cpp
template <typename T>
struct S {
struct C;
struct C {
static constexpr T X = 5;
};
};
auto x = S<int>::C::X;
```
```cpp
template <typename T>
struct S {
enum class E : T;
enum class E : T { X = 5 };
};
auto x = S<int>::E::X;
```
... you can see [here on Compiler Explorer](https://godbolt.org/z/TEh95eqcv) that the second declarations in the instantiation simply refer to the previous and do not generate another definition.
Note that this issue does also not occur for function-local enumerations:
```cpp
template <typename T>
T f() {
enum E : T;
enum E : T { X = 5 };
return (T)X;
}
auto x = f<int>();
```
See [here on Compiler Explorer](https://godbolt.org/z/djoW8soEn).
I also added tests to make sure that out-of-class definitions are still supported.
https://github.com/llvm/llvm-project/pull/124407
More information about the cfe-commits
mailing list