eliminate more casts, () in a function definition means no parameters not unspecified...
authorMatthias Braun <matze@braunis.de>
Tue, 27 Nov 2007 18:28:39 +0000 (18:28 +0000)
committerMatthias Braun <matze@braunis.de>
Tue, 27 Nov 2007 18:28:39 +0000 (18:28 +0000)
[r18555]

Makefile
ast.c
ast2firm.c
ast_t.h
parser.c
type.c
type_hash.c
type_t.h

index 90ebb25..3812b37 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@ GOAL = cparser
 FIRM_HOME = $(HOME)/projects/firm
 FIRM_BUILD = $(FIRM_HOME)/build/i686-pc-linux-gnu/debug/
 FIRM_CFLAGS = -I$(FIRM_HOME)/libfirm/include -I$(FIRM_HOME)/obstack -I$(FIRM_HOME)/libcore -I$(FIRM_HOME)/libcore/libcore -I$(FIRM_HOME)
-FIRM_LIBS = -L$(FIRM_BUILD) -lfirm -llpp -lcore -lm -ldl -lz
+FIRM_LIBS = -L$(FIRM_BUILD) -lfirm -llpp -lcore -lm -lz
 
 CPPFLAGS  = -DHAVE_CONFIG_H -DFIRM_BACKEND
 CPPFLAGS += -I.
diff --git a/ast.c b/ast.c
index 8ca0dad..413226a 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -264,40 +264,40 @@ void print_expression(const expression_t *expression)
        case EXPR_FUNCTION:
        case EXPR_PRETTY_FUNCTION:
        case EXPR_STRING_LITERAL:
-               print_string_literal(&expression->string_literal);
+               print_string_literal(&expression->string);
                break;
        case EXPR_CALL:
-               print_call_expression((const call_expression_t*) expression);
+               print_call_expression(&expression->call);
                break;
        case EXPR_BINARY:
-               print_binary_expression((const binary_expression_t*) expression);
+               print_binary_expression(&expression->binary);
                break;
        case EXPR_REFERENCE:
-               print_reference_expression((const reference_expression_t*) expression);
+               print_reference_expression(&expression->reference);
                break;
        case EXPR_ARRAY_ACCESS:
-               print_array_expression((const array_access_expression_t*) expression);
+               print_array_expression(&expression->array_access);
                break;
        case EXPR_UNARY:
-               print_unary_expression((const unary_expression_t*) expression);
+               print_unary_expression(&expression->unary);
                break;
        case EXPR_SIZEOF:
-               print_sizeof_expression((const sizeof_expression_t*) expression);
+               print_sizeof_expression(&expression->sizeofe);
                break;
        case EXPR_BUILTIN_SYMBOL:
-               print_builtin_symbol((const builtin_symbol_expression_t*) expression);
+               print_builtin_symbol(&expression->builtin_symbol);
                break;
        case EXPR_CONDITIONAL:
-               print_conditional((const conditional_expression_t*) expression);
+               print_conditional(&expression->conditional);
                break;
        case EXPR_VA_ARG:
-               print_va_arg((const va_arg_expression_t*) expression);
+               print_va_arg(&expression->va_arge);
                break;
        case EXPR_SELECT:
-               print_select((const select_expression_t*) expression);
+               print_select(&expression->select);
                break;
        case EXPR_CLASSIFY_TYPE:
-               print_classify_type_expression((const classify_type_expression_t*)expression);
+               print_classify_type_expression(&expression->classify_type);
                break;
 
        case EXPR_OFFSETOF:
index 07c29f5..b156f48 100644 (file)
@@ -242,7 +242,6 @@ static unsigned get_type_size(type_t *type)
        case TYPE_BUILTIN:
        case TYPE_TYPEDEF:
        case TYPE_TYPEOF:
-       case TYPE_COUNT:
        case TYPE_INVALID:
                break;
        }
@@ -524,7 +523,6 @@ static ir_type *get_ir_type(type_t *type)
        case TYPE_BUILTIN:
        case TYPE_TYPEOF:
        case TYPE_TYPEDEF:
-       case TYPE_COUNT:
        case TYPE_INVALID:
                break;
        }
@@ -1646,7 +1644,7 @@ static ir_node *_expression_to_firm(const expression_t *expression)
        case EXPR_CONST:
                return const_to_firm(&expression->conste);
        case EXPR_STRING_LITERAL:
-               return string_literal_to_firm(&expression->string_literal);
+               return string_literal_to_firm(&expression->string);
        case EXPR_REFERENCE:
                return reference_expression_to_firm(&expression->reference);
        case EXPR_CALL:
@@ -1667,7 +1665,7 @@ static ir_node *_expression_to_firm(const expression_t *expression)
                return classify_type_to_firm(&expression->classify_type);
        case EXPR_FUNCTION:
        case EXPR_PRETTY_FUNCTION:
-               return function_name_to_firm(&expression->string_literal);
+               return function_name_to_firm(&expression->string);
        case EXPR_STATEMENT:
                return statement_expression_to_firm(&expression->statement);
        case EXPR_OFFSETOF:
diff --git a/ast_t.h b/ast_t.h
index 8154643..e6f7f4d 100644 (file)
--- a/ast_t.h
+++ b/ast_t.h
@@ -202,7 +202,7 @@ union expression_t {
        expression_type_t            type;
        expression_base_t            base;
        const_expression_t           conste;
-       string_literal_expression_t  string_literal;
+       string_literal_expression_t  string;
        builtin_symbol_expression_t  builtin_symbol;
        reference_expression_t       reference;
        call_expression_t            call;
@@ -233,7 +233,7 @@ typedef enum {
        NAMESPACE_STRUCT,
        NAMESPACE_UNION,
        NAMESPACE_ENUM,
-       NAMESPACE_LABEL
+       NAMESPACE_LABEL,
 } namespace_t;
 
 typedef enum {
index 19b00c0..17a6fdf 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -115,6 +115,7 @@ static void *allocate_ast_zero(size_t size)
 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),
@@ -136,10 +137,18 @@ static size_t get_expression_struct_size(expression_type_t type)
        assert(sizeof(sizes) / sizeof(sizes[0]) == EXPR_STATEMENT + 1);
        assert(type <= EXPR_STATEMENT);
        assert(sizes[type] != 0);
-       (void) get_expression_struct_size;
        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[] = {
@@ -700,14 +709,13 @@ static type_t *promote_integer(type_t *type)
 static expression_t *create_cast_expression(expression_t *expression,
                                             type_t *dest_type)
 {
-       unary_expression_t *cast = allocate_ast_zero(sizeof(cast[0]));
+       expression_t *cast = allocate_expression_zero(EXPR_UNARY);
 
-       cast->expression.type     = EXPR_UNARY;
-       cast->type                = UNEXPR_CAST;
-       cast->value               = expression;
-       cast->expression.datatype = dest_type;
+       cast->unary.type    = UNEXPR_CAST;
+       cast->unary.value   = expression;
+       cast->base.datatype = dest_type;
 
-       return (expression_t*) cast;
+       return cast;
 }
 
 static bool is_null_expression(const expression_t *const expression)
@@ -1028,8 +1036,7 @@ static initializer_t *initializer_from_expression(type_t *type,
                                        || atype == ATOMIC_TYPE_SCHAR
                                        || atype == ATOMIC_TYPE_UCHAR) {
 
-                               string_literal_expression_t *literal
-                                       = &expression->string_literal;
+                               string_literal_expression_t *literal = &expression->string;
                                return initializer_from_string(array_type, literal->value);
                        }
                }
@@ -1809,7 +1816,11 @@ static void parse_identifier_list(void)
                                             T_IDENTIFIER, 0);
                        return;
                }
+               declaration_t *declaration = allocate_ast_zero(sizeof(declaration[0]));
+               declaration->symbol        = token.v.symbol;
+
                next_token();
+
                if(token.type != ',')
                        break;
                next_token();
@@ -2264,22 +2275,20 @@ static void parse_init_declarators(const declaration_specifiers_t *specifiers)
                                array_type_t *array_type = &type->array;
 
                                if(array_type->size == NULL) {
-                                       const_expression_t
-                                               *cnst = allocate_ast_zero(sizeof(cnst[0]));
+                                       expression_t *cnst = allocate_expression_zero(EXPR_CONST);
 
-                                       cnst->expression.type     = EXPR_CONST;
-                                       cnst->expression.datatype = type_size_t;
+                                       cnst->base.datatype = type_size_t;
 
                                        if(initializer->type == INITIALIZER_LIST) {
                                                initializer_list_t *list = &initializer->list;
-                                               cnst->v.int_value = list->len;
+                                               cnst->conste.v.int_value = list->len;
                                        } else {
                                                assert(initializer->type == INITIALIZER_STRING);
                                                initializer_string_t *string = &initializer->string;
-                                               cnst->v.int_value = strlen(string->string) + 1;
+                                               cnst->conste.v.int_value = strlen(string->string) + 1;
                                        }
 
-                                       array_type->size = (expression_t*) cnst;
+                                       array_type->size = cnst;
                                }
                        }
 
@@ -2294,6 +2303,18 @@ static void parse_init_declarators(const declaration_specifiers_t *specifiers)
                                eat_block();
                                continue;
                        }
