jhjourdan / C11parser

A correct C89/C90/C99/C11/C18 parser written using Menhir and OCaml
Other
192 stars 17 forks source link

Questions about test bitfield_declaration_ambiguity.c #26

Closed zmajeed closed 5 months ago

zmajeed commented 5 months ago

This is tests/bitfield_declaration_ambiguity.c

1.  // bitfield_declaration_ambiguity.c
2.  typedef signed int T;
3.  struct S {
4.    unsigned T:3; // bit-field named T with type unsigned
5.    const T:3;    // anonymous bit-field with type const T
6.  };

And how it's listed in tests/tests.t

SHOULD FAIL:
  $ $PARSECMD < $TESTDIR/bitfield_declaration_ambiguity.c

Some comments on this test

  1. The test does not fail with GCC-14 nor with parse built in this repo
    
    gcc -std=c18 -fsyntax-only -Wpedantic -pedantic-errors tests/bitfield_declaration_ambiguity.c

echo $? 0

parse -std c11 -atomic-permissive-syntax <tests/bitfield_declaration_ambiguity.c

lexer: return INT lexer: return VARIABLE lexer: return VARIABLE lexer: return TYPE lexer: return TYPE translation_unit_file: external_declaration EOF translation_unit_file: external_declaration translation_unit_file

echo $? 0


2. The test still passes with line 5 removed - which is essentially `tests/bitfield_declaration_ambiguity.ok.c`
```c
typedef signed int T;
struct S {
  unsigned T:3; // bit-field named T with type unsigned
};
  1. But fails with line 4 removed for nothing to do with bitfields - essentially tests/bitfield_declaration_ambiguity.fail.c
    typedef signed int T;
    struct S {
    const T:3;    // anonymous bit-field with type const T
    };
bitfield_declaration_ambiguity.2.c:2:8: error: struct has no named members [-Wpedantic]
    2 | struct S {
      |        ^
  1. Adding a named field makes it pass

    typedef signed int T;
    struct S {
    int x;
    const T:3;    // anonymous bit-field with type const T
    };
  2. Normally signed and unsigned cannot be used together

    unsigned signed int x;
unsigned_signed_int.c:1:10: error: both ‘signed’ and ‘unsigned’ in declaration specifiers
    1 | unsigned signed int x;
  1. Even with typedef but the error is not informative
    typedef signed int T;
    unsigned T x;
unsigned_signed_typedef.c:2:12: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘x’
    2 | unsigned T x;
  1. What is the purpose of test bitfield_declaration_ambiguity.c?
jhjourdan commented 5 months ago

Again, "SHOULD FAIL" in tests.t does not refer to this test, but only to dangling_else_misleading.fail.c. This test does not fail, because it is correct C syntax.

  1. The test does not fail with GCC-14 nor with parse built in this repo
  2. The test still passes with line 5 removed - which is essentially tests/bitfield_declaration_ambiguity.ok.c

Indeed, this is intended.

  1. But fails with line 4 removed for nothing to do with bitfields - essentially tests/bitfield_declaration_ambiguity.fail.c

That is not correct. When given to GCC 14 with option -Wpedantic, this test emits a warning, complaining about the fact that this struct does not contain a named member. This warning can be turned into an error with -Werror, which I assume you use.

Our parser accepts this, because this is valid C syntax. Indeed, the standard (6.7.2.1 §8) tells that such a structure has undefined behavior, which means that the runtime semantics is undefined, but not that the program syntax is invalid. A compiler (such as GCC without these options) is right to accept such a program.

  1. Normally signed and unsigned cannot be used together

Yes, and therefore it is incorrect to consider T on line 4 as referring to the typedef above. And hence, it can only be considered as the name of the field we declare.

  1. Even with typedef but the error is not informative

The same thing happens here: the parser knows that T cannot refer to the typedef, because there would be two type specifiers. Therefore, the parser considers that T is the name of the declarator. When encountering x, it raises a syntax error, because there has already been a named declarator, and an identifier is unexpected. It lists all the tokens that can appear after a declarator.

  1. What is the purpose of test bitfield_declaration_ambiguity.c?

The point of these three tests is to check that we are doing the right thing with a subtle ambiguity in the C grammar, which is solved by the rule that only some type specifiers are allowed in declarations. For more information, please refer to:

Anyway, please correct me if I'm wrong, but I don't see any problem with this test.

zmajeed commented 5 months ago

Thanks for the response - section 2.3 plus your comments are helpful