static entity_t **inner_functions;
static ir_node *ijmp_list;
static bool constant_folding;
-static symbol_t *sym_C;
extern bool have_const_functions;
/* 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) {
rts_idents[i] = new_id_from_str(rts_data[i].name);
}
- sym_C = symbol_table_insert("C");
-
entitymap_init(&entitymap);
}
#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);
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');
}
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 */
{
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;
}
}
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);
}
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;
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();
}
end_error:
- assert(current_linkage == symbol);
+ assert(current_linkage == new_linkage);
current_linkage = old_linkage;
}
for (int i = 0; i < MAX_LOOKAHEAD + 2; ++i) {
next_token();
}
+ current_linkage = c_mode & _CXX ? LINKAGE_CXX : LINKAGE_C;
parse_translation_unit();
}
*/
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);
result ^= hash_ptr(parameter->type);
parameter = parameter->next;
}
- result ^= hash_ptr(type->linkage);
+ result += type->linkage;
result += type->calling_convention;
return result;
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. */
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;