E.g. w/ -std=c++11 #include <iostream> int main() { enum: unsigned int32_t { FOO, BAR } foobar = FOO; std::cout << ((time(nullptr) % 2) ? foobar : 13) << std::endl; } The initial error is: error: ambiguous overload for ‘operator<<’ (operand types are ‘std::ostream’ {aka ‘std::basic_ostream<char>’} and ‘unsigned int’) in gcc9.2 & gcc 11.2.0 gcc7 happily compiles the code. with -Wextra, all 3 versions warn: error: enumerated and non-enumerated type in conditional expression Version: 11.2.0 system: CentOS Linux 7.7.1908 on Intel Xeon command: g++ -Wall -Wextra -std=c++11 20211017-bug.cpp
Hmm: <source>:4:9: error: 'unsigned' specified with 'int32_t' {aka 'int'} [-Wpedantic] 4 | enum: unsigned int32_t { FOO, BAR } foobar = FOO; | ^~~~~~~~ Looks like this is the cause of the problem, Changing it to unsigned or uint32_t and the error goes away ...
unsigned int32_t is invalid. You cannot use unsigned (or short or long) with a typedef, only with 'int'. GCC was changed to diagnose that fairly recently, which is probably why the behaviour changed since GCC 7.
I think it was pr 84701
Thus invalid.
Richard, is there a way to represent the part of this that is a bug? Presumably accepting the construct but having it break template specialization with an error that can be arbitrarily disconnected from the definition is not a desired behavior. In the production code that I eventually isolated this from, there is in fact no reference at all to the header that contained the enum. Also, it seems likely that the compiler state is bad at that point (?), as the error message indicates an 'unsigned int' ambiguity that doesn't actually exist.
This is a bug, we should either reject 'unsigned int32_t' immediately (which we only do with -pedantic-errors) or we should accept it and treat it consistently as unsigned int. Reduced: enum: unsigned int32_t { FOO, BAR } foobar = FOO; int f(int); int f(unsigned); auto x = f(1 ? foobar : 13); With r254043 we just have a pedwarn: 102804.C:2:16: warning: long, short, signed or unsigned used invalidly for 'type name' [-Wpedantic] enum: unsigned int32_t { FOO, BAR } foobar = FOO; ^~~~~~~ With r254046 we get the error: 102804.C:2:16: warning: long, short, signed or unsigned used invalidly for 'type name' [-Wpedantic] enum: unsigned int32_t { FOO, BAR } foobar = FOO; ^~~~~~~ 102804.C:5:27: error: call of overloaded 'f(unsigned int)' is ambiguous auto x = f(1 ? foobar : 13); ^ 102804.C:3:5: note: candidate: 'int f(int)' int f(int); ^ 102804.C:4:5: note: candidate: 'int f(unsigned int)' int f(unsigned); ^ re PR c++/82307 (unscoped enum-base incorrect cast) /cp 2017-10-24 Mukesh Kapoor <mukesh.kapoor@oracle.com> Paolo Carlini <paolo.carlini@oracle.com> PR c++/82307 * cvt.c (type_promotes_to): Implement C++17, 7.6/4, about unscoped enumeration type whose underlying type is fixed. So it was actually caused by fixing the promotion rules for enums (PR 82307), not by the handling of 'unsigned' applied to a typedef.
Oops, sorry the reduced example was missing the first line. Fixed, and further reduced: using int32_t = int; enum: unsigned int32_t { foo }; int f(int); int f(unsigned); auto x = f(1 ? foo : 1);
The master branch has been updated by Jason Merrill <jason@gcc.gnu.org>: https://gcc.gnu.org/g:e580f81d22d61153564959f08d9a6d3bcc7fd386 commit r12-8173-ge580f81d22d61153564959f08d9a6d3bcc7fd386 Author: Jason Merrill <jason@redhat.com> Date: Thu Apr 14 17:49:47 2022 -0400 c++: unsigned int32_t enum promotion [PR102804] There's been an extension for a long time to allow applying 'unsigned' to an int typedef, but that was confusing the integer promotion code. Fixed by forgetting about the typedef in that case. I'm going to make this an unconditional pedwarn in stage 1. PR c++/102804 gcc/cp/ChangeLog: * decl.cc (grokdeclarator): Drop typedef used with 'unsigned'. gcc/testsuite/ChangeLog: * g++.dg/ext/unsigned-typedef1.C: New test.
GCC 9 branch is being closed
GCC 10.4 is being released, retargeting bugs to GCC 10.5.
GCC 10 branch is being closed.