robertoraggi / cplusplus

A compiler front end for the C++ language
https://robertoraggi.github.io/cplusplus/
MIT License
118 stars 11 forks source link

expected a statement #311

Open mingodad opened 6 months ago

mingodad commented 6 months ago

With this issue solved now I'm getting the error shown bellow (that is a reduced case of this https://github.com/robertoraggi/cplusplus/issues/309#issuecomment-1872235706).

void test()
{
    int i;
    ( ({ long __cpu = ((long) i); }));
}
g++ -fsyntax-only test-bloc-in-parens.cpp
# no error
cxx test-bloc-in-parens.cpp
createSourceFile: test-bloc-in-parens.cpp
test-bloc-in-parens.cpp:4:33: expected a statement
    ( ({ long __cpu = ((long) i); }));
                                   ^
mingodad commented 6 months ago

Ast dump from clang:

clang-17-env clang -Xclang -ast-dump -fsyntax-only test-bloc-in-parens.cpp
TranslationUnitDecl 0x55df55b5f438 <<invalid sloc>> <invalid sloc>
|-TypedefDecl 0x55df55b5fca0 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128'
| `-BuiltinType 0x55df55b5fa00 '__int128'
|-TypedefDecl 0x55df55b5fd10 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128'
| `-BuiltinType 0x55df55b5fa20 'unsigned __int128'
|-TypedefDecl 0x55df55b60088 <<invalid sloc>> <invalid sloc> implicit __NSConstantString '__NSConstantString_tag'
| `-RecordType 0x55df55b5fe00 '__NSConstantString_tag'
|   `-CXXRecord 0x55df55b5fd68 '__NSConstantString_tag'
|-TypedefDecl 0x55df55b60120 <<invalid sloc>> <invalid sloc> implicit __builtin_ms_va_list 'char *'
| `-PointerType 0x55df55b600e0 'char *'
|   `-BuiltinType 0x55df55b5f4e0 'char'
|-TypedefDecl 0x55df55ba7d48 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list '__va_list_tag[1]'
| `-ConstantArrayType 0x55df55ba7cf0 '__va_list_tag[1]' 1 
|   `-RecordType 0x55df55b60210 '__va_list_tag'
|     `-CXXRecord 0x55df55b60178 '__va_list_tag'
`-FunctionDecl 0x55df55ba7de8 <test-bloc-in-parens.cpp:1:1, line:5:1> line:1:6 test 'void ()'
  `-CompoundStmt 0x55df55ba8110 <line:2:1, line:5:1>
    |-DeclStmt 0x55df55ba7f58 <line:3:2, col:7>
    | `-VarDecl 0x55df55ba7ef0 <col:2, col:6> col:6 used i 'int'
    `-ParenExpr 0x55df55ba80f0 <line:4:2, col:34> 'void'
      `-StmtExpr 0x55df55ba80d0 <col:4, col:33> 'void'
        `-CompoundStmt 0x55df55ba80b8 <col:5, col:32>
          `-DeclStmt 0x55df55ba80a0 <col:7, col:30>
            `-VarDecl 0x55df55ba7f88 <col:7, col:29> col:12 __cpu 'long' cinit
              `-ParenExpr 0x55df55ba8080 <col:20, col:29> 'long'
                `-CStyleCastExpr 0x55df55ba8058 <col:21, col:28> 'long' <NoOp>
                  `-ImplicitCastExpr 0x55df55ba8040 <col:28> 'long' <IntegralCast> part_of_explicit_cast
                    `-ImplicitCastExpr 0x55df55ba8028 <col:28> 'int' <LValueToRValue> part_of_explicit_cast
                      `-DeclRefExpr 0x55df55ba7ff0 <col:28> 'int' lvalue Var 0x55df55ba7ef0 'i' 'int'
mingodad commented 6 months ago

This PR https://github.com/robertoraggi/cplusplus/pull/316 solves :

/usr/include/x86_64-linux-gnu/bits/select.h:36:13: expected '('
    __asm__ __volatile__ ("cld; rep; " __FD_ZERO_STOS                 \
            ^
mingodad commented 6 months ago

Even circle https://www.circle-lang.org/ segfaults with this:

void test()
{
    int i;
    ( ({ long __cpu = ((long) i); }));
}

The grammar spec doesn't cover this, but g++ and clang++ does manage it. The tree-sitter playground https://tree-sitter.github.io/tree-sitter/playground also can't manage it.

mingodad commented 6 months ago

This is what is here https://github.com/llvm/llvm-project/blob/ff804146208bacb7dbb73e2b1da7943cb60125d2/clang/lib/Parse/ParseExpr.cpp#L2914 :

/// ParseParenExpression - This parses the unit that starts with a '(' token,
/// based on what is allowed by ExprType.  The actual thing parsed is returned
/// in ExprType. If stopIfCastExpr is true, it will only return the parsed type,
/// not the parsed cast-expression.
///
/// \verbatim
///       primary-expression: [C99 6.5.1]
///         '(' expression ')'
/// [GNU]   '(' compound-statement ')'      (if !ParenExprOnly)
///       postfix-expression: [C99 6.5.2]
///         '(' type-name ')' '{' initializer-list '}'
///         '(' type-name ')' '{' initializer-list ',' '}'
///       cast-expression: [C99 6.5.4]
///         '(' type-name ')' cast-expression
/// [ARC]   bridged-cast-expression
/// [ARC] bridged-cast-expression:
///         (__bridge type-name) cast-expression
///         (__bridge_transfer type-name) cast-expression
///         (__bridge_retained type-name) cast-expression
///       fold-expression: [C++1z]
///         '(' cast-expression fold-operator '...' ')'
///         '(' '...' fold-operator cast-expression ')'
///         '(' cast-expression fold-operator '...'
///                 fold-operator cast-expression ')'
/// [OPENMP] Array shaping operation
///       '(' '[' expression ']' { '[' expression ']' } cast-expression
/// \endverbatim
mingodad commented 6 months ago

I've added the g++-3.3.6 grammar here https://mingodad.github.io/cpp-grammars/g++-3.3.6.ebnf.xhtml#primary , it's the last g++ grammar that was yacc/bison based and it was easy to get a railroad diagram.

It shows the ( compstmt_or_stmtexpr ) in primary.