Illegal C++ in header files

20 Feb 2011

Hi,

While experimenting with offline compilers (I miss easy refactoring) I ran into compilation issues with the mbed header files, in particular the approach of defining a typedef before the corresponding enum, e.g from PinNames.h.

typedef enum PinMode PinMode;
enum PinMode {
    PullUp = 0
    , PullDown = 3
    , PullNone = 2
    , OpenDrain = 4
};

AFAIK this is not legal C++ as the typedef is forward referencing the enum.

20 Feb 2011

It might be a compiler-specific extension, which would work only when the size of the enum representation is known beforehand. And it _will_ be known because the proper declaration directly follows.

20 Feb 2011

Hi Graham,

Thanks for the report. I'll get that changed (removed).

Simon

20 Feb 2011

AFAIK a typedef just defines an alias for an existing type, it does not matter how the type is defined. This is why putting the typedef before the enum declaration is illegal, as the enum isn't yet a type in scope.

Although mbed, Keil RV and Visual Studio 2010 all compile it without error I'm pretty certain they're not conforming to the standard here. GCC (4.5.1) produces two errors for the typedef:

error: use of enum ‘PinMode’ without previous declaration
error: invalid type in declaration before ‘;’ token

which are understandable after I found out about the scoping rule for typedefs.

I guess the compilers that don't complain are using file scope instead of lexical scope.

21 Feb 2011

Judging from what I found with google the standard doesn't explicitely forbid this. One cannot have a forward declaration for a type where the compiler doesn't know anything about it's size - that's why typically a enum cannot be forward declared. But when the ARM compiler always creates enums with the same size, it can surely do a forward declaration. ARM states this here.

21 Feb 2011

The typedef statement isn't a declaration of a type, it's introducing an alias into the namespace for a type that's currently in scope.

At the point where the typedef alias is used then the size of the aliased type is required.