Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error parsing statement expressions #46

Open
genotrance opened this issue Jul 2, 2020 · 5 comments
Open

Error parsing statement expressions #46

genotrance opened this issue Jul 2, 2020 · 5 comments

Comments

@genotrance
Copy link

Source:

static inline void* sx__aligned_alloc(const sx_alloc* alloc, size_t size, uint32_t align,
                                      const char* file, const char* func, uint32_t line)
{
    align = ({ typeof((int)align) var__a = ((int)align); typeof(8) var__b = (8); (void)(&var__a == &var__b); var__a > 8 ? var__a : var__b; });
    const size_t total = size + align + sizeof(uint32_t);
    uint8_t* ptr = (uint8_t*)sx__malloc(alloc, total, 0, file, func, line);
    ;
    uint8_t* aligned = (uint8_t*)sx_align_ptr(ptr, sizeof(uint32_t), align);
    uint32_t* header = (uint32_t*)aligned - 1;
    *header = (uint32_t)(uintptr_t)(aligned - ptr);
    return aligned;
}

Results in error:

(translation_unit 2 1 662
 (function_definition 2 1 321
  (storage_class_specifier 2 1 6 "static")
  (storage_class_specifier 2 8 6 "inline")
  (primitive_type 2 15 4 "void")
  (pointer_declarator 2 19 160
   (function_declarator 2 21 158
    (identifier 2 21 17 "sx__aligned_alloc")
    (parameter_list 2 38 141
     (parameter_declaration 2 39 21
      (type_qualifier 2 39 5 "const")
      (type_identifier 2 45 8 "sx_alloc")
      (pointer_declarator 2 53 7
       (identifier 2 55 5 "alloc")
      )
     )
     (parameter_declaration 2 62 11
      (primitive_type 2 62 6 "size_t")
      (identifier 2 69 4 "size")
     )
     (parameter_declaration 2 75 14
      (primitive_type 2 75 8 "uint32_t")
      (identifier 2 84 5 "align")
     )
     (parameter_declaration 3 39 16
      (type_qualifier 3 39 5 "const")
      (primitive_type 3 45 4 "char")
      (pointer_declarator 3 49 6
       (identifier 3 51 4 "file")
      )
     )
     (parameter_declaration 3 57 16
      (type_qualifier 3 57 5 "const")
      (primitive_type 3 63 4 "char")
      (pointer_declarator 3 67 6
       (identifier 3 69 4 "func")
      )
     )
     (parameter_declaration 3 75 13
      (primitive_type 3 75 8 "uint32_t")
      (identifier 3 84 4 "line")
     )
    )
   )
  )
  (compound_statement 4 1 142
   (expression_statement 5 5 52
    (assignment_expression 5 5 51
     (identifier 5 5 5 "align")
     (parenthesized_expression 5 13 43
      (ERROR 5 14 20
       (call_expression 5 16 18 "typeof((int)align)"
        (identifier 5 16 6 "typeof")
        (argument_list 5 22 12 "((int)align)"
         (cast_expression 5 23 10 "(int)align"
          (type_descriptor 5 24 3 "int"
           (primitive_type 5 24 3 "int")
          )
          (identifier 5 28 5 "align")
         )
        )
       )
      )
      (assignment_expression 5 35 21
       (identifier 5 35 6 "var__a")
       (parenthesized_expression 5 44 12 "((int)align)"
        (cast_expression 5 45 10 "(int)align"
         (type_descriptor 5 46 3 "int"
          (primitive_type 5 46 3 "int")
         )
         (identifier 5 50 5 "align")
        )
       )
      )
     )
    )
   )
   (expression_statement 5 58 23
    (assignment_expression 5 58 22
     (call_expression 5 58 9 "typeof(8)"
      (identifier 5 58 6 "typeof")
      (argument_list 5 64 3 "(8)"
       (number_literal 5 65 1 "8")
      )
     )
     (ERROR 5 68 6 "var__b"
      (identifier 5 68 6 "var__b")
     )
     (parenthesized_expression 5 77 3 "(8)"
      (number_literal 5 78 1 "8")
     )
    )
   )
   (expression_statement 5 82 27
    (cast_expression 5 82 26
     (type_descriptor 5 83 4 "void"
      (primitive_type 5 83 4 "void")
     )
     (parenthesized_expression 5 88 20
      (binary_expression 5 89 18
       (pointer_expression 5 89 7 "&var__a"
        (identifier 5 90 6 "var__a")
       )
       (pointer_expression 5 100 7 "&var__b"
        (identifier 5 101 6 "var__b")
       )
      )
     )
    )
   )
   (expression_statement 5 110 29
    (conditional_expression 5 110 28
     (binary_expression 5 110 10
      (identifier 5 110 6 "var__a")
      (number_literal 5 119 1 "8")
     )
     (identifier 5 123 6 "var__a")
     (identifier 5 132 6 "var__b")
    )
   )
  )
 )
 (ERROR 5 141 1 ")")
 (expression_statement 5 142 1 ";")
 (declaration 6 5 53
  (type_qualifier 6 5 5 "const")
  (primitive_type 6 11 6 "size_t")
  (init_declarator 6 18 39
   (identifier 6 18 5 "total")
   (binary_expression 6 26 31
    (binary_expression 6 26 12
     (identifier 6 26 4 "size")
     (identifier 6 33 5 "align")
    )
    (sizeof_expression 6 41 16 "sizeof(uint32_t)"
     (type_descriptor 6 48 8 "uint32_t"
      (primitive_type 6 48 8 "uint32_t")
     )
    )
   )
  )
 )
 (declaration 7 5 71
  (primitive_type 7 5 7 "uint8_t")
  (init_declarator 7 12 63
   (pointer_declarator 7 12 5
    (identifier 7 14 3 "ptr")
   )
   (cast_expression 7 20 55
    (type_descriptor 7 21 8 "uint8_t*"
     (primitive_type 7 21 7 "uint8_t")
     (abstract_pointer_declarator 7 28 1 "*")
    )
    (call_expression 7 30 45
     (identifier 7 30 10 "sx__malloc")
     (argument_list 7 40 35
      (identifier 7 41 5 "alloc")
      (identifier 7 48 5 "total")
      (number_literal 7 55 1 "0")
      (identifier 7 58 4 "file")
      (identifier 7 64 4 "func")
      (identifier 7 70 4 "line")
     )
    )
   )
  )
 )
 (expression_statement 8 5 1 ";")
 (declaration 9 5 72
  (primitive_type 9 5 7 "uint8_t")
  (init_declarator 9 12 64
   (pointer_declarator 9 12 9
    (identifier 9 14 7 "aligned")
   )
   (cast_expression 9 24 52
    (type_descriptor 9 25 8 "uint8_t*"
     (primitive_type 9 25 7 "uint8_t")
     (abstract_pointer_declarator 9 32 1 "*")
    )
    (call_expression 9 34 42
     (identifier 9 34 12 "sx_align_ptr")
     (argument_list 9 46 30
      (identifier 9 47 3 "ptr")
      (sizeof_expression 9 52 16 "sizeof(uint32_t)"
       (type_descriptor 9 59 8 "uint32_t"
        (primitive_type 9 59 8 "uint32_t")
       )
      )
      (identifier 9 70 5 "align")
     )
    )
   )
  )
 )
 (declaration 10 5 42
  (primitive_type 10 5 8 "uint32_t")
  (init_declarator 10 13 33
   (pointer_declarator 10 13 8
    (identifier 10 15 6 "header")
   )
   (binary_expression 10 24 22
    (cast_expression 10 24 18 "(uint32_t*)aligned"
     (type_descriptor 10 25 9 "uint32_t*"
      (primitive_type 10 25 8 "uint32_t")
      (abstract_pointer_declarator 10 33 1 "*")
     )
     (identifier 10 35 7 "aligned")
    )
    (number_literal 10 45 1 "1")
   )
  )
 )
 (expression_statement 11 5 47
  (assignment_expression 11 5 46
   (pointer_expression 11 5 7 "*header"
    (identifier 11 6 6 "header")
   )
   (cast_expression 11 15 36
    (type_descriptor 11 16 8 "uint32_t"
     (primitive_type 11 16 8 "uint32_t")
    )
    (cast_expression 11 25 26
     (type_descriptor 11 26 9 "uintptr_t"
      (primitive_type 11 26 9 "uintptr_t")
     )
     (parenthesized_expression 11 36 15
      (binary_expression 11 37 13
       (identifier 11 37 7 "aligned")
       (identifier 11 47 3 "ptr")
      )
     )
    )
   )
  )
 )
 (return_statement 12 5 15
  (identifier 12 12 7 "aligned")
 )
 (ERROR 13 1 1 "}")
)

