9

For such code:

typedef enum FooEnum : int FooEnum;
enum FooEnum : int { A = 1, B };

clang (linux/7.0.0) reports no errors [-c -std=c++11 -pedantic], but gcc (linux/8.2.1) doesn't compile it:

g++ -c -std=c++11 -pedantic test2.cpp
test2.cpp:1:28: error: expected ';' or '{' before 'FooEnum'
 typedef enum FooEnum : int FooEnum;
                            ^~~~~~~
test2.cpp:1:28: error: expected class-key before 'FooEnum'
test2.cpp:2:16: error: using typedef-name 'FooEnum' after 'enum'
 enum FooEnum : int { A = 1, B };
                ^~~
test2.cpp:1:28: note: 'FooEnum' has a previous declaration here
 typedef enum FooEnum : int FooEnum;

In fact I have no idea why use typedef for enum in C++, but question is this is bug in clang, because it accepts invalid code, or this is bug in c++11 standard, that allow different implementation?

Update: as it was explained to me, the first typedef is used for objc++ compability, to use the same header during c++ code compilation and objc++.

user1244932
  • 7,352
  • 5
  • 46
  • 103
  • 1
    Note that it's not a standard violation to *accept* ill-formed code. It *is* a standard violation to not diagnose ill-formed code (unless otherwise specified in the standard). – eerorika Oct 24 '18 at 14:18
  • @user2079303 So have no sense to report this to clang dev team? – user1244932 Oct 24 '18 at 14:23
  • Somewhat interestingly `using FooEnum = enum FooEnum : int;` does compile on both compilers (https://godbolt.org/z/Sw49IP) – UnholySheep Oct 24 '18 at 14:26
  • 3
    @user1244932 If this is ill-formed, and clang doesn't show a diagnostic (and standard doesn't say that diagnostic isn't required), then this should be reported. – eerorika Oct 24 '18 at 14:27
  • Might be related to [Why must an enumeration's size be provided when it is forward declared?](https://stackoverflow.com/q/29035225/1708801) – Shafik Yaghmour Oct 24 '18 at 15:55
  • FWIW, [MSVC also accepts the code without diagnostic](https://godbolt.org/z/nrVLp8) – Arne Vogel Oct 25 '18 at 14:41

2 Answers2

7

This is a clang bug, you cannot have a opaque-enum-declaration after a typedef specifier.

[dcl.typedef]/1

The typedef specifier shall not be combined in a decl-specifier-seq with any other kind of specifier except a defining-type-specifier,[...]

[dcl.type]/1

defining-type-specifier:

  • type-specifier

  • class-specifier

  • enum-specifier

[dcl.enum]/1

enum-specifier:

  • enum-head { enumerator-listopt }

  • enum-head { enumerator-list , }

So the code bellow is legal c++:

typedef enum FooEnum : int { A = 1, B } FooEnum;

but this one is not legal c++:

typedef enum FooEnum : int FooEnum;

Because enum FooEnum:int is not a defining-type-specifier.

Community
  • 1
  • 1
Oliv
  • 17,610
  • 1
  • 29
  • 72
0
typedef enum FooEnum : int FooEnum;

The above line is not valid. I assume you are trying to forward declare. Please refer to the example below.

enum class FooEnum;

int fooStar(FooEnum&);

enum class FooEnum : int {
    A =1,
    B
};

int foo(FooEnum fooEnum) {
  return static_cast<int>(fooEnum);
}

int fooStar(FooEnum& fooEnum) {
  return static_cast<int>(fooEnum);
}
Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
balki
  • 26,394
  • 30
  • 105
  • 151
  • 1
    This example is about enum class not about usual enum with underlying type specified like OP asked. – Öö Tiib Oct 24 '18 at 14:20
  • 1
    an example cannot prove the standard. To see if the example compiles you need to compile it but thats just what the question is about: Which compiler is right when accepting/rejecting OPs code – 463035818_is_not_an_ai Oct 24 '18 at 14:24
  • 1
    Since the title was `strong enum`, I assumed OP wanted `enum class` – balki Oct 24 '18 at 14:27
  • I thought that if the full declaration was going to include the underlying type (`int` in this case, don't know what the grammar calls it officially) then the forward decl needed to include it also. – davidbak Oct 24 '18 at 14:28
  • @davidbak It doesn't work like that for classes. I don't think it should be any different for enums. The point of forward declaration is to be able to use in context where you don't need to know the size or implementation of the type. – balki Oct 24 '18 at 14:31