grammars-v4
grammars-v4 copied to clipboard
[C Language] Pointer Problem in Declaration
I made the fix: pull request #2614
The current parser for pointers in the declaration is not correct. The error is produced by the pull request #1067.
The pull request #1067 claims that it add the parser rules for function returns pointer type & function pointer. However, the parser rules had actually been already supported by the original grammar, which is referred from the C language standard.
According to the related issue #1065 and the issue #1066, I guess what @smwikipedia wants to do is to make the grammar support a Microsoft Visual C extension __cdecl. The pull request #1067 make the following changes:
typeSpecifier
: ('void'
| 'char'
...
| enumSpecifier
| typedefName
| '__typeof__' '(' constantExpression ')' // GCC extension
| typeSpecifier pointer // => Added by pull request #1067
;
directDeclarator
: Identifier
| '(' declarator ')'
| directDeclarator '[' typeQualifierList? assignmentExpression? ']'
| directDeclarator '[' 'static' typeQualifierList? assignmentExpression ']'
| directDeclarator '[' typeQualifierList 'static' assignmentExpression ']'
| directDeclarator '[' typeQualifierList? '*' ']'
| directDeclarator '(' parameterTypeList ')'
| directDeclarator '(' identifierList? ')'
| Identifier ':' DigitSequence // bit field
| '(' typeSpecifier? pointer directDeclarator ')' // function pointer like: (__cdecl *f) => Added by pull request #1067
;
This change makes typeSpecifier can accept a pointer, which is not consistent with the C language standard (section 6.7.2, page 110).
This is a mistake because we know that for a C declaration:
int * x, y;
In the C standard, only int is typeSpecifier, which specifies the type for *x and y. Thus, we conclude that x is a pointer of int and y is int.
However, if we allow typeSpecifier to accept a pointer, the analysis result will become that both x and y are pointers of int, which is completely wrong!
To solve the @smwikipedia's problem, i.e., make the grammar to support a Microsoft Visual C extension __cdecl, I referred to the
Microsoft document and made the following changes (including reverting the pull request #1067).
typeSpecifier
: ('void'
| 'char'
...
| enumSpecifier
| typedefName
| '__typeof__' '(' constantExpression ')' // GCC extension
;
directDeclarator
: Identifier
| '(' declarator ')'
| directDeclarator '[' typeQualifierList? assignmentExpression? ']'
| directDeclarator '[' 'static' typeQualifierList? assignmentExpression ']'
| directDeclarator '[' typeQualifierList 'static' assignmentExpression ']'
| directDeclarator '[' typeQualifierList? '*' ']'
| directDeclarator '(' parameterTypeList ')'
| directDeclarator '(' identifierList? ')'
| Identifier ':' DigitSequence // bit field
| vcSpecificModifer Identifier // Visual C Extension <= My fix
| '(' vcSpecificModifer declarator ')' // Visual C Extension <= My fix
;
vcSpecificModifer
: ('__cdecl'
| '__clrcall'
| '__stdcall'
| '__fastcall'
| '__thiscall'
| '__vectorcall')
;
After that, the comment by @Dzialo3 in the pull request #1067 is also resolved.
Parser Tree Example
I made some examples to show the changes of the parser tree for the C standard, pull request #1067, and my fix.
int *x; // a pointer of int
C Standard Result:

Pull Request #1067 Result:

My Fix Result:

int *x(int, int); // a function, whose return type is a pointer of int and the parameter are two int
C Standard Result:

Pull Request #1067 Result:

My Fix Result:

int * __cdecl x(int, int); // a function labeled with __cdecl, whose return type is a pointer of int and the paramater are two int
C Standard Result: Not support visual C extension
Pull Request #1067 Result:

My Fix Result:

Test my fix on a more complex example
int * (* __cdecl x)(int, int); // a function pointer labeled with __cdecl, whose return type is a pointer of int and the paramater are two int

It would be good to add semantic predicates in the grammar for a particular compiler extension--such as for the MS C or GNU--over the ISO Spec. As you note, it's hard to understand why someone mucked around with the grammar unless it is clearly labeled.