First line of function itself fails by itself.

@maxbrunsfeld
Copy link
Contributor

Can you try to reduce this down to make it easier to identify the problem?

@genotrance
Copy link
Author

The first line of the function itself fails. Reducing it even further:

align = ({ typeof((int)align) var__a = ((int)align);});
(translation_unit 2 1 57
 (expression_statement 2 1 56
  (assignment_expression 2 1 55
   (identifier 2 1 5 "align")
   (parenthesized_expression 2 9 47
    (ERROR 2 10 20
     (call_expression 2 12 18 "typeof((int)align)"
      (identifier 2 12 6 "typeof")
      (argument_list 2 18 12 "((int)align)"
       (cast_expression 2 19 10 "(int)align"
        (type_descriptor 2 20 3 "int"
         (primitive_type 2 20 3 "int")
        )
        (identifier 2 24 5 "align")
       )
      )
     )
    )
    (assignment_expression 2 31 21
     (identifier 2 31 6 "var__a")
     (parenthesized_expression 2 40 12 "((int)align)"
      (cast_expression 2 41 10 "(int)align"
       (type_descriptor 2 42 3 "int"
        (primitive_type 2 42 3 "int")
       )
       (identifier 2 46 5 "align")
      )
     )
    )
    (ERROR 2 52 3)
   )
  )
 )
)

