+static size_t get_statement_struct_size(statement_type_t type)
+{
+ static const size_t sizes[] = {
+ [STATEMENT_COMPOUND] = sizeof(compound_statement_t),
+ [STATEMENT_RETURN] = sizeof(return_statement_t),
+ [STATEMENT_DECLARATION] = sizeof(declaration_statement_t),
+ [STATEMENT_IF] = sizeof(if_statement_t),
+ [STATEMENT_SWITCH] = sizeof(switch_statement_t),
+ [STATEMENT_EXPRESSION] = sizeof(expression_statement_t),
+ [STATEMENT_CONTINUE] = sizeof(statement_base_t),
+ [STATEMENT_BREAK] = sizeof(statement_base_t),
+ [STATEMENT_GOTO] = sizeof(goto_statement_t),
+ [STATEMENT_LABEL] = sizeof(label_statement_t),
+ [STATEMENT_CASE_LABEL] = sizeof(case_label_statement_t),
+ [STATEMENT_WHILE] = sizeof(while_statement_t),
+ [STATEMENT_DO_WHILE] = sizeof(do_while_statement_t),
+ [STATEMENT_FOR] = sizeof(for_statement_t),
+ [STATEMENT_ASM] = sizeof(asm_statement_t)
+ };
+ assert(type <= sizeof(sizes) / sizeof(sizes[0]));
+ assert(sizes[type] != 0);
+ return sizes[type];
+}
+
+static statement_t *allocate_statement_zero(statement_type_t type)
+{
+ size_t size = get_statement_struct_size(type);
+ statement_t *res = allocate_ast_zero(size);
+
+ res->base.type = type;
+ return res;
+}
+
+
+static size_t get_expression_struct_size(expression_type_t type)
+{
+ static const size_t sizes[] = {
+ [EXPR_INVALID] = sizeof(expression_base_t),
+ [EXPR_REFERENCE] = sizeof(reference_expression_t),
+ [EXPR_CONST] = sizeof(const_expression_t),
+ [EXPR_STRING_LITERAL] = sizeof(string_literal_expression_t),
+ [EXPR_WIDE_STRING_LITERAL] = sizeof(wide_string_literal_expression_t),
+ [EXPR_CALL] = sizeof(call_expression_t),
+ [EXPR_UNARY_FIRST] = sizeof(unary_expression_t),
+ [EXPR_BINARY_FIRST] = sizeof(binary_expression_t),
+ [EXPR_CONDITIONAL] = sizeof(conditional_expression_t),
+ [EXPR_SELECT] = sizeof(select_expression_t),
+ [EXPR_ARRAY_ACCESS] = sizeof(array_access_expression_t),
+ [EXPR_SIZEOF] = sizeof(sizeof_expression_t),
+ [EXPR_CLASSIFY_TYPE] = sizeof(classify_type_expression_t),
+ [EXPR_FUNCTION] = sizeof(string_literal_expression_t),
+ [EXPR_PRETTY_FUNCTION] = sizeof(string_literal_expression_t),
+ [EXPR_BUILTIN_SYMBOL] = sizeof(builtin_symbol_expression_t),
+ [EXPR_OFFSETOF] = sizeof(offsetof_expression_t),
+ [EXPR_VA_START] = sizeof(va_start_expression_t),
+ [EXPR_VA_ARG] = sizeof(va_arg_expression_t),
+ [EXPR_STATEMENT] = sizeof(statement_expression_t),
+ };
+ if(type >= EXPR_UNARY_FIRST && type <= EXPR_UNARY_LAST) {
+ return sizes[EXPR_UNARY_FIRST];
+ }
+ if(type >= EXPR_BINARY_FIRST && type <= EXPR_BINARY_LAST) {
+ return sizes[EXPR_BINARY_FIRST];
+ }
+ assert(type <= sizeof(sizes) / sizeof(sizes[0]));
+ assert(sizes[type] != 0);
+ return sizes[type];
+}
+
+static expression_t *allocate_expression_zero(expression_type_t type)
+{
+ size_t size = get_expression_struct_size(type);
+ expression_t *res = allocate_ast_zero(size);
+
+ res->base.type = type;
+ return res;
+}
+
+static size_t get_type_struct_size(type_type_t type)
+{
+ static const size_t sizes[] = {
+ [TYPE_ATOMIC] = sizeof(atomic_type_t),
+ [TYPE_COMPOUND_STRUCT] = sizeof(compound_type_t),
+ [TYPE_COMPOUND_UNION] = sizeof(compound_type_t),
+ [TYPE_ENUM] = sizeof(enum_type_t),
+ [TYPE_FUNCTION] = sizeof(function_type_t),
+ [TYPE_POINTER] = sizeof(pointer_type_t),
+ [TYPE_ARRAY] = sizeof(array_type_t),
+ [TYPE_BUILTIN] = sizeof(builtin_type_t),
+ [TYPE_TYPEDEF] = sizeof(typedef_type_t),
+ [TYPE_TYPEOF] = sizeof(typeof_type_t),
+ };
+ assert(sizeof(sizes) / sizeof(sizes[0]) == (int) TYPE_TYPEOF + 1);
+ assert(type <= TYPE_TYPEOF);
+ assert(sizes[type] != 0);
+ return sizes[type];
+}
+
+static type_t *allocate_type_zero(type_type_t type)