Implement mangling of complex and imaginary types.
[cparser] / parser.c
index 3937d62..39e0e88 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -100,34 +100,34 @@ typedef struct parse_initializer_env_t {
 typedef entity_t* (*parsed_declaration_func) (entity_t *declaration, bool is_definition);
 
 /** The current token. */
-static token_t             token;
+static token_t              token;
 /** The lookahead ring-buffer. */
-static token_t             lookahead_buffer[MAX_LOOKAHEAD];
+static token_t              lookahead_buffer[MAX_LOOKAHEAD];
 /** Position of the next token in the lookahead buffer. */
-static int                 lookahead_bufpos;
-static stack_entry_t      *environment_stack = NULL;
-static stack_entry_t      *label_stack       = NULL;
-static scope_t            *file_scope        = NULL;
-static scope_t            *current_scope     = NULL;
+static int                  lookahead_bufpos;
+static stack_entry_t       *environment_stack = NULL;
+static stack_entry_t       *label_stack       = NULL;
+static scope_t             *file_scope        = NULL;
+static scope_t             *current_scope     = NULL;
 /** Point to the current function declaration if inside a function. */
-static function_t         *current_function  = NULL;
-static entity_t           *current_init_decl = NULL;
-static switch_statement_t *current_switch    = NULL;
-static statement_t        *current_loop      = NULL;
-static statement_t        *current_parent    = NULL;
-static ms_try_statement_t *current_try       = NULL;
-static linkage_kind_t      current_linkage   = LINKAGE_INVALID;
-static goto_statement_t   *goto_first        = NULL;
-static goto_statement_t   *goto_last         = NULL;
-static label_statement_t  *label_first       = NULL;
-static label_statement_t  *label_last        = NULL;
+static function_t          *current_function  = NULL;
+static entity_t            *current_init_decl = NULL;
+static switch_statement_t  *current_switch    = NULL;
+static statement_t         *current_loop      = NULL;
+static statement_t         *current_parent    = NULL;
+static ms_try_statement_t  *current_try       = NULL;
+static linkage_kind_t       current_linkage   = LINKAGE_INVALID;
+static goto_statement_t    *goto_first        = NULL;
+static goto_statement_t   **goto_anchor       = NULL;
+static label_statement_t   *label_first       = NULL;
+static label_statement_t  **label_anchor      = NULL;
 /** current translation unit. */
-static translation_unit_t *unit              = NULL;
+static translation_unit_t  *unit              = NULL;
 /** true if we are in a type property context (evaluation only for type. */
-static bool                in_type_prop      = false;
+static bool                 in_type_prop      = false;
 /** true in we are in a __extension__ context. */
-static bool                in_gcc_extension  = false;
-static struct obstack      temp_obst;
+static bool                 in_gcc_extension  = false;
+static struct obstack       temp_obst;
 
 
 #define PUSH_PARENT(stmt)                          \
@@ -4201,53 +4201,27 @@ end_error:
        return (construct_type_t*) array;
 }
 
-static construct_type_t *parse_function_declarator(scope_t *scope)
+static construct_type_t *parse_function_declarator(scope_t *scope,
+                                                   decl_modifiers_t modifiers)
 {
-       type_t *type = allocate_type_zero(TYPE_FUNCTION);
+       type_t          *type  = allocate_type_zero(TYPE_FUNCTION);
+       function_type_t *ftype = &type->function;
 
-       type->function.linkage = current_linkage;
+       ftype->linkage = current_linkage;
 
-       /* TODO: revive this... once we know exactly how to do it */
-#if 0
-       decl_modifiers_t  modifiers = entity->declaration.modifiers;
-
-       unsigned mask = modifiers & (DM_CDECL|DM_STDCALL|DM_FASTCALL|DM_THISCALL);
+       switch (modifiers & (DM_CDECL | DM_STDCALL | DM_FASTCALL | DM_THISCALL)) {
+               case DM_NONE:     break;
+               case DM_CDECL:    ftype->calling_convention = CC_CDECL;    break;
+               case DM_STDCALL:  ftype->calling_convention = CC_STDCALL;  break;
+               case DM_FASTCALL: ftype->calling_convention = CC_FASTCALL; break;
+               case DM_THISCALL: ftype->calling_convention = CC_THISCALL; break;
 
-       if (mask & (mask-1)) {
-               const char *first = NULL, *second = NULL;
-
-               /* more than one calling convention set */
-               if (modifiers & DM_CDECL) {
-                       if (first == NULL)       first = "cdecl";
-                       else if (second == NULL) second = "cdecl";
-               }
-               if (modifiers & DM_STDCALL) {
-                       if (first == NULL)       first = "stdcall";
-                       else if (second == NULL) second = "stdcall";
-               }
-               if (modifiers & DM_FASTCALL) {
-                       if (first == NULL)       first = "fastcall";
-                       else if (second == NULL) second = "fastcall";
-               }
-               if (modifiers & DM_THISCALL) {
-                       if (first == NULL)       first = "thiscall";
-                       else if (second == NULL) second = "thiscall";
-               }
-               errorf(&entity->base.source_position,
-                          "%s and %s attributes are not compatible", first, second);
+               default:
+                       errorf(HERE, "multiple calling conventions in declaration");
+                       break;
        }
 
-       if (modifiers & DM_CDECL)
-               type->function.calling_convention = CC_CDECL;
-       else if (modifiers & DM_STDCALL)
-               type->function.calling_convention = CC_STDCALL;
-       else if (modifiers & DM_FASTCALL)
-               type->function.calling_convention = CC_FASTCALL;
-       else if (modifiers & DM_THISCALL)
-               type->function.calling_convention = CC_THISCALL;
-#endif
-
-       parse_parameters(&type->function, scope);
+       parse_parameters(ftype, scope);
 
        construct_function_type_t *construct_function_type =
                obstack_alloc(&temp_obst, sizeof(construct_function_type[0]));
@@ -4292,8 +4266,10 @@ static construct_type_t *parse_inner_declarator(parse_declarator_env_t *env,
                modifiers |= parse_attributes(&attributes);
        }
 
-       if (env != NULL)
-               env->modifiers |= modifiers;
+       if (env != NULL) {
+               modifiers      |= env->modifiers;
+               env->modifiers  = modifiers;
+       }
 
        construct_type_t *inner_types = NULL;
 
@@ -4336,7 +4312,7 @@ static construct_type_t *parse_inner_declarator(parse_declarator_env_t *env,
                        if (env != NULL)
                                scope = &env->parameters;
 
-                       type = parse_function_declarator(scope);
+                       type = parse_function_declarator(scope, modifiers);
                        break;
                }
                case '[':
@@ -4544,6 +4520,7 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers,
 {
        parse_declarator_env_t env;
        memset(&env, 0, sizeof(env));
+       env.modifiers = specifiers->modifiers;
 
        construct_type_t *construct_type
                = parse_inner_declarator(&env, may_be_abstract);
@@ -4583,11 +4560,11 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers,
                        }
                }
 
-               entity->base.source_position  = env.source_position;
-               entity->base.symbol           = env.symbol;
-               entity->base.namespc          = NAMESPACE_NORMAL;
-               entity->declaration.type      = type;
-               entity->declaration.modifiers = env.modifiers | specifiers->modifiers;
+               entity->base.source_position          = env.source_position;
+               entity->base.symbol                   = env.symbol;
+               entity->base.namespc                  = NAMESPACE_NORMAL;
+               entity->declaration.type              = type;
+               entity->declaration.modifiers         = env.modifiers;
                entity->declaration.deprecated_string = specifiers->deprecated_string;
 
                storage_class_t storage_class = specifiers->storage_class;
@@ -5272,8 +5249,6 @@ static void check_labels(void)
                               "label '%Y' used but not defined", label->base.symbol);
                 }
        }
-       goto_first = NULL;
-       goto_last  = NULL;
 
        if (warning.unused_label) {
                for (const label_statement_t *label_statement = label_first;
@@ -5288,7 +5263,6 @@ static void check_labels(void)
                        }
                }
        }
-       label_first = label_last = NULL;
 }
 
 static void warn_unused_decl(entity_t *entity, entity_t *end,
@@ -5969,7 +5943,12 @@ static void parse_external_declaration(void)
                current_function                 = function;
                current_parent                   = NULL;
 
-               statement_t *const body     = parse_compound_statement(false);
+               goto_first   = NULL;
+               goto_anchor  = &goto_first;
+               label_first  = NULL;
+               label_anchor = &label_first;
+
+               statement_t *const body = parse_compound_statement(false);
                function->statement = body;
                first_err = true;
                check_labels();
@@ -6312,10 +6291,10 @@ static expression_t *parse_character_constant(void)
        cnst->conste.v.character = token.v.string;
 
        if (cnst->conste.v.character.size != 1) {
-               if (warning.multichar && GNU_MODE) {
+               if (!GNU_MODE) {
+                       errorf(HERE, "more than 1 character in character constant");
+               } else if (warning.multichar) {
                        warningf(HERE, "multi-character character constant");
-               } else {
-                       errorf(HERE, "more than 1 characters in character constant");
                }
        }
        next_token();
@@ -6333,10 +6312,10 @@ static expression_t *parse_wide_character_constant(void)
        cnst->conste.v.wide_character = token.v.wide_string;
 
        if (cnst->conste.v.wide_character.size != 1) {
-               if (warning.multichar && GNU_MODE) {
+               if (!GNU_MODE) {
+                       errorf(HERE, "more than 1 character in character constant");
+               } else if (warning.multichar) {
                        warningf(HERE, "multi-character character constant");
-               } else {
-                       errorf(HERE, "more than 1 characters in character constant");
                }
        }
        next_token();
@@ -7440,8 +7419,6 @@ static expression_t *parse_typeprop(expression_kind_t const kind)
 
        eat(kind == EXPR_SIZEOF ? T_sizeof : T___alignof__);
 
-       char const* const what = kind == EXPR_SIZEOF ? "sizeof" : "alignof";
-
        /* we only refer to a type property, mark this case */
        bool old     = in_type_prop;
        in_type_prop = true;
@@ -7479,6 +7456,7 @@ typeprop_expression:
                type->kind == TYPE_BITFIELD ? "bitfield"            :
                NULL;
        if (wrong_type != NULL) {
+               char const* const what = kind == EXPR_SIZEOF ? "sizeof" : "alignof";
                errorf(&tp_expression->base.source_position,
                                "operand of %s expression must not be of %s type '%T'",
                                what, wrong_type, orig_type);
@@ -9131,8 +9109,8 @@ static void init_expression_parsers(void)
  */
 static asm_argument_t *parse_asm_arguments(bool is_out)
 {
-       asm_argument_t *result = NULL;
-       asm_argument_t *last   = NULL;
+       asm_argument_t  *result = NULL;
+       asm_argument_t **anchor = &result;
 
        while (token.type == T_STRING_LITERAL || token.type == '[') {
                asm_argument_t *argument = allocate_ast_zero(sizeof(argument[0]));
@@ -9215,12 +9193,8 @@ static asm_argument_t *parse_asm_arguments(bool is_out)
 
                set_address_taken(expression, true);
 
-               if (last != NULL) {
-                       last->next = argument;
-               } else {
-                       result = argument;
-               }
-               last = argument;
+               *anchor = argument;
+               anchor  = &argument->next;
 
                if (token.type != ',')
                        break;
@@ -9512,12 +9486,8 @@ static statement_t *parse_label_statement(void)
        }
 
        /* remember the labels in a list for later checking */
-       if (label_last == NULL) {
-               label_first = &statement->label;
-       } else {
-               label_last->next = &statement->label;
-       }
-       label_last = &statement->label;
+       *label_anchor = &statement->label;
+       label_anchor  = &statement->label.next;
 
        POP_PARENT;
        return statement;
@@ -9816,8 +9786,8 @@ static statement_t *parse_goto(void)
                expression_t *expression = parse_expression();
                mark_vars_read(expression, NULL);
 
-               /* Argh: although documentation say the expression must be of type void *,
-                * gcc excepts anything that can be casted into void * without error */
+               /* Argh: although documentation says the expression must be of type void*,
+                * gcc accepts anything that can be casted into void* without error */
                type_t *type = expression->base.type;
 
                if (type != type_error_type) {
@@ -9848,12 +9818,8 @@ static statement_t *parse_goto(void)
        }
 
        /* remember the goto's in a list for later checking */
-       if (goto_last == NULL) {
-               goto_first = &statement->gotos;
-       } else {
-               goto_last->next = &statement->gotos;
-       }
-       goto_last = &statement->gotos;
+       *goto_anchor = &statement->gotos;
+       goto_anchor  = &statement->gotos.next;
 
        expect(';');