Improve linkage specification
authorChristoph Mallon <christoph.mallon@gmx.de>
Sat, 15 Nov 2008 13:17:12 +0000 (13:17 +0000)
committerChristoph Mallon <christoph.mallon@gmx.de>
Sat, 15 Nov 2008 13:17:12 +0000 (13:17 +0000)
- linkage is an enum now
- accept extern "C++", which is required by the C++ standard.

[r23680]

ast2firm.c
mangle.c
parser.c
type.c
type_hash.c
type_t.h

index 79c5078..0d8f1eb 100644 (file)
@@ -63,7 +63,6 @@ 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;
 
@@ -1026,14 +1025,9 @@ static ir_entity *get_function_entity(entity_t *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) {
+               if (type->function.linkage != LINKAGE_C) {
                        type_t *new_type           = duplicate_type(type);
-                       new_type->function.linkage = sym_C;
+                       new_type->function.linkage = LINKAGE_C;
 
                        type = typehash_insert(new_type);
                        if (type != new_type) {
@@ -5448,8 +5442,6 @@ void init_ast2firm(void)
                rts_idents[i] = new_id_from_str(rts_data[i].name);
        }
 
-       sym_C = symbol_table_insert("C");
-
        entitymap_init(&entitymap);
 }
 
index 43dfd9c..e83bcb3 100644 (file)
--- a/mangle.c
+++ b/mangle.c
@@ -32,8 +32,6 @@
 #include "adt/error.h"
 
 static ident          *id_underscore;
-static ident          *id_imp;
-static symbol_t       *sym_C;
 static struct obstack  obst;
 
 static void mangle_type(type_t *type);
@@ -76,7 +74,7 @@ static void mangle_pointer_type(const pointer_type_t *type)
 static void mangle_function_type(const function_type_t *type)
 {
        obstack_1grow(&obst, 'F');
-       if (type->linkage == sym_C) {
+       if (type->linkage == LINKAGE_C) {
                obstack_1grow(&obst, 'Y');
        }
 
@@ -191,10 +189,17 @@ ident *create_name_win32(entity_t *entity)
                        default:          panic("unhandled calling convention");
                }
 
-               if (c_mode & _CXX && entity->declaration.type->function.linkage == NULL) {
-                       mangle_entity(entity);
-               } else {
-                       obstack_printf(o, "%s", entity->base.symbol->string);
+               switch (entity->declaration.type->function.linkage) {
+                       case LINKAGE_INVALID:
+                               break;
+
+                       case LINKAGE_C:
+                               obstack_printf(o, "%s", entity->base.symbol->string);
+                               break;
+
+                       case LINKAGE_CXX:
+                               mangle_entity(entity);
+                               break;
                }
 
                /* calling convention suffix */
@@ -238,14 +243,11 @@ 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 (entity->kind == ENTITY_FUNCTION) {
+               switch (entity->declaration.type->function.linkage) {
+                       case LINKAGE_INVALID: break;
+                       case LINKAGE_C:       break;
+                       case LINKAGE_CXX:     needs_mangling = true; break;
                }
        }
 
@@ -278,8 +280,6 @@ ident *create_name_macho(entity_t *entity)
 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");
 
        obstack_init(&obst);
 }
index 1c332d1..0852cec 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -116,7 +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 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;
@@ -10469,13 +10469,19 @@ 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);
+       const char *linkage = parse_string_literals().begin;
 
-
-       symbol_t *old_linkage = current_linkage;
-       current_linkage       = symbol;
+       linkage_kind_t old_linkage = current_linkage;
+       linkage_kind_t new_linkage;
+       if (strcmp(linkage, "C") == 0) {
+               new_linkage = LINKAGE_C;
+       } else if (strcmp(linkage, "C++") == 0) {
+               new_linkage = LINKAGE_CXX;
+       } else {
+               errorf(HERE, "linkage string \"%s\" not recognized", linkage);
+               new_linkage = LINKAGE_INVALID;
+       }
+       current_linkage = new_linkage;
 
        if (token.type == '{') {
                next_token();
@@ -10486,7 +10492,7 @@ static void parse_linkage_specification(void)
        }
 
 end_error:
-       assert(current_linkage == symbol);
+       assert(current_linkage == new_linkage);
        current_linkage = old_linkage;
 }
 
@@ -10641,6 +10647,7 @@ void parse(void)
        for (int i = 0; i < MAX_LOOKAHEAD + 2; ++i) {
                next_token();
        }
+       current_linkage = c_mode & _CXX ? LINKAGE_CXX : LINKAGE_C;
        parse_translation_unit();
 }
 
diff --git a/type.c b/type.c
index d089e25..3ab686d 100644 (file)
--- a/type.c
+++ b/type.c
@@ -295,10 +295,19 @@ 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);
+       switch (type->linkage) {
+               case LINKAGE_INVALID:
+                       break;
+
+               case LINKAGE_C:
+                       if (c_mode & _CXX)
+                               fputs("extern \"C\" ",   out);
+                       break;
+
+               case LINKAGE_CXX:
+                       if (!(c_mode & _CXX))
+                               fputs("extern \"C++\" ", out);
+                       break;
        }
 
        print_type_qualifiers(type->base.qualifiers);
index 9eddefe..ad0732f 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 ^= hash_ptr(type->linkage);
+       result += type->linkage;
        result += type->calling_convention;
 
        return result;
index b9cfcc8..a8f07fc 100644 (file)
--- a/type_t.h
+++ b/type_t.h
@@ -116,6 +116,13 @@ struct function_parameter_t {
        function_parameter_t *next;  /**< Points to the next type inthe parameter list.*/
 };
 
+/** Linkage specifications. */
+typedef enum linkage_kind_t {
+       LINKAGE_INVALID,
+       LINKAGE_C,       /**< C linkage. */
+       LINKAGE_CXX      /**< C++ linkage. */
+} linkage_kind_t;
+
 /** Calling conventions. */
 typedef enum cc_kind_t {
        CC_DEFAULT,      /**< default calling convention. */
@@ -132,7 +139,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. */
-       symbol_t             *linkage;
+       linkage_kind_t        linkage;
        cc_kind_t             calling_convention; /**< The specified calling convention. */
        bool                  variadic : 1;
        bool                  unspecified_parameters : 1;