]> git.draconx.ca Git - cdecl99.git/commitdiff
Restrict the contexts in which typedef names can appear.
authorNick Bowler <nbowler@draconx.ca>
Sat, 25 Jun 2011 12:52:17 +0000 (08:52 -0400)
committerNick Bowler <nbowler@draconx.ca>
Sat, 25 Jun 2011 13:08:57 +0000 (09:08 -0400)
This should resolve a rather nasty ambiguity in the C grammar:

  [declaration] -> [declaration-specifiers] ;
                -> [type-specifier] [declaration-specifiers] ;
                -> int [declaration-specifiers] ;
                -> int [type-specifier] ;
                -> int [typedef-name] ;
                -> int [identifier] ;
                -> int x ;

versus

  [declaration] -> [declaration-specifiers] [init-declarator-list] ;
                -> [type-specifier] [init-declarator-list] ;
                -> int [init-declarator-list] ;
                -> int [init-declarator] ;
                -> int [declarator] ;
                -> int [direct-declarator] ;
                -> int [identifier] ;
                -> int x ;

The standard resolves this ambiguity by having a constraint that is not
part of the context-free grammar.  This ambiguity gets really nasty with
things like int f (x); -- is it a declaration of x with two type
specifiers or a declaration of f (a function with one parameter) with
with one type specifier?

A side-effect of this change is that the parser will now reject
declarations without any type specifiers at all, which probably makes
the error messages a bit less informative.

src/parse.y

index c003cc1e47aebf9586fe9379021c67324ea2026c..394c12a083e1fb30ebbb9bb3e63381ee165654e2 100644 (file)
@@ -140,8 +140,9 @@ void cdecl_free(struct cdecl *decl)
 %token T_UNION    "union"
 %token T_ENUM     "enum"
 
-%type <uintval>    declspec_simple
-%type <declspec>   declspec declspecs
+%type <uintval>    declspec_simple typespec_simple
+%type <declspec>   declspec_notype declspec_noid typespec_noid typespec
+%type <declspec>   declspecs declspecs_noid
 %type <declarator> declarator declarators
 %type <decl>       declaration
 
@@ -157,9 +158,17 @@ declaration: declspecs declarators T_SEMICOLON {
                .declarators = $2);
 };
 
-declspecs: { $$ = NULL; } | declspecs declspec {
-       $$ = $2;
-       $$->next = $1;
+declspecs: declspec_notype declspecs {
+       $$ = $1;
+       $$->next = $2;
+} | typespec declspecs_noid {
+       $$ = $1;
+       $$->next = $2;
+}
+
+declspecs_noid: { $$ = NULL; } | declspec_noid declspecs_noid {
+       $$ = $1;
+       $$->next = $2;
 }
 
 declarators: declarator | declarator T_COMMA declarators {
@@ -167,7 +176,17 @@ declarators: declarator | declarator T_COMMA declarators {
        $$->next = $3;
 };
 
-declspec_simple: T_VOID { $$ = CDECL_TYPE_VOID;     }
+declspec_simple: T_AUTO { $$ = CDECL_STOR_AUTO;     }
+       | T_TYPEDEF     { $$ = CDECL_STOR_TYPEDEF;  }
+       | T_EXTERN      { $$ = CDECL_STOR_EXTERN;   }
+       | T_STATIC      { $$ = CDECL_STOR_STATIC;   }
+       | T_REGISTER    { $$ = CDECL_STOR_REGISTER; }
+       | T_RESTRICT    { $$ = CDECL_QUAL_RESTRICT; }
+       | T_VOLATILE    { $$ = CDECL_QUAL_VOLATILE; }
+       | T_CONST       { $$ = CDECL_QUAL_CONST;    }
+       | T_INLINE      { $$ = CDECL_FUNC_INLINE;   }
+
+typespec_simple: T_VOID { $$ = CDECL_TYPE_VOID;     }
        | T_CHAR        { $$ = CDECL_TYPE_CHAR;     }
        | T_SHORT       { $$ = CDECL_TYPE_SHORT;    }
        | T_INT         { $$ = CDECL_TYPE_INT;      }
@@ -178,20 +197,16 @@ declspec_simple: T_VOID { $$ = CDECL_TYPE_VOID;     }
        | T_UNSIGNED    { $$ = CDECL_TYPE_UNSIGNED; }
        | T_BOOL        { $$ = CDECL_TYPE_BOOL;     }
        | T_COMPLEX     { $$ = CDECL_TYPE_COMPLEX;  }
-       | T_TYPEDEF     { $$ = CDECL_STOR_TYPEDEF;  }
-       | T_EXTERN      { $$ = CDECL_STOR_EXTERN;   }
-       | T_STATIC      { $$ = CDECL_STOR_STATIC;   }
-       | T_AUTO        { $$ = CDECL_STOR_AUTO;     }
-       | T_REGISTER    { $$ = CDECL_STOR_REGISTER; }
-       | T_RESTRICT    { $$ = CDECL_QUAL_RESTRICT; }
-       | T_VOLATILE    { $$ = CDECL_QUAL_VOLATILE; }
-       | T_CONST       { $$ = CDECL_QUAL_CONST;    }
-       | T_INLINE      { $$ = CDECL_FUNC_INLINE;   }
-       ;
 
-declspec: declspec_simple  {
+declspec_notype: declspec_simple  {
        ALLOC_STRUCT($$, struct cdecl_declspec, .type = $1);
-} | T_STRUCT T_IDENT {
+}
+
+typespec_noid: typespec_simple {
+       ALLOC_STRUCT($$, struct cdecl_declspec, .type = $1);
+}
+
+typespec: typespec_noid | T_STRUCT T_IDENT {
        ALLOC_STRUCT($$, struct cdecl_declspec,
                .type = CDECL_TYPE_STRUCT,
                .ident = $2);
@@ -207,7 +222,9 @@ declspec: declspec_simple  {
        ALLOC_STRUCT($$, struct cdecl_declspec,
                .type = CDECL_TYPE_IDENT,
                .ident = $1);
-};
+}
+
+declspec_noid: declspec_notype | typespec_noid
 
 declarator: T_IDENT {
        ALLOC_STRUCT($$, struct cdecl_declarator,