Some comments on the parser:
The after_type_declarator
/ notype_declarator
hack is necessary in order to allow redeclarations of TYPENAME
s, for instance
typedef int foo; class A { char *foo; };
In the above, the first foo
is parsed as a notype_declarator
, and the second as a after_type_declarator
.
Ambiguities:
There are currently four reduce/reduce ambiguities in the parser. They are:
1) Between template_parm
and named_class_head_sans_basetype
, for the tokens aggr identifier
. This situation occurs in code looking like
template <class T> class A { };
It is ambiguous whether class T
should be parsed as the declaration of a template type parameter named T
or an unnamed constant parameter of type class T
. Section 14.6, paragraph 3 of the January '94 working paper states that the first interpretation is the correct one. This ambiguity results in two reduce/reduce conflicts.
2) Between primary
and type_id
for code like `int()' in places where both can be accepted, such as the argument to sizeof
. Section 8.1 of the pre-San Diego working paper specifies that these ambiguous constructs will be interpreted as typename
s. This ambiguity results in six reduce/reduce conflicts between `absdcl' and `functional_cast'.
3) Between functional_cast
and complex_direct_notype_declarator
, for various token strings. This situation occurs in code looking like
int (*a);
This code is ambiguous; it could be a declaration of the variable `a' as a pointer to `int', or it could be a functional cast of `*a' to `int'. Section 6.8 specifies that the former interpretation is correct. This ambiguity results in 7 reduce/reduce conflicts. Another aspect of this ambiguity is code like 'int (x[2]);', which is resolved at the '[' and accounts for 6 reduce/reduce conflicts between `direct_notype_declarator' and `primary'/`overqualified_id'. Finally, there are 4 r/r conflicts between `expr_or_declarator' and `primary' over code like 'int (a);', which could probably be resolved but would also probably be more trouble than it's worth. In all, this situation accounts for 17 conflicts. Ack!
The second case above is responsible for the failure to parse 'LinppFile ppfile (String (argv[1]), &outs, argc, argv);' (from Rogue Wave Math.h++) as an object declaration, and must be fixed so that it does not resolve until later.
4) Indirectly between after_type_declarator
and parm
, for type names. This occurs in (as one example) code like
typedef int foo, bar; class A { foo (bar); };
What is bar
inside the class definition? We currently interpret it as a parm
, as does Cfront, but IBM xlC interprets it as an after_type_declarator
. I believe that xlC is correct, in light of 7.1p2, which says "The longest sequence of decl-specifiers that could possibly be a type name is taken as the decl-specifier-seq of a declaration." However, it seems clear that this rule must be violated in the case of constructors. This ambiguity accounts for 8 conflicts.
Unlike the others, this ambiguity is not recognized by the Working Paper.