grammars-v4 icon indicating copy to clipboard operation
grammars-v4 copied to clipboard

[C Language] Pointer Problem in Declaration

Open xurongchen opened this issue 3 years ago • 1 comments

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: image

Pull Request #1067 Result: image

My Fix Result: image

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

C Standard Result: image

Pull Request #1067 Result: image

My Fix Result: image

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: image

My Fix Result: image

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

image

xurongchen avatar May 07 '22 09:05 xurongchen

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.

kaby76 avatar May 07 '22 09:05 kaby76