@maxbrunsfeld
Copy link
Contributor

That doesn’t look like standard C. What is that syntax called?

@genotrance
Copy link
Author

I found this in the sx library:

align = sx_max((int)align, SX_CONFIG_ALLOCATOR_NATURAL_ALIGNMENT);

// https://github.com/septag/sx/blob/master/include/sx/allocator.h#L136

gets expanded to the following after preprocessing (gcc -E):

align = ({ typeof((int)align) var__a = ((int)align); typeof(8) var__b = (8); (void)(&var__a == &var__b); var__a > 8 ? var__a : var__b; });

This is because they define sx_max() as follows:

#ifndef __cplusplus
#    if SX_COMPILER_GCC || SX_COMPILER_CLANG
#        define sx_max(a, b)                  \
            ({                                \
                typeof(a) var__a = (a);       \
                typeof(b) var__b = (b);       \
                (void)(&var__a == &var__b);   \
                var__a > b ? var__a : var__b; \
            })

// https://github.com/septag/sx/blob/master/include/sx/sx.h#L78

Looks like a block syntax using {}, gcc doesn't mind.

@dcreager
Copy link

dcreager commented Jul 7, 2020

This example uses a couple of GCC extensions: typeof and statement expressions. Not sure what our policy is for supporting syntax extensions in the grammar — if we do, we should add these. typeof should be handled similarly to sizeof (i.e. it's an operator with an alphabetic name, not a standard function or macro being called).

@dcreager dcreager changed the title ERROR parsing expression Error parsing statement expressions Jul 7, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants