More work for C++ mode:
authorMatthias Braun <matze@braunis.de>
Fri, 14 Nov 2008 15:34:32 +0000 (15:34 +0000)
committerMatthias Braun <matze@braunis.de>
Fri, 14 Nov 2008 15:34:32 +0000 (15:34 +0000)
* Can parse (but not produce usefull code) for namespace now
* mangle function names according to Itanium C++ ABI
* Parse custom linkage for function types

[r23661]

18 files changed:
Makefile
ast.c
ast2firm.c
ast2firm.h
ast_t.h
driver/firm_opt.c
entity.h
entity_t.h
main.c
mangle.c [new file with mode: 0644]
mangle.h [new file with mode: 0644]
parser.c
preprocessor.c
tokens.inc
type.c
type_hash.c
type_t.h
types.c

index f7f50ca..8a75c20 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -34,6 +34,7 @@ SOURCES := \
        format_check.c \
        lexer.c \
        main.c \
+       mangle.c \
        walk_statements.c \
        symbol_table.c \
        token.c \
diff --git a/ast.c b/ast.c
index 201039e..164c864 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -1477,6 +1477,34 @@ static void print_ms_modifiers(const declaration_t *declaration)
                fputs(") ", out);
 }
 
+static void print_scope(const scope_t *scope)
+{
+       const entity_t *entity = scope->entities;
+       for ( ; entity != NULL; entity = entity->base.next) {
+               print_indent();
+               print_entity(entity);
+               fputs("\n", out);
+       }
+}
+
+static void print_namespace(const namespace_t *namespace)
+{
+       fputs("namespace ", out);
+       if (namespace->base.symbol != NULL) {
+               fputs(namespace->base.symbol->string, out);
+               fputc(' ', out);
+       }
+
+       fputs("{\n", out);
+       ++indent;
+
+       print_scope(&namespace->members);
+
+       --indent;
+       print_indent();
+       fputs("}\n", out);
+}
+
 /**
  * Print a variable or function declaration
  */
@@ -1543,10 +1571,12 @@ void print_entity(const entity_t *entity)
 
        switch ((entity_kind_tag_t) entity->kind) {
        case ENTITY_VARIABLE:
-       case ENTITY_FUNCTION:
        case ENTITY_COMPOUND_MEMBER:
                print_declaration(entity);
                return;
+       case ENTITY_FUNCTION:
+               print_declaration(entity);
+               return;
        case ENTITY_TYPEDEF:
                print_typedef(entity);
                return;
@@ -1575,6 +1605,9 @@ void print_entity(const entity_t *entity)
                print_enum_definition(&entity->enume);
                fputc(';', out);
                return;
+       case ENTITY_NAMESPACE:
+               print_namespace(&entity->namespacee);
+               return;
        case ENTITY_LABEL:
        case ENTITY_ENUM_VALUE:
        case ENTITY_LOCAL_LABEL:
index 09d7592..25725f8 100644 (file)
 #include "diagnostic.h"
 #include "lang_features.h"
 #include "types.h"
+#include "type_hash.h"
+#include "mangle.h"
 #include "walk_statements.h"
 #include "warning.h"
 #include "entitymap_t.h"
 #include "driver/firm_opt.h"
 #include "driver/firm_cmdline.h"
 
-/* some idents needed for name mangling */
-static ident *id_underscore;
-static ident *id_imp;
-
 static ir_type *ir_type_const_char;
 static ir_type *ir_type_wchar_t;
 static ir_type *ir_type_void;
@@ -65,6 +63,7 @@ static label_t  **all_labels;
 static entity_t **inner_functions;
 static ir_node   *ijmp_list;
 static bool       constant_folding;
+static symbol_t  *sym_C;
 
 extern bool       have_const_functions;
 
@@ -73,6 +72,7 @@ static ir_node            *current_function_name;
 static ir_node            *current_funcsig;
 static switch_statement_t *current_switch;
 static ir_graph           *current_function;
+static translation_unit_t *current_translation_unit;
 
 static entitymap_t  entitymap;
 
@@ -89,7 +89,7 @@ typedef enum declaration_kind_t {
        DECLARATION_KIND_INNER_FUNCTION
 } declaration_kind_t;
 
-static ir_type *get_ir_type(type_t *type);
+static ir_mode *get_ir_mode(type_t *type);
 static ir_type *get_ir_type_incomplete(type_t *type);
 
 static void enqueue_inner_function(entity_t *entity)
@@ -151,7 +151,6 @@ static ir_mode *mode_int, *mode_uint;
 
 static ir_node *_expression_to_firm(const expression_t *expression);
 static ir_node *expression_to_firm(const expression_t *expression);
-static inline ir_mode *get_ir_mode(type_t *type);
 static void create_local_declaration(entity_t *entity);
 
 static ir_mode *init_atomic_ir_mode(atomic_type_kind_t kind)
@@ -399,6 +398,8 @@ static ir_type *create_method_type(const function_type_t *function_type)
                set_method_variadicity(irtype, variadicity_variadic);
        }
 
+#if 0
+       /* TODO: revive this with linkage stuff */
        unsigned cc = get_method_calling_convention(irtype);
        switch (function_type->calling_convention) {
        case CC_DEFAULT: /* unspecified calling convention, equal to one of the other, typically cdecl */
@@ -426,6 +427,8 @@ is_cdecl:
                /* Hmm, leave default, not accepted by the parser yet. */
                break;
        }
+#endif
+
        return irtype;
 }
 
@@ -497,7 +500,7 @@ static ir_type *get_signed_int_type_for_bit_size(ir_type *base_tp,
        snprintf(name, sizeof(name), "I%u", size);
        ident *id = new_id_from_str(name);
        dbg_info *dbgi = get_dbg_info(&builtin_source_position);
-       res = new_d_type_primitive(mangle_u(get_type_ident(base_tp), id), mode, dbgi);
+       res = new_d_type_primitive(id_mangle_u(get_type_ident(base_tp), id), mode, dbgi);
        set_primitive_base_type(res, base_tp);
 
        return res;
@@ -533,7 +536,7 @@ static ir_type *get_unsigned_int_type_for_bit_size(ir_type *base_tp,
        snprintf(name, sizeof(name), "U%u", size);
        ident *id = new_id_from_str(name);
        dbg_info *dbgi = get_dbg_info(&builtin_source_position);
-       res = new_d_type_primitive(mangle_u(get_type_ident(base_tp), id), mode, dbgi);
+       res = new_d_type_primitive(id_mangle_u(get_type_ident(base_tp), id), mode, dbgi);
        set_primitive_base_type(res, base_tp);
 
        return res;
@@ -803,7 +806,7 @@ static ir_type *get_ir_type_incomplete(type_t *type)
        }
 }
 
-static ir_type *get_ir_type(type_t *type)
+ir_type *get_ir_type(type_t *type)
 {
        assert(type != NULL);
 
@@ -868,7 +871,7 @@ static ir_type *get_ir_type(type_t *type)
        return firm_type;
 }
 
-static inline ir_mode *get_ir_mode(type_t *type)
+ir_mode *get_ir_mode(type_t *type)
 {
        ir_type *irtype = get_ir_type(type);
 
@@ -966,59 +969,8 @@ static const struct {
 
 static ident *rts_idents[sizeof(rts_data) / sizeof(rts_data[0])];
 
-/**
- * Mangles an entity linker (ld) name for win32 usage.
- *
- * @param ent          the entity to be mangled
- * @param declaration  the declaration
- */
-static ident *create_ld_ident_win32(ir_entity *irentity, entity_t *entity)
-{
-       ident *id;
-
-       if (is_Method_type(get_entity_type(irentity)))
-               id = decorate_win32_c_fkt(irentity, get_entity_ident(irentity));
-       else {
-               /* always add an underscore in win32 */
-               id = mangle(id_underscore, get_entity_ident(irentity));
-       }
-
-       assert(is_declaration(entity));
-       decl_modifiers_t decl_modifiers = entity->declaration.modifiers;
-       if (decl_modifiers & DM_DLLIMPORT) {
-               /* add prefix for imported symbols */
-               id = mangle(id_imp, id);
-       }
-       return id;
-}
-
-/**
- * Mangles an entity linker (ld) name for Linux ELF usage.
- *
- * @param ent          the entity to be mangled
- * @param declaration  the declaration
- */
-static ident *create_ld_ident_linux_elf(ir_entity *irentity, entity_t *entity)
-{
-       (void) entity;
-       return get_entity_ident(irentity);
-}
-
-/**
- * Mangles an entity linker (ld) name for Mach-O usage.
- *
- * @param ent          the entity to be mangled
- * @param declaration  the declaration
- */
-static ident *create_ld_ident_macho(ir_entity *irentity, entity_t *entity)
-{
-       (void) entity;
-       ident *id = mangle(id_underscore, get_entity_ident(irentity));
-       return id;
-}
-
-typedef ident* (*create_ld_ident_func)(ir_entity *irentity, entity_t *entity);
-create_ld_ident_func create_ld_ident = create_ld_ident_linux_elf;
+typedef ident* (*create_ld_ident_func)(entity_t *entity);
+create_ld_ident_func create_ld_ident = create_name_linux_elf;
 
 /**
  * Handle GNU attributes for entities
@@ -1046,6 +998,22 @@ static void handle_gnu_attributes_ent(ir_entity *irentity, entity_t *entity)
        }
 }
 
+static bool is_main(entity_t *entity)
+{
+       static symbol_t *sym_main = NULL;
+       if (sym_main == NULL) {
+               sym_main = symbol_table_insert("main");
+       }
+
+       if (entity->base.symbol != sym_main)
+               return false;
+       /* must be in outermost scope */
+       if (entity->base.parent_scope != &current_translation_unit->scope)
+               return false;
+
+       return true;
+}
+
 /**
  * Creates an entity representing a function.
  *
@@ -1058,6 +1026,27 @@ static ir_entity *get_function_entity(entity_t *entity)
                return entity->function.entity;
        }
 
+       if (is_main(entity)) {
+               /* force main to C linkage */
+               type_t *type = entity->declaration.type;
+               assert(is_type_function(type));
+               if (type->function.linkage != NULL && type->function.linkage != sym_C) {
+                       errorf(&entity->base.source_position,
+                              "main must have \"C\" linkage");
+               }
+
+               if (type->function.linkage == NULL || type->function.linkage != sym_C) {
+                       type_t *new_type           = duplicate_type(type);
+                       new_type->function.linkage = sym_C;
+
+                       type = typehash_insert(new_type);
+                       if (type != new_type) {
+                               obstack_free(type_obst, new_type);
+                       }
+                       entity->declaration.type = type;
+               }
+       }
+
        symbol_t *symbol = entity->base.symbol;
        ident    *id     = new_id_from_str(symbol->string);
 
@@ -1077,7 +1066,7 @@ static ir_entity *get_function_entity(entity_t *entity)
 
        dbg_info *const dbgi = get_dbg_info(&entity->base.source_position);
        irentity             = new_d_entity(global_type, id, ir_type_method, dbgi);
-       set_entity_ld_ident(irentity, create_ld_ident(irentity, entity));
+       set_entity_ld_ident(irentity, create_ld_ident(entity));
 
        handle_gnu_attributes_ent(irentity, entity);
 
@@ -3270,7 +3259,7 @@ static void create_variable_entity(entity_t *variable,
        variable->declaration.kind  = (unsigned char) declaration_kind;
        variable->variable.v.entity = irentity;
        set_entity_variability(irentity, variability_uninitialized);
-       set_entity_ld_ident(irentity, create_ld_ident(irentity, variable));
+       set_entity_ld_ident(irentity, create_ld_ident(variable));
        if (parent_type == get_tls_type())
                set_entity_allocation(irentity, allocation_automatic);
        else if (declaration_kind == DECLARATION_KIND_GLOBAL_VARIABLE)
@@ -4028,7 +4017,7 @@ static void create_local_static_variable(entity_t *entity)
 
        entity->declaration.kind  = DECLARATION_KIND_GLOBAL_VARIABLE;
        entity->variable.v.entity = irentity;
-       set_entity_ld_ident(irentity, create_ld_ident(irentity, entity));
+       set_entity_ld_ident(irentity, id);
        set_entity_variability(irentity, variability_uninitialized);
        set_entity_visibility(irentity, visibility_local);
        set_entity_allocation(irentity, allocation_static);
@@ -5305,7 +5294,7 @@ static void create_function(entity_t *entity)
 
                        ir_node *in[1];
                        /* ยง5.1.2.2.3 main implicitly returns 0 */
-                       if (strcmp(entity->base.symbol->string, "main") == 0) {
+                       if (is_main(entity)) {
                                in[0] = new_Const(mode, get_mode_null(mode));
                        } else {
                                in[0] = new_Unknown(mode);
@@ -5416,20 +5405,19 @@ void init_ast2firm(void)
        obstack_init(&asm_obst);
        init_atomic_modes();
 
-       id_underscore = new_id_from_chars("_", 1);
-       id_imp        = new_id_from_chars("__imp_", 6);
-
        /* OS option must be set to the backend */
        switch (firm_opt.os_support) {
        case OS_SUPPORT_MINGW:
-               create_ld_ident = create_ld_ident_win32;
+               create_ld_ident = create_name_win32;
                break;
        case OS_SUPPORT_LINUX:
-               create_ld_ident = create_ld_ident_linux_elf;
+               create_ld_ident = create_name_linux_elf;
                break;
        case OS_SUPPORT_MACHO:
-               create_ld_ident = create_ld_ident_macho;
+               create_ld_ident = create_name_macho;
                break;
+       default:
+               panic("unexpected OS support mode");
        }
 
        /* create idents for all known runtime functions */
@@ -5437,6 +5425,8 @@ void init_ast2firm(void)
                rts_idents[i] = new_id_from_str(rts_data[i].name);
        }
 
+       sym_C = symbol_table_insert("C");
+
        entitymap_init(&entitymap);
 }
 
@@ -5479,9 +5469,10 @@ static void global_asm_to_firm(statement_t *s)
 void translation_unit_to_firm(translation_unit_t *unit)
 {
        /* just to be sure */
-       continue_label      = NULL;
-       break_label         = NULL;
-       current_switch_cond = NULL;
+       continue_label           = NULL;
+       break_label              = NULL;
+       current_switch_cond      = NULL;
+       current_translation_unit = unit;
 
        init_ir_types();
        inner_functions = NEW_ARR_F(entity_t *, 0);
@@ -5492,5 +5483,6 @@ void translation_unit_to_firm(translation_unit_t *unit)
        DEL_ARR_F(inner_functions);
        inner_functions  = NULL;
 
-       current_ir_graph = NULL;
+       current_ir_graph         = NULL;
+       current_translation_unit = NULL;
 }
index 0112cf8..2314ab3 100644 (file)
@@ -30,5 +30,6 @@ void init_ast2firm(void);
 void exit_ast2firm(void);
 
 ir_mode *get_atomic_mode(atomic_type_kind_t kind);
+ir_type *get_ir_type(type_t *type);
 
 #endif
diff --git a/ast_t.h b/ast_t.h
index eefd350..332cc85 100644 (file)
--- a/ast_t.h
+++ b/ast_t.h
@@ -27,7 +27,7 @@
 #include "symbol.h"
 #include "token_t.h"
 #include "type.h"
-#include "entity.h"
+#include "entity_t.h"
 #include "adt/obst.h"
 
 /** The AST obstack contains all data that must stay in the AST. */
@@ -228,16 +228,6 @@ typedef enum funcname_kind_t {
        EXPR_UNARY_CASES_MANDATORY \
        EXPR_UNARY_CASES_OPTIONAL
 
-/**
- * A scope containing declarations.
- */
-struct scope_t {
-       entity_t *entities;     /**< List of declarations in this scope. */
-       entity_t *last_entity;  /**< last declaration in this scope. */
-       scope_t  *parent;       /**< points to the parent scope. */
-       unsigned  depth;        /**< while parsing, the depth of this scope in the scope stack. */
-};
-
 struct expression_base_t {
        expression_kind_t   kind;
        type_t             *type;
index eb75247..7b0e3a6 100644 (file)
@@ -538,12 +538,6 @@ static void do_firm_optimizations(const char *input_filename)
   for (i = 0; i < get_irp_n_irgs(); i++) {
     ir_graph *irg = get_irp_irg(i);
 
-#ifdef FIRM_EXT_GRS
-    /* If SIMD optimization is on, make sure we have only 1 return */
-    if (firm_ext_grs.create_pattern || firm_ext_grs.simd_opt)
-      do_irg_opt("onereturn");
-#endif
-
     do_irg_opt(irg, "scalar");
     do_irg_opt(irg, "local");
     do_irg_opt(irg, "reassoc");
@@ -915,13 +909,6 @@ void gen_firm_init(void)
   params.cc_mask               = 0; /* no regparam, cdecl */
   params.builtin_dbg           = NULL;
 
-  #ifdef FIRM_EXT_GRS
-  /* Activate Graph rewriting if SIMD optimization is turned on */
-  /* This has to be done before init_firm() is called! */
-  if (firm_ext_grs.simd_opt)
-    ext_grs_activate();
-#endif
-
   init_firm(&params);
 
   if (firm_be_opt.selection == BE_FIRM_BE) {
@@ -939,23 +926,9 @@ void gen_firm_init(void)
     if (be_params->has_imm_fp_mode)
       firm_imm_fp_mode = be_params->imm_fp_mode;
   }
-  /* OS option must be set to the backend */
-  switch (firm_opt.os_support) {
-  case OS_SUPPORT_MINGW:
-    firm_be_option("ia32-gasmode=mingw");
-    break;
-  case OS_SUPPORT_MACHO:
-    firm_be_option("ia32-gasmode=macho");
-    break;
-  case OS_SUPPORT_LINUX:
-  default:
-    firm_be_option("ia32-gasmode=linux");
-    break;
-  }
 
   dbg_init(NULL, NULL, dbg_snprint);
   edges_init_dbg(firm_opt.vrfy_edges);
-  //cbackend_set_debug_retrieve(dbg_retrieve);
 
   set_opt_precise_exc_context(firm_opt.precise_exc);
   set_opt_fragile_ops(firm_opt.fragile_ops);
@@ -1090,23 +1063,6 @@ void gen_firm_finish(FILE *out, const char *input_filename, int c_mode, int new_
   for (i = get_irp_n_irgs() - 1; i >= 0; --i)
     set_irg_phase_low(get_irp_irg(i));
 
-
-#ifdef FIRM_EXT_GRS
-  /** SIMD Optimization  Extensions **/
-
-  /* Pattern creation step. No code has to be generated, so
-     exit after pattern creation */
-  if (firm_ext_grs.create_pattern) {
-    ext_grs_create_pattern();
-    exit(0);
-  }
-
-  /* SIMD optimization step. Uses graph patterns to find
-     rich instructions and rewrite */
-  if (firm_ext_grs.simd_opt)
-    ext_grs_simd_opt();
-#endif
-
   if (firm_dump.statistic & STAT_FINAL_IR)
     stat_dump_snapshot(input_filename, "final-ir");
 
@@ -1116,18 +1072,14 @@ void gen_firm_finish(FILE *out, const char *input_filename, int c_mode, int new_
 
   if (firm_dump.statistic & STAT_FINAL)
     stat_dump_snapshot(input_filename, "final");
-
-#if 0
-  if (firm_opt.ycomp_dbg)
-    firm_finish_ycomp_debugger();
-#endif
-}  /* gen_firm_finish */
+}
 
 /**
  * Do very early initializations
  */
-void firm_early_init(void) {
+void firm_early_init(void)
+{
   /* arg: need this here for command line options */
   be_opt_register();
   firm_init_options(NULL, 0, NULL);
-}  /* firm_early_init */
+}
index f7d4375..ee0db10 100644 (file)
--- a/entity.h
+++ b/entity.h
@@ -27,6 +27,7 @@ typedef struct compound_t                   compound_t;
 typedef struct enum_t                       enum_t;
 typedef struct enum_value_t                 enum_value_t;
 typedef struct label_t                      label_t;
+typedef struct namespace_t                  namespace_t;
 typedef struct declaration_t                declaration_t;
 typedef struct typedef_t                    typedef_t;
 typedef struct variable_t                   variable_t;
index d6002f9..c9e2294 100644 (file)
@@ -20,6 +20,8 @@
 #ifndef ENTITY_T_H
 #define ENTITY_T_H
 
+#include "lexer.h"
+#include "symbol.h"
 #include "entity.h"
 
 typedef enum {
@@ -33,7 +35,8 @@ typedef enum {
        ENTITY_ENUM,
        ENTITY_ENUM_VALUE,
        ENTITY_LABEL,
-       ENTITY_LOCAL_LABEL
+       ENTITY_LOCAL_LABEL,
+       ENTITY_NAMESPACE
 } entity_kind_tag_t;
 typedef unsigned char entity_kind_t;
 
@@ -45,7 +48,7 @@ typedef enum namespace_tag_t {
        NAMESPACE_ENUM,
        NAMESPACE_LABEL
 } namespace_tag_t;
-typedef unsigned char namespace_t;
+typedef unsigned char entity_namespace_t;
 
 typedef enum storage_class_tag_t {
        STORAGE_CLASS_NONE,
@@ -91,13 +94,24 @@ typedef enum decl_modifier_t {
 
 typedef unsigned decl_modifiers_t;
 
+/**
+ * A scope containing entities.
+ */
+struct scope_t {
+       entity_t *entities;
+       entity_t *last_entity;
+       scope_t  *parent;       /**< points to the parent scope. */
+       unsigned  depth;        /**< while parsing, the depth of this scope in the
+                                    scope stack. */
+};
+
 /**
  * a named entity is something which can be referenced by its name
  * (a symbol)
  */
 struct entity_base_t {
        entity_kind_t       kind;
-       namespace_t         namespc;
+       entity_namespace_t  namespc;
        symbol_t           *symbol;
        source_position_t   source_position;
        scope_t            *parent_scope;       /**< The parent scope where this declaration lives. */
@@ -147,6 +161,11 @@ struct label_t {
        ir_node       *block;
 };
 
+struct namespace_t {
+       entity_base_t  base;
+       scope_t        members;
+};
+
 struct typedef_t {
        entity_base_t     base;
        decl_modifiers_t  modifiers;
@@ -217,6 +236,7 @@ union entity_t {
        enum_t             enume;
        enum_value_t       enum_value;
        label_t            label;
+       namespace_t        namespacee;
        typedef_t          typedefe;
        declaration_t      declaration;
        variable_t         variable;
diff --git a/main.c b/main.c
index 9d60894..8e0c7d8 100644 (file)
--- a/main.c
+++ b/main.c
 #define HAVE_MKSTEMP
 #endif
 
-#ifndef WITH_LIBCORE
-#define WITH_LIBCORE
-#endif
-
 #include <libfirm/firm.h>
 #include <libfirm/be.h>
 
@@ -79,6 +75,7 @@
 #include "write_caml.h"
 #include "revision.h"
 #include "warning.h"
+#include "mangle.h"
 
 #ifndef PREPROCESSOR
 #ifdef __APPLE__
@@ -118,6 +115,8 @@ bool use_builtins = false;
 /** we have extern function with const attribute. */
 bool have_const_functions = false;
 
+atomic_type_kind_t wchar_atomic_kind = ATOMIC_TYPE_INT;
+
 /* to switch on printing of implicit casts */
 extern bool print_implicit_casts;
 
@@ -1053,6 +1052,7 @@ int main(int argc, char **argv)
        init_ast();
        init_parser();
        init_ast2firm();
+       init_mangle();
 
        if (construct_dep_target) {
                if (outname != 0 && strlen(outname) >= 2) {
@@ -1371,6 +1371,7 @@ do_parsing:
        obstack_free(&ldflags_obst, NULL);
        obstack_free(&file_obst, NULL);
 
+       exit_mangle();
        exit_ast2firm();
        exit_parser();
        exit_ast();
diff --git a/mangle.c b/mangle.c
new file mode 100644 (file)
index 0000000..b4149c6
--- /dev/null
+++ b/mangle.c
@@ -0,0 +1,263 @@
+/*
+ * This file is part of cparser.
+ * Copyright (C) 2007-2008 Matthias Braun <matze@braunis.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#include <config.h>
+
+#include <libfirm/firm.h>
+#include <string.h>
+
+#include "entity_t.h"
+#include "type_t.h"
+#include "symbol_t.h"
+#include "mangle.h"
+#include "diagnostic.h"
+#include "ast2firm.h"
+#include "lang_features.h"
+#include "adt/error.h"
+
+static ident          *id_underscore;
+static ident          *id_imp;
+static symbol_t       *sym_C;
+static symbol_t       *sym_stdcall;
+static struct obstack  obst;
+
+static void mangle_type(type_t *type);
+
+static const char *get_atomic_type_mangle(atomic_type_kind_t kind)
+{
+       switch (kind) {
+       case ATOMIC_TYPE_INVALID: break;
+       case ATOMIC_TYPE_VOID:        return "v";
+       case ATOMIC_TYPE_BOOL:        return "b";
+       case ATOMIC_TYPE_CHAR:        return "c";
+       case ATOMIC_TYPE_SCHAR:       return "a";
+       case ATOMIC_TYPE_UCHAR:       return "h";
+       case ATOMIC_TYPE_INT:         return "i";
+       case ATOMIC_TYPE_UINT:        return "j";
+       case ATOMIC_TYPE_SHORT:       return "s";
+       case ATOMIC_TYPE_USHORT:      return "t";
+       case ATOMIC_TYPE_LONG:        return "l";
+       case ATOMIC_TYPE_ULONG:       return "m";
+       case ATOMIC_TYPE_LONGLONG:    return "x";
+       case ATOMIC_TYPE_ULONGLONG:   return "y";
+       case ATOMIC_TYPE_LONG_DOUBLE: return "e";
+       case ATOMIC_TYPE_FLOAT:       return "f";
+       case ATOMIC_TYPE_DOUBLE:      return "d";
+       }
+       panic("invalid atomic type in mangler");
+}
+
+static void mangle_atomic_type(const atomic_type_t *type)
+{
+       obstack_printf(&obst, "%s", get_atomic_type_mangle(type->akind));
+}
+
+static void mangle_pointer_type(const pointer_type_t *type)
+{
+       obstack_printf(&obst, "P");
+       mangle_type(type->points_to);
+}
+
+static void mangle_function_type(const function_type_t *type)
+{
+       obstack_printf(&obst, "F");
+       if (type->linkage == sym_C) {
+               obstack_printf(&obst, "Y");
+       }
+
+       mangle_type(type->return_type);
+
+       function_parameter_t *parameter = type->parameters;
+       for ( ; parameter != NULL; parameter = parameter->next) {
+               mangle_type(parameter->type);
+       }
+       if (type->variadic) {
+               obstack_printf(&obst, "z");
+       }
+       if (type->unspecified_parameters)
+               panic("can't mangle unspecified parameter types");
+       if (type->kr_style_parameters)
+               panic("can't mangle kr_style_parameters type");
+
+       obstack_printf(&obst, "E");
+}
+
+static void mangle_qualifiers(type_qualifiers_t qualifiers)
+{
+       if (qualifiers & TYPE_QUALIFIER_CONST)
+               obstack_printf(&obst, "K");
+       if (qualifiers & TYPE_QUALIFIER_VOLATILE)
+               obstack_printf(&obst, "V");
+       if (qualifiers & TYPE_QUALIFIER_RESTRICT)
+               obstack_printf(&obst, "r");
+
+       /* handle MS extended qualifiers? */
+}
+
+static void mangle_type(type_t *orig_type)
+{
+       type_t *type = skip_typeref(orig_type);
+
+       mangle_qualifiers(type->base.qualifiers);
+
+       switch (type->kind) {
+       case TYPE_ATOMIC:
+               mangle_atomic_type(&type->atomic);
+               return;
+       case TYPE_POINTER:
+               mangle_pointer_type(&type->pointer);
+               return;
+       case TYPE_FUNCTION:
+               mangle_function_type(&type->function);
+               return;
+       case TYPE_INVALID:
+               panic("invalid type encountered while mangling");
+       case TYPE_ERROR:
+               panic("error type encountered while mangling");
+       case TYPE_BUILTIN:
+       case TYPE_TYPEDEF:
+       case TYPE_TYPEOF:
+               panic("typeref not resolved while manging?!?");
+
+       case TYPE_BITFIELD:
+       case TYPE_COMPLEX:
+       case TYPE_IMAGINARY:
+       case TYPE_COMPOUND_STRUCT:
+       case TYPE_COMPOUND_UNION:
+       case TYPE_ENUM:
+       case TYPE_ARRAY:
+               panic("no mangling for this type implemented yet");
+               break;
+       }
+       panic("invalid type encountered while mangling");
+}
+
+
+/**
+ * Mangles an entity linker (ld) name for win32 usage.
+ *
+ * @param ent          the entity to be mangled
+ * @param declaration  the declaration
+ */
+ident *create_name_win32(entity_t *entity)
+{
+       ident *id = new_id_from_str(entity->base.symbol->string);
+
+       if (entity->kind == ENTITY_FUNCTION) {
+               if (entity->declaration.type->function.linkage == sym_stdcall) {
+                       char     buf[16];
+                       ir_type *irtype = get_ir_type(entity->declaration.type);
+                       size_t   size   = 0;
+                       for (int i = get_method_n_params(irtype) - 1; i >= 0; --i) {
+                               size += get_type_size_bytes(get_method_param_type(irtype, i));
+                       }
+
+                       snprintf(buf, sizeof(buf), "@%d", size);
+                       return id_mangle3("_", id, buf);
+               }
+       } else {
+               /* always add an underscore in win32 */
+               id = id_mangle(id_underscore, id);
+       }
+
+       assert(is_declaration(entity));
+       decl_modifiers_t decl_modifiers = entity->declaration.modifiers;
+       if (decl_modifiers & DM_DLLIMPORT) {
+               /* add prefix for imported symbols */
+               id = id_mangle(id_imp, id);
+       }
+       return id;
+}
+
+static void mangle_entity(entity_t *entity)
+{
+       assert(obstack_object_size(&obst) == 0);
+       obstack_printf(&obst, "_Z");
+
+       /* TODO: mangle scope */
+
+       symbol_t *symbol = entity->base.symbol;
+       obstack_printf(&obst, "%u%s", strlen(symbol->string), symbol->string);
+
+       if (entity->kind == ENTITY_FUNCTION) {
+               mangle_type(entity->declaration.type);
+       }
+}
+
+/**
+ * Mangles an entity linker (ld) name for Linux ELF usage.
+ *
+ * @param ent          the entity to be mangled
+ * @param declaration  the declaration
+ */
+ident *create_name_linux_elf(entity_t *entity)
+{
+       bool needs_mangling = false;
+
+       if (entity->kind == ENTITY_FUNCTION && (c_mode & _CXX)) {
+               symbol_t *linkage = entity->declaration.type->function.linkage;
+
+               if (linkage == NULL) {
+                       needs_mangling = true;
+               } else if (linkage != sym_C) {
+                       errorf(&entity->base.source_position,
+                              "Unknown linkage type \"%Y\" found\n", linkage);
+               }
+       }
+
+       if (needs_mangling) {
+               mangle_entity(entity);
+               obstack_1grow(&obst, '\0');
+               char *str = obstack_finish(&obst);
+
+               ident *id = new_id_from_str(str);
+               obstack_free(&obst, str);
+
+               return id;
+       }
+
+       return new_id_from_str(entity->base.symbol->string);
+}
+
+/**
+ * Mangles an entity linker (ld) name for Mach-O usage.
+ *
+ * @param ent          the entity to be mangled
+ * @param declaration  the declaration
+ */
+ident *create_name_macho(entity_t *entity)
+{
+       ident *id = new_id_from_str(entity->base.symbol->string);
+       return id_mangle(id_underscore, id);
+}
+
+void init_mangle(void)
+{
+       id_underscore = new_id_from_chars("_", 1);
+       id_imp        = new_id_from_chars("__imp_", 6);
+       sym_C         = symbol_table_insert("C");
+       sym_stdcall   = symbol_table_insert("stdcall");
+
+       obstack_init(&obst);
+}
+
+void exit_mangle(void)
+{
+       obstack_free(&obst, NULL);
+}
diff --git a/mangle.h b/mangle.h
new file mode 100644 (file)
index 0000000..6f576de
--- /dev/null
+++ b/mangle.h
@@ -0,0 +1,33 @@
+/*
+ * This file is part of cparser.
+ * Copyright (C) 2007-2008 Matthias Braun <matze@braunis.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#ifndef MANGLE_H
+#define MANGLE_H
+
+#include "entity.h"
+#include <libfirm/firm_types.h>
+
+ident *create_name_linux_elf(entity_t *entity);
+ident *create_name_macho(entity_t *entity);
+ident *create_name_win32(entity_t *entity);
+
+void init_mangle(void);
+void exit_mangle(void);
+
+#endif
index 13f2cbb..b6deeef 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -45,9 +45,9 @@
 #define MAX_LOOKAHEAD 2
 
 typedef struct {
-       entity_t    *old_entity;
-       symbol_t    *symbol;
-       namespace_t  namespc;
+       entity_t           *old_entity;
+       symbol_t           *symbol;
+       entity_namespace_t  namespc;
 } stack_entry_t;
 
 typedef struct argument_list_t argument_list_t;
@@ -107,10 +107,8 @@ static token_t             lookahead_buffer[MAX_LOOKAHEAD];
 static int                 lookahead_bufpos;
 static stack_entry_t      *environment_stack = NULL;
 static stack_entry_t      *label_stack       = NULL;
-/** The global file scope. */
 static scope_t            *file_scope        = NULL;
-/** The current scope. */
-static scope_t            *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;
@@ -118,6 +116,7 @@ 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 symbol_t           *current_linkage   = NULL;
 static goto_statement_t   *goto_first        = NULL;
 static goto_statement_t   *goto_last         = NULL;
 static label_statement_t  *label_first       = NULL;
@@ -176,6 +175,8 @@ static statement_t *parse_statement(void);
 static expression_t *parse_sub_expression(precedence_t);
 static expression_t *parse_expression(void);
 static type_t       *parse_typename(void);
+static void          parse_externals(void);
+static void          parse_external(void);
 
 static void parse_compound_type_entries(compound_t *compound_declaration);
 static entity_t *parse_declarator(const declaration_specifiers_t *specifiers,
@@ -193,6 +194,13 @@ static void semantic_comparison(binary_expression_t *expression);
        case T_register:        \
        case T___thread:
 
+#define STORAGE_CLASSES_NO_EXTERN \
+       case T_typedef:         \
+       case T_static:          \
+       case T_auto:            \
+       case T_register:        \
+       case T___thread:
+
 #define TYPE_QUALIFIERS     \
        case T_const:           \
        case T_restrict:        \
@@ -232,6 +240,11 @@ static void semantic_comparison(binary_expression_t *expression);
        TYPE_QUALIFIERS         \
        TYPE_SPECIFIERS
 
+#define DECLARATION_START_NO_EXTERN \
+       STORAGE_CLASSES_NO_EXTERN       \
+       TYPE_QUALIFIERS                 \
+       TYPE_SPECIFIERS
+
 #define TYPENAME_START      \
        TYPE_QUALIFIERS         \
        TYPE_SPECIFIERS
@@ -312,7 +325,8 @@ static size_t get_entity_struct_size(entity_kind_t kind)
                [ENTITY_ENUM]            = sizeof(enum_t),
                [ENTITY_ENUM_VALUE]      = sizeof(enum_value_t),
                [ENTITY_LABEL]           = sizeof(label_t),
-               [ENTITY_LOCAL_LABEL]     = sizeof(label_t)
+               [ENTITY_LOCAL_LABEL]     = sizeof(label_t),
+               [ENTITY_NAMESPACE]       = sizeof(namespace_t)
        };
        assert(kind < sizeof(sizes) / sizeof(sizes[0]));
        assert(sizes[kind] != 0);
@@ -761,22 +775,23 @@ static void type_error_incompatible(const char *msg,
 
 static void scope_push(scope_t *new_scope)
 {
-       if (scope != NULL) {
-               new_scope->depth = scope->depth + 1;
+       if (current_scope != NULL) {
+               new_scope->depth = current_scope->depth + 1;
        }
-       new_scope->parent = scope;
-       scope             = new_scope;
+       new_scope->parent = current_scope;
+       current_scope     = new_scope;
 }
 
 static void scope_pop(void)
 {
-       scope = scope->parent;
+       current_scope = current_scope->parent;
 }
 
 /**
  * Search an entity by its symbol in a given namespace.
  */
-static entity_t *get_entity(const symbol_t *const symbol, namespace_t namespc)
+static entity_t *get_entity(const symbol_t *const symbol,
+                            namespace_tag_t namespc)
 {
        entity_t *entity = symbol->entity;
        for( ; entity != NULL; entity = entity->base.symbol_next) {
@@ -793,8 +808,8 @@ static entity_t *get_entity(const symbol_t *const symbol, namespace_t namespc)
  */
 static void stack_push(stack_entry_t **stack_ptr, entity_t *entity)
 {
-       symbol_t    *symbol  = entity->base.symbol;
-       namespace_t  namespc = entity->base.namespc;
+       symbol_t           *symbol  = entity->base.symbol;
+       entity_namespace_t  namespc = entity->base.namespc;
        assert(namespc != NAMESPACE_INVALID);
 
        /* replace/add entity into entity list of the symbol */
@@ -859,9 +874,9 @@ static void stack_pop_to(stack_entry_t **stack_ptr, size_t new_top)
        for(i = top; i > new_top; --i) {
                stack_entry_t *entry = &stack[i - 1];
 
-               entity_t    *old_entity = entry->old_entity;
-               symbol_t    *symbol     = entry->symbol;
-               namespace_t  namespc    = entry->namespc;
+               entity_t           *old_entity = entry->old_entity;
+               symbol_t           *symbol     = entry->symbol;
+               entity_namespace_t  namespc    = entry->namespc;
 
                /* replace with old_entity/remove */
                entity_t **anchor;
@@ -2941,13 +2956,13 @@ static compound_t *parse_compound_type_specifier(bool is_struct)
                symbol = token.v.symbol;
                next_token();
 
-               namespace_t const namespc =
+               namespace_tag_t const namespc =
                        is_struct ? NAMESPACE_STRUCT : NAMESPACE_UNION;
                entity_t *entity = get_entity(symbol, namespc);
                if (entity != NULL) {
                        assert(entity->kind == (is_struct ? ENTITY_STRUCT : ENTITY_UNION));
                        compound = &entity->compound;
-                       if (compound->base.parent_scope != scope &&
+                       if (compound->base.parent_scope != current_scope &&
                            (token.type == '{' || token.type == ';')) {
                                /* we're in an inner scope and have a definition. Override
                                   existing definition in outer scope */
@@ -2982,11 +2997,11 @@ static compound_t *parse_compound_type_specifier(bool is_struct)
                        (is_struct ? NAMESPACE_STRUCT : NAMESPACE_UNION);
                compound->base.source_position = token.source_position;
                compound->base.symbol          = symbol;
-               compound->base.parent_scope    = scope;
+               compound->base.parent_scope    = current_scope;
                if (symbol != NULL) {
                        environment_push(entity);
                }
-               append_entity(scope, entity);
+               append_entity(current_scope, entity);
        }
 
        if (token.type == '{') {
@@ -3076,7 +3091,7 @@ static type_t *parse_enum_specifier(void)
                entity->base.namespc         = NAMESPACE_ENUM;
                entity->base.source_position = token.source_position;
                entity->base.symbol          = symbol;
-               entity->base.parent_scope    = scope;
+               entity->base.parent_scope    = current_scope;
        }
 
        type_t *const type = allocate_type_zero(TYPE_ENUM);
@@ -3090,7 +3105,7 @@ static type_t *parse_enum_specifier(void)
                if (symbol != NULL) {
                        environment_push(entity);
                }
-               append_entity(scope, entity);
+               append_entity(current_scope, entity);
                entity->enume.complete = true;
 
                parse_enum_entries(type);
@@ -4190,6 +4205,8 @@ static construct_type_t *parse_function_declarator(scope_t *scope)
 {
        type_t *type = allocate_type_zero(TYPE_FUNCTION);
 
+       type->function.linkage = current_linkage;
+
        /* TODO: revive this... once we know exactly how to do it */
 #if 0
        decl_modifiers_t  modifiers = entity->declaration.modifiers;
@@ -4576,7 +4593,8 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers,
                storage_class_t storage_class = specifiers->storage_class;
                entity->declaration.declared_storage_class = storage_class;
 
-               if (storage_class == STORAGE_CLASS_NONE && scope != file_scope) {
+               if (storage_class == STORAGE_CLASS_NONE
+                               && current_scope != file_scope) {
                        storage_class = STORAGE_CLASS_AUTO;
                }
                entity->declaration.storage_class = storage_class;
@@ -4668,6 +4686,34 @@ static bool is_sym_main(const symbol_t *const sym)
        return strcmp(sym->string, "main") == 0;
 }
 
+static const char *get_entity_kind_name(entity_kind_t kind)
+{
+       switch ((entity_kind_tag_t) kind) {
+       case ENTITY_FUNCTION:        return "function";
+       case ENTITY_VARIABLE:        return "variable";
+       case ENTITY_COMPOUND_MEMBER: return "compound type member";
+       case ENTITY_STRUCT:          return "struct";
+       case ENTITY_UNION:           return "union";
+       case ENTITY_ENUM:            return "enum";
+       case ENTITY_ENUM_VALUE:      return "enum value";
+       case ENTITY_LABEL:           return "label";
+       case ENTITY_LOCAL_LABEL:     return "local label";
+       case ENTITY_TYPEDEF:         return "typedef";
+       case ENTITY_NAMESPACE:       return "namespace";
+       case ENTITY_INVALID:         break;
+       }
+
+       panic("Invalid entity kind encountered in get_entity_kind_name");
+}
+
+static void error_redefined_as_different_kind(const source_position_t *pos,
+               const entity_t *old, entity_kind_t new_kind)
+{
+       errorf(pos, "redeclaration of %s '%Y' as %s (declared %P)",
+              get_entity_kind_name(old->kind), old->base.symbol, new_kind,
+              &old->base.source_position);
+}
+
 /**
  * record entities for the NAMESPACE_NORMAL, and produce error messages/warnings
  * for various problems that occur for multiple definitions
@@ -4675,7 +4721,7 @@ static bool is_sym_main(const symbol_t *const sym)
 static entity_t *record_entity(entity_t *entity, const bool is_definition)
 {
        const symbol_t *const    symbol  = entity->base.symbol;
-       const namespace_t        namespc = entity->base.namespc;
+       const namespace_tag_t    namespc = entity->base.namespc;
        const source_position_t *pos     = &entity->base.source_position;
 
        assert(symbol != NULL);
@@ -4695,7 +4741,8 @@ static entity_t *record_entity(entity_t *entity, const bool is_definition)
                                         orig_type, symbol);
                }
 
-               if (warning.main && scope == file_scope && is_sym_main(symbol)) {
+               if (warning.main && current_scope == file_scope
+                               && is_sym_main(symbol)) {
                        check_type_of_main(entity);
                }
        }
@@ -4703,7 +4750,7 @@ static entity_t *record_entity(entity_t *entity, const bool is_definition)
        if (is_declaration(entity)) {
                if (warning.nested_externs
                                && entity->declaration.storage_class == STORAGE_CLASS_EXTERN
-                               && scope != file_scope) {
+                               && current_scope != file_scope) {
                        warningf(pos, "nested extern declaration of '%#T'",
                                 entity->declaration.type, symbol);
                }
@@ -4711,7 +4758,7 @@ static entity_t *record_entity(entity_t *entity, const bool is_definition)
 
        if (previous_entity != NULL
            && previous_entity->base.parent_scope == &current_function->parameters
-               && scope->depth == previous_entity->base.parent_scope->depth + 1) {
+               && current_scope->depth == previous_entity->base.parent_scope->depth+1){
 
                assert(previous_entity->kind == ENTITY_VARIABLE);
                errorf(pos,
@@ -4723,12 +4770,11 @@ static entity_t *record_entity(entity_t *entity, const bool is_definition)
        }
 
        if (previous_entity != NULL
-                       && previous_entity->base.parent_scope == scope) {
+                       && previous_entity->base.parent_scope == current_scope) {
 
                if (previous_entity->kind != entity->kind) {
-                       errorf(pos,
-                              "redeclaration of '%Y' as different kind of symbol (declared %P)",
-                              symbol, &previous_entity->base.source_position);
+                       error_redefined_as_different_kind(pos, previous_entity,
+                                                         entity->kind);
                        goto finish;
                }
                if (previous_entity->kind == ENTITY_ENUM_VALUE) {
@@ -4885,7 +4931,7 @@ error_redeclaration:
                }
        } else if (warning.missing_declarations
                        && entity->kind == ENTITY_VARIABLE
-                       && scope == file_scope) {
+                       && current_scope == file_scope) {
                declaration_t *declaration = &entity->declaration;
                if (declaration->storage_class == STORAGE_CLASS_NONE ||
                                declaration->storage_class == STORAGE_CLASS_THREAD) {
@@ -4896,12 +4942,12 @@ error_redeclaration:
 
 finish:
        assert(entity->base.parent_scope == NULL);
-       assert(scope != NULL);
+       assert(current_scope != NULL);
 
-       entity->base.parent_scope = scope;
+       entity->base.parent_scope = current_scope;
        entity->base.namespc      = NAMESPACE_NORMAL;
        environment_push(entity);
-       append_entity(scope, entity);
+       append_entity(current_scope, entity);
 
        return entity;
 }
@@ -5050,7 +5096,7 @@ static entity_t *finished_kr_declaration(entity_t *entity, bool is_definition)
        assert(entity->base.namespc == NAMESPACE_NORMAL);
        entity_t *previous_entity = get_entity(symbol, NAMESPACE_NORMAL);
        if (previous_entity == NULL
-                       || previous_entity->base.parent_scope != scope) {
+                       || previous_entity->base.parent_scope != current_scope) {
                errorf(HERE, "expected declaration of a function parameter, found '%Y'",
                       symbol);
                return entity;
@@ -5114,7 +5160,7 @@ static void parse_kr_declaration_list(entity_t *entity)
        entity_t *parameter = entity->function.parameters.entities;
        for ( ; parameter != NULL; parameter = parameter->base.next) {
                assert(parameter->base.parent_scope == NULL);
-               parameter->base.parent_scope = scope;
+               parameter->base.parent_scope = current_scope;
                environment_push(parameter);
        }
 
@@ -5124,7 +5170,7 @@ static void parse_kr_declaration_list(entity_t *entity)
        }
 
        /* pop function parameters */
-       assert(scope == &entity->function.parameters);
+       assert(current_scope == &entity->function.parameters);
        scope_pop();
        environment_pop_to(top);
 
@@ -5843,11 +5889,9 @@ static void parse_external_declaration(void)
        }
 
        assert(is_declaration(ndeclaration));
-       type_t *type = ndeclaration->declaration.type;
+       type_t *type = skip_typeref(ndeclaration->declaration.type);
 
-       /* note that we don't skip typerefs: the standard doesn't allow them here
-        * (so we can't use is_type_function here) */
-       if (type->kind != TYPE_FUNCTION) {
+       if (!is_type_function(type)) {
                if (is_type_valid(type)) {
                        errorf(HERE, "declarator '%#T' has a body but is not a function type",
                               type, ndeclaration->base.symbol);
@@ -5903,11 +5947,11 @@ static void parse_external_declaration(void)
        entity_t *parameter = function->parameters.entities;
        for( ; parameter != NULL; parameter = parameter->base.next) {
                if (parameter->base.parent_scope == &ndeclaration->function.parameters) {
-                       parameter->base.parent_scope = scope;
+                       parameter->base.parent_scope = current_scope;
                }
                assert(parameter->base.parent_scope == NULL
-                               || parameter->base.parent_scope == scope);
-               parameter->base.parent_scope = scope;
+                               || parameter->base.parent_scope == current_scope);
+               parameter->base.parent_scope = current_scope;
                if (parameter->base.symbol == NULL) {
                        errorf(&parameter->base.source_position, "parameter name omitted");
                        continue;
@@ -5953,7 +5997,7 @@ static void parse_external_declaration(void)
                label_pop_to(label_stack_top);
        }
 
-       assert(scope == &function->parameters);
+       assert(current_scope == &function->parameters);
        scope_pop();
        environment_pop_to(top);
 }
@@ -7182,8 +7226,8 @@ static label_t *get_label(symbol_t *symbol)
        label = get_entity(symbol, NAMESPACE_LABEL);
        /* if we found a local label, we already created the declaration */
        if (label != NULL && label->kind == ENTITY_LOCAL_LABEL) {
-               if (label->base.parent_scope != scope) {
-                       assert(label->base.parent_scope->depth < scope->depth);
+               if (label->base.parent_scope != current_scope) {
+                       assert(label->base.parent_scope->depth < current_scope->depth);
                        current_function->goto_to_outer = true;
                }
                return &label->label;
@@ -9736,7 +9780,7 @@ static statement_t *parse_for(void)
        rem_anchor_token(')');
        statement->fors.body = parse_loop_body(statement);
 
-       assert(scope == &statement->fors.scope);
+       assert(current_scope == &statement->fors.scope);
        scope_pop();
        environment_pop_to(top);
 
@@ -9746,7 +9790,7 @@ static statement_t *parse_for(void)
 end_error:
        POP_PARENT;
        rem_anchor_token(')');
-       assert(scope == &statement->fors.scope);
+       assert(current_scope == &statement->fors.scope);
        scope_pop();
        environment_pop_to(top);
 
@@ -9932,7 +9976,7 @@ static statement_t *parse_return(void)
                mark_vars_read(return_value, NULL);
        }
 
-       const type_t *const func_type = current_function->base.type;
+       const type_t *const func_type = skip_typeref(current_function->base.type);
        assert(is_type_function(func_type));
        type_t *const return_type = skip_typeref(func_type->function.return_type);
 
@@ -9980,18 +10024,18 @@ static statement_t *parse_declaration_statement(void)
 {
        statement_t *statement = allocate_statement_zero(STATEMENT_DECLARATION);
 
-       entity_t *before = scope->last_entity;
+       entity_t *before = current_scope->last_entity;
        if (GNU_MODE)
                parse_external_declaration();
        else
                parse_declaration(record_entity);
 
        if (before == NULL) {
-               statement->declaration.declarations_begin = scope->entities;
+               statement->declaration.declarations_begin = current_scope->entities;
        } else {
                statement->declaration.declarations_begin = before->base.next;
        }
-       statement->declaration.declarations_end = scope->last_entity;
+       statement->declaration.declarations_end = current_scope->last_entity;
 
        return statement;
 }
@@ -10087,13 +10131,13 @@ static statement_t *parse_local_label_declaration(void)
                }
                symbol_t *symbol = token.v.symbol;
                entity_t *entity = get_entity(symbol, NAMESPACE_LABEL);
-               if (entity != NULL && entity->base.parent_scope == scope) {
+               if (entity != NULL && entity->base.parent_scope == current_scope) {
                        errorf(HERE, "multiple definitions of '__label__ %Y' (previous definition %P)",
                               symbol, &entity->base.source_position);
                } else {
                        entity = allocate_entity_zero(ENTITY_LOCAL_LABEL);
 
-                       entity->base.parent_scope    = scope;
+                       entity->base.parent_scope    = current_scope;
                        entity->base.namespc         = NAMESPACE_LABEL;
                        entity->base.source_position = token.source_position;
                        entity->base.symbol          = symbol;
@@ -10119,6 +10163,55 @@ end_error:
        return statement;
 }
 
+static void parse_namespace_definition(void)
+{
+       eat(T_namespace);
+
+       entity_t *entity = NULL;
+       symbol_t *symbol = NULL;
+
+       if (token.type == T_IDENTIFIER) {
+               symbol = token.v.symbol;
+               next_token();
+
+               entity = get_entity(symbol, NAMESPACE_NORMAL);
+               if (entity != NULL && entity->kind != ENTITY_NAMESPACE
+                               && entity->base.parent_scope == current_scope) {
+                       error_redefined_as_different_kind(&token.source_position,
+                                                         entity, ENTITY_NAMESPACE);
+                       entity = NULL;
+               }
+       }
+
+       if (entity == NULL) {
+               entity                       = allocate_entity_zero(ENTITY_NAMESPACE);
+               entity->base.symbol          = symbol;
+               entity->base.source_position = token.source_position;
+               entity->base.namespc         = NAMESPACE_NORMAL;
+               entity->base.parent_scope    = current_scope;
+       }
+
+       if (token.type == '=') {
+               /* TODO: parse namespace alias */
+               panic("namespace alias definition not supported yet");
+       }
+
+       environment_push(entity);
+       append_entity(current_scope, entity);
+
+       size_t const top = environment_top();
+       scope_push(&entity->namespacee.members);
+
+       expect('{');
+       parse_externals();
+       expect('}');
+
+end_error:
+       assert(current_scope == &entity->namespacee.members);
+       scope_pop();
+       environment_pop_to(top);
+}
+
 /**
  * Parse a statement.
  * There's also parse_statement() which additionally checks for
@@ -10182,22 +10275,22 @@ expression_statment:
                statement = parse_local_label_declaration();
                break;
 
-       case ';':        statement = parse_empty_statement();         break;
-       case '{':        statement = parse_compound_statement(false); break;
-       case T___leave:  statement = parse_leave_statement();         break;
-       case T___try:    statement = parse_ms_try_statment();         break;
-       case T_asm:      statement = parse_asm_statement();           break;
-       case T_break:    statement = parse_break();                   break;
-       case T_case:     statement = parse_case_statement();          break;
-       case T_continue: statement = parse_continue();                break;
-       case T_default:  statement = parse_default_statement();       break;
-       case T_do:       statement = parse_do();                      break;
-       case T_for:      statement = parse_for();                     break;
-       case T_goto:     statement = parse_goto();                    break;
-       case T_if:       statement = parse_if();                      break;
-       case T_return:   statement = parse_return();                  break;
-       case T_switch:   statement = parse_switch();                  break;
-       case T_while:    statement = parse_while();                   break;
+       case ';':         statement = parse_empty_statement();         break;
+       case '{':         statement = parse_compound_statement(false); break;
+       case T___leave:   statement = parse_leave_statement();         break;
+       case T___try:     statement = parse_ms_try_statment();         break;
+       case T_asm:       statement = parse_asm_statement();           break;
+       case T_break:     statement = parse_break();                   break;
+       case T_case:      statement = parse_case_statement();          break;
+       case T_continue:  statement = parse_continue();                break;
+       case T_default:   statement = parse_default_statement();       break;
+       case T_do:        statement = parse_do();                      break;
+       case T_for:       statement = parse_for();                     break;
+       case T_goto:      statement = parse_goto();                    break;
+       case T_if:        statement = parse_if();                      break;
+       case T_return:    statement = parse_return();                  break;
+       case T_switch:    statement = parse_switch();                  break;
+       case T_while:     statement = parse_while();                   break;
 
        EXPRESSION_START
                statement = parse_expression_statement();
@@ -10309,7 +10402,7 @@ static statement_t *parse_compound_statement(bool inside_expression_statement)
 
 end_error:
        rem_anchor_token('}');
-       assert(scope == &statement->compound.scope);
+       assert(current_scope == &statement->compound.scope);
        scope_pop();
        environment_pop_to(top);
 
@@ -10371,18 +10464,88 @@ static void parse_global_asm(void)
 end_error:;
 }
 
-/**
- * Parse a translation unit.
- */
-static void parse_translation_unit(void)
+static void parse_linkage_specification(void)
 {
+       eat(T_extern);
+       assert(token.type == T_STRING_LITERAL);
+
+       string_t  linkage = parse_string_literals();
+       /* convert to symbol for easier handling... */
+       symbol_t *symbol = symbol_table_insert(linkage.begin);
+
+
+       symbol_t *old_linkage = current_linkage;
+       current_linkage       = symbol;
+
+       if (token.type == '{') {
+               next_token();
+               parse_externals();
+               expect('}');
+       } else {
+               parse_external();
+       }
+
+end_error:
+       assert(current_linkage == symbol);
+       current_linkage = old_linkage;
+}
+
+static void parse_external(void)
+{
+       switch (token.type) {
+               DECLARATION_START_NO_EXTERN
+               case T_IDENTIFIER:
+               case T___extension__:
+               case '(': /* for function declarations with implicit return type and
+                                  * parenthesized declarator, i.e. (f)(void); */
+                       parse_external_declaration();
+                       return;
+
+               case T_extern:
+                       if (look_ahead(1)->type == T_STRING_LITERAL) {
+                               parse_linkage_specification();
+                       } else {
+                               parse_external_declaration();
+                       }
+                       return;
+
+               case T_asm:
+                       parse_global_asm();
+                       return;
+
+               case T_namespace:
+                       parse_namespace_definition();
+                       return;
+
+               case ';':
+                       if (!strict_mode) {
+                               if (warning.other)
+                                       warningf(HERE, "stray ';' outside of function");
+                               next_token();
+                               return;
+                       }
+                       /* FALLTHROUGH */
+
+               default:
+                       errorf(HERE, "stray %K outside of function", &token);
+                       if (token.type == '(' || token.type == '{' || token.type == '[')
+                               eat_until_matching_token(token.type);
+                       next_token();
+                       return;
+       }
+}
+
+static void parse_externals(void)
+{
+       add_anchor_token('}');
        add_anchor_token(T_EOF);
 
 #ifndef NDEBUG
        unsigned char token_anchor_copy[T_LAST_TOKEN];
        memcpy(token_anchor_copy, token_anchor_set, sizeof(token_anchor_copy));
 #endif
-       for (;;) {
+
+       while (token.type != T_EOF && token.type != '}') {
 #ifndef NDEBUG
                bool anchor_leak = false;
                for (int i = 0; i != T_LAST_TOKEN; ++i) {
@@ -10401,39 +10564,30 @@ static void parse_translation_unit(void)
                        abort();
 #endif
 
-               switch (token.type) {
-                       DECLARATION_START
-                       case T_IDENTIFIER:
-                       case T___extension__:
-                       case '(': /* for function declarations with implicit return type and
-                                  * parenthesized declarator, i.e. (f)(void); */
-                               parse_external_declaration();
-                               break;
+               parse_external();
+       }
 
-                       case T_asm:
-                               parse_global_asm();
-                               break;
+       rem_anchor_token(T_EOF);
+       rem_anchor_token('}');
+}
 
-                       case T_EOF:
-                               rem_anchor_token(T_EOF);
-                               return;
+/**
+ * Parse a translation unit.
+ */
+static void parse_translation_unit(void)
+{
+       add_anchor_token(T_EOF);
 
-                       case ';':
-                               if (!strict_mode) {
-                                       if (warning.other)
-                                               warningf(HERE, "stray ';' outside of function");
-                                       next_token();
-                                       break;
-                               }
-                               /* FALLTHROUGH */
+       while (true) {
+               parse_externals();
 
-                       default:
-                               errorf(HERE, "stray %K outside of function", &token);
-                               if (token.type == '(' || token.type == '{' || token.type == '[')
-                                       eat_until_matching_token(token.type);
-                               next_token();
-                               break;
-               }
+               if (token.type == T_EOF)
+                       break;
+
+               errorf(HERE, "stray %K outside of function", &token);
+               if (token.type == '(' || token.type == '{' || token.type == '[')
+                       eat_until_matching_token(token.type);
+               next_token();
        }
 }
 
@@ -10459,15 +10613,15 @@ void start_parsing(void)
        assert(file_scope == NULL);
        file_scope = &unit->scope;
 
-       assert(scope == NULL);
+       assert(current_scope == NULL);
        scope_push(&unit->scope);
 }
 
 translation_unit_t *finish_parsing(void)
 {
        /* do NOT use scope_pop() here, this will crash, will it by hand */
-       assert(scope == &unit->scope);
-       scope            = NULL;
+       assert(current_scope == &unit->scope);
+       current_scope = NULL;
 
        assert(file_scope == &unit->scope);
        check_unused_globals();
index f56a182..39b2bb7 100644 (file)
@@ -1264,7 +1264,7 @@ static void print_line_directive(const source_position_t *pos, const char *add)
 
 static void print_spaces(void)
 {
-       if (counted_newlines >= 8) {
+       if (counted_newlines >= 9) {
                if (input.had_non_space) {
                        fputc('\n', out);
                }
index 11f4a7f..bca37bb 100644 (file)
@@ -140,91 +140,91 @@ S(_MS, __FUNCDNAME__)
 #endif
 
 #define S(mode, x, val) T(mode, x, #x, val)
-S(_ANSI|_C99,   signed,               )
-S(_ALL,       __signed,               = T_signed)
-S(_ALL,       __signed__,             = T_signed)
-S(_C99|_GNUC,  _Complex,              )
-S(_ALL,       __complex__,            = T__Complex)
-S(_ALL,       __complex,              = T__Complex)
-S(_C99|_GNUC,  _Imaginary,            )
-S(_ALL,       __real__,               )
-S(_ALL,       __real,                 = T___real__)
-S(_ALL,       __imag__,               )
-S(_ALL,       __imag,                 = T___imag__)
-S(_ALL,       __alignof__,            )
-S(_ALL,       __alignof,              = T___alignof__)
-S(_MS,         _alignof,              = T___alignof__)
-S(_ANSI|_C99,   const,                )
-S(_ALL,       __const,                = T_const)
-S(_ALL,       __const__,              = T_const)
-S(_C99,         restrict,             )
-S(_ALL,       __restrict__,           = T_restrict)
-S(_ALL,       __restrict,             = T_restrict)
-S(_MS,         _restrict,             = T_restrict)
-S(_ALL,         asm,                  )
-S(_ALL,       __asm__,                = T_asm)
-S(_MS,         _asm,                  = T_asm)
-S(_ALL,       __asm,                  = T_asm)
-S(_ANSI|_C99,   volatile,             )
-S(_ALL,       __volatile,             = T_volatile)
-S(_ALL,       __volatile__,           = T_volatile)
-S(_C99|_CXX,    inline,               )
-S(_ALL,       __inline,               = T_inline)
-S(_ALL,       __inline__,             = T_inline)
-S(_GNUC,        typeof,               )
-S(_ALL,       __typeof,               = T_typeof)
-S(_ALL,       __typeof__,             = T_typeof)
-S(_ALL,       __attribute__,          )
+S(_ANSI|_C99|_CXX,   signed,               )
+S(_ALL,            __signed,               = T_signed)
+S(_ALL,            __signed__,             = T_signed)
+S(_C99|_GNUC,       _Complex,              )
+S(_ALL,            __complex__,            = T__Complex)
+S(_ALL,            __complex,              = T__Complex)
+S(_C99|_GNUC,       _Imaginary,            )
+S(_ALL,            __real__,               )
+S(_ALL,            __real,                 = T___real__)
+S(_ALL,            __imag__,               )
+S(_ALL,            __imag,                 = T___imag__)
+S(_ALL,            __alignof__,            )
+S(_ALL,            __alignof,              = T___alignof__)
+S(_MS,              _alignof,              = T___alignof__)
+S(_ANSI|_C99|_CXX,   const,                )
+S(_ALL,            __const,                = T_const)
+S(_ALL,            __const__,              = T_const)
+S(_C99,              restrict,             )
+S(_ALL,            __restrict__,           = T_restrict)
+S(_ALL,            __restrict,             = T_restrict)
+S(_MS,              _restrict,             = T_restrict)
+S(_ALL,              asm,                  )
+S(_ALL,            __asm__,                = T_asm)
+S(_MS,              _asm,                  = T_asm)
+S(_ALL,            __asm,                  = T_asm)
+S(_ANSI|_C99|_CXX,   volatile,             )
+S(_ALL,            __volatile,             = T_volatile)
+S(_ALL,            __volatile__,           = T_volatile)
+S(_C99|_CXX,         inline,               )
+S(_ALL,            __inline,               = T_inline)
+S(_ALL,            __inline__,             = T_inline)
+S(_GNUC,             typeof,               )
+S(_ALL,            __typeof,               = T_typeof)
+S(_ALL,            __typeof__,             = T_typeof)
+S(_ALL,            __attribute__,          )
 
-S(_ALL,       __builtin_va_start,     )
-S(_ALL,       __builtin_stdarg_start, = T___builtin_va_start)
+S(_ALL,            __builtin_va_start,     )
+S(_ALL,            __builtin_stdarg_start, = T___builtin_va_start)
 
-S(_MS,         _near,                 )
-S(_MS,        __near,                 = T__near)
-S(_MS,         _far,                  )
-S(_MS,        __far,                  = T__far)
-S(_MS,          cdecl,                )
-S(_MS,         _cdecl,                = T_cdecl)
-S(_MS,        __cdecl,                = T_cdecl)
-S(_MS,         _stdcall,              )
-S(_MS,        __stdcall,              = T__stdcall)
-S(_MS,         _fastcall,             )
-S(_MS,        __fastcall,             = T__fastcall)
-S(_MS,        __thiscall,             )
-S(_MS,         _forceinline,          )
-S(_MS,        __forceinline,          = T__forceinline)
-S(_MS,        __unaligned,            )
-S(_MS,         _assume,               )
-S(_MS,        __assume,               = T__assume)
-S(_MS,         _try,                  )
-S(_MS,        __try,                  = T__try)
-S(_MS,         _finally,              )
-S(_MS,        __finally,              = T__finally)
-S(_MS,         _leave,                )
-S(_MS,        __leave,                = T__leave)
-S(_MS,         _except,               )
-S(_MS,        __except,               = T__except)
-S(_MS,         _declspec,             )
-S(_MS,        __declspec,             = T__declspec)
-S(_MS,         _based,                )
-S(_MS,        __based,                = T__based)
-S(_MS,        __noop,                 )
+S(_MS,              _near,                 )
+S(_MS,             __near,                 = T__near)
+S(_MS,              _far,                  )
+S(_MS,             __far,                  = T__far)
+S(_MS,               cdecl,                )
+S(_MS,              _cdecl,                = T_cdecl)
+S(_MS,             __cdecl,                = T_cdecl)
+S(_MS,              _stdcall,              )
+S(_MS,             __stdcall,              = T__stdcall)
+S(_MS,              _fastcall,             )
+S(_MS,             __fastcall,             = T__fastcall)
+S(_MS,             __thiscall,             )
+S(_MS,              _forceinline,          )
+S(_MS,             __forceinline,          = T__forceinline)
+S(_MS,             __unaligned,            )
+S(_MS,              _assume,               )
+S(_MS,             __assume,               = T__assume)
+S(_MS,              _try,                  )
+S(_MS,             __try,                  = T__try)
+S(_MS,              _finally,              )
+S(_MS,             __finally,              = T__finally)
+S(_MS,              _leave,                )
+S(_MS,             __leave,                = T__leave)
+S(_MS,              _except,               )
+S(_MS,             __except,               = T__except)
+S(_MS,              _declspec,             )
+S(_MS,             __declspec,             = T__declspec)
+S(_MS,              _based,                )
+S(_MS,             __based,                = T__based)
+S(_MS,             __noop,                 )
 
-S(_MS,        __ptr32,                )
-S(_MS,        __ptr64,                )
-S(_MS,        __sptr,                 )
-S(_MS,        __uptr,                 )
-S(_MS,         _w64,                  )
-S(_MS,        __w64,                  = T__w64)
+S(_MS,             __ptr32,                )
+S(_MS,             __ptr64,                )
+S(_MS,             __sptr,                 )
+S(_MS,             __uptr,                 )
+S(_MS,              _w64,                  )
+S(_MS,             __w64,                  = T__w64)
 
-S(_MS,         _int8,                 )
-S(_MS,        __int8,                 = T__int8)
-S(_MS,         _int16,                )
-S(_MS,        __int16,                = T__int16)
-S(_MS,         _int32,                )
-S(_MS,        __int32,                = T__int32)
-S(_MS,         _int64,                )
-S(_MS,        __int64,                = T__int64)
-S(_MS,         _int128,               )
-S(_MS,        __int128,               = T__int128)
+S(_MS,              _int8,                 )
+S(_MS,             __int8,                 = T__int8)
+S(_MS,              _int16,                )
+S(_MS,             __int16,                = T__int16)
+S(_MS,              _int32,                )
+S(_MS,             __int32,                = T__int32)
+S(_MS,              _int64,                )
+S(_MS,             __int64,                = T__int64)
+S(_MS,              _int128,               )
+S(_MS,             __int128,               = T__int128)
 #undef S
diff --git a/type.c b/type.c
index ce14faa..204d6f0 100644 (file)
--- a/type.c
+++ b/type.c
@@ -295,14 +295,21 @@ void print_imaginary_type(const imaginary_type_t *type)
  */
 static void print_function_type_pre(const function_type_t *type, bool top)
 {
+       if (type->linkage != NULL) {
+               fputs("extern \"", out);
+               fputs(type->linkage->string, out);
+               fputs("\" ", out);
+       }
+
        print_type_qualifiers(type->base.qualifiers);
        if (type->base.qualifiers != 0)
                fputc(' ', out);
 
-
        intern_print_type_pre(type->return_type, false);
 
-       switch (type->calling_convention) {
+#if 0
+       /* TODO: revive with linkage */
+       switch (type->linkage) {
        case CC_CDECL:
                fputs("__cdecl ", out);
                break;
@@ -318,6 +325,7 @@ static void print_function_type_pre(const function_type_t *type, bool top)
        case CC_DEFAULT:
                break;
        }
+#endif
 
        /* don't emit parenthesis if we're the toplevel type... */
        if (!top)
@@ -1029,7 +1037,7 @@ static bool function_types_compatible(const function_type_t *func1,
        if (!types_compatible(ret1, ret2))
                return false;
 
-       if (func1->calling_convention != func2->calling_convention)
+       if (func1->linkage != func2->linkage)
                return false;
 
        /* can parameters be compared? */
index d20759f..88de01c 100644 (file)
@@ -98,7 +98,7 @@ static unsigned hash_function_type(const function_type_t *type)
                result   ^= hash_ptr(parameter->type);
                parameter = parameter->next;
        }
-       result += type->calling_convention;
+       result ^= hash_ptr(type->linkage);
 
        return result;
 }
@@ -208,7 +208,7 @@ static bool function_types_equal(const function_type_t *type1,
                return false;
        if (type1->kr_style_parameters != type2->kr_style_parameters)
                return false;
-       if (type1->calling_convention != type2->calling_convention)
+       if (type1->linkage != type2->linkage)
                return false;
 
        function_parameter_t *param1 = type1->parameters;
index 5fed59d..0773f70 100644 (file)
--- a/type_t.h
+++ b/type_t.h
@@ -132,7 +132,7 @@ struct function_type_t {
        type_base_t           base;
        type_t               *return_type;        /**< The return type. */
        function_parameter_t *parameters;         /**< A list of the parameter types. */
-       cc_kind_t             calling_convention; /**< The specified calling convention. */
+       symbol_t             *linkage;
        bool                  variadic : 1;
        bool                  unspecified_parameters : 1;
        bool                  kr_style_parameters : 1;
diff --git a/types.c b/types.c
index 98e75ce..586b95b 100644 (file)
--- a/types.c
+++ b/types.c
@@ -22,8 +22,6 @@
 #include "lang_features.h"
 #include "entity_t.h"
 
-atomic_type_kind_t wchar_atomic_kind = ATOMIC_TYPE_INT;
-
 /** The error type. */
 type_t *type_error_type;