llvm / llvm-project

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

Integral promotion on incomplete enum types #49922

Open 7318a870-54d1-4d9b-a5cf-8ce660251251 opened 3 years ago

7318a870-54d1-4d9b-a5cf-8ce660251251 commented 3 years ago
Bugzilla Link 50578
Version unspecified
OS All
CC @DougGregor,@zygoloid

Extended Description

int f(int); template E&& g(); enum E { e = decltype(f(g()))(42), };

This is rejected by clang 9 and accepted since 10.

Initialization of the parameter of f involves an lvalue-to-rvalue conversion on g() followed by an integral promotion. The former should be ill-formed by [conv.lval]p1:

A glvalue of a non-function, non-array type T can be converted to a prvalue. If T is an incomplete type, a program that necessitates this conversion is ill-formed.

wheatman commented 10 months ago

This code is still accepted as of post 17 trunk(60c4f82d3c4e9cfc337c360f489d830d0379b04d) https://godbolt.org/z/oT7h6Ga8a

The code is also accepted by msvc (19.39.33321 ) and rejected by gcc (13.2)

code

int f(int);
template<class E>
E&& g();
enum E {
    e = decltype(f(g<E>()))(42),
};

gcc error message

<source>:5:24: error: cannot convert 'E' to 'int'
    5 |     e = decltype(f(g<E>()))(42),
      |                    ~~~~^~
      |                        |
      |                        E
<source>:1:7: note:   initializing argument 1 of 'int f(int)'
    1 | int f(int);
      |       ^~~
<source>:5:24: error: cannot convert 'E' to 'int'
    5 |     e = decltype(f(g<E>()))(42),
      |                    ~~~~^~
      |                        |
      |                        E
<source>:1:7: note:   initializing argument 1 of 'int f(int)'
    1 | int f(int);
      |       ^~~
Compiler returned: 1
llvmbot commented 10 months ago

@llvm/issue-subscribers-clang-frontend

Author: None (7318a870-54d1-4d9b-a5cf-8ce660251251)

| | | | --- | --- | | Bugzilla Link | [50578](https://llvm.org/bz50578) | | Version | unspecified | | OS | All | | CC | @DougGregor,@zygoloid | ## Extended Description int f(int); template<class E> E&& g(); enum E { e = decltype(f(g<E>()))(42), }; This is rejected by clang 9 and accepted since 10. Initialization of the parameter of f involves an lvalue-to-rvalue conversion on g<E>() followed by an integral promotion. The former should be ill-formed by [conv.lval]p1: A glvalue of a non-function, non-array type T can be converted to a prvalue. If T is an incomplete type, a program that necessitates this conversion is ill-formed.
shafik commented 10 months ago

This is an unevaluated context and so I don't believe it needs to be complete since we can determine the result from f which is int and therefore no conversions are actually required.

CC @zygoloid