tree-sitter-c
tree-sitter-c copied to clipboard
Error parsing statement expressions
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.
Can you try to reduce this down to make it easier to identify the problem?
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)
)
)
)
)
That doesn’t look like standard C. What is that syntax called?
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.
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).