+                       function_type_t *function_type = &type->function;
+                       /* ยง 6.7.5.3 (14) a function definition with () */
+                       if(function_type->unspecified_parameters) {
+                               type_t *duplicate = duplicate_type(type);
+                               duplicate->function.unspecified_parameters = true;
+
+                               type = typehash_insert(duplicate);
+                               if(type != duplicate) {
+                                       obstack_free(type_obst, duplicate);
+                               }
+                               function_type = &type->function;
+                       }
 
                        if(declaration->init.statement != NULL) {
                                parser_error_multiple_definition(declaration, ndeclaration);
@@ -2465,8 +2486,7 @@ expression_parser_function_t expression_parsers[T_LAST_TOKEN];
 
 static expression_t *make_invalid_expression(void)
 {
-       expression_t *expression         = allocate_ast_zero(sizeof(expression[0]));
-       expression->type                 = EXPR_INVALID;
+       expression_t *expression         = allocate_expression_zero(EXPR_INVALID);
        expression->base.source_position = token.source_position;
        return expression;
 }
@@ -2485,39 +2505,33 @@ static expression_t *expected_expression_error(void)
 
 static expression_t *parse_string_const(void)
 {
-       string_literal_expression_t *cnst = allocate_ast_zero(sizeof(cnst[0]));
+       expression_t *cnst  = allocate_expression_zero(EXPR_STRING_LITERAL);
+       cnst->base.datatype = type_string;
+       cnst->string.value  = parse_string_literals();
 
-       cnst->expression.type     = EXPR_STRING_LITERAL;
-       cnst->expression.datatype = type_string;
-       cnst->value               = parse_string_literals();
-
-       return (expression_t*) cnst;
+       return cnst;
 }
 
 static expression_t *parse_int_const(void)
 {
-       const_expression_t *cnst = allocate_ast_zero(sizeof(cnst[0]));
-
-       cnst->expression.type     = EXPR_CONST;
-       cnst->expression.datatype = token.datatype;
-       cnst->v.int_value         = token.v.intvalue;
+       expression_t *cnst       = allocate_expression_zero(EXPR_CONST);
+       cnst->base.datatype      = token.datatype;
+       cnst->conste.v.int_value = token.v.intvalue;
 
        next_token();
 
-       return (expression_t*) cnst;
+       return cnst;
 }
 
 static expression_t *parse_float_const(void)
 {
-       const_expression_t *cnst = allocate_ast_zero(sizeof(cnst[0]));
-
-       cnst->expression.type     = EXPR_CONST;
-       cnst->expression.datatype = token.datatype;
-       cnst->v.float_value       = token.v.floatvalue;
+       expression_t *cnst         = allocate_expression_zero(EXPR_CONST);
+       cnst->base.datatype        = token.datatype;
+       cnst->conste.v.float_value = token.v.floatvalue;
 
        next_token();
 
-       return (expression_t*) cnst;
+       return cnst;
 }
 
 static declaration_t *create_implicit_function(symbol_t *symbol,
@@ -2619,18 +2633,15 @@ type_t *revert_automatic_type_conversion(const expression_t *expression)
 
        switch(expression->type) {
        case EXPR_REFERENCE: {
-               const reference_expression_t *ref
-                       = (const reference_expression_t*) expression;
+               const reference_expression_t *ref = &expression->reference;
                return ref->declaration->type;
        }
        case EXPR_SELECT: {
-               const select_expression_t *select
-                       = (const select_expression_t*) expression;
+               const select_expression_t *select = &expression->select;
                return select->compound_entry->type;
        }
        case EXPR_UNARY: {
-               const unary_expression_t *unary
-                       = (const unary_expression_t*) expression;
+               const unary_expression_t *unary = &expression->unary;
                if(unary->type == UNEXPR_DEREFERENCE) {
                        expression_t   *value        = unary->value;
                        type_t         *type         = skip_typeref(value->base.datatype);
@@ -2642,7 +2653,7 @@ type_t *revert_automatic_type_conversion(const expression_t *expression)
        }
        case EXPR_BUILTIN_SYMBOL: {
                const builtin_symbol_expression_t *builtin
-                       = (const builtin_symbol_expression_t*) expression;
+                       = &expression->builtin_symbol;
                return get_builtin_symbol_type(builtin->symbol);
        }
        case EXPR_ARRAY_ACCESS: {
@@ -2664,10 +2675,10 @@ type_t *revert_automatic_type_conversion(const expression_t *expression)
 
 static expression_t *parse_reference(void)
 {
-       reference_expression_t *ref = allocate_ast_zero(sizeof(ref[0]));
+       expression_t *expression = allocate_expression_zero(EXPR_REFERENCE);
 
-       ref->expression.type = EXPR_REFERENCE;
-       ref->symbol          = token.v.symbol;
+       reference_expression_t *ref = &expression->reference;
+       ref->symbol = token.v.symbol;
 
        declaration_t *declaration = get_declaration(ref->symbol, NAMESPACE_NORMAL);
 
@@ -2689,7 +2700,7 @@ static expression_t *parse_reference(void)
                {
                        parser_print_error_prefix();
                        fprintf(stderr, "unknown symbol '%s' found.\n", ref->symbol->string);
-                       return (expression_t*) ref;
+                       return expression;
                }
        }
 
@@ -2701,7 +2712,7 @@ static expression_t *parse_reference(void)
        ref->declaration         = declaration;
        ref->expression.datatype = type;
 
-       return (expression_t*) ref;
+       return expression;
 }
 
 static void check_cast_allowed(expression_t *expression, type_t *dest_type)
@@ -2713,11 +2724,10 @@ static void check_cast_allowed(expression_t *expression, type_t *dest_type)
 
 static expression_t *parse_cast(void)
 {
-       unary_expression_t *cast = allocate_ast_zero(sizeof(cast[0]));
+       expression_t *cast = allocate_expression_zero(EXPR_UNARY);
 
-       cast->expression.type            = EXPR_UNARY;
-       cast->type                       = UNEXPR_CAST;
-       cast->expression.source_position = token.source_position;
+       cast->unary.type           = UNEXPR_CAST;
+       cast->base.source_position = token.source_position;
 
        type_t *type  = parse_typename();
 
@@ -2726,28 +2736,25 @@ static expression_t *parse_cast(void)
 
        check_cast_allowed(value, type);
 
-       cast->expression.datatype = type;
-       cast->value               = value;
+       cast->base.datatype = type;
+       cast->unary.value   = value;
 
-       return (expression_t*) cast;
+       return cast;
 }
 
 static expression_t *parse_statement_expression(void)
 {
-       statement_expression_t *expression
-               = allocate_ast_zero(sizeof(expression[0]));
-       expression->expression.type = EXPR_STATEMENT;
+       expression_t *expression = allocate_expression_zero(EXPR_STATEMENT);
 
-       statement_t *statement = parse_compound_statement();
-       expression->statement  = statement;
+       statement_t *statement          = parse_compound_statement();
+       expression->statement.statement = statement;
        if(statement == NULL) {
                expect(')');
                return NULL;
        }
 
        assert(statement->type == STATEMENT_COMPOUND);
-       compound_statement_t *compound_statement
-               = (compound_statement_t*) statement;
+       compound_statement_t *compound_statement = &statement->compound;
 
        /* find last statement and use it's type */
        const statement_t *last_statement = NULL;
@@ -2757,17 +2764,17 @@ static expression_t *parse_statement_expression(void)
        }
 
        if(last_statement->type == STATEMENT_EXPRESSION) {
-               const expression_statement_t *expression_statement =
-                       (const expression_statement_t*) last_statement;
-               expression->expression.datatype
+               const expression_statement_t *expression_statement
+                       = &last_statement->expression;
+               expression->base.datatype
                        = expression_statement->expression->base.datatype;
        } else {
-               expression->expression.datatype = type_void;
+               expression->base.datatype = type_void;
        }
 
        expect(')');
 
-       return (expression_t*) expression;
+       return expression;
 }
 
 static expression_t *parse_brace_expression(void)
@@ -2883,50 +2890,47 @@ static expression_t *parse_offsetof(void)
 {
        eat(T___builtin_offsetof);
 
-       offsetof_expression_t *expression
-               = allocate_ast_zero(sizeof(expression[0]));
-       expression->expression.type     = EXPR_OFFSETOF;
-       expression->expression.datatype = type_size_t;
+       expression_t *expression  = allocate_expression_zero(EXPR_OFFSETOF);
+       expression->base.datatype = type_size_t;
 
        expect('(');
-       expression->type = parse_typename();
+       expression->offsetofe.type = parse_typename();
        expect(',');
-       expression->designator = parse_designator();
+       expression->offsetofe.designator = parse_designator();
        expect(')');
 
-       return (expression_t*) expression;
+       return expression;
 }
 
 static expression_t *parse_va_arg(void)
 {
        eat(T___builtin_va_arg);
 
-       va_arg_expression_t *expression = allocate_ast_zero(sizeof(expression[0]));
-       expression->expression.type     = EXPR_VA_ARG;
+       expression_t *expression = allocate_expression_zero(EXPR_VA_ARG);
 
        expect('(');
-       expression->arg = parse_assignment_expression();
+       expression->va_arge.arg = parse_assignment_expression();
        expect(',');
-       expression->expression.datatype = parse_typename();
+       expression->base.datatype = parse_typename();
        expect(')');
 
-       return (expression_t*) expression;
+       return expression;
 }
 
 static expression_t *parse_builtin_symbol(void)
 {
-       builtin_symbol_expression_t *expression
-               = allocate_ast_zero(sizeof(expression[0]));
-       expression->expression.type = EXPR_BUILTIN_SYMBOL;
+       expression_t *expression = allocate_expression_zero(EXPR_BUILTIN_SYMBOL);
 
-       expression->symbol = token.v.symbol;
+       symbol_t *symbol = token.v.symbol;
+
+       expression->builtin_symbol.symbol = symbol;
        next_token();
 
-       type_t *type = get_builtin_symbol_type(expression->symbol);
+       type_t *type = get_builtin_symbol_type(symbol);
        type = automatic_type_conversion(type);
 
-       expression->expression.datatype = type;
-       return (expression_t*) expression;
+       expression->base.datatype = type;
+       return expression;
 }
 
 static expression_t *parse_primary_expression(void)
@@ -3078,17 +3082,15 @@ static expression_t *parse_select_expression(unsigned precedence,
        bool is_pointer = (token.type == T_MINUSGREATER);
        next_token();
 
-       select_expression_t *select = allocate_ast_zero(sizeof(select[0]));
-
-       select->expression.type = EXPR_SELECT;
-       select->compound        = compound;
+       expression_t *select    = allocate_expression_zero(EXPR_SELECT);
+       select->select.compound = compound;
 
        if(token.type != T_IDENTIFIER) {
                parse_error_expected("while parsing select", T_IDENTIFIER, 0);
-               return (expression_t*) select;
+               return select;
        }
-       symbol_t *symbol = token.v.symbol;
-       select->symbol   = symbol;
+       symbol_t *symbol      = token.v.symbol;
+       select->select.symbol = symbol;
        next_token();
 
        type_t *orig_type = compound->base.datatype;
@@ -3150,18 +3152,19 @@ static expression_t *parse_select_expression(unsigned precedence,
         * code to revert this! */
        type_t *expression_type = automatic_type_conversion(iter->type);
 
-       select->compound_entry      = iter;
-       select->expression.datatype = expression_type;
-       return (expression_t*) select;
+       select->select.compound_entry = iter;
+       select->base.datatype         = expression_type;
+       return select;
 }
 
 static expression_t *parse_call_expression(unsigned precedence,
                                            expression_t *expression)
 {
        (void) precedence;
-       call_expression_t *call = allocate_ast_zero(sizeof(call[0]));
-       call->expression.type   = EXPR_CALL;
-       call->function          = expression;
+       expression_t *result = allocate_expression_zero(EXPR_CALL);
+
+       call_expression_t *call  = &result->call;
+       call->function           = expression;
 
        function_type_t *function_type = NULL;
        type_t          *orig_type     = expression->base.datatype;
@@ -3261,7 +3264,7 @@ static expression_t *parse_call_expression(unsigned precedence,
                }
        }
 
-       return (expression_t*) call;
+       return result;
 }
 
 static type_t *semantic_arithmetic(type_t *type_left, type_t *type_right);
diff --git a/type.c b/type.c
index 566b574..8719ec1 100644 (file)
--- a/type.c
+++ b/type.c
@@ -252,7 +252,6 @@ static void print_typeof_type_pre(typeof_type_t *type)
 static void intern_print_type_pre(type_t *type)
 {
        switch(type->type) {
-       case TYPE_COUNT:
        case TYPE_INVALID:
                fputs("invalid", out);
                return;
@@ -301,7 +300,6 @@ static void intern_print_type_post(type_t *type)
                print_array_type_post(&type->array);
                return;
        case TYPE_INVALID:
-       case TYPE_COUNT:
        case TYPE_ATOMIC:
        case TYPE_ENUM:
        case TYPE_COMPOUND_STRUCT:
@@ -491,7 +489,6 @@ bool is_type_incomplete(const type_t *type)
        case TYPE_TYPEOF:
        case TYPE_BUILTIN:
                panic("is_type_incomplete called without typerefs skipped");
-       case TYPE_COUNT:
        case TYPE_INVALID:
                break;
        }
@@ -539,7 +536,6 @@ static size_t get_type_size(type_t *type)
        case TYPE_BUILTIN:         return sizeof(builtin_type_t); break;
        case TYPE_TYPEDEF:         return sizeof(typedef_type_t); break;
        case TYPE_TYPEOF:          return sizeof(typeof_type_t); break;
-       case TYPE_COUNT:
        case TYPE_INVALID:         panic("invalid type found"); break;
        }
        panic("unknown type found");
@@ -549,7 +545,7 @@ static size_t get_type_size(type_t *type)
  * duplicates a type
  * note that this does not produce a deep copy!
  */
-static type_t *duplicate_type(type_t *type)
+type_t *duplicate_type(type_t *type)
 {
        size_t size = get_type_size(type);
 
index 15d5557..1b491af 100644 (file)
@@ -82,7 +82,6 @@ static unsigned hash_type(const type_t *type)
        unsigned hash = 0;
 
        switch(type->type) {
-       case TYPE_COUNT:
        case TYPE_INVALID:
                panic("internalizing void or invalid types not possible");
                return 0;
@@ -219,7 +218,6 @@ static bool types_equal(const type_t *type1, const type_t *type2)
                return false;
 
        switch(type1->type) {
-       case TYPE_COUNT:
        case TYPE_INVALID:
                return false;
        case TYPE_ATOMIC:
index b9365c2..a100c69 100644 (file)
--- a/type_t.h
+++ b/type_t.h
@@ -26,7 +26,6 @@ typedef enum {
        TYPE_BUILTIN,
        TYPE_TYPEDEF,
        TYPE_TYPEOF,
-       TYPE_COUNT
 } type_type_t;
 
 /* note that the constant values represent the rank of the types as defined
@@ -157,6 +156,8 @@ union type_t {
 type_t *make_atomic_type(atomic_type_type_t type, type_qualifiers_t qualifiers);
 type_t *make_pointer_type(type_t *points_to, type_qualifiers_t qualifiers);
 
+type_t *duplicate_type(type_t *type);
+
 static inline bool is_typeref(const type_t *type)
 {
        return type->type == TYPE_TYPEDEF || type->type == TYPE_TYPEOF;