Is typedef name optional in typedef declaration?

I was very surprised when I saw that the following code compiles without errors or warnings in g ++ - 4.2:

typedef enum test { one }; 

My assumption was that if you used the typedef keyword, you would need an additional identifier, for example:

 typedef enum test { one } test; 

As already mentioned, g ++ - 4.2 accepts it even without warning. Clang ++ 3.0 warns "warning: typedef requires name", similarly, Como warns "warning: declaration requires name typedef", and g ++ - 4.6 reports: "warning:" typedef "was ignored in this declaration."

I could not determine where the standard allows it, and I find it a bit confusing that two of the compilers warn that this is necessary, shouldn't it be an error if typedef is required, but not?

UPDATE I checked in C with the same compilers. Clang and goau give the same result, gcc gives a warning: “warning: useless storage class specifier in an empty declaration”, which seems even more confusing.

UPDATE : I checked the removal of the enumeration name and the results will be the same:

 typedef enum { one }; 

Similarly named structure:

 typedef struct named { int x }; 

But not with an unnamed structure, in which case the code was rejected in g ++ (4.2 / 4.6) with "error: missing type-name in typedef-declaration", gcc (4.2 / 4.6) gave a warning: "warning: unnamed struct / union , which does not define instances, "clang ++" warning: declaration does not declare anything, "error on startup": declaration requires the name typedef "

+30
c ++ c typedef
Jun 19 2018-11-11T00:
source share
3 answers

This is a non-degenerate syntax that is allowed but does not provide any benefit. Most modern compilers can be triggered by a warning about this; by default they cannot. Without a typedef name, the typedef keyword is redundant; in your example, this is completely equivalent:

 enum test { one }; 

Another place where this can happen is with the structure:

 typedef struct SomeThing { int whatever; }; 

This is equivalent to:

 struct SomeThing { int whatever; }; 

Note that typedef formally (or syntactically) a “storage class specifier,” such as static , extern , auto and register .




C Standard

In ISO / IEC 9899: 1999 (which is standard C) we find:

§6.7 Announcements

Syntax

declaration:

Declaration-specs init-declarator-list opt ;

declaring specifiers:

storage specifier opt

opt ad specifier specifier

type-qualifier opt qualifiers

function-specifier opt -declaration

INIT-descriptor-list:

init-declarator

init-declarator-list, init-declarator

INIT descriptor:

declarator

declarator = initializer

And (upon request):

§6.7.1 Storage class qualifiers

Syntax

storage class specifier:

typedef

extern

static

auto

register

If you track this syntax, there are many degenerate possibilities, and what you have shown is one of many.




C ++ standard

It is possible that C ++ has different rules.

In ISO / IEC 14882: 1998 (the original C ++ standard) we find in §7.1.1 "Storage class specifiers" that C ++ does not treat typedef as a storage class; the list adds mutable and excludes typedef . So, the grammar specification of typedef in C ++ is definitely different from the specification of C.

§7 Announcements

Ads indicate how names should be interpreted. Ads take the form

Statement-cl:

Ad

declaration-seq declaration

declaration:

block declaration

function definition

ad template

Explicit Presentation

Explicit Specification

binding specification

namespace-definition

block declaration:

simple declaration

asm-definition

namespace-alias-definition

using-declaration

using directive

simple declaration:

decl-specifier-seq opt init-declarator-list opt ;

...

¶5 If decl-specifier-seq contains a typedef specifier, the declaration is called a typedef declaration and the name of each init-declarator declared as typedef-name, a synonym for the type associated with it (7.1.3).

§7.1. Qualifiers [dcl.spec]

Qualifiers that can be used in an ad are

Decl specifier:

storage class specifier

type specifier

function-specifier

friend

typedef

Decl-specifier-cl:

decl-specifier-seq opt

decl-specifier

§7.1.1 Storage class qualifiers [dcl.stc]

storage class specifier:

auto

register

static

extern

mutable

§7.1.2 Function specifiers [dcl.fct.spec]

specifier function:

inline

virtual

explicit

§7.1.3 typedef specifier [dcl.typedef]

Declarations containing the decl typedef specifier declare identifiers that can be used later for naming fundamental (3.9.1) or complex (3.9.2) types. The typedef specifier should not be used in the definition of function (8.4), and it should not be combined in the decl-seq specifier with any other specifier other than the type specifier.

Bureye name:

identifier

...

In a given area, the typedef specifier can be used to override the name of any type declared in this area to indicate the type to which it already belongs. [Example:

 typedef struct s { /* ... */ } s; typedef int I; typedef int I; typedef II; 

-end example]

§7.1.4 Friend specifier [dcl.friend]

A friend specifier is used to indicate access to class members; see 11.4.

§7.1.5 Type specifiers [dcl.type]

type specifier:

simple type specifier

class-specifier

enum-specifier

specified type specifier

cv-qualifier




Since § 7 ¶5 says that typedef names come from init-declarator, and 'opt' is marked in the init-declarator list, I think it means that typedef can be omitted in C ++, just like in C.

+36
Jun 19 '11 at 1:28
source share
— -

The only thing I could find was the following in the C ++ 03 §7.1.3 [dcl.typedef] p1 :

Bureye name:

  • identifier

A name declared using the typedef qualifier becomes the name of the typedef.

Notice the missing opt after the identifier, which indicates at least to me that an identifier is needed for the typedef name. It is strange that all tested compilers (silently) accept this.




Change After @Jonathan's answer, I found the following in the same standard as above:

Decl specifier:

  • storage class specifier
  • type specifier
  • Function specifier
  • friend
  • typedef

As you can see, it provides an additional case for typedef , and a list for storage class specifiers confirms this:

storage class specifier:

  • auto
  • register
  • static
  • extern
  • mutable

So, we are as ignorant as before in the case of C ++.

+3
Jun 19 2018-11-11T00:
source share

In my opinion, this is similar to the difference between C and C ++. C ++ implicitly typedefs structures and combines their tags; therefore, adding a typedef is redundant, but not a mistake. I don't know if this works for enumerations.

Next, find out which variable definitions are allowed after these declarations.

 enum test etest; test etest2; struct named snamed; named snamed2; 
0
Jun 19 '11 at 6:01
source share



All Articles