[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