adt/obstack_printf.c \
adt/xmalloc.c \
ast.c \
- ast2firm.c \
diagnostic.c \
entitymap.c \
format_check.c \
lexer.c \
main.c \
- parser.c \
walk_statements.c \
symbol_table.c \
token.c \
types.c \
type_hash.c \
warning.c \
+ parser.c \
+ ast2firm.c \
write_fluffy.c \
write_caml.c \
driver/firm_cmdline.c \
#include "type_t.h"
#include "parser.h"
#include "lang_features.h"
+#include "entity_t.h"
#include <assert.h>
#include <stdio.h>
if (*c == border) {
fputc('\\', out);
}
- switch(*c) {
+ switch (*c) {
case '\\': fputs("\\\\", out); break;
case '\a': fputs("\\a", out); break;
case '\b': fputs("\\b", out); break;
const funcname_expression_t *funcname)
{
const char *s = "";
- switch(funcname->kind) {
+ switch (funcname->kind) {
case FUNCNAME_FUNCTION: s = (c_mode & _C99) ? "__func__" : "__FUNCTION__"; break;
case FUNCNAME_PRETTY_FUNCTION: s = "__PRETTY_FUNCTION__"; break;
case FUNCNAME_FUNCSIG: s = "__FUNCSIG__"; break;
static void print_unary_expression(const unary_expression_t *unexpr)
{
unsigned prec = get_expression_precedence(unexpr->base.kind);
- switch(unexpr->base.kind) {
+ switch (unexpr->base.kind) {
case EXPR_UNARY_NEGATE: fputc('-', out); break;
case EXPR_UNARY_PLUS: fputc('+', out); break;
case EXPR_UNARY_NOT: fputc('!', out); break;
*/
static void print_reference_expression(const reference_expression_t *ref)
{
- fputs(ref->declaration->symbol->string, out);
+ fputs(ref->entity->base.symbol->string, out);
}
/**
*/
static void print_label_address_expression(const label_address_expression_t *le)
{
- fprintf(out, "&&%s", le->declaration->symbol->string);
+ fprintf(out, "&&%s", le->label->base.symbol->string);
}
/**
fputs("__builtin_va_start(", out);
print_expression_prec(expression->ap, 2 * PREC_ASSIGNMENT);
fputs(", ", out);
- fputs(expression->parameter->symbol->string, out);
+ fputs(expression->parameter->base.base.symbol->string, out);
fputc(')', out);
}
} else {
fputc('.', out);
}
- fputs(expression->compound_entry->symbol->string, out);
+ fputs(expression->compound_entry->base.symbol->string, out);
}
/**
top_prec = PREC_TOP;
if (top_prec > prec)
fputc('(', out);
- switch(expression->kind) {
+ switch (expression->kind) {
case EXPR_UNKNOWN:
case EXPR_INVALID:
fputs("$invalid expression$", out);
fputc('*', out);
print_expression(statement->expression);
} else {
- fputs(statement->label->symbol->string, out);
+ fputs(statement->label->base.symbol->string, out);
}
fputs(";\n", out);
}
*/
static void print_label_statement(const label_statement_t *statement)
{
- fprintf(out, "%s:\n", statement->label->symbol->string);
+ fprintf(out, "%s:\n", statement->label->base.symbol->string);
print_indent();
print_statement(statement->statement);
}
}
}
+static void print_local_label(const local_label_statement_t *statement)
+{
+ fputs("__label__ ", out);
+
+ bool first = true;
+ entity_t *entity = statement->labels_begin;
+ for (;
+ entity != statement->labels_end->base.next;
+ entity = entity->base.next) {
+ if (!first) {
+ fputs(", ", out);
+ } else {
+ first = false;
+ }
+ fputs(entity->base.symbol->string, out);
+ }
+ fputs(";\n", out);
+}
+
+static void print_typedef(const entity_t *entity)
+{
+ fputs("typedef ", out);
+ print_type_ext(entity->typedefe.type, entity->base.symbol, NULL);
+ fputs(";", out);
+}
+
+/**
+ * returns true if the entity is a compiler generated one and has no real
+ * correspondenc in the source file
+ */
+static bool is_generated_entity(const entity_t *entity)
+{
+ if (entity->kind == ENTITY_TYPEDEF)
+ return entity->typedefe.builtin;
+
+ if (is_declaration(entity))
+ return entity->declaration.implicit;
+
+ return false;
+}
+
/**
* Print a declaration statement.
*
const declaration_statement_t *statement)
{
bool first = true;
- declaration_t *declaration = statement->declarations_begin;
-
- if (declaration->namespc == NAMESPACE_LOCAL_LABEL) {
- fputs("__label__ ", out);
- for (;
- declaration != statement->declarations_end->next;
- declaration = declaration->next) {
- if (!first) {
- fputs(", ", out);
- } else {
- first = false;
- }
- fputs(declaration->symbol->string, out);
+ entity_t *entity = statement->declarations_begin;
+ for (;
+ entity != statement->declarations_end->base.next;
+ entity = entity->base.next) {
+ if (!is_declaration(entity) && entity->kind != ENTITY_TYPEDEF)
+ continue;
+ if (is_generated_entity(entity))
+ continue;
+
+ if (!first) {
+ print_indent();
+ } else {
+ first = false;
}
- fputs(";\n", out);
- } else {
- for (;
- declaration != statement->declarations_end->next;
- declaration = declaration->next) {
- if (declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
- continue;
- if (declaration->implicit)
- continue;
-
- if (!first) {
- print_indent();
- } else {
- first = false;
- }
- print_declaration(declaration);
- fputc('\n', out);
+
+ if (entity->kind == ENTITY_TYPEDEF) {
+ print_typedef(entity);
+ } else {
+ assert(is_declaration(entity));
+ print_declaration(entity);
}
+
+ fputc('\n', out);
}
}
static void print_for_statement(const for_statement_t *statement)
{
fputs("for (", out);
- declaration_t *decl = statement->scope.declarations;
- while (decl != NULL && decl->implicit)
- decl = decl->next;
- if (decl != NULL) {
+ entity_t *entity = statement->scope.entities;
+ while (entity != NULL && is_generated_entity(entity))
+ entity = entity->base.next;
+
+ if (entity != NULL) {
assert(statement->initialisation == NULL);
- print_declaration(decl);
- if (decl->next != NULL) {
+ assert(is_declaration(entity));
+ print_declaration(entity);
+ if (entity->base.next != NULL) {
panic("multiple declarations in for statement not supported yet");
}
fputc(' ', out);
case STATEMENT_LABEL:
print_label_statement(&statement->label);
break;
+ case STATEMENT_LOCAL_LABEL:
+ print_local_label(&statement->local_label);
+ break;
case STATEMENT_GOTO:
print_goto_statement(&statement->gotos);
break;
*/
static void print_storage_class(storage_class_tag_t storage_class)
{
- switch(storage_class) {
- case STORAGE_CLASS_ENUM_ENTRY:
+ switch (storage_class) {
case STORAGE_CLASS_NONE:
break;
case STORAGE_CLASS_TYPEDEF: fputs("typedef ", out); break;
return;
}
- switch(initializer->kind) {
+ switch (initializer->kind) {
case INITIALIZER_VALUE: {
const initializer_value_t *value = &initializer->value;
print_expression(value->value);
/**
* Print microsoft extended declaration modifiers.
*/
-static void print_ms_modifiers(const declaration_t *declaration) {
+static void print_ms_modifiers(const declaration_t *declaration)
+{
if((c_mode & _MS) == 0)
return;
decl_modifiers_t modifiers = declaration->modifiers;
- /* DM_FORCEINLINE handled outside. */
- if ((modifiers & ~DM_FORCEINLINE) != 0 ||
- declaration->alignment != 0 ||
- declaration->get_property_sym != NULL ||
- declaration->put_property_sym != NULL) {
- char *next = "(";
+ bool ds_shown = false;
+ const char *next = "(";
+
+ if (declaration->base.kind == ENTITY_VARIABLE) {
+ variable_t *variable = (variable_t*) declaration;
+ if (variable->alignment != 0
+ || variable->get_property_sym != NULL
+ || variable->put_property_sym != NULL) {
+ if (!ds_shown) {
+ fputs("__declspec", out);
+ ds_shown = true;
+ }
+
+ if(variable->alignment != 0) {
+ fputs(next, out); next = ", "; fprintf(out, "align(%u)", variable->alignment);
+ }
+ if(variable->get_property_sym != NULL
+ || variable->put_property_sym != NULL) {
+ char *comma = "";
+ fputs(next, out); next = ", "; fputs("property(", out);
+ if(variable->get_property_sym != NULL) {
+ fprintf(out, "get=%s", variable->get_property_sym->string);
+ comma = ", ";
+ }
+ if(variable->put_property_sym != NULL)
+ fprintf(out, "%sput=%s", comma, variable->put_property_sym->string);
+ fputc(')', out);
+ }
+ }
+ }
- fputs("__declspec", out);
+ /* DM_FORCEINLINE handled outside. */
+ if ((modifiers & ~DM_FORCEINLINE) != 0) {
+ if (!ds_shown) {
+ fputs("__declspec", out);
+ ds_shown = true;
+ }
if(modifiers & DM_DLLIMPORT) {
fputs(next, out); next = ", "; fputs("dllimport", out);
}
if (modifiers & DM_DEPRECATED) {
fputs(next, out); next = ", "; fputs("deprecated", out);
if(declaration->deprecated_string != NULL)
- fprintf(out, "(\"%s\")", declaration->deprecated_string);
- }
- if(declaration->alignment != 0) {
- fputs(next, out); next = ", "; fprintf(out, "align(%u)", declaration->alignment);
+ fprintf(out, "(\"%s\")",
+ declaration->deprecated_string);
}
if(modifiers & DM_RESTRICT) {
fputs(next, out); next = ", "; fputs("restrict", out);
if(modifiers & DM_NOALIAS) {
fputs(next, out); next = ", "; fputs("noalias", out);
}
- if(declaration->get_property_sym != NULL || declaration->put_property_sym != NULL) {
- char *comma = "";
- fputs(next, out); next = ", "; fputs("property(", out);
- if(declaration->get_property_sym != NULL) {
- fprintf(out, "get=%s", declaration->get_property_sym->string);
- comma = ", ";
- }
- if(declaration->put_property_sym != NULL)
- fprintf(out, "%sput=%s", comma, declaration->put_property_sym->string);
- fputc(')', out);
- }
- fputs(") ", out);
}
+
+ if (ds_shown)
+ fputs(") ", out);
}
/**
- * Print a declaration in the NORMAL namespace.
- *
- * @param declaration the declaration
+ * Print a variable or function declaration
*/
-static void print_normal_declaration(const declaration_t *declaration)
+void print_declaration(const entity_t *entity)
{
+ assert(is_declaration(entity));
+ const declaration_t *declaration = &entity->declaration;
+
print_storage_class((storage_class_tag_t) declaration->declared_storage_class);
- if (declaration->is_inline) {
- if (declaration->modifiers & DM_FORCEINLINE) {
- fputs("__forceinline ", out);
- } else if (declaration->modifiers & DM_MICROSOFT_INLINE) {
- fputs("__inline ", out);
- } else {
- fputs("inline ", out);
+ if (entity->kind == ENTITY_FUNCTION) {
+ function_t *function = (function_t*) declaration;
+ if (function->is_inline) {
+ if (declaration->modifiers & DM_FORCEINLINE) {
+ fputs("__forceinline ", out);
+ } else if (declaration->modifiers & DM_MICROSOFT_INLINE) {
+ fputs("__inline ", out);
+ } else {
+ fputs("inline ", out);
+ }
}
}
print_ms_modifiers(declaration);
- print_type_ext(declaration->type, declaration->symbol,
- &declaration->scope);
+ if (entity->kind == ENTITY_FUNCTION) {
+ print_type_ext(entity->declaration.type, entity->base.symbol,
+ &entity->function.parameters);
- if(declaration->type->kind == TYPE_FUNCTION) {
- if(declaration->init.statement != NULL) {
+ if (entity->function.statement != NULL) {
fputs("\n", out);
print_indent();
- print_statement(declaration->init.statement);
+ print_statement(entity->function.statement);
return;
}
- } else if(declaration->init.initializer != NULL) {
- fputs(" = ", out);
- print_initializer(declaration->init.initializer);
+ } else {
+ print_type_ext(declaration->type, declaration->base.symbol, NULL);
+
+ if (entity->kind == ENTITY_VARIABLE
+ && entity->variable.initializer != NULL) {
+ fputs(" = ", out);
+ print_initializer(entity->variable.initializer);
+ }
}
fputc(';', out);
}
*
* @param declaration the declaration
*/
-void print_declaration(const declaration_t *declaration)
+void print_entity(const entity_t *entity)
{
- if (declaration->namespc != NAMESPACE_NORMAL &&
- declaration->symbol == NULL)
+ if (entity->base.namespc != NAMESPACE_NORMAL && entity->base.symbol == NULL)
return;
- switch (declaration->namespc) {
- case NAMESPACE_NORMAL:
- print_normal_declaration(declaration);
- break;
- case NAMESPACE_STRUCT:
+ switch ((entity_kind_tag_t) entity->kind) {
+ case ENTITY_VARIABLE:
+ case ENTITY_FUNCTION:
+ case ENTITY_COMPOUND_MEMBER:
+ print_declaration(entity);
+ return;
+ case ENTITY_TYPEDEF:
+ print_typedef(entity);
+ return;
+ case ENTITY_STRUCT:
fputs("struct ", out);
- fputs(declaration->symbol->string, out);
- if (declaration->init.complete) {
+ fputs(entity->base.symbol->string, out);
+ if (entity->structe.complete) {
fputc(' ', out);
- print_compound_definition(declaration);
+ print_compound_definition(&entity->structe);
}
fputc(';', out);
- break;
- case NAMESPACE_UNION:
+ return;
+ case ENTITY_UNION:
fputs("union ", out);
- fputs(declaration->symbol->string, out);
- if (declaration->init.complete) {
+ fputs(entity->base.symbol->string, out);
+ if (entity->unione.complete) {
fputc(' ', out);
- print_compound_definition(declaration);
+ print_compound_definition(&entity->unione);
}
fputc(';', out);
- break;
- case NAMESPACE_ENUM:
+ return;
+ case ENTITY_ENUM:
fputs("enum ", out);
- fputs(declaration->symbol->string, out);
- if (declaration->init.complete) {
- fputc(' ', out);
- print_enum_definition(declaration);
- }
+ fputs(entity->base.symbol->string, out);
+ fputc(' ', out);
+ print_enum_definition(&entity->enume);
fputc(';', out);
+ return;
+ case ENTITY_LABEL:
+ case ENTITY_ENUM_VALUE:
+ case ENTITY_LOCAL_LABEL:
+ panic("print_entity used on unexpected entity type");
+ case ENTITY_INVALID:
break;
}
+ panic("Invalid entity type encountered");
}
/**
{
inc_type_visited();
- declaration_t *declaration = unit->scope.declarations;
- for( ; declaration != NULL; declaration = declaration->next) {
- if(declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
+ entity_t *entity = unit->scope.entities;
+ for ( ; entity != NULL; entity = entity->base.next) {
+ if (entity->kind == ENTITY_ENUM_VALUE)
continue;
- if(declaration->namespc != NAMESPACE_NORMAL &&
- declaration->symbol == NULL)
+ if (entity->base.namespc != NAMESPACE_NORMAL
+ && entity->base.symbol == NULL)
continue;
- if (declaration->implicit)
+ if (is_generated_entity(entity))
continue;
print_indent();
- print_declaration(declaration);
+ print_entity(entity);
fputc('\n', out);
}
}
bool is_constant_initializer(const initializer_t *initializer)
{
- switch(initializer->kind) {
+ switch (initializer->kind) {
case INITIALIZER_STRING:
case INITIALIZER_WIDE_STRING:
case INITIALIZER_DESIGNATOR:
static bool is_object_with_linker_constant_address(const expression_t *expression)
{
- switch(expression->kind) {
+ switch (expression->kind) {
case EXPR_UNARY_DEREFERENCE:
return is_address_constant(expression->unary.value);
&& is_address_constant(expression->array_access.array_ref);
case EXPR_REFERENCE: {
- declaration_t *declaration = expression->reference.declaration;
- switch((storage_class_tag_t) declaration->storage_class) {
- case STORAGE_CLASS_NONE:
- case STORAGE_CLASS_EXTERN:
- case STORAGE_CLASS_STATIC:
- return true;
- default:
- return false;
+ entity_t *entity = expression->reference.entity;
+ if (is_declaration(entity)) {
+ switch ((storage_class_tag_t) entity->declaration.storage_class) {
+ case STORAGE_CLASS_NONE:
+ case STORAGE_CLASS_EXTERN:
+ case STORAGE_CLASS_STATIC:
+ return true;
+
+ case STORAGE_CLASS_REGISTER:
+ case STORAGE_CLASS_TYPEDEF:
+ case STORAGE_CLASS_AUTO:
+ case STORAGE_CLASS_THREAD:
+ case STORAGE_CLASS_THREAD_EXTERN:
+ case STORAGE_CLASS_THREAD_STATIC:
+ break;
+ }
}
+ return false;
}
default:
bool is_address_constant(const expression_t *expression)
{
- switch(expression->kind) {
+ switch (expression->kind) {
case EXPR_UNARY_TAKE_ADDRESS:
return is_object_with_linker_constant_address(expression->unary.value);
}
case EXPR_REFERENCE: {
- declaration_t *declaration = expression->reference.declaration;
- type_t *type = skip_typeref(declaration->type);
+ entity_t *entity = expression->reference.entity;
+ if (!is_declaration(entity))
+ return false;
+
+ type_t *type = skip_typeref(entity->declaration.type);
if(is_type_function(type))
return true;
if(is_type_array(type)) {
static bool is_object_with_constant_address(const expression_t *expression)
{
- switch(expression->kind) {
+ switch (expression->kind) {
case EXPR_SELECT: {
expression_t *compound = expression->select.compound;
type_t *compound_type = compound->base.type;
case EXPR_ALIGNOF:
case EXPR_BUILTIN_CONSTANT_P:
case EXPR_LABEL_ADDRESS:
+ case EXPR_REFERENCE_ENUM_VALUE:
return true;
case EXPR_SIZEOF: {
case EXPR_VA_START:
case EXPR_VA_ARG:
case EXPR_STATEMENT:
+ case EXPR_REFERENCE:
case EXPR_UNARY_POSTFIX_INCREMENT:
case EXPR_UNARY_POSTFIX_DECREMENT:
case EXPR_UNARY_PREFIX_INCREMENT:
return is_constant_expression(expression->conditional.false_expression);
}
- case EXPR_REFERENCE: {
- declaration_t *declaration = expression->reference.declaration;
- if(declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
- return true;
-
- return false;
- }
-
case EXPR_INVALID:
return true;
#include <stdio.h>
#include <stdbool.h>
-
-typedef struct scope_t scope_t;
+#include "entity.h"
typedef struct expression_base_t expression_base_t;
typedef struct const_expression_t const_expression_t;
typedef struct initializer_designator_t initializer_designator_t;
typedef union initializer_t initializer_t;
-typedef struct declaration_t declaration_t;
-
typedef struct statement_base_t statement_base_t;
typedef struct invalid_statement_t invalid_statement_t;
typedef struct empty_statement_t empty_statement_t;
typedef struct if_statement_t if_statement_t;
typedef struct switch_statement_t switch_statement_t;
typedef struct declaration_statement_t declaration_statement_t;
+typedef struct local_label_statement_t local_label_statement_t;
typedef struct expression_statement_t expression_statement_t;
typedef struct goto_statement_t goto_statement_t;
typedef struct label_statement_t label_statement_t;
void print_initializer(const initializer_t *initializer);
void print_ast(const translation_unit_t *unit);
void print_indent(void);
-void print_declaration(const declaration_t *declaration);
+void print_declaration(const entity_t *entity);
+void print_entity(const entity_t *entity);
void change_indent(int delta);
void *allocate_ast(size_t size);
#include "token_t.h"
#include "type_t.h"
#include "ast_t.h"
+#include "entity_t.h"
#include "parser.h"
#include "diagnostic.h"
#include "lang_features.h"
static ir_type *ir_type_void;
static ir_type *ir_type_int;
-static int next_value_number_function;
-static ir_node *continue_label;
-static ir_node *break_label;
-static ir_node *current_switch_cond;
-static bool saw_default_label;
-static declaration_t **all_labels;
-static declaration_t **inner_functions;
-static int inner_function_idx;
-static ir_node *ijmp_list;
-static bool constant_folding;
-
-extern bool have_const_functions;
-
-static const declaration_t *current_function_decl;
-static ir_node *current_function_name;
-static ir_node *current_funcsig;
-static switch_statement_t *current_switch;
-static ir_graph *current_function;
+static int next_value_number_function;
+static ir_node *continue_label;
+static ir_node *break_label;
+static ir_node *current_switch_cond;
+static bool saw_default_label;
+static label_t **all_labels;
+static entity_t **inner_functions;
+static ir_node *ijmp_list;
+static bool constant_folding;
+
+extern bool have_const_functions;
+
+static const entity_t *current_function_entity;
+static ir_node *current_function_name;
+static ir_node *current_funcsig;
+static switch_statement_t *current_switch;
+static ir_graph *current_function;
static entitymap_t entitymap;
typedef enum declaration_kind_t {
DECLARATION_KIND_UNKNOWN,
- DECLARATION_KIND_FUNCTION,
DECLARATION_KIND_VARIABLE_LENGTH_ARRAY,
DECLARATION_KIND_GLOBAL_VARIABLE,
DECLARATION_KIND_LOCAL_VARIABLE,
DECLARATION_KIND_LOCAL_VARIABLE_ENTITY,
+ DECLARATION_KIND_FUNCTION,
DECLARATION_KIND_COMPOUND_MEMBER,
- DECLARATION_KIND_LABEL_BLOCK,
- DECLARATION_KIND_ENUM_ENTRY,
- DECLARATION_KIND_COMPOUND_TYPE_INCOMPLETE,
- DECLARATION_KIND_COMPOUND_TYPE_COMPLETE,
- DECLARATION_KIND_TYPE,
DECLARATION_KIND_INNER_FUNCTION
} declaration_kind_t;
static ir_type *get_ir_type(type_t *type);
static ir_type *get_ir_type_incomplete(type_t *type);
-static void enqueue_inner_function(declaration_t *declaration) {
- if (inner_functions == NULL) {
- inner_functions = NEW_ARR_F(declaration_t *, 16);
- inner_functions[0] = declaration;
- inner_function_idx = 1;
- } else {
- int size = ARR_LEN(inner_functions);
- if (inner_function_idx >= size) {
- ARR_RESIZE(declaration_t *, inner_functions, size + 16);
- }
- inner_functions[inner_function_idx++] = declaration;
- }
+static void enqueue_inner_function(entity_t *entity)
+{
+ ARR_APP1(entity_t*, inner_functions, entity);
}
-static declaration_t *next_inner_function(void) {
- if (inner_function_idx == 0)
- return 0;
- return inner_functions[--inner_function_idx];
+static entity_t *next_inner_function(void)
+{
+ int len = ARR_LEN(inner_functions);
+ if (len == 0)
+ return NULL;
+
+ entity_t *entity = inner_functions[len-1];
+ ARR_SHRINKLEN(inner_functions, len-1);
+
+ return entity;
}
ir_node *uninitialized_local_var(ir_graph *irg, ir_mode *mode, int pos)
{
- const declaration_t *declaration = get_irg_loc_description(irg, pos);
+ const variable_t *variable = get_irg_loc_description(irg, pos);
- if (declaration != NULL) {
- warningf(&declaration->source_position,
+ if (variable != NULL) {
+ warningf(&variable->base.base.source_position,
"variable '%#T' might be used uninitialized",
- declaration->type, declaration->symbol);
+ variable->base.type, variable->base.base.symbol);
}
return new_r_Unknown(irg, mode);
}
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(declaration_t *declaration);
+static void create_local_declaration(entity_t *entity);
static ir_mode *init_atomic_ir_mode(atomic_type_kind_t kind)
{
*/
static void init_atomic_modes(void)
{
- for(int i = 0; i <= ATOMIC_TYPE_LAST; ++i) {
+ for (int i = 0; i <= ATOMIC_TYPE_LAST; ++i) {
_atomic_modes[i] = init_atomic_ir_mode((atomic_type_kind_t) i);
}
mode_int = _atomic_modes[ATOMIC_TYPE_INT];
{
type = skip_typeref(type);
if (type->base.modifiers & TYPE_MODIFIER_TRANSPARENT_UNION) {
- declaration_t *decl = type->compound.declaration;
- type = decl->scope.declarations->type;
+ compound_t *compound = type->compound.compound;
+ type = compound->members.entities->declaration.type;
}
return type;
static ir_type *create_method_type(const function_type_t *function_type)
{
- type_t *return_type = function_type->return_type;
+ type_t *return_type = skip_typeref(function_type->return_type);
ident *id = id_unique("functiontype.%u");
int n_parameters = count_parameters(function_type);
size_t *outer_offset, size_t *outer_align,
bool incomplete, bool is_union)
{
- declaration_t *declaration = type->declaration;
- declaration_kind_t kind = (declaration_kind_t)declaration->declaration_kind;
+ compound_t *compound = type->compound;
- if (kind == DECLARATION_KIND_COMPOUND_TYPE_COMPLETE
- || (kind == DECLARATION_KIND_COMPOUND_TYPE_INCOMPLETE
- && incomplete))
- return declaration->v.irtype;
+ if (compound->irtype != NULL && (compound->irtype_complete || incomplete)) {
+ return compound->irtype;
+ }
size_t align_all = 1;
size_t offset = 0;
size_t size = 0;
if (irtype == NULL) {
- symbol_t *symbol = declaration->symbol;
+ symbol_t *symbol = compound->base.symbol;
ident *id;
if (symbol != NULL) {
id = new_id_from_str(symbol->string);
id = id_unique("__anonymous_struct.%u");
}
}
- dbg_info *dbgi = get_dbg_info(&declaration->source_position);
+ dbg_info *dbgi = get_dbg_info(&compound->base.source_position);
if (is_union) {
irtype = new_d_type_union(id, dbgi);
irtype = new_d_type_struct(id, dbgi);
}
- declaration->declaration_kind
- = DECLARATION_KIND_COMPOUND_TYPE_INCOMPLETE;
- declaration->v.irtype = irtype;
- //type->base.firm_type = irtype;
+ compound->irtype_complete = false;
+ compound->irtype = irtype;
} else {
offset = *outer_offset;
align_all = *outer_align;
if (incomplete)
return irtype;
- declaration->declaration_kind = DECLARATION_KIND_COMPOUND_TYPE_COMPLETE;
+ compound->irtype_complete = true;
- declaration_t *entry = declaration->scope.declarations;
- for( ; entry != NULL; entry = entry->next) {
- if (entry->namespc != NAMESPACE_NORMAL)
+ entity_t *entry = compound->members.entities;
+ for ( ; entry != NULL; entry = entry->base.next) {
+ if (entry->kind != ENTITY_COMPOUND_MEMBER)
continue;
size_t prev_offset = offset;
- symbol_t *symbol = entry->symbol;
- type_t *entry_type = skip_typeref(entry->type);
- dbg_info *dbgi = get_dbg_info(&entry->source_position);
+ symbol_t *symbol = entry->base.symbol;
+ type_t *entry_type = skip_typeref(entry->declaration.type);
+ dbg_info *dbgi = get_dbg_info(&entry->base.source_position);
ident *ident;
if (symbol != NULL) {
set_entity_offset_bits_remainder(entity,
(unsigned char) bits_remainder);
//add_struct_member(irtype, entity);
- entry->declaration_kind = DECLARATION_KIND_COMPOUND_MEMBER;
- assert(entry->v.entity == NULL);
- entry->v.entity = entity;
+ entry->declaration.kind = DECLARATION_KIND_COMPOUND_MEMBER;
+ assert(entry->compound_member.entity == NULL);
+ entry->compound_member.entity = entity;
finished_member:
if (is_union) {
bool constant_folding_old = constant_folding;
constant_folding = true;
- declaration_t *declaration = type->declaration->next;
- for (; declaration != NULL; declaration = declaration->next) {
- if (declaration->storage_class != STORAGE_CLASS_ENUM_ENTRY)
+ enum_t *enume = type->enume;
+ entity_t *entry = enume->base.next;
+ for (; entry != NULL; entry = entry->base.next) {
+ if (entry->kind != ENTITY_ENUM_VALUE)
break;
- declaration->declaration_kind = DECLARATION_KIND_ENUM_ENTRY;
-
- expression_t *const init = declaration->init.enum_value;
+ expression_t *const init = entry->enum_value.value;
if (init != NULL) {
ir_node *const cnst = expression_to_firm(init);
if (!is_Const(cnst)) {
}
tv_next = get_Const_tarval(cnst);
}
- declaration->v.enum_val = tv_next;
+ entry->enum_value.tv = tv_next;
tv_next = tarval_add(tv_next, one);
}
* @param ent the entity to be mangled
* @param declaration the declaration
*/
-static ident *create_ld_ident_win32(ir_entity *ent, declaration_t *declaration)
+static ident *create_ld_ident_win32(ir_entity *irentity, entity_t *entity)
{
ident *id;
- if (is_Method_type(get_entity_type(ent)))
- id = decorate_win32_c_fkt(ent, get_entity_ident(ent));
+ 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(ent));
+ id = mangle(id_underscore, get_entity_ident(irentity));
}
- decl_modifiers_t decl_modifiers = declaration->modifiers;
+ 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);
* @param ent the entity to be mangled
* @param declaration the declaration
*/
-static ident *create_ld_ident_linux_elf(ir_entity *entity,
- declaration_t *declaration)
+static ident *create_ld_ident_linux_elf(ir_entity *irentity, entity_t *entity)
{
- (void) declaration;
- return get_entity_ident(entity);
+ (void) entity;
+ return get_entity_ident(irentity);
}
/**
* @param ent the entity to be mangled
* @param declaration the declaration
*/
-static ident *create_ld_ident_macho(ir_entity *ent, declaration_t *declaration)
+static ident *create_ld_ident_macho(ir_entity *irentity, entity_t *entity)
{
- (void) declaration;
- ident *id = mangle(id_underscore, get_entity_ident(ent));
+ (void) entity;
+ ident *id = mangle(id_underscore, get_entity_ident(irentity));
return id;
}
-typedef ident* (*create_ld_ident_func)(ir_entity *entity,
- declaration_t *declaration);
-create_ld_ident_func create_ld_ident = create_ld_ident_linux_elf;
+typedef ident* (*create_ld_ident_func)(ir_entity *irentity, entity_t *entity);
+create_ld_ident_func create_ld_ident = create_ld_ident_linux_elf;
/**
* Handle GNU attributes for entities
* @param ent the entity
* @param decl the routine declaration
*/
-static void handle_gnu_attributes_ent(ir_entity *ent, declaration_t *decl)
+static void handle_gnu_attributes_ent(ir_entity *irentity, entity_t *entity)
{
- if (decl->modifiers & DM_PURE) {
+ assert(is_declaration(entity));
+ decl_modifiers_t modifiers = entity->declaration.modifiers;
+ if (modifiers & DM_PURE) {
/* TRUE if the declaration includes the GNU
__attribute__((pure)) specifier. */
- set_entity_additional_property(ent, mtp_property_pure);
+ set_entity_additional_property(irentity, mtp_property_pure);
}
- if (decl->modifiers & DM_CONST) {
- set_entity_additional_property(ent, mtp_property_const);
+ if (modifiers & DM_CONST) {
+ set_entity_additional_property(irentity, mtp_property_const);
have_const_functions = true;
}
- if (decl->modifiers & DM_USED) {
+ if (modifiers & DM_USED) {
/* TRUE if the declaration includes the GNU
__attribute__((used)) specifier. */
- set_entity_stickyness(ent, stickyness_sticky);
+ set_entity_stickyness(irentity, stickyness_sticky);
}
}
*
* @param declaration the function declaration
*/
-static ir_entity *get_function_entity(declaration_t *declaration)
+static ir_entity *get_function_entity(entity_t *entity)
{
- if (declaration->declaration_kind == DECLARATION_KIND_FUNCTION ||
- declaration->declaration_kind == DECLARATION_KIND_INNER_FUNCTION)
- return declaration->v.entity;
- assert(declaration->declaration_kind == DECLARATION_KIND_UNKNOWN);
+ assert(entity->kind == ENTITY_FUNCTION);
+ if (entity->function.entity != NULL) {
+ return entity->function.entity;
+ }
- symbol_t *symbol = declaration->symbol;
+ symbol_t *symbol = entity->base.symbol;
ident *id = new_id_from_str(symbol->string);
- ir_type *global_type = get_glob_type();
- ir_type *ir_type_method = get_ir_type(declaration->type);
- assert(is_Method_type(ir_type_method));
+ ir_type *global_type = get_glob_type();
+ ir_type *ir_type_method = get_ir_type(entity->declaration.type);
+ bool const has_body = entity->function.statement != NULL;
/* already an entity defined? */
- ir_entity *entity = entitymap_get(&entitymap, symbol);
- if (entity != NULL) {
- if (get_entity_visibility(entity) == visibility_external_allocated
- && declaration->init.statement != NULL) {
- set_entity_visibility(entity, visibility_external_visible);
+ ir_entity *irentity = entitymap_get(&entitymap, symbol);
+ if (irentity != NULL) {
+ if (get_entity_visibility(irentity) == visibility_external_allocated
+ && has_body) {
+ set_entity_visibility(irentity, visibility_external_visible);
}
goto entity_created;
}
- dbg_info *const dbgi = get_dbg_info(&declaration->source_position);
- entity = new_d_entity(global_type, id, ir_type_method, dbgi);
- set_entity_ld_ident(entity, create_ld_ident(entity, declaration));
+ 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));
- handle_gnu_attributes_ent(entity, declaration);
+ handle_gnu_attributes_ent(irentity, entity);
/* static inline => local
* extern inline => local
* inline without definition => local
* inline with definition => external_visible */
- storage_class_tag_t const storage_class = (storage_class_tag_t)declaration->storage_class;
- bool const is_inline = declaration->is_inline;
- bool const has_body = declaration->init.statement != NULL;
+ storage_class_tag_t const storage_class
+ = (storage_class_tag_t) entity->declaration.storage_class;
+ bool const is_inline = entity->function.is_inline;
if (is_inline && storage_class == STORAGE_CLASS_NONE && has_body) {
- set_entity_visibility(entity, visibility_external_visible);
+ set_entity_visibility(irentity, visibility_external_visible);
} else if (storage_class == STORAGE_CLASS_STATIC ||
(is_inline && has_body)) {
if (!has_body) {
/* this entity was declared, but is defined nowhere */
- set_entity_peculiarity(entity, peculiarity_description);
+ set_entity_peculiarity(irentity, peculiarity_description);
}
- set_entity_visibility(entity, visibility_local);
+ set_entity_visibility(irentity, visibility_local);
} else if (has_body) {
- set_entity_visibility(entity, visibility_external_visible);
+ set_entity_visibility(irentity, visibility_external_visible);
} else {
- set_entity_visibility(entity, visibility_external_allocated);
+ set_entity_visibility(irentity, visibility_external_allocated);
}
- set_entity_allocation(entity, allocation_static);
+ set_entity_allocation(irentity, allocation_static);
/* We should check for file scope here, but as long as we compile C only
this is not needed. */
if ((c_mode & rts_data[i].flags) == 0)
continue;
assert(rts_entities[rts_data[i].id] == NULL);
- rts_entities[rts_data[i].id] = entity;
+ rts_entities[rts_data[i].id] = irentity;
}
}
- entitymap_insert(&entitymap, symbol, entity);
+ entitymap_insert(&entitymap, symbol, irentity);
entity_created:
- declaration->declaration_kind = DECLARATION_KIND_FUNCTION;
- declaration->v.entity = entity;
+ entity->declaration.kind = DECLARATION_KIND_FUNCTION;
+ entity->function.entity = irentity;
- return entity;
+ return irentity;
}
/**
set_type_state(type, layout_fixed);
tarval **const tvs = xmalloc(slen * sizeof(tvs[0]));
- for(size_t i = 0; i < slen; ++i) {
+ for (size_t i = 0; i < slen; ++i) {
tvs[i] = new_tarval_from_long(string[i], mode);
}
set_type_state(type, layout_fixed);
tarval **const tvs = xmalloc(slen * sizeof(tvs[0]));
- for(size_t i = 0; i < slen; ++i) {
+ for (size_t i = 0; i < slen; ++i) {
tvs[i] = new_tarval_from_long(string[i], mode);
}
}
static ir_node *get_global_var_address(dbg_info *const dbgi,
- const declaration_t *const decl)
+ const entity_t *const entity)
{
- assert(decl->declaration_kind == DECLARATION_KIND_GLOBAL_VARIABLE);
+ assert(entity->kind == ENTITY_VARIABLE);
+ assert(entity->declaration.kind == DECLARATION_KIND_GLOBAL_VARIABLE);
- ir_entity *const entity = decl->v.entity;
- switch ((storage_class_tag_t)decl->storage_class) {
+ ir_entity *const irentity = entity->variable.v.entity;
+ switch ((storage_class_tag_t) entity->declaration.storage_class) {
case STORAGE_CLASS_THREAD:
case STORAGE_CLASS_THREAD_EXTERN:
case STORAGE_CLASS_THREAD_STATIC: {
ir_node *const no_mem = new_NoMem();
ir_node *const tls = get_irg_tls(current_ir_graph);
- return new_d_simpleSel(dbgi, no_mem, tls, entity);
+ return new_d_simpleSel(dbgi, no_mem, tls, irentity);
}
default:
- return create_symconst(dbgi, mode_P_data, entity);
+ return create_symconst(dbgi, mode_P_data, irentity);
}
}
set_cur_block(old);
}
+static ir_node *reference_expression_enum_value_to_firm(
+ const reference_expression_t *ref)
+{
+ entity_t *entity = ref->entity;
+ type_t *type = skip_typeref(entity->enum_value.enum_type);
+ /* make sure the type is constructed */
+ (void) get_ir_type(type);
+
+ ir_mode *const mode = get_ir_mode(type);
+ return new_Const(mode, entity->enum_value.tv);
+}
+
static ir_node *reference_expression_to_firm(const reference_expression_t *ref)
{
- dbg_info *dbgi = get_dbg_info(&ref->base.source_position);
- declaration_t *declaration = ref->declaration;
- type_t *type = skip_typeref(declaration->type);
+ dbg_info *dbgi = get_dbg_info(&ref->base.source_position);
+ entity_t *entity = ref->entity;
+ assert(is_declaration(entity));
+ type_t *type = skip_typeref(entity->declaration.type);
/* make sure the type is constructed */
(void) get_ir_type(type);
- switch ((declaration_kind_t)declaration->declaration_kind) {
- case DECLARATION_KIND_TYPE:
+ switch ((declaration_kind_t) entity->declaration.kind) {
case DECLARATION_KIND_UNKNOWN:
break;
- case DECLARATION_KIND_ENUM_ENTRY: {
- ir_mode *const mode = get_ir_mode(type);
- return new_Const(mode, declaration->v.enum_val);
- }
-
case DECLARATION_KIND_LOCAL_VARIABLE: {
ir_mode *const mode = get_ir_mode(type);
- return get_value(declaration->v.value_number, mode);
+ return get_value(entity->variable.v.value_number, mode);
}
case DECLARATION_KIND_FUNCTION: {
ir_mode *const mode = get_ir_mode(type);
- return create_symconst(dbgi, mode, declaration->v.entity);
+ return create_symconst(dbgi, mode, entity->function.entity);
}
case DECLARATION_KIND_INNER_FUNCTION: {
ir_mode *const mode = get_ir_mode(type);
- if (! declaration->goto_to_outer && !declaration->need_closure) {
+ if (!entity->function.goto_to_outer && !entity->function.need_closure) {
/* inner function not using the closure */
- return create_symconst(dbgi, mode, declaration->v.entity);
+ return create_symconst(dbgi, mode, entity->function.entity);
} else {
/* TODO: need trampoline here */
panic("Trampoline code not implemented");
- return create_symconst(dbgi, mode, declaration->v.entity);
+ return create_symconst(dbgi, mode, entity->function.entity);
}
}
case DECLARATION_KIND_GLOBAL_VARIABLE: {
- ir_node *const addr = get_global_var_address(dbgi, declaration);
- return deref_address(dbgi, declaration->type, addr);
+ ir_node *const addr = get_global_var_address(dbgi, entity);
+ return deref_address(dbgi, entity->declaration.type, addr);
}
case DECLARATION_KIND_LOCAL_VARIABLE_ENTITY: {
- ir_entity *entity = declaration->v.entity;
- ir_node *frame = get_local_frame(entity);
- ir_node *sel = new_d_simpleSel(dbgi, new_NoMem(), frame, entity);
- return deref_address(dbgi, declaration->type, sel);
+ ir_entity *irentity = entity->variable.v.entity;
+ ir_node *frame = get_local_frame(irentity);
+ ir_node *sel = new_d_simpleSel(dbgi, new_NoMem(), frame, irentity);
+ return deref_address(dbgi, entity->declaration.type, sel);
}
case DECLARATION_KIND_VARIABLE_LENGTH_ARRAY:
- return declaration->v.vla_base;
+ return entity->variable.v.vla_base;
- case DECLARATION_KIND_COMPOUND_TYPE_INCOMPLETE:
- case DECLARATION_KIND_COMPOUND_TYPE_COMPLETE:
case DECLARATION_KIND_COMPOUND_MEMBER:
- case DECLARATION_KIND_LABEL_BLOCK:
panic("not implemented reference type");
}
static ir_node *reference_addr(const reference_expression_t *ref)
{
- dbg_info *dbgi = get_dbg_info(&ref->base.source_position);
- declaration_t *declaration = ref->declaration;
+ dbg_info *dbgi = get_dbg_info(&ref->base.source_position);
+ entity_t *entity = ref->entity;
+ assert(is_declaration(entity));
- switch((declaration_kind_t) declaration->declaration_kind) {
- case DECLARATION_KIND_TYPE:
+ switch((declaration_kind_t) entity->declaration.kind) {
case DECLARATION_KIND_UNKNOWN:
break;
case DECLARATION_KIND_LOCAL_VARIABLE:
* as an indicator for no real address) */
return NULL;
case DECLARATION_KIND_GLOBAL_VARIABLE: {
- ir_node *const addr = get_global_var_address(dbgi, declaration);
+ ir_node *const addr = get_global_var_address(dbgi, entity);
return addr;
}
case DECLARATION_KIND_LOCAL_VARIABLE_ENTITY: {
- ir_entity *entity = declaration->v.entity;
- ir_node *frame = get_local_frame(entity);
- ir_node *sel = new_d_simpleSel(dbgi, new_NoMem(), frame, entity);
+ ir_entity *irentity = entity->variable.v.entity;
+ ir_node *frame = get_local_frame(irentity);
+ ir_node *sel = new_d_simpleSel(dbgi, new_NoMem(), frame, irentity);
return sel;
}
case DECLARATION_KIND_VARIABLE_LENGTH_ARRAY:
- return declaration->v.vla_base;
-
- case DECLARATION_KIND_ENUM_ENTRY:
- panic("trying to reference enum entry");
+ return entity->variable.v.vla_base;
case DECLARATION_KIND_FUNCTION: {
- type_t *const type = skip_typeref(declaration->type);
+ type_t *const type = skip_typeref(entity->declaration.type);
ir_mode *const mode = get_ir_mode(type);
- return create_symconst(dbgi, mode, declaration->v.entity);
+ return create_symconst(dbgi, mode, entity->function.entity);
}
case DECLARATION_KIND_INNER_FUNCTION:
- case DECLARATION_KIND_COMPOUND_TYPE_INCOMPLETE:
- case DECLARATION_KIND_COMPOUND_TYPE_COMPLETE:
case DECLARATION_KIND_COMPOUND_MEMBER:
- case DECLARATION_KIND_LABEL_BLOCK:
panic("not implemented reference type");
}
return process_builtin_call(call);
}
if (function->kind == EXPR_REFERENCE) {
- const reference_expression_t *ref = &function->reference;
- declaration_t *declaration = ref->declaration;
-
- if ((declaration_kind_t)declaration->declaration_kind == DECLARATION_KIND_FUNCTION) {
- if (declaration->v.entity == rts_entities[rts_alloca]) {
- /* handle alloca() call */
- expression_t *argument = call->arguments->expression;
- ir_node *size = expression_to_firm(argument);
-
- size = create_conv(dbgi, size, get_ir_mode(type_size_t));
-
- ir_node *store = get_store();
- dbg_info *dbgi = get_dbg_info(&call->base.source_position);
- ir_node *alloca = new_d_Alloc(dbgi, store, size, firm_unknown_type,
- stack_alloc);
- ir_node *proj_m = new_Proj(alloca, mode_M, pn_Alloc_M);
- set_store(proj_m);
- ir_node *res = new_Proj(alloca, mode_P_data, pn_Alloc_res);
-
- return res;
- }
+ const reference_expression_t *ref = &function->reference;
+ entity_t *entity = ref->entity;
+
+ if (entity->kind == ENTITY_FUNCTION
+ && entity->function.entity == rts_entities[rts_alloca]) {
+ /* handle alloca() call */
+ expression_t *argument = call->arguments->expression;
+ ir_node *size = expression_to_firm(argument);
+
+ size = create_conv(dbgi, size, get_ir_mode(type_size_t));
+
+ ir_node *store = get_store();
+ dbg_info *dbgi = get_dbg_info(&call->base.source_position);
+ ir_node *alloca = new_d_Alloc(dbgi, store, size, firm_unknown_type,
+ stack_alloc);
+ ir_node *proj_m = new_Proj(alloca, mode_M, pn_Alloc_M);
+ set_store(proj_m);
+ ir_node *res = new_Proj(alloca, mode_P_data, pn_Alloc_res);
+
+ return res;
}
}
ir_node *callee = expression_to_firm(function);
ir_type *new_method_type = NULL;
if (function_type->variadic || function_type->unspecified_parameters) {
const call_argument_t *argument = call->arguments;
- for( ; argument != NULL; argument = argument->next) {
+ for ( ; argument != NULL; argument = argument->next) {
++n_parameters;
}
set_method_variadicity(new_method_type,
get_method_variadicity(ir_method_type));
- for(int i = 0; i < n_res; ++i) {
+ for (int i = 0; i < n_res; ++i) {
set_method_res_type(new_method_type, i,
get_method_res_type(ir_method_type, i));
}
argument = call->arguments;
- for(int i = 0; i < n_parameters; ++i, argument = argument->next) {
+ for (int i = 0; i < n_parameters; ++i, argument = argument->next) {
expression_t *expression = argument->expression;
ir_type *irtype = get_ir_type(expression->base.type);
set_method_param_type(new_method_type, i, irtype);
ir_node *in[n_parameters];
const call_argument_t *argument = call->arguments;
- for(int n = 0; n < n_parameters; ++n) {
+ for (int n = 0; n < n_parameters; ++n) {
expression_t *expression = argument->expression;
ir_node *arg_node = expression_to_firm(expression);
}
if (function->kind == EXPR_REFERENCE &&
- function->reference.declaration->modifiers & DM_NORETURN) {
+ function->reference.entity->declaration.modifiers & DM_NORETURN) {
/* A dead end: Keep the Call and the Block. Also place all further
* nodes into a new and unreachable block. */
keep_alive(node);
set_store(load_mem);
/* kill upper bits */
- ir_entity *entity = expression->compound_entry->v.entity;
+ assert(expression->compound_entry->kind == ENTITY_COMPOUND_MEMBER);
+ ir_entity *entity = expression->compound_entry->compound_member.entity;
int bitoffset = get_entity_offset_bits_remainder(entity);
ir_type *entity_type = get_entity_type(entity);
int bitsize = get_mode_size_bits(get_type_mode(entity_type));
return create_conv(dbgi, shiftr, mode);
}
+/* make sure the selected compound type is constructed */
+static void construct_select_compound(const select_expression_t *expression)
+{
+ type_t *type = skip_typeref(expression->compound->base.type);
+ if (is_type_pointer(type)) {
+ type = type->pointer.points_to;
+ }
+ (void) get_ir_type(type);
+}
+
static void set_value_for_expression_addr(const expression_t *expression,
ir_node *value, ir_node *addr)
{
if (expression->kind == EXPR_REFERENCE) {
const reference_expression_t *ref = &expression->reference;
- declaration_t *declaration = ref->declaration;
- assert(declaration->declaration_kind != DECLARATION_KIND_UNKNOWN);
- if (declaration->declaration_kind == DECLARATION_KIND_LOCAL_VARIABLE) {
- set_value(declaration->v.value_number, value);
+ entity_t *entity = ref->entity;
+ assert(is_declaration(entity));
+ assert(entity->declaration.kind != DECLARATION_KIND_UNKNOWN);
+ if (entity->declaration.kind == DECLARATION_KIND_LOCAL_VARIABLE) {
+ set_value(entity->variable.v.value_number, value);
return;
}
}
if (expression->kind == EXPR_SELECT) {
const select_expression_t *select = &expression->select;
- declaration_t *declaration = select->compound_entry;
- if (declaration->type->kind == TYPE_BITFIELD) {
- ir_entity *entity = select->compound_entry->v.entity;
+ construct_select_compound(select);
+
+ entity_t *entity = select->compound_entry;
+ assert(entity->kind == ENTITY_COMPOUND_MEMBER);
+ if (entity->declaration.type->kind == TYPE_BITFIELD) {
+ ir_entity *irentity = entity->compound_member.entity;
bool set_volatile
= select->base.type->base.qualifiers & TYPE_QUALIFIER_VOLATILE;
- bitfield_store_to_firm(dbgi, entity, addr, value, set_volatile);
+ bitfield_store_to_firm(dbgi, irentity, addr, value, set_volatile);
return;
}
}
if (expression->kind == EXPR_REFERENCE) {
const reference_expression_t *ref = &expression->reference;
- declaration_t *declaration = ref->declaration;
- assert(declaration->declaration_kind != DECLARATION_KIND_UNKNOWN);
- if (declaration->declaration_kind == DECLARATION_KIND_LOCAL_VARIABLE) {
+ entity_t *entity = ref->entity;
+ assert(entity->kind == ENTITY_VARIABLE);
+ assert(entity->declaration.kind != DECLARATION_KIND_UNKNOWN);
+ if (entity->declaration.kind == DECLARATION_KIND_LOCAL_VARIABLE) {
assert(addr == NULL);
ir_mode *mode = get_ir_mode(expression->base.type);
- return get_value(declaration->v.value_number, mode);
+ return get_value(entity->variable.v.value_number, mode);
}
}
ir_node *value;
if (expression->kind == EXPR_SELECT &&
- expression->select.compound_entry->type->kind == TYPE_BITFIELD){
+ expression->select.compound_entry->declaration.type->kind == TYPE_BITFIELD){
+ construct_select_compound(&expression->select);
value = bitfield_extract_to_firm(&expression->select, addr);
} else {
value = deref_address(dbgi, expression->base.type, addr);
{
if (expression->kind != EXPR_REFERENCE)
return false;
- reference_expression_t *ref_expr = &expression->reference;
- declaration_t *declaration = ref_expr->declaration;
- return declaration->declaration_kind == DECLARATION_KIND_LOCAL_VARIABLE;
+ reference_expression_t *ref_expr = &expression->reference;
+ entity_t *entity = ref_expr->entity;
+ if (entity->kind != ENTITY_VARIABLE)
+ return false;
+ assert(entity->declaration.kind != DECLARATION_KIND_UNKNOWN);
+ return entity->declaration.kind == DECLARATION_KIND_LOCAL_VARIABLE;
}
static pn_Cmp get_pnc(const expression_kind_t kind, type_t *const type)
static ir_node *handle_assume_compare(dbg_info *dbi,
const binary_expression_t *expression)
{
- expression_t *op1 = expression->left;
- expression_t *op2 = expression->right;
- declaration_t *var2, *var = NULL;
- ir_node *res = NULL;
- pn_Cmp cmp_val;
+ expression_t *op1 = expression->left;
+ expression_t *op2 = expression->right;
+ entity_t *var2, *var = NULL;
+ ir_node *res = NULL;
+ pn_Cmp cmp_val;
cmp_val = get_pnc(expression->base.kind, op1->base.type);
if (is_local_variable(op1) && is_local_variable(op2)) {
- var = op1->reference.declaration;
- var2 = op2->reference.declaration;
+ var = op1->reference.entity;
+ var2 = op2->reference.entity;
- type_t *const type = skip_typeref(var->type);
+ type_t *const type = skip_typeref(var->declaration.type);
ir_mode *const mode = get_ir_mode(type);
- ir_node *const irn1 = get_value(var->v.value_number, mode);
- ir_node *const irn2 = get_value(var2->v.value_number, mode);
+ ir_node *const irn1 = get_value(var->variable.v.value_number, mode);
+ ir_node *const irn2 = get_value(var2->variable.v.value_number, mode);
res = new_d_Confirm(dbi, irn2, irn1, get_inversed_pnc(cmp_val));
- set_value(var2->v.value_number, res);
+ set_value(var2->variable.v.value_number, res);
res = new_d_Confirm(dbi, irn1, irn2, cmp_val);
- set_value(var->v.value_number, res);
+ set_value(var->variable.v.value_number, res);
return res;
}
expression_t *con;
if (is_local_variable(op1) && is_constant_expression(op2)) {
- var = op1->reference.declaration;
+ var = op1->reference.entity;
con = op2;
} else if (is_constant_expression(op1) && is_local_variable(op2)) {
cmp_val = get_inversed_pnc(cmp_val);
- var = op2->reference.declaration;
+ var = op2->reference.entity;
con = op1;
}
if (var != NULL) {
- type_t *const type = skip_typeref(var->type);
+ type_t *const type = skip_typeref(var->declaration.type);
ir_mode *const mode = get_ir_mode(type);
- res = get_value(var->v.value_number, mode);
+ res = get_value(var->variable.v.value_number, mode);
res = new_d_Confirm(dbi, res, expression_to_firm(con), cmp_val);
- set_value(var->v.value_number, res);
+ set_value(var->variable.v.value_number, res);
}
return res;
}
long offset = 0;
designator_t *designator = expression->designator;
- for( ; designator != NULL; designator = designator->next) {
+ for ( ; designator != NULL; designator = designator->next) {
type_t *type = skip_typeref(orig_type);
/* be sure the type is constructed */
(void) get_ir_type(type);
assert(is_type_compound(type));
symbol_t *symbol = designator->symbol;
- declaration_t *declaration = type->compound.declaration;
- declaration_t *iter = declaration->scope.declarations;
- for( ; iter != NULL; iter = iter->next) {
- if (iter->symbol == symbol) {
+ compound_t *compound = type->compound.compound;
+ entity_t *iter = compound->members.entities;
+ for ( ; iter != NULL; iter = iter->base.next) {
+ if (iter->base.symbol == symbol) {
break;
}
}
assert(iter != NULL);
- assert(iter->declaration_kind == DECLARATION_KIND_COMPOUND_MEMBER);
- offset += get_entity_offset(iter->v.entity);
+ assert(iter->kind == ENTITY_COMPOUND_MEMBER);
+ assert(iter->declaration.kind == DECLARATION_KIND_COMPOUND_MEMBER);
+ offset += get_entity_offset(iter->compound_member.entity);
- orig_type = iter->type;
+ orig_type = iter->declaration.type;
} else {
expression_t *array_index = designator->array_index;
assert(designator->array_index != NULL);
/* beware: if expression is a variable reference, return the
alignment of the variable. */
const expression_t *tp_expression = expression->tp_expression;
- const declaration_t *declaration = expr_is_variable(tp_expression);
- if (declaration != NULL) {
+ const entity_t *entity = expression_is_variable(tp_expression);
+ if (entity != NULL) {
/* TODO: get the alignment of this variable. */
+ (void) entity;
}
type = tp_expression->base.type;
assert(type != NULL);
{
dbg_info *dbgi = get_dbg_info(&expression->base.source_position);
- ir_node *compound_addr = expression_to_firm(expression->compound);
+ construct_select_compound(expression);
- /* make sure the type is constructed */
- type_t *type = skip_typeref(expression->compound->base.type);
- if (is_type_pointer(type)) {
- type = type->pointer.points_to;
- }
- (void) get_ir_type(type);
+ ir_node *compound_addr = expression_to_firm(expression->compound);
- declaration_t *entry = expression->compound_entry;
- assert(entry->declaration_kind == DECLARATION_KIND_COMPOUND_MEMBER);
- ir_entity *entity = entry->v.entity;
+ entity_t *entry = expression->compound_entry;
+ assert(entry->kind == ENTITY_COMPOUND_MEMBER);
+ assert(entry->declaration.kind == DECLARATION_KIND_COMPOUND_MEMBER);
+ ir_entity *irentity = entry->compound_member.entity;
- assert(entity != NULL);
+ assert(irentity != NULL);
- ir_node *sel = new_d_simpleSel(dbgi, new_NoMem(), compound_addr, entity);
+ ir_node *sel = new_d_simpleSel(dbgi, new_NoMem(), compound_addr, irentity);
return sel;
}
(const expression_t*) expression);
type = skip_typeref(type);
- declaration_t *entry = expression->compound_entry;
- type_t *entry_type = skip_typeref(entry->type);
+ entity_t *entry = expression->compound_entry;
+ assert(entry->kind == ENTITY_COMPOUND_MEMBER);
+ type_t *entry_type = skip_typeref(entry->declaration.type);
if (entry_type->kind == TYPE_BITFIELD) {
return bitfield_extract_to_firm(expression, addr);
case FUNCNAME_FUNCDNAME:
if (current_function_name == NULL) {
const source_position_t *const src_pos = &expr->base.source_position;
- const char *const name = current_function_decl->symbol->string;
+ const char *name = current_function_entity->base.symbol->string;
const string_t string = { name, strlen(name) + 1 };
current_function_name = string_to_firm(src_pos, "__func__.%u", &string);
}
static ir_node *va_start_expression_to_firm(
const va_start_expression_t *const expr)
{
- ir_type *const method_type = get_ir_type(current_function_decl->type);
+ type_t *const type = current_function_entity->declaration.type;
+ ir_type *const method_type = get_ir_type(type);
int const n = get_method_n_params(method_type) - 1;
ir_entity *const parm_ent = get_method_value_param_ent(method_type, n);
ir_node *const arg_base = get_irg_value_param_base(current_ir_graph);
ir_node *const arg_sel =
new_d_simpleSel(dbgi, no_mem, arg_base, parm_ent);
- ir_node *const cnst = get_type_size(expr->parameter->type);
+ ir_node *const cnst = get_type_size(expr->parameter->base.type);
ir_node *const add = new_d_Add(dbgi, arg_sel, cnst, mode_P_data);
set_value_for_expression(expr->ap, add);
return NULL;
}
-static ir_node *get_label_block(declaration_t *label)
+static ir_node *get_label_block(label_t *label)
{
- assert(label->namespc == NAMESPACE_LABEL || label->namespc == NAMESPACE_LOCAL_LABEL);
-
- if (label->declaration_kind == DECLARATION_KIND_LABEL_BLOCK) {
- return label->v.block;
- }
- assert(label->declaration_kind == DECLARATION_KIND_UNKNOWN);
+ if (label->block != NULL)
+ return label->block;
/* beware: might be called from create initializer with current_ir_graph
* set to const_code_irg. */
ir_node *block = new_immBlock();
set_cur_block(old_cur_block);
- label->declaration_kind = DECLARATION_KIND_LABEL_BLOCK;
- label->v.block = block;
+ label->block = block;
- ARR_APP1(declaration_t *, all_labels, label);
+ ARR_APP1(label_t *, all_labels, label);
current_ir_graph = rem;
return block;
static ir_node *label_address_to_firm(
const label_address_expression_t *label)
{
- ir_node *block = get_label_block(label->declaration);
+ ir_node *block = get_label_block(label->label);
ir_label_t nr = get_Block_label(block);
if (nr == 0) {
return wide_string_literal_to_firm(&expression->wide_string);
case EXPR_REFERENCE:
return reference_expression_to_firm(&expression->reference);
+ case EXPR_REFERENCE_ENUM_VALUE:
+ return reference_expression_enum_value_to_firm(&expression->reference);
case EXPR_CALL:
return call_expression_to_firm(&expression->call);
EXPR_UNARY_CASES
}
-
-static void create_declaration_entity(declaration_t *declaration,
- declaration_kind_t declaration_kind,
- ir_type *parent_type)
+static void create_variable_entity(entity_t *variable,
+ declaration_kind_t declaration_kind,
+ ir_type *parent_type)
{
- type_t *const type = skip_typeref(declaration->type);
- if (is_type_function(type)) {
- (void) get_function_entity(declaration);
- return;
- }
+ assert(variable->kind == ENTITY_VARIABLE);
+ type_t *const type = skip_typeref(variable->declaration.type);
+ ident *const id = new_id_from_str(variable->base.symbol->string);
+ ir_type *const irtype = get_ir_type(type);
+ dbg_info *const dbgi = get_dbg_info(&variable->base.source_position);
+ ir_entity *const irentity = new_d_entity(parent_type, id, irtype, dbgi);
- ident *const id = new_id_from_str(declaration->symbol->string);
- ir_type *const irtype = get_ir_type(type);
- dbg_info *const dbgi = get_dbg_info(&declaration->source_position);
- ir_entity *const entity = new_d_entity(parent_type, id, irtype, dbgi);
-
- handle_gnu_attributes_ent(entity, declaration);
+ handle_gnu_attributes_ent(irentity, variable);
- declaration->declaration_kind = (unsigned char) declaration_kind;
- declaration->v.entity = entity;
- set_entity_variability(entity, variability_uninitialized);
- set_entity_ld_ident(entity, create_ld_ident(entity, declaration));
+ 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));
if (parent_type == get_tls_type())
- set_entity_allocation(entity, allocation_automatic);
+ set_entity_allocation(irentity, allocation_automatic);
else if (declaration_kind == DECLARATION_KIND_GLOBAL_VARIABLE)
- set_entity_allocation(entity, allocation_static);
+ set_entity_allocation(irentity, allocation_static);
if (type->base.qualifiers & TYPE_QUALIFIER_VOLATILE) {
- set_entity_volatility(entity, volatility_is_volatile);
+ set_entity_volatility(irentity, volatility_is_volatile);
}
}
type_t *type;
ir_initializer_t *initializer;
size_t index;
- declaration_t *compound_entry;
+ entity_t *compound_entry;
};
typedef struct type_path_t type_path_t;
{
size_t len = ARR_LEN(path->path);
- for(size_t i = 0; i < len; ++i) {
+ for (size_t i = 0; i < len; ++i) {
const type_path_entry_t *entry = & path->path[i];
type_t *type = skip_typeref(entry->type);
if (is_type_compound(type)) {
- fprintf(stderr, ".%s", entry->compound_entry->symbol->string);
+ fprintf(stderr, ".%s", entry->compound_entry->base.symbol->string);
} else if (is_type_array(type)) {
fprintf(stderr, "[%zu]", entry->index);
} else {
return result;
}
-static size_t get_compound_size(const compound_type_t *type)
+static size_t get_compound_member_count(const compound_type_t *type)
{
- declaration_t *declaration = type->declaration;
- declaration_t *member = declaration->scope.declarations;
- size_t size = 0;
- for( ; member != NULL; member = member->next) {
- ++size;
+ compound_t *compound = type->compound;
+ size_t n_members = 0;
+ entity_t *member = compound->members.entities;
+ for ( ; member != NULL; member = member->base.next) {
+ ++n_members;
}
- /* TODO: cache results? */
- return size;
+ return n_members;
}
static ir_initializer_t *get_initializer_entry(type_path_t *path)
size_t len;
if (is_type_compound(top_type)) {
- declaration_t *declaration = top_type->compound.declaration;
- declaration_t *entry = declaration->scope.declarations;
+ compound_t *compound = top_type->compound.compound;
+ entity_t *entry = compound->members.entities;
top->compound_entry = entry;
top->index = 0;
- len = get_compound_size(&top_type->compound);
- if (entry != NULL)
- path->top_type = entry->type;
+ len = get_compound_member_count(&top_type->compound);
+ if (entry != NULL) {
+ assert(entry->kind == ENTITY_COMPOUND_MEMBER);
+ path->top_type = entry->declaration.type;
+ }
} else {
assert(is_type_array(top_type));
assert(top_type->array.size > 0);
/* designators start at current object type */
ARR_RESIZE(type_path_entry_t, path->path, 1);
- for( ; designator != NULL; designator = designator->next) {
+ for ( ; designator != NULL; designator = designator->next) {
type_path_entry_t *top = get_type_path_top(path);
type_t *orig_type = top->type;
type_t *type = skip_typeref(orig_type);
size_t index = 0;
symbol_t *symbol = designator->symbol;
- declaration_t *declaration = type->compound.declaration;
- declaration_t *iter = declaration->scope.declarations;
- for( ; iter != NULL; iter = iter->next, ++index) {
- if (iter->symbol == symbol) {
+ compound_t *compound = type->compound.compound;
+ entity_t *iter = compound->members.entities;
+ for ( ; iter != NULL; iter = iter->base.next, ++index) {
+ if (iter->base.symbol == symbol) {
+ assert(iter->kind == ENTITY_COMPOUND_MEMBER);
break;
}
}
top->type = orig_type;
top->compound_entry = iter;
top->index = index;
- orig_type = iter->type;
+ orig_type = iter->declaration.type;
} else {
expression_t *array_index = designator->array_index;
assert(designator->array_index != NULL);
if (is_type_union(type)) {
top->compound_entry = NULL;
} else if (is_type_struct(type)) {
- declaration_t *entry = top->compound_entry;
+ entity_t *entry = top->compound_entry;
top->index++;
- entry = entry->next;
+ entry = entry->base.next;
top->compound_entry = entry;
if (entry != NULL) {
- path->top_type = entry->type;
+ assert(entry->kind == ENTITY_COMPOUND_MEMBER);
+ path->top_type = entry->declaration.type;
return;
}
} else {
descend_into_subtype(&path);
- for(size_t i = 0; i < initializer->len; ++i) {
+ for (size_t i = 0; i < initializer->len; ++i) {
const initializer_t *sub_initializer = initializer->initializers[i];
if (sub_initializer->kind == INITIALIZER_DESIGNATOR) {
const char *string = initializer->string.begin;
ir_mode *mode = get_ir_mode(type->array.element_type);
- for(size_t i = 0; i < len; ++i) {
+ for (size_t i = 0; i < len; ++i) {
char c = 0;
if (i < string_len)
c = string[i];
const wchar_rep_t *string = initializer->string.begin;
ir_mode *mode = get_type_mode(ir_type_wchar_t);
- for(size_t i = 0; i < len; ++i) {
+ for (size_t i = 0; i < len; ++i) {
wchar_rep_t c = 0;
if (i < string_len) {
c = string[i];
n_members = get_compound_n_members(type);
}
- for(int i = 0; i < n_members; ++i) {
+ for (int i = 0; i < n_members; ++i) {
ir_node *addr;
ir_type *irtype;
if (is_Array_type(type)) {
!= (unsigned) n_members)
panic("initializer doesn't match compound type");
- for(int i = 0; i < n_members; ++i) {
+ for (int i = 0; i < n_members; ++i) {
ir_node *addr;
ir_type *irtype;
ir_entity *sub_entity;
set_store(copyb_mem);
}
-static void create_initializer_local_variable_entity(declaration_t *declaration)
+static void create_initializer_local_variable_entity(entity_t *entity)
{
- initializer_t *initializer = declaration->init.initializer;
- dbg_info *dbgi = get_dbg_info(&declaration->source_position);
- ir_entity *entity = declaration->v.entity;
- type_t *type = declaration->type;
- create_local_initializer(initializer, dbgi, entity, type);
+ assert(entity->kind == ENTITY_VARIABLE);
+ initializer_t *initializer = entity->variable.initializer;
+ dbg_info *dbgi = get_dbg_info(&entity->base.source_position);
+ ir_entity *irentity = entity->variable.v.entity;
+ type_t *type = entity->declaration.type;
+ create_local_initializer(initializer, dbgi, irentity, type);
}
-static void create_declaration_initializer(declaration_t *declaration)
+static void create_variable_initializer(entity_t *entity)
{
- initializer_t *initializer = declaration->init.initializer;
+ assert(entity->kind == ENTITY_VARIABLE);
+ initializer_t *initializer = entity->variable.initializer;
if (initializer == NULL)
return;
declaration_kind_t declaration_kind
- = (declaration_kind_t) declaration->declaration_kind;
+ = (declaration_kind_t) entity->declaration.kind;
if (declaration_kind == DECLARATION_KIND_LOCAL_VARIABLE_ENTITY) {
- create_initializer_local_variable_entity(declaration);
+ create_initializer_local_variable_entity(entity);
return;
}
- type_t *type = declaration->type;
+ type_t *type = entity->declaration.type;
type_qualifiers_t tq = get_type_qualifier(type, true);
if (initializer->kind == INITIALIZER_VALUE) {
initializer_value_t *initializer_value = &initializer->value;
- dbg_info *dbgi
- = get_dbg_info(&declaration->source_position);
+ dbg_info *dbgi = get_dbg_info(&entity->base.source_position);
ir_node *value = expression_to_firm(initializer_value->value);
value = do_strict_conv(dbgi, value);
if (declaration_kind == DECLARATION_KIND_LOCAL_VARIABLE) {
- set_value(declaration->v.value_number, value);
+ set_value(entity->variable.v.value_number, value);
} else {
assert(declaration_kind == DECLARATION_KIND_GLOBAL_VARIABLE);
- ir_entity *entity = declaration->v.entity;
+ ir_entity *irentity = entity->variable.v.entity;
if (tq & TYPE_QUALIFIER_CONST) {
- set_entity_variability(entity, variability_constant);
+ set_entity_variability(irentity, variability_constant);
} else {
- set_entity_variability(entity, variability_initialized);
+ set_entity_variability(irentity, variability_initialized);
}
- set_atomic_ent_value(entity, value);
+ set_atomic_ent_value(irentity, value);
}
} else {
assert(declaration_kind == DECLARATION_KIND_LOCAL_VARIABLE_ENTITY ||
declaration_kind == DECLARATION_KIND_GLOBAL_VARIABLE);
- ir_entity *entity = declaration->v.entity;
+ ir_entity *irentity = entity->variable.v.entity;
ir_initializer_t *irinitializer
= create_ir_initializer(initializer, type);
if (tq & TYPE_QUALIFIER_CONST) {
- set_entity_variability(entity, variability_constant);
+ set_entity_variability(irentity, variability_constant);
} else {
- set_entity_variability(entity, variability_initialized);
+ set_entity_variability(irentity, variability_initialized);
}
- set_entity_initializer(entity, irinitializer);
+ set_entity_initializer(irentity, irinitializer);
}
}
-static void create_variable_length_array(declaration_t *declaration)
+static void create_variable_length_array(entity_t *entity)
{
- /* initializers are not allowed for VLAs */
- assert(declaration->init.initializer == NULL);
+ assert(entity->kind == ENTITY_VARIABLE);
+ assert(entity->variable.initializer == NULL);
- declaration->declaration_kind = DECLARATION_KIND_VARIABLE_LENGTH_ARRAY;
- declaration->v.vla_base = NULL;
+ entity->declaration.kind = DECLARATION_KIND_VARIABLE_LENGTH_ARRAY;
+ entity->variable.v.vla_base = NULL;
/* TODO: record VLA somewhere so we create the free node when we leave
* it's scope */
}
-static void allocate_variable_length_array(declaration_t *declaration)
+static void allocate_variable_length_array(entity_t *entity)
{
- /* initializers are not allowed for VLAs */
- assert(declaration->init.initializer == NULL);
+ assert(entity->kind == ENTITY_VARIABLE);
+ assert(entity->variable.initializer == NULL);
assert(get_cur_block() != NULL);
- dbg_info *dbgi = get_dbg_info(&declaration->source_position);
- type_t *type = declaration->type;
+ dbg_info *dbgi = get_dbg_info(&entity->base.source_position);
+ type_t *type = entity->declaration.type;
ir_type *el_type = get_ir_type(type->array.element_type);
/* make sure size_node is calculated */
ir_node *addr = new_d_Proj(dbgi, alloc, mode_P_data, pn_Alloc_res);
set_store(proj_m);
- assert(declaration->declaration_kind
- == DECLARATION_KIND_VARIABLE_LENGTH_ARRAY);
- declaration->v.vla_base = addr;
+ assert(entity->declaration.kind == DECLARATION_KIND_VARIABLE_LENGTH_ARRAY);
+ entity->variable.v.vla_base = addr;
}
/**
* Creates a Firm local variable from a declaration.
*/
-static void create_local_variable(declaration_t *declaration)
+static void create_local_variable(entity_t *entity)
{
- assert(declaration->declaration_kind == DECLARATION_KIND_UNKNOWN);
+ assert(entity->kind == ENTITY_VARIABLE);
+ assert(entity->declaration.kind == DECLARATION_KIND_UNKNOWN);
- bool needs_entity = declaration->address_taken;
- type_t *type = skip_typeref(declaration->type);
+ bool needs_entity = entity->variable.address_taken;
+ type_t *type = skip_typeref(entity->declaration.type);
/* is it a variable length array? */
if (is_type_array(type) && !type->array.size_constant) {
- create_variable_length_array(declaration);
+ create_variable_length_array(entity);
return;
} else if (is_type_array(type) || is_type_compound(type)) {
needs_entity = true;
if (needs_entity) {
ir_type *frame_type = get_irg_frame_type(current_ir_graph);
- create_declaration_entity(declaration,
- DECLARATION_KIND_LOCAL_VARIABLE_ENTITY,
- frame_type);
+ create_variable_entity(entity,
+ DECLARATION_KIND_LOCAL_VARIABLE_ENTITY,
+ frame_type);
} else {
- declaration->declaration_kind = DECLARATION_KIND_LOCAL_VARIABLE;
- declaration->v.value_number = next_value_number_function;
- set_irg_loc_description(current_ir_graph, next_value_number_function, declaration);
+ entity->declaration.kind = DECLARATION_KIND_LOCAL_VARIABLE;
+ entity->variable.v.value_number = next_value_number_function;
+ set_irg_loc_description(current_ir_graph, next_value_number_function,
+ (variable_t*) &entity->variable);
++next_value_number_function;
}
}
-static void create_local_static_variable(declaration_t *declaration)
+static void create_local_static_variable(entity_t *entity)
{
- assert(declaration->declaration_kind == DECLARATION_KIND_UNKNOWN);
+ assert(entity->kind == ENTITY_VARIABLE);
+ assert(entity->declaration.kind == DECLARATION_KIND_UNKNOWN);
- type_t *const type = skip_typeref(declaration->type);
+ type_t *const type = skip_typeref(entity->declaration.type);
ir_type *const global_type = get_glob_type();
ir_type *const irtype = get_ir_type(type);
- dbg_info *const dbgi = get_dbg_info(&declaration->source_position);
+ dbg_info *const dbgi = get_dbg_info(&entity->base.source_position);
- size_t l = strlen(declaration->symbol->string);
+ size_t l = strlen(entity->base.symbol->string);
char buf[l + sizeof(".%u")];
- snprintf(buf, sizeof(buf), "%s.%%u", declaration->symbol->string);
+ snprintf(buf, sizeof(buf), "%s.%%u", entity->base.symbol->string);
ident *const id = id_unique(buf);
- ir_entity *const entity = new_d_entity(global_type, id, irtype, dbgi);
+ ir_entity *const irentity = new_d_entity(global_type, id, irtype, dbgi);
if (type->base.qualifiers & TYPE_QUALIFIER_VOLATILE) {
- set_entity_volatility(entity, volatility_is_volatile);
+ set_entity_volatility(irentity, volatility_is_volatile);
}
- declaration->declaration_kind = DECLARATION_KIND_GLOBAL_VARIABLE;
- declaration->v.entity = entity;
- set_entity_ld_ident(entity, create_ld_ident(entity, declaration));
- set_entity_variability(entity, variability_uninitialized);
- set_entity_visibility(entity, visibility_local);
- set_entity_allocation(entity, allocation_static);
+ entity->declaration.kind = DECLARATION_KIND_GLOBAL_VARIABLE;
+ entity->variable.v.entity = irentity;
+ set_entity_ld_ident(irentity, create_ld_ident(irentity, entity));
+ set_entity_variability(irentity, variability_uninitialized);
+ set_entity_visibility(irentity, visibility_local);
+ set_entity_allocation(irentity, allocation_static);
ir_graph *const old_current_ir_graph = current_ir_graph;
current_ir_graph = get_const_code_irg();
- create_declaration_initializer(declaration);
+ create_variable_initializer(entity);
assert(current_ir_graph == get_const_code_irg());
current_ir_graph = old_current_ir_graph;
return;
dbg_info *dbgi = get_dbg_info(&statement->base.source_position);
- ir_type *func_irtype = get_ir_type(current_function_decl->type);
+ type_t *type = current_function_entity->declaration.type;
+ ir_type *func_irtype = get_ir_type(type);
ir_node *in[1];
static ir_node *compound_statement_to_firm(compound_statement_t *compound)
{
- declaration_t *declaration = compound->scope.declarations;
- for( ; declaration != NULL; declaration = declaration->next) {
- create_local_declaration(declaration);
+ entity_t *entity = compound->scope.entities;
+ for ( ; entity != NULL; entity = entity->base.next) {
+ if (!is_declaration(entity))
+ continue;
+
+ create_local_declaration(entity);
}
ir_node *result = NULL;
statement_t *statement = compound->statements;
- for( ; statement != NULL; statement = statement->base.next) {
+ for ( ; statement != NULL; statement = statement->base.next) {
if (statement->base.next == NULL
&& statement->kind == STATEMENT_EXPRESSION) {
result = expression_statement_to_firm(
return result;
}
-static void create_global_variable(declaration_t *declaration)
+static void create_global_variable(entity_t *entity)
{
+ assert(entity->kind == ENTITY_VARIABLE);
+
ir_visibility vis;
ir_type *var_type;
- switch ((storage_class_tag_t)declaration->storage_class) {
+ switch ((storage_class_tag_t) entity->declaration.storage_class) {
case STORAGE_CLASS_STATIC:
vis = visibility_local;
goto global_var;
goto create_var;
create_var:
- create_declaration_entity(declaration,
- DECLARATION_KIND_GLOBAL_VARIABLE,
- var_type);
- if (!is_type_function(skip_typeref(declaration->type))) {
+ create_variable_entity(entity,
+ DECLARATION_KIND_GLOBAL_VARIABLE,
+ var_type);
+ /* Matze: I'm confused, shouldn't we only be here when creating
+ * variables? */
+#if 0
+ if (!is_type_function(skip_typeref(entity->declaration.type))) {
set_entity_visibility(declaration->v.entity, vis);
}
+#else
+ set_entity_visibility(entity->variable.v.entity, vis);
+#endif
return;
case STORAGE_CLASS_TYPEDEF:
case STORAGE_CLASS_AUTO:
case STORAGE_CLASS_REGISTER:
- case STORAGE_CLASS_ENUM_ENTRY:
break;
}
panic("Invalid storage class for global variable");
}
-static void create_local_declaration(declaration_t *declaration)
+static void create_local_declaration(entity_t *entity)
{
- if (declaration->namespc != NAMESPACE_NORMAL)
- return;
+ assert(is_declaration(entity));
+
/* construct type */
- (void) get_ir_type(declaration->type);
- if (declaration->symbol == NULL) {
+ (void) get_ir_type(entity->declaration.type);
+ if (entity->base.symbol == NULL) {
return;
}
- type_t *type = skip_typeref(declaration->type);
-
- switch ((storage_class_tag_t) declaration->storage_class) {
+ switch ((storage_class_tag_t) entity->declaration.storage_class) {
case STORAGE_CLASS_STATIC:
- create_local_static_variable(declaration);
+ create_local_static_variable(entity);
return;
case STORAGE_CLASS_EXTERN:
- create_global_variable(declaration);
- create_declaration_initializer(declaration);
+ if (entity->kind == ENTITY_FUNCTION) {
+ assert(entity->function.statement == NULL);
+ get_function_entity(entity);
+ } else {
+ create_global_variable(entity);
+ create_variable_initializer(entity);
+ }
return;
case STORAGE_CLASS_NONE:
case STORAGE_CLASS_AUTO:
case STORAGE_CLASS_REGISTER:
- if (is_type_function(type)) {
- if (declaration->init.statement != NULL) {
- get_function_entity(declaration);
- declaration->declaration_kind = DECLARATION_KIND_INNER_FUNCTION;
- enqueue_inner_function(declaration);
+ if (entity->kind == ENTITY_FUNCTION) {
+ if (entity->function.statement != NULL) {
+ get_function_entity(entity);
+ entity->declaration.kind = DECLARATION_KIND_INNER_FUNCTION;
+ enqueue_inner_function(entity);
} else {
- get_function_entity(declaration);
+ get_function_entity(entity);
}
} else {
- create_local_variable(declaration);
+ create_local_variable(entity);
}
return;
- case STORAGE_CLASS_ENUM_ENTRY:
- /* should already be handled */
- assert(declaration->declaration_kind == DECLARATION_KIND_ENUM_ENTRY);
- return;
case STORAGE_CLASS_TYPEDEF:
- declaration->declaration_kind = DECLARATION_KIND_TYPE;
- return;
case STORAGE_CLASS_THREAD:
case STORAGE_CLASS_THREAD_EXTERN:
case STORAGE_CLASS_THREAD_STATIC:
panic("invalid storage class found");
}
-static void initialize_local_declaration(declaration_t *declaration)
+static void initialize_local_declaration(entity_t *entity)
{
- if (declaration->symbol == NULL || declaration->namespc != NAMESPACE_NORMAL)
+ if (entity->base.symbol == NULL)
return;
- switch ((declaration_kind_t) declaration->declaration_kind) {
+ switch ((declaration_kind_t) entity->declaration.kind) {
case DECLARATION_KIND_LOCAL_VARIABLE:
case DECLARATION_KIND_LOCAL_VARIABLE_ENTITY:
- create_declaration_initializer(declaration);
+ create_variable_initializer(entity);
return;
case DECLARATION_KIND_VARIABLE_LENGTH_ARRAY:
- allocate_variable_length_array(declaration);
+ allocate_variable_length_array(entity);
return;
- case DECLARATION_KIND_LABEL_BLOCK:
case DECLARATION_KIND_COMPOUND_MEMBER:
case DECLARATION_KIND_GLOBAL_VARIABLE:
- case DECLARATION_KIND_COMPOUND_TYPE_INCOMPLETE:
- case DECLARATION_KIND_COMPOUND_TYPE_COMPLETE:
case DECLARATION_KIND_FUNCTION:
- case DECLARATION_KIND_TYPE:
- case DECLARATION_KIND_ENUM_ENTRY:
case DECLARATION_KIND_INNER_FUNCTION:
return;
static void declaration_statement_to_firm(declaration_statement_t *statement)
{
- declaration_t *declaration = statement->declarations_begin;
- declaration_t *end = statement->declarations_end->next;
- for( ; declaration != end; declaration = declaration->next) {
- if (declaration->namespc != NAMESPACE_NORMAL)
+ entity_t *entity = statement->declarations_begin;
+ entity_t *end = statement->declarations_end->base.next;
+ for ( ; entity != end; entity = entity->base.next) {
+ if (!is_declaration(entity))
continue;
- initialize_local_declaration(declaration);
+ initialize_local_declaration(entity);
}
}
ir_node *jmp = NULL;
/* create declarations */
- declaration_t *declaration = statement->scope.declarations;
- for( ; declaration != NULL; declaration = declaration->next) {
- create_local_declaration(declaration);
+ entity_t *entity = statement->scope.entities;
+ for ( ; entity != NULL; entity = entity->base.next) {
+ if (!is_declaration(entity))
+ continue;
+
+ create_local_declaration(entity);
}
if (get_cur_block() != NULL) {
- declaration = statement->scope.declarations;
- for( ; declaration != NULL; declaration = declaration->next) {
- initialize_local_declaration(declaration);
+ entity = statement->scope.entities;
+ for ( ; entity != NULL; entity = entity->base.next) {
+ if (!is_declaration(entity))
+ continue;
+
+ initialize_local_declaration(entity);
}
if (statement->initialisation != NULL) {
size_t n_clobbers = 0;
asm_clobber_t *clobber = statement->clobbers;
- for( ; clobber != NULL; clobber = clobber->next) {
+ for ( ; clobber != NULL; clobber = clobber->next) {
const char *clobber_str = clobber->clobber.begin;
if (!be_is_valid_clobber(clobber_str)) {
in_size * sizeof(tmp_in_constraints[0]));
/* find and count input and output arguments */
argument = statement->inputs;
- for( ; argument != NULL; argument = argument->next) {
+ for ( ; argument != NULL; argument = argument->next) {
const char *constraints = argument->constraints.begin;
asm_constraint_flags_t asm_flags
= be_parse_asm_constraints(constraints);
statement->base.transformed = true;
#endif
- switch(statement->kind) {
+ switch (statement->kind) {
case STATEMENT_INVALID:
panic("invalid statement found");
return;
case STATEMENT_LABEL:
label_to_firm(&statement->label);
return;
+ case STATEMENT_LOCAL_LABEL:
+ /* local labels transform the semantics of labels while parsing
+ * they don't need any special treatment here */
+ return;
case STATEMENT_GOTO:
goto_to_firm(&statement->gotos);
return;
panic("Statement not implemented\n");
}
-static int count_local_declarations(const declaration_t * decl,
- const declaration_t *const end)
+static int count_local_variables(const entity_t *entity,
+ const entity_t *const end)
{
int count = 0;
- for (; decl != end; decl = decl->next) {
- if (decl->namespc != NAMESPACE_NORMAL)
+ for (; entity != end; entity = entity->base.next) {
+ if (entity->kind != ENTITY_VARIABLE)
continue;
- type_t *type = skip_typeref(decl->type);
+ type_t *type = skip_typeref(entity->declaration.type);
- if (!decl->address_taken && is_type_scalar(type))
+ if (!entity->variable.address_taken && is_type_scalar(type))
++count;
}
return count;
}
-static void count_decls_in_stmt(statement_t *stmt, void *const env)
+static void count_local_variables_in_stmt(statement_t *stmt, void *const env)
{
int *const count = env;
switch (stmt->kind) {
- case STATEMENT_DECLARATION: {
- const declaration_statement_t *const decl_stmt = &stmt->declaration;
- *count += count_local_declarations(decl_stmt->declarations_begin,
- decl_stmt->declarations_end->next);
- break;
- }
+ case STATEMENT_DECLARATION: {
+ const declaration_statement_t *const decl_stmt = &stmt->declaration;
+ *count += count_local_variables(decl_stmt->declarations_begin,
+ decl_stmt->declarations_end->base.next);
+ break;
+ }
- case STATEMENT_FOR:
- *count += count_local_declarations(stmt->fors.scope.declarations, NULL);
- break;
+ case STATEMENT_FOR:
+ *count += count_local_variables(stmt->fors.scope.entities, NULL);
+ break;
- default:
- break;
+ default:
+ break;
}
}
-static int get_function_n_local_vars(declaration_t *declaration)
+static int get_function_n_local_vars(entity_t *entity)
{
int count = 0;
/* count parameters */
- count += count_local_declarations(declaration->scope.declarations, NULL);
+ count += count_local_variables(entity->function.parameters.entities, NULL);
/* count local variables declared in body */
- walk_statements(declaration->init.statement, count_decls_in_stmt, &count);
+ walk_statements(entity->function.statement, count_local_variables_in_stmt,
+ &count);
return count;
}
-static void initialize_function_parameters(declaration_t *declaration)
+static void initialize_function_parameters(entity_t *entity)
{
- ir_graph *irg = current_ir_graph;
- ir_node *args = get_irg_args(irg);
- ir_node *start_block = get_irg_start_block(irg);
- ir_type *function_irtype = get_ir_type(declaration->type);
+ assert(entity->kind == ENTITY_FUNCTION);
+ ir_graph *irg = current_ir_graph;
+ ir_node *args = get_irg_args(irg);
+ ir_node *start_block = get_irg_start_block(irg);
+ ir_type *function_irtype = get_ir_type(entity->declaration.type);
- int n = 0;
- declaration_t *parameter = declaration->scope.declarations;
- for( ; parameter != NULL; parameter = parameter->next, ++n) {
- assert(parameter->declaration_kind == DECLARATION_KIND_UNKNOWN);
- type_t *type = skip_typeref(parameter->type);
+ int n = 0;
+ entity_t *parameter = entity->function.parameters.entities;
+ for ( ; parameter != NULL; parameter = parameter->base.next, ++n) {
+ assert(parameter->kind == ENTITY_VARIABLE);
+ assert(parameter->declaration.kind == DECLARATION_KIND_UNKNOWN);
+ type_t *type = skip_typeref(parameter->declaration.type);
- bool needs_entity = parameter->address_taken;
+ bool needs_entity = parameter->variable.address_taken;
assert(!is_type_array(type));
if (is_type_compound(type)) {
needs_entity = true;
if (needs_entity) {
ir_entity *entity = get_method_value_param_ent(function_irtype, n);
- ident *id = new_id_from_str(parameter->symbol->string);
+ ident *id = new_id_from_str(parameter->base.symbol->string);
set_entity_ident(entity, id);
- parameter->declaration_kind
+ parameter->declaration.kind
= DECLARATION_KIND_LOCAL_VARIABLE_ENTITY;
- parameter->v.entity = entity;
+ parameter->variable.v.entity = entity;
continue;
}
value = create_conv(NULL, value, mode);
value = do_strict_conv(NULL, value);
- parameter->declaration_kind = DECLARATION_KIND_LOCAL_VARIABLE;
- parameter->v.value_number = next_value_number_function;
- set_irg_loc_description(current_ir_graph, next_value_number_function, parameter);
+ parameter->declaration.kind = DECLARATION_KIND_LOCAL_VARIABLE;
+ parameter->variable.v.value_number = next_value_number_function;
+ set_irg_loc_description(current_ir_graph, next_value_number_function,
+ (variable_t*) ¶meter->variable);
++next_value_number_function;
- set_value(parameter->v.value_number, value);
+ set_value(parameter->variable.v.value_number, value);
}
}
/**
* Create code for a function.
*/
-static void create_function(declaration_t *declaration)
+static void create_function(entity_t *entity)
{
- ir_entity *function_entity = get_function_entity(declaration);
+ assert(entity->kind == ENTITY_FUNCTION);
+ ir_entity *function_entity = get_function_entity(entity);
- if (declaration->init.statement == NULL)
+ if (entity->function.statement == NULL)
return;
- if (declaration->modifiers & DM_CONSTRUCTOR) {
+ if (entity->declaration.modifiers & DM_CONSTRUCTOR) {
ir_type *segment = get_segment_type(IR_SEGMENT_CONSTRUCTORS);
add_function_pointer(segment, function_entity, "constructor_ptr.%u");
}
- if (declaration->modifiers & DM_DESTRUCTOR) {
+ if (entity->declaration.modifiers & DM_DESTRUCTOR) {
ir_type *segment = get_segment_type(IR_SEGMENT_DESTRUCTORS);
add_function_pointer(segment, function_entity, "destructor_ptr.%u");
}
- current_function_decl = declaration;
- current_function_name = NULL;
- current_funcsig = NULL;
+ current_function_entity = entity;
+ current_function_name = NULL;
+ current_funcsig = NULL;
assert(all_labels == NULL);
- all_labels = NEW_ARR_F(declaration_t *, 0);
+ all_labels = NEW_ARR_F(label_t *, 0);
ijmp_list = NULL;
- int n_local_vars = get_function_n_local_vars(declaration);
+ int n_local_vars = get_function_n_local_vars(entity);
ir_graph *irg = new_ir_graph(function_entity, n_local_vars);
ir_graph *old_current_function = current_function;
ir_node *first_block = get_cur_block();
/* set inline flags */
- if (declaration->is_inline)
+ if (entity->function.is_inline)
set_irg_inline_property(irg, irg_inline_recomended);
- handle_decl_modifier_irg(irg, declaration->modifiers);
+ handle_decl_modifier_irg(irg, entity->declaration.modifiers);
next_value_number_function = 0;
- initialize_function_parameters(declaration);
+ initialize_function_parameters(entity);
- statement_to_firm(declaration->init.statement);
+ statement_to_firm(entity->function.statement);
ir_node *end_block = get_irg_end_block(irg);
/* do we have a return statement yet? */
if (get_cur_block() != NULL) {
- type_t *type = skip_typeref(declaration->type);
+ type_t *type = skip_typeref(entity->declaration.type);
assert(is_type_function(type));
const function_type_t *func_type = &type->function;
const type_t *return_type
ir_node *in[1];
/* §5.1.2.2.3 main implicitly returns 0 */
- if (strcmp(declaration->symbol->string, "main") == 0) {
+ if (strcmp(entity->base.symbol->string, "main") == 0) {
in[0] = new_Const(mode, get_mode_null(mode));
} else {
in[0] = new_Unknown(mode);
bool has_computed_gotos = false;
for (int i = ARR_LEN(all_labels) - 1; i >= 0; --i) {
- declaration_t *label = all_labels[i];
+ label_t *label = all_labels[i];
if (label->address_taken) {
- gen_ijmp_branches(label->v.block);
+ gen_ijmp_branches(label->block);
has_computed_gotos = true;
}
- mature_immBlock(label->v.block);
+ mature_immBlock(label->block);
}
if (has_computed_gotos) {
/* if we have computed goto's in the function, we cannot inline it */
if (get_irg_inline_property(irg) >= irg_inline_recomended) {
- warningf(&declaration->source_position,
- "function '%Y' can never be inlined because it contains a computed goto",
- declaration->symbol);
+ warningf(&entity->base.source_position,
+ "function '%Y' can never be inlined because it contains a computed goto",
+ entity->base.symbol);
}
set_irg_inline_property(irg, irg_inline_forbidden);
}
int n = get_compound_n_members(frame_type);
int align_all = 4;
int offset = 0;
- for(int i = 0; i < n; ++i) {
+ for (int i = 0; i < n; ++i) {
ir_entity *entity = get_compound_member(frame_type, i);
ir_type *entity_type = get_entity_type(entity);
irg_vrfy(irg);
current_function = old_current_function;
+
+ /* create inner functions */
+ entity_t *inner;
+ for (inner = next_inner_function(); inner != NULL;
+ inner = next_inner_function()) {
+ create_function(inner);
+ }
}
static void scope_to_firm(scope_t *scope)
{
/* first pass: create declarations */
- declaration_t *declaration = scope->declarations;
- for( ; declaration != NULL; declaration = declaration->next) {
- if (declaration->namespc != NAMESPACE_NORMAL)
- continue;
- if (declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY
- || declaration->storage_class == STORAGE_CLASS_TYPEDEF)
- continue;
- if (declaration->symbol == NULL)
+ entity_t *entity = scope->entities;
+ for ( ; entity != NULL; entity = entity->base.next) {
+ if (entity->base.symbol == NULL)
continue;
- type_t *type = skip_typeref(declaration->type);
- if (is_type_function(type)) {
- get_function_entity(declaration);
- } else {
- create_global_variable(declaration);
+ if (entity->kind == ENTITY_FUNCTION) {
+ get_function_entity(entity);
+ } else if (entity->kind == ENTITY_VARIABLE) {
+ create_global_variable(entity);
}
}
/* second pass: create code/initializers */
- declaration = scope->declarations;
- for( ; declaration != NULL; declaration = declaration->next) {
- if (declaration->namespc != NAMESPACE_NORMAL)
- continue;
- if (declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY
- || declaration->storage_class == STORAGE_CLASS_TYPEDEF)
- continue;
- if (declaration->symbol == NULL)
+ entity = scope->entities;
+ for ( ; entity != NULL; entity = entity->base.next) {
+ if (entity->base.symbol == NULL)
continue;
- type_t *type = declaration->type;
- if (type->kind == TYPE_FUNCTION) {
- create_function(declaration);
- declaration_t *inner;
- for (inner = next_inner_function(); inner != NULL;
- inner = next_inner_function())
- create_function(inner);
- } else {
- assert(declaration->declaration_kind
+ if (entity->kind == ENTITY_FUNCTION) {
+ create_function(entity);
+ } else if (entity->kind == ENTITY_VARIABLE) {
+ assert(entity->declaration.kind
== DECLARATION_KIND_GLOBAL_VARIABLE);
current_ir_graph = get_const_code_irg();
- create_declaration_initializer(declaration);
+ create_variable_initializer(entity);
}
}
}
current_switch_cond = NULL;
init_ir_types();
+ inner_functions = NEW_ARR_F(entity_t *, 0);
scope_to_firm(&unit->scope);
global_asm_to_firm(unit->global_asm);
+ DEL_ARR_F(inner_functions);
+ inner_functions = NULL;
+
current_ir_graph = NULL;
}
#include "symbol.h"
#include "token_t.h"
#include "type.h"
+#include "entity.h"
#include "adt/obst.h"
/** The AST obstack contains all data that must stay in the AST. */
EXPR_UNKNOWN = 0,
EXPR_INVALID,
EXPR_REFERENCE,
+ EXPR_REFERENCE_ENUM_VALUE,
EXPR_CONST,
EXPR_CHARACTER_CONSTANT,
EXPR_WIDE_CHARACTER_CONSTANT,
* A scope containing declarations.
*/
struct scope_t {
- declaration_t *declarations; /**< List of declarations in this scope. */
- declaration_t *last_declaration; /**< 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. */
+ 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 {
struct reference_expression_t {
expression_base_t base;
- declaration_t *declaration;
+ entity_t *entity;
};
struct call_argument_t {
struct select_expression_t {
expression_base_t base;
expression_t *compound;
- declaration_t *compound_entry;
+ entity_t *compound_entry;
};
struct array_access_expression_t {
struct va_start_expression_t {
expression_base_t base;
expression_t *ap;
- declaration_t *parameter;
+ variable_t *parameter;
};
struct va_arg_expression_t {
struct label_address_expression_t {
expression_base_t base;
- declaration_t *declaration;
+ label_t *label;
};
union expression_t {
label_address_expression_t label_address;
};
-typedef enum storage_class_tag_t {
- STORAGE_CLASS_NONE,
- STORAGE_CLASS_EXTERN,
- STORAGE_CLASS_STATIC,
- STORAGE_CLASS_TYPEDEF,
- STORAGE_CLASS_AUTO,
- STORAGE_CLASS_REGISTER,
- STORAGE_CLASS_ENUM_ENTRY,
- STORAGE_CLASS_THREAD,
- STORAGE_CLASS_THREAD_EXTERN,
- STORAGE_CLASS_THREAD_STATIC,
-} storage_class_tag_t;
-
-typedef enum namespace_t {
- NAMESPACE_NORMAL,
- NAMESPACE_STRUCT,
- NAMESPACE_UNION,
- NAMESPACE_ENUM,
- NAMESPACE_LABEL,
- NAMESPACE_LOCAL_LABEL
-} namespace_t;
-
typedef enum initializer_kind_t {
INITIALIZER_VALUE,
INITIALIZER_LIST,
GNU_AK_LAST
} gnu_attribute_kind_t;
-/**
- * Extended microsoft modifier.
- */
-typedef enum decl_modifier_t {
- DM_DLLIMPORT = 1 << 0,
- DM_DLLEXPORT = 1 << 1,
- DM_THREAD = 1 << 2,
- DM_NAKED = 1 << 3,
- DM_MICROSOFT_INLINE = 1 << 4,
- DM_FORCEINLINE = 1 << 5,
- DM_SELECTANY = 1 << 6,
- DM_NOTHROW = 1 << 7,
- DM_NOVTABLE = 1 << 8,
- DM_NORETURN = 1 << 9,
- DM_NOINLINE = 1 << 10,
- DM_RESTRICT = 1 << 11,
- DM_NOALIAS = 1 << 12,
- DM_PACKED = 1 << 13,
- DM_TRANSPARENT_UNION = 1 << 14,
- DM_CONST = 1 << 15,
- DM_PURE = 1 << 16,
- DM_CONSTRUCTOR = 1 << 17,
- DM_DESTRUCTOR = 1 << 18,
- DM_UNUSED = 1 << 19,
- DM_USED = 1 << 20,
- DM_CDECL = 1 << 21,
- DM_FASTCALL = 1 << 22,
- DM_STDCALL = 1 << 23,
- DM_THISCALL = 1 << 24,
- DM_DEPRECATED = 1 << 25
-} decl_modifier_t;
-
-typedef unsigned decl_modifiers_t;
-
-struct declaration_t {
- unsigned char namespc;
- unsigned char declared_storage_class;
- unsigned char storage_class;
- unsigned char alignment; /**< Alignment of the declaration, 0 for default. */
- decl_modifiers_t modifiers; /**< modifiers. */
- const char *deprecated_string; /**< MS deprecated string if any. */
- symbol_t *get_property_sym; /**< MS get property. */
- symbol_t *put_property_sym; /**< MS put property. */
- unsigned int address_taken : 1; /**< Set if the address of this declaration was taken. */
- unsigned int is_inline : 1;
- unsigned int used : 1; /**< Set if the declaration is used. */
- unsigned int read : 1;
- unsigned int implicit : 1; /**< Set for implicit (not found in source code) declarations. */
- unsigned int need_closure : 1; /**< Inner function needs closure. */
- unsigned int goto_to_outer : 1; /**< Inner function has goto to outer function. */
- type_t *type;
- il_size_t offset; /**< The offset of this member inside a compound. */
- symbol_t *symbol;
- source_position_t source_position;
- union {
- bool complete; /**< used to indicate whether struct/union types are already defined or if just the name is declared */
- statement_t *statement;
- initializer_t *initializer;
- expression_t *enum_value;
- } init;
- scope_t scope; /**< The scope that this declaration opens. */
- scope_t *parent_scope; /**< The parent scope where this declaration lives. */
-
- /** next declaration in a scope */
- declaration_t *next;
- /** next declaration with same symbol */
- declaration_t *symbol_next;
-
- /* the following fields are used in ast2firm module */
- unsigned char declaration_kind;
- union {
- unsigned int value_number;
- ir_entity *entity;
- ir_node *block;
- ir_node *vla_base;
- tarval *enum_val;
- ir_type *irtype;
- } v;
-};
-
typedef enum statement_kind_t {
STATEMENT_INVALID,
STATEMENT_EMPTY,
STATEMENT_COMPOUND,
STATEMENT_RETURN,
STATEMENT_DECLARATION,
+ STATEMENT_LOCAL_LABEL,
STATEMENT_IF,
STATEMENT_SWITCH,
STATEMENT_EXPRESSION,
struct declaration_statement_t {
statement_base_t base;
- declaration_t *declarations_begin;
- declaration_t *declarations_end;
+ entity_t *declarations_begin;
+ entity_t *declarations_end;
+};
+
+struct local_label_statement_t {
+ statement_base_t base;
+ entity_t *labels_begin;
+ entity_t *labels_end;
};
struct if_statement_t {
struct goto_statement_t {
statement_base_t base;
- declaration_t *label; /**< The destination label. */
+ label_t *label; /**< The destination label. */
expression_t *expression; /**< The expression for an assigned goto. */
goto_statement_t *next; /**< links all goto statements of a function */
};
struct label_statement_t {
statement_base_t base;
- declaration_t *label;
+ label_t *label;
statement_t *statement;
label_statement_t *next; /**< links all label statements of a function */
};
return_statement_t returns;
compound_statement_t compound;
declaration_statement_t declaration;
+ local_label_statement_t local_label;
if_statement_t ifs;
switch_statement_t switchs;
goto_statement_t gotos;
--- /dev/null
+/*
+ * 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 ENTITY_H
+#define ENTITY_H
+
+typedef struct scope_t scope_t;
+
+typedef struct entity_base_t entity_base_t;
+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 declaration_t declaration_t;
+typedef struct typedef_t typedef_t;
+typedef struct variable_t variable_t;
+typedef struct function_t function_t;
+typedef struct compound_member_t compound_member_t;
+typedef union entity_t entity_t;
+
+#endif
--- /dev/null
+/*
+ * 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 ENTITY_T_H
+#define ENTITY_T_H
+
+#include "entity.h"
+
+typedef enum {
+ ENTITY_INVALID,
+ ENTITY_VARIABLE,
+ ENTITY_COMPOUND_MEMBER,
+ ENTITY_FUNCTION,
+ ENTITY_TYPEDEF,
+ ENTITY_STRUCT,
+ ENTITY_UNION,
+ ENTITY_ENUM,
+ ENTITY_ENUM_VALUE,
+ ENTITY_LABEL,
+ ENTITY_LOCAL_LABEL
+} entity_kind_tag_t;
+typedef unsigned char entity_kind_t;
+
+typedef enum namespace_tag_t {
+ NAMESPACE_INVALID,
+ NAMESPACE_NORMAL,
+ NAMESPACE_STRUCT,
+ NAMESPACE_UNION,
+ NAMESPACE_ENUM,
+ NAMESPACE_LABEL,
+ NAMESPACE_LOCAL_LABEL
+} namespace_tag_t;
+typedef unsigned char namespace_t;
+
+typedef enum storage_class_tag_t {
+ STORAGE_CLASS_NONE,
+ STORAGE_CLASS_EXTERN,
+ STORAGE_CLASS_STATIC,
+ STORAGE_CLASS_TYPEDEF,
+ STORAGE_CLASS_AUTO,
+ STORAGE_CLASS_REGISTER,
+ STORAGE_CLASS_THREAD,
+ STORAGE_CLASS_THREAD_EXTERN,
+ STORAGE_CLASS_THREAD_STATIC,
+} storage_class_tag_t;
+typedef unsigned char storage_class_t;
+
+typedef enum decl_modifier_t {
+ DM_DLLIMPORT = 1 << 0,
+ DM_DLLEXPORT = 1 << 1,
+ DM_THREAD = 1 << 2,
+ DM_NAKED = 1 << 3,
+ DM_MICROSOFT_INLINE = 1 << 4,
+ DM_FORCEINLINE = 1 << 5,
+ DM_SELECTANY = 1 << 6,
+ DM_NOTHROW = 1 << 7,
+ DM_NOVTABLE = 1 << 8,
+ DM_NORETURN = 1 << 9,
+ DM_NOINLINE = 1 << 10,
+ DM_RESTRICT = 1 << 11,
+ DM_NOALIAS = 1 << 12,
+ DM_PACKED = 1 << 13,
+ DM_TRANSPARENT_UNION = 1 << 14,
+ DM_CONST = 1 << 15,
+ DM_PURE = 1 << 16,
+ DM_CONSTRUCTOR = 1 << 17,
+ DM_DESTRUCTOR = 1 << 18,
+ DM_UNUSED = 1 << 19,
+ DM_USED = 1 << 20,
+ DM_CDECL = 1 << 21,
+ DM_FASTCALL = 1 << 22,
+ DM_STDCALL = 1 << 23,
+ DM_THISCALL = 1 << 24,
+ DM_DEPRECATED = 1 << 25
+} decl_modifier_t;
+
+typedef unsigned decl_modifiers_t;
+
+/**
+ * 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;
+ symbol_t *symbol;
+ source_position_t source_position;
+ scope_t *parent_scope; /**< The parent scope where this declaration lives. */
+
+ /** next declaration in a scope */
+ entity_t *next;
+ /** next declaration with same symbol */
+ entity_t *symbol_next;
+};
+
+struct compound_t {
+ entity_base_t base;
+ scope_t members;
+ decl_modifiers_t modifiers;
+ bool complete : 1;
+
+ /* ast2firm info */
+ ir_type *irtype;
+ bool irtype_complete : 1;
+};
+
+struct enum_t {
+ entity_base_t base;
+ bool complete : 1;
+
+ /* ast2firm info */
+ ir_type *irtype;
+};
+
+struct enum_value_t {
+ entity_base_t base;
+ expression_t *value;
+ type_t *enum_type;
+
+ /* ast2firm info */
+ tarval *tv;
+};
+
+struct label_t {
+ entity_base_t base;
+ bool used : 1;
+ bool address_taken : 1;
+ statement_t *statement;
+
+ /* ast2firm info */
+ ir_node *block;
+};
+
+struct typedef_t {
+ entity_base_t base;
+ decl_modifiers_t modifiers;
+ type_t *type;
+ bool builtin : 1;
+};
+
+struct declaration_t {
+ entity_base_t base;
+ storage_class_t declared_storage_class;
+ storage_class_t storage_class;
+ decl_modifiers_t modifiers;
+ const char *deprecated_string; /**< MS deprecated string if any. */
+ bool used : 1; /**< Set if the declaration is used. */
+ bool implicit : 1; /**< Set for implicit (not found in source code) declarations. */
+ type_t *type;
+
+ /* ast2firm info */
+ unsigned char kind;
+};
+
+struct compound_member_t {
+ declaration_t base;
+ bool read : 1;
+
+ /* ast2firm info */
+ ir_entity *entity;
+ il_size_t offset; /**< The offset of this member inside a compound. */
+};
+
+struct variable_t {
+ declaration_t base;
+ bool address_taken : 1; /**< Set if the address of this declaration was taken. */
+ bool read : 1;
+ unsigned char alignment; /**< Alignment of the declaration, 0 for default. */
+ symbol_t *get_property_sym; /**< MS get property. */
+ symbol_t *put_property_sym; /**< MS put property. */
+
+ initializer_t *initializer;
+
+ /* ast2firm info */
+ union {
+ unsigned int value_number;
+ ir_entity *entity;
+ ir_node *vla_base;
+ } v;
+};
+
+struct function_t {
+ declaration_t base;
+ bool is_inline : 1;
+ bool need_closure : 1; /**< Inner function needs closure. */
+ bool goto_to_outer : 1; /**< Inner function has goto to outer function. */
+
+ scope_t parameters;
+ statement_t *statement;
+
+ /* ast2firm info */
+ ir_entity *entity;
+};
+
+union entity_t {
+ entity_kind_t kind;
+ entity_base_t base;
+ compound_t structe;
+ compound_t unione;
+ compound_t compound;
+ enum_t enume;
+ enum_value_t enum_value;
+ label_t label;
+ typedef_t typedefe;
+ declaration_t declaration;
+ variable_t variable;
+ function_t function;
+ compound_member_t compound_member;
+};
+
+static inline bool is_declaration(const entity_t *entity)
+{
+ return entity->kind == ENTITY_FUNCTION || entity->kind == ENTITY_VARIABLE
+ || entity->kind == ENTITY_COMPOUND_MEMBER;
+}
+
+#endif
#include "format_check.h"
#include "symbol_t.h"
#include "ast_t.h"
+#include "entity_t.h"
#include "diagnostic.h"
#include "types.h"
#include "type_t.h"
if (func_expr->kind != EXPR_REFERENCE)
return;
- const declaration_t *const decl = func_expr->reference.declaration;
- const call_argument_t * arg = call->arguments;
+ const entity_t *const entity = func_expr->reference.entity;
+ const call_argument_t * arg = call->arguments;
if(false) {
/* the declaration has a GNU format attribute, check it */
* For some functions we always check the format, even if it was not specified.
* This allows to check format even in MS mode or without header included.
*/
- const char *const name = decl->symbol->string;
+ const char *const name = entity->base.symbol->string;
for(size_t i = 0; i < sizeof(builtin_table) / sizeof(builtin_table[0]); ++i) {
if(strcmp(name, builtin_table[i].name) == 0) {
if(builtin_table[i].fmt_kind == FORMAT_PRINTF) {
#include "type_t.h"
#include "type_hash.h"
#include "ast_t.h"
+#include "entity_t.h"
#include "lang_features.h"
#include "walk_statements.h"
#include "warning.h"
#define MAX_LOOKAHEAD 2
typedef struct {
- declaration_t *old_declaration;
- symbol_t *symbol;
- unsigned short namespc;
+ entity_t *old_entity;
+ symbol_t *symbol;
+ namespace_t namespc;
} stack_entry_t;
typedef struct argument_list_t argument_list_t;
typedef struct declaration_specifiers_t declaration_specifiers_t;
struct declaration_specifiers_t {
source_position_t source_position;
- unsigned char declared_storage_class;
+ storage_class_t storage_class;
unsigned char alignment; /**< Alignment, 0 if not set. */
- unsigned int is_inline : 1;
- unsigned int deprecated : 1;
+ bool is_inline : 1;
+ bool deprecated : 1;
decl_modifiers_t modifiers; /**< declaration modifiers */
gnu_attribute_t *gnu_attributes; /**< list of GNU attributes */
const char *deprecated_string; /**< can be set if declaration was marked deprecated. */
* An environment for parsing initializers (and compound literals).
*/
typedef struct parse_initializer_env_t {
- type_t *type; /**< the type of the initializer. In case of an
- array type with unspecified size this gets
- adjusted to the actual size. */
- declaration_t *declaration; /**< the declaration that is initialized if any */
- bool must_be_constant;
+ type_t *type; /**< the type of the initializer. In case of an
+ array type with unspecified size this gets
+ adjusted to the actual size. */
+ entity_t *entity; /**< the variable that is initialized if any */
+ bool must_be_constant;
} parse_initializer_env_t;
-typedef declaration_t* (*parsed_declaration_func) (declaration_t *declaration, bool is_definition);
+typedef entity_t* (*parsed_declaration_func) (entity_t *declaration, bool is_definition);
/** The current token. */
static token_t token;
static scope_t *file_scope = NULL;
/** The current scope. */
static scope_t *scope = NULL;
-static declaration_t *last_declaration = NULL;
/** Point to the current function declaration if inside a function. */
-static declaration_t *current_function = NULL;
-static declaration_t *current_init_decl = 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 expression_t *parse_expression(void);
static type_t *parse_typename(void);
-static void parse_compound_type_entries(declaration_t *compound_declaration);
-static declaration_t *parse_declarator(
- const declaration_specifiers_t *specifiers, bool may_be_abstract);
-static declaration_t *record_declaration(declaration_t *declaration, bool is_definition);
+static void parse_compound_type_entries(compound_t *compound_declaration);
+static entity_t *parse_declarator(const declaration_specifiers_t *specifiers,
+ bool may_be_abstract,
+ bool create_compound_member);
+static entity_t *record_entity(entity_t *entity, bool is_definition);
static void semantic_comparison(binary_expression_t *expression);
return res;
}
-static declaration_t *allocate_declaration_zero(void)
+static size_t get_entity_struct_size(entity_kind_t kind)
{
- declaration_t *declaration = allocate_ast_zero(sizeof(declaration_t));
- declaration->type = type_error_type;
- declaration->alignment = 0;
- return declaration;
+ static const size_t sizes[] = {
+ [ENTITY_VARIABLE] = sizeof(variable_t),
+ [ENTITY_COMPOUND_MEMBER] = sizeof(variable_t),
+ [ENTITY_FUNCTION] = sizeof(function_t),
+ [ENTITY_TYPEDEF] = sizeof(typedef_t),
+ [ENTITY_STRUCT] = sizeof(compound_t),
+ [ENTITY_UNION] = sizeof(compound_t),
+ [ENTITY_ENUM] = sizeof(enum_t),
+ [ENTITY_ENUM_VALUE] = sizeof(enum_value_t),
+ [ENTITY_LABEL] = sizeof(label_t),
+ [ENTITY_LOCAL_LABEL] = sizeof(label_t)
+ };
+ assert(kind <= sizeof(sizes) / sizeof(sizes[0]));
+ assert(sizes[kind] != 0);
+ return sizes[kind];
+}
+
+static entity_t *allocate_entity_zero(entity_kind_t kind)
+{
+ size_t size = get_entity_struct_size(kind);
+ entity_t *entity = allocate_ast_zero(size);
+ entity->kind = kind;
+ return entity;
}
/**
[STATEMENT_COMPOUND] = sizeof(compound_statement_t),
[STATEMENT_RETURN] = sizeof(return_statement_t),
[STATEMENT_DECLARATION] = sizeof(declaration_statement_t),
+ [STATEMENT_LOCAL_LABEL] = sizeof(local_label_statement_t),
[STATEMENT_IF] = sizeof(if_statement_t),
[STATEMENT_SWITCH] = sizeof(switch_statement_t),
[STATEMENT_EXPRESSION] = sizeof(expression_statement_t),
static const size_t sizes[] = {
[EXPR_INVALID] = sizeof(expression_base_t),
[EXPR_REFERENCE] = sizeof(reference_expression_t),
+ [EXPR_REFERENCE_ENUM_VALUE] = sizeof(reference_expression_t),
[EXPR_CONST] = sizeof(const_expression_t),
[EXPR_CHARACTER_CONSTANT] = sizeof(const_expression_t),
[EXPR_WIDE_CHARACTER_CONSTANT] = sizeof(const_expression_t),
static void scope_push(scope_t *new_scope)
{
if (scope != NULL) {
- scope->last_declaration = last_declaration;
- new_scope->depth = scope->depth + 1;
+ new_scope->depth = scope->depth + 1;
}
new_scope->parent = scope;
scope = new_scope;
-
- last_declaration = new_scope->last_declaration;
}
static void scope_pop(void)
{
- scope->last_declaration = last_declaration;
scope = scope->parent;
- last_declaration = scope->last_declaration;
}
/**
- * Search a symbol in a given namespace and returns its declaration or
- * NULL if this symbol was not found.
+ * Search an entity by its symbol in a given namespace.
*/
-static declaration_t *get_declaration(const symbol_t *const symbol,
- const namespace_t namespc)
+static entity_t *get_entity(const symbol_t *const symbol, namespace_t namespc)
{
- declaration_t *declaration = symbol->declaration;
- for( ; declaration != NULL; declaration = declaration->symbol_next) {
- if (declaration->namespc == namespc)
- return declaration;
+ entity_t *entity = symbol->entity;
+ for( ; entity != NULL; entity = entity->base.symbol_next) {
+ if (entity->base.namespc == namespc)
+ return entity;
}
return NULL;
}
/**
- * pushs an environment_entry on the environment stack and links the
- * corresponding symbol to the new entry
+ * pushs an entity on the environment stack and links the corresponding symbol
+ * it.
*/
-static void stack_push(stack_entry_t **stack_ptr, declaration_t *declaration)
+static void stack_push(stack_entry_t **stack_ptr, entity_t *entity)
{
- symbol_t *symbol = declaration->symbol;
- namespace_t namespc = (namespace_t) declaration->namespc;
+ symbol_t *symbol = entity->base.symbol;
+ namespace_t namespc = entity->base.namespc;
+ assert(namespc != NAMESPACE_INVALID);
- /* replace/add declaration into declaration list of the symbol */
- declaration_t **anchor;
- declaration_t *iter;
- for (anchor = &symbol->declaration;; anchor = &iter->symbol_next) {
+ /* replace/add entity into entity list of the symbol */
+ entity_t **anchor;
+ entity_t *iter;
+ for (anchor = &symbol->entity; ; anchor = &iter->base.symbol_next) {
iter = *anchor;
if (iter == NULL)
break;
/* replace an entry? */
- if (iter->namespc == namespc) {
- declaration->symbol_next = iter->symbol_next;
+ if (iter->base.namespc == namespc) {
+ entity->base.symbol_next = iter->base.symbol_next;
break;
}
}
- *anchor = declaration;
+ *anchor = entity;
/* remember old declaration */
stack_entry_t entry;
- entry.symbol = symbol;
- entry.old_declaration = iter;
- entry.namespc = (unsigned short) namespc;
+ entry.symbol = symbol;
+ entry.old_entity = iter;
+ entry.namespc = namespc;
ARR_APP1(stack_entry_t, *stack_ptr, entry);
}
/**
- * Push a declaration on the environment stack.
- *
- * @param declaration the declaration
+ * Push an entity on the environment stack.
*/
-static void environment_push(declaration_t *declaration)
+static void environment_push(entity_t *entity)
{
- assert(declaration->source_position.input_name != NULL);
- assert(declaration->parent_scope != NULL);
- stack_push(&environment_stack, declaration);
+ assert(entity->base.source_position.input_name != NULL);
+ assert(entity->base.parent_scope != NULL);
+ stack_push(&environment_stack, entity);
}
/**
*
* @param declaration the declaration
*/
-static void label_push(declaration_t *declaration)
+static void label_push(entity_t *label)
{
- declaration->parent_scope = ¤t_function->scope;
- stack_push(&label_stack, declaration);
+ /* we abuse the parameters scope as parent for the labels */
+ label->base.parent_scope = ¤t_function->parameters;
+ stack_push(&label_stack, label);
}
/**
*
* @param declaration the declaration
*/
-static void local_label_push(declaration_t *declaration)
+static void local_label_push(entity_t *label)
{
- assert(declaration->parent_scope != NULL);
- stack_push(&local_label_stack, declaration);
+ assert(label->base.parent_scope != NULL);
+ label->base.parent_scope = scope;
+ stack_push(&local_label_stack, label);
}
/**
for(i = top; i > new_top; --i) {
stack_entry_t *entry = &stack[i - 1];
- declaration_t *old_declaration = entry->old_declaration;
- symbol_t *symbol = entry->symbol;
- namespace_t namespc = (namespace_t)entry->namespc;
+ entity_t *old_entity = entry->old_entity;
+ symbol_t *symbol = entry->symbol;
+ namespace_t namespc = entry->namespc;
- /* replace/remove declaration */
- declaration_t **anchor;
- declaration_t *iter;
- for (anchor = &symbol->declaration;; anchor = &iter->symbol_next) {
+ /* replace with old_entity/remove */
+ entity_t **anchor;
+ entity_t *iter;
+ for (anchor = &symbol->entity; ; anchor = &iter->base.symbol_next) {
iter = *anchor;
assert(iter != NULL);
/* replace an entry? */
- if (iter->namespc == namespc)
+ if (iter->base.namespc == namespc)
break;
}
- /* Not all declarations adhere scopes (e.g. jump labels), so this
- * correction is necessary */
- if (old_declaration != NULL) {
- old_declaration->symbol_next = iter->symbol_next;
- *anchor = old_declaration;
+ /* restore definition from outer scopes (if there was one) */
+ if (old_entity != NULL) {
+ old_entity->base.symbol_next = iter->base.symbol_next;
+ *anchor = old_entity;
} else {
- *anchor = iter->symbol_next;
+ /* remove entry from list */
+ *anchor = iter->base.symbol_next;
}
}
static type_t *make_global_typedef(const char *name, type_t *type)
{
- symbol_t *const symbol = symbol_table_insert(name);
+ symbol_t *const symbol = symbol_table_insert(name);
- declaration_t *const declaration = allocate_declaration_zero();
- declaration->namespc = NAMESPACE_NORMAL;
- declaration->storage_class = STORAGE_CLASS_TYPEDEF;
- declaration->declared_storage_class = STORAGE_CLASS_TYPEDEF;
- declaration->type = type;
- declaration->symbol = symbol;
- declaration->source_position = builtin_source_position;
- declaration->implicit = true;
+ entity_t *const entity = allocate_entity_zero(ENTITY_TYPEDEF);
+ entity->base.symbol = symbol;
+ entity->base.source_position = builtin_source_position;
+ entity->base.namespc = NAMESPACE_NORMAL;
+ entity->typedefe.type = type;
+ entity->typedefe.builtin = true;
- record_declaration(declaration, false);
+ record_entity(entity, false);
- type_t *typedef_type = allocate_type_zero(TYPE_TYPEDEF);
- typedef_type->typedeft.declaration = declaration;
+ type_t *typedef_type = allocate_type_zero(TYPE_TYPEDEF);
+ typedef_type->typedeft.typedefe = &entity->typedefe;
return typedef_type;
}
attribute->have_arguments = true;
}
- switch(kind) {
+ switch (kind) {
case GNU_AK_VOLATILE:
case GNU_AK_NAKED:
case GNU_AK_MALLOC:
decl_modifiers_t modifiers = 0;
while (true) {
- switch(token.type) {
+ switch (token.type) {
case T___attribute__:
modifiers |= parse_gnu_attribute(attributes);
continue;
}
}
-static void mark_decls_read(expression_t *expr, declaration_t *lhs_decl);
+static void mark_vars_read(expression_t *expr, variable_t *lhs_var);
-static declaration_t *determine_lhs_decl(expression_t *const expr, declaration_t *lhs_decl)
+static variable_t *determine_lhs_var(expression_t *const expr,
+ variable_t *lhs_var)
{
switch (expr->kind) {
case EXPR_REFERENCE: {
- declaration_t *const decl = expr->reference.declaration;
- return decl;
+ entity_t *const entity = expr->reference.entity;
+ /* we should only find variables as lavlues... */
+ if (entity->base.kind != ENTITY_VARIABLE)
+ return NULL;
+
+ return &entity->variable;
}
case EXPR_ARRAY_ACCESS: {
- expression_t *const ref = expr->array_access.array_ref;
- declaration_t * decl = NULL;
+ expression_t *const ref = expr->array_access.array_ref;
+ variable_t * var = NULL;
if (is_type_array(skip_typeref(revert_automatic_type_conversion(ref)))) {
- decl = determine_lhs_decl(ref, lhs_decl);
- lhs_decl = decl;
+ var = determine_lhs_var(ref, lhs_var);
+ lhs_var = var;
} else {
- mark_decls_read(expr->select.compound, lhs_decl);
+ mark_vars_read(expr->select.compound, lhs_var);
}
- mark_decls_read(expr->array_access.index, lhs_decl);
- return decl;
+ mark_vars_read(expr->array_access.index, lhs_var);
+ return var;
}
case EXPR_SELECT: {
if (is_type_compound(skip_typeref(expr->base.type))) {
- return determine_lhs_decl(expr->select.compound, lhs_decl);
+ return determine_lhs_var(expr->select.compound, lhs_var);
} else {
- mark_decls_read(expr->select.compound, lhs_decl);
+ mark_vars_read(expr->select.compound, lhs_var);
return NULL;
}
}
expression_t *const val = expr->unary.value;
if (val->kind == EXPR_UNARY_TAKE_ADDRESS) {
/* *&x is a NOP */
- return determine_lhs_decl(val->unary.value, lhs_decl);
+ return determine_lhs_var(val->unary.value, lhs_var);
} else {
- mark_decls_read(val, NULL);
+ mark_vars_read(val, NULL);
return NULL;
}
}
default:
- mark_decls_read(expr, NULL);
+ mark_vars_read(expr, NULL);
return NULL;
}
}
-#define DECL_ANY ((declaration_t*)-1)
+#define VAR_ANY ((variable_t*)-1)
/**
* Mark declarations, which are read. This is used to deted variables, which
* x and y are not detected as "not read", because multiple variables are
* involved.
*/
-static void mark_decls_read(expression_t *const expr, declaration_t *lhs_decl)
+static void mark_vars_read(expression_t *const expr, variable_t *lhs_var)
{
switch (expr->kind) {
case EXPR_REFERENCE: {
- declaration_t *const decl = expr->reference.declaration;
- if (lhs_decl != decl && lhs_decl != DECL_ANY)
- decl->read = true;
+ entity_t *const entity = expr->reference.entity;
+ if (entity->kind != ENTITY_VARIABLE)
+ return;
+
+ variable_t *variable = &entity->variable;
+ if (lhs_var != variable && lhs_var != VAR_ANY) {
+ variable->read = true;
+ }
return;
}
case EXPR_CALL:
// TODO respect pure/const
- mark_decls_read(expr->call.function, NULL);
+ mark_vars_read(expr->call.function, NULL);
for (call_argument_t *arg = expr->call.arguments; arg != NULL; arg = arg->next) {
- mark_decls_read(arg->expression, NULL);
+ mark_vars_read(arg->expression, NULL);
}
return;
case EXPR_CONDITIONAL:
// TODO lhs_decl should depend on whether true/false have an effect
- mark_decls_read(expr->conditional.condition, NULL);
+ mark_vars_read(expr->conditional.condition, NULL);
if (expr->conditional.true_expression != NULL)
- mark_decls_read(expr->conditional.true_expression, lhs_decl);
- mark_decls_read(expr->conditional.false_expression, lhs_decl);
+ mark_vars_read(expr->conditional.true_expression, lhs_var);
+ mark_vars_read(expr->conditional.false_expression, lhs_var);
return;
case EXPR_SELECT:
- if (lhs_decl == DECL_ANY && !is_type_compound(skip_typeref(expr->base.type)))
- lhs_decl = NULL;
- mark_decls_read(expr->select.compound, lhs_decl);
+ if (lhs_var == VAR_ANY && !is_type_compound(skip_typeref(expr->base.type)))
+ lhs_var = NULL;
+ mark_vars_read(expr->select.compound, lhs_var);
return;
case EXPR_ARRAY_ACCESS: {
expression_t *const ref = expr->array_access.array_ref;
- mark_decls_read(ref, lhs_decl);
- lhs_decl = determine_lhs_decl(ref, lhs_decl);
- mark_decls_read(expr->array_access.index, lhs_decl);
+ mark_vars_read(ref, lhs_var);
+ lhs_var = determine_lhs_var(ref, lhs_var);
+ mark_vars_read(expr->array_access.index, lhs_var);
return;
}
case EXPR_VA_ARG:
- mark_decls_read(expr->va_arge.ap, lhs_decl);
+ mark_vars_read(expr->va_arge.ap, lhs_var);
return;
case EXPR_UNARY_CAST:
/* Special case: Use void cast to mark a variable as "read" */
if (is_type_atomic(skip_typeref(expr->base.type), ATOMIC_TYPE_VOID))
- lhs_decl = NULL;
+ lhs_var = NULL;
goto unary;
case EXPR_UNARY_DEREFERENCE:
case EXPR_UNARY_DELETE:
case EXPR_UNARY_DELETE_ARRAY:
- if (lhs_decl == DECL_ANY)
- lhs_decl = NULL;
+ if (lhs_var == VAR_ANY)
+ lhs_var = NULL;
goto unary;
case EXPR_UNARY_NEGATE:
case EXPR_UNARY_CAST_IMPLICIT:
case EXPR_UNARY_ASSUME:
unary:
- mark_decls_read(expr->unary.value, lhs_decl);
+ mark_vars_read(expr->unary.value, lhs_var);
return;
case EXPR_BINARY_ADD:
case EXPR_BINARY_ISLESSEQUAL:
case EXPR_BINARY_ISLESSGREATER:
case EXPR_BINARY_ISUNORDERED:
- mark_decls_read(expr->binary.left, lhs_decl);
- mark_decls_read(expr->binary.right, lhs_decl);
+ mark_vars_read(expr->binary.left, lhs_var);
+ mark_vars_read(expr->binary.right, lhs_var);
return;
case EXPR_BINARY_ASSIGN:
case EXPR_BINARY_BITWISE_AND_ASSIGN:
case EXPR_BINARY_BITWISE_XOR_ASSIGN:
case EXPR_BINARY_BITWISE_OR_ASSIGN: {
- if (lhs_decl == DECL_ANY)
- lhs_decl = NULL;
- lhs_decl = determine_lhs_decl(expr->binary.left, lhs_decl);
- mark_decls_read(expr->binary.right, lhs_decl);
+ if (lhs_var == VAR_ANY)
+ lhs_var = NULL;
+ lhs_var = determine_lhs_var(expr->binary.left, lhs_var);
+ mark_vars_read(expr->binary.right, lhs_var);
return;
}
case EXPR_VA_START:
- determine_lhs_decl(expr->va_starte.ap, lhs_decl);
+ determine_lhs_var(expr->va_starte.ap, lhs_var);
return;
case EXPR_UNKNOWN:
case EXPR_STATEMENT: // TODO
case EXPR_LABEL_ADDRESS:
case EXPR_BINARY_BUILTIN_EXPECT:
+ case EXPR_REFERENCE_ENUM_VALUE:
return;
}
while (true) {
designator_t *designator;
- switch(token.type) {
+ switch (token.type) {
case '[':
designator = allocate_ast_zero(sizeof(designator[0]));
designator->source_position = token.source_position;
}
expression_t *expression = parse_assignment_expression();
- mark_decls_read(expression, NULL);
+ mark_vars_read(expression, NULL);
if (must_be_constant && !is_initializer_constant(expression)) {
errorf(&expression->base.source_position,
"Initialisation expression '%E' is not constant\n",
assert(i == len-1);
continue;
}
- fprintf(stderr, ".%s", entry->v.compound_entry->symbol->string);
+ fprintf(stderr, ".%s",
+ entry->v.compound_entry->base.symbol->string);
} else if (is_type_array(type)) {
fprintf(stderr, "[%zu]", entry->v.index);
} else {
}
/**
- * Descending into a sub-type. Enter the scope of the current
- * top_type.
+ * Descending into a sub-type. Enter the scope of the current top_type.
*/
static void descend_into_subtype(type_path_t *path)
{
top->type = top_type;
if (is_type_compound(top_type)) {
- declaration_t *declaration = top_type->compound.declaration;
- declaration_t *entry = declaration->scope.declarations;
- top->v.compound_entry = entry;
+ compound_t *compound = top_type->compound.compound;
+ entity_t *entry = compound->members.entities;
if (entry != NULL) {
- path->top_type = entry->type;
+ assert(entry->kind == ENTITY_COMPOUND_MEMBER);
+ top->v.compound_entry = &entry->declaration;
+ path->top_type = entry->declaration.type;
} else {
- path->top_type = NULL;
+ path->top_type = NULL;
}
} else if (is_type_array(top_type)) {
top->v.index = 0;
top->v.compound_entry = NULL;
orig_type = type_error_type;
} else {
- declaration_t *declaration = type->compound.declaration;
- declaration_t *iter = declaration->scope.declarations;
- for( ; iter != NULL; iter = iter->next) {
- if (iter->symbol == symbol) {
+ compound_t *compound = type->compound.compound;
+ entity_t *iter = compound->members.entities;
+ for( ; iter != NULL; iter = iter->base.next) {
+ if (iter->base.symbol == symbol) {
break;
}
}
"'%T' has no member named '%Y'", orig_type, symbol);
goto failed;
}
+ assert(iter->kind == ENTITY_COMPOUND_MEMBER);
if (used_in_offsetof) {
- type_t *real_type = skip_typeref(iter->type);
+ type_t *real_type = skip_typeref(iter->declaration.type);
if (real_type->kind == TYPE_BITFIELD) {
errorf(&designator->source_position,
"offsetof designator '%Y' may not specify bitfield",
}
top->type = orig_type;
- top->v.compound_entry = iter;
- orig_type = iter->type;
+ top->v.compound_entry = &iter->declaration;
+ orig_type = iter->declaration.type;
}
} else {
expression_t *array_index = designator->array_index;
} else if (is_type_struct(type)) {
declaration_t *entry = top->v.compound_entry;
- entry = entry->next;
+ entity_t *next_entity = entry->base.next;
+ if (next_entity != NULL) {
+ assert(is_declaration(next_entity));
+ entry = &next_entity->declaration;
+ } else {
+ entry = NULL;
+ }
+
top->v.compound_entry = entry;
if (entry != NULL) {
path->top_type = entry->type;
} else {
eat('{');
if (type == NULL) {
- if (env->declaration != NULL) {
- errorf(HERE, "extra brace group at end of initializer for '%Y'",
- env->declaration->symbol);
+ if (env->entity != NULL) {
+ errorf(HERE,
+ "extra brace group at end of initializer for '%Y'",
+ env->entity->base.symbol);
} else {
errorf(HERE, "extra brace group at end of initializer");
}
/* we are already outside, ... */
type_t *const outer_type_skip = skip_typeref(outer_type);
if (is_type_compound(outer_type_skip) &&
- !outer_type_skip->compound.declaration->init.complete) {
+ !outer_type_skip->compound.compound->complete) {
goto error_parse_next;
}
goto error_excess;
} else {
error_excess:
if (warning.other) {
- if (env->declaration != NULL) {
+ if (env->entity != NULL) {
warningf(HERE, "excess elements in struct initializer for '%Y'",
- env->declaration->symbol);
+ env->entity->base.symbol);
} else {
warningf(HERE, "excess elements in struct initializer");
}
return NULL;
}
-static declaration_t *append_declaration(declaration_t *declaration);
+static void append_entity(scope_t *scope, entity_t *entity)
+{
+ if (scope->last_entity != NULL) {
+ scope->last_entity->base.next = entity;
+ } else {
+ scope->entities = entity;
+ }
+ scope->last_entity = entity;
+}
+
-static declaration_t *parse_compound_type_specifier(bool is_struct)
+static compound_t *parse_compound_type_specifier(bool is_struct)
{
gnu_attribute_t *attributes = NULL;
decl_modifiers_t modifiers = 0;
eat(T_union);
}
- symbol_t *symbol = NULL;
- declaration_t *declaration = NULL;
+ symbol_t *symbol = NULL;
+ compound_t *compound = NULL;
if (token.type == T___attribute__) {
modifiers |= parse_attributes(&attributes);
namespace_t const namespc =
is_struct ? NAMESPACE_STRUCT : NAMESPACE_UNION;
- declaration = get_declaration(symbol, namespc);
- if (declaration != NULL) {
- if (declaration->parent_scope != scope &&
+ 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 &&
(token.type == '{' || token.type == ';')) {
- declaration = NULL;
- } else if (declaration->init.complete &&
- token.type == '{') {
+ /* we're in an inner scope and have a definition. Override
+ existing definition in outer scope */
+ compound = NULL;
+ } else if (compound->complete && token.type == '{') {
assert(symbol != NULL);
errorf(HERE, "multiple definitions of '%s %Y' (previous definition at %P)",
is_struct ? "struct" : "union", symbol,
- &declaration->source_position);
- declaration->scope.declarations = NULL;
+ &compound->base.source_position);
+ /* clear members in the hope to avoid further errors */
+ compound->members.entities = NULL;
}
}
} else if (token.type != '{') {
return NULL;
}
- if (declaration == NULL) {
- declaration = allocate_declaration_zero();
- declaration->namespc =
+ if (compound == NULL) {
+ entity_kind_t kind = is_struct ? ENTITY_STRUCT : ENTITY_UNION;
+ entity_t *entity = allocate_entity_zero(kind);
+ compound = &entity->compound;
+
+ compound->base.namespc =
(is_struct ? NAMESPACE_STRUCT : NAMESPACE_UNION);
- declaration->source_position = token.source_position;
- declaration->symbol = symbol;
- declaration->parent_scope = scope;
+ compound->base.source_position = token.source_position;
+ compound->base.symbol = symbol;
+ compound->base.parent_scope = scope;
if (symbol != NULL) {
- environment_push(declaration);
+ environment_push(entity);
}
- append_declaration(declaration);
+ append_entity(scope, entity);
}
if (token.type == '{') {
- declaration->init.complete = true;
+ compound->complete = true;
- parse_compound_type_entries(declaration);
+ parse_compound_type_entries(compound);
modifiers |= parse_attributes(&attributes);
}
- declaration->modifiers |= modifiers;
- return declaration;
+ compound->modifiers |= modifiers;
+ return compound;
}
static void parse_enum_entries(type_t *const enum_type)
return;
}
- declaration_t *const entry = allocate_declaration_zero();
- entry->storage_class = STORAGE_CLASS_ENUM_ENTRY;
- entry->type = enum_type;
- entry->symbol = token.v.symbol;
- entry->source_position = token.source_position;
+ entity_t *entity = allocate_entity_zero(ENTITY_ENUM_VALUE);
+ entity->enum_value.enum_type = enum_type;
+ entity->base.symbol = token.v.symbol;
+ entity->base.source_position = token.source_position;
next_token();
if (token.type == '=') {
expression_t *value = parse_constant_expression();
value = create_implicit_cast(value, enum_type);
- entry->init.enum_value = value;
+ entity->enum_value.value = value;
/* TODO semantic */
}
- record_declaration(entry, false);
+ record_entity(entity, false);
if (token.type != ',')
break;
static type_t *parse_enum_specifier(void)
{
gnu_attribute_t *attributes = NULL;
- declaration_t *declaration;
+ entity_t *entity;
symbol_t *symbol;
eat(T_enum);
symbol = token.v.symbol;
next_token();
- declaration = get_declaration(symbol, NAMESPACE_ENUM);
+ entity = get_entity(symbol, NAMESPACE_ENUM);
+ assert(entity == NULL || entity->kind == ENTITY_ENUM);
} else if (token.type != '{') {
parse_error_expected("while parsing enum type specifier",
T_IDENTIFIER, '{', NULL);
return NULL;
} else {
- declaration = NULL;
- symbol = NULL;
+ entity = NULL;
+ symbol = NULL;
}
- if (declaration == NULL) {
- declaration = allocate_declaration_zero();
- declaration->namespc = NAMESPACE_ENUM;
- declaration->source_position = token.source_position;
- declaration->symbol = symbol;
- declaration->parent_scope = scope;
+ if (entity == NULL) {
+ entity = allocate_entity_zero(ENTITY_ENUM);
+ entity->base.namespc = NAMESPACE_ENUM;
+ entity->base.source_position = token.source_position;
+ entity->base.symbol = symbol;
+ entity->base.parent_scope = scope;
}
- type_t *const type = allocate_type_zero(TYPE_ENUM);
- type->enumt.declaration = declaration;
+ type_t *const type = allocate_type_zero(TYPE_ENUM);
+ type->enumt.enume = &entity->enume;
if (token.type == '{') {
- if (declaration->init.complete) {
- errorf(HERE, "multiple definitions of enum %Y", symbol);
+ if (entity->enume.complete) {
+ errorf(HERE, "multiple definitions of enum %Y (previous definition at %P)",
+ symbol, &entity->base.source_position);
}
if (symbol != NULL) {
- environment_push(declaration);
+ environment_push(entity);
}
- append_declaration(declaration);
- declaration->init.complete = true;
+ append_entity(scope, entity);
+ entity->enume.complete = true;
parse_enum_entries(type);
parse_attributes(&attributes);
+ } else if(!entity->enume.complete && !(c_mode & _GNUC)) {
+ errorf(HERE, "enum %Y used before definition (incomplete enumes are a GNU extension)",
+ symbol);
}
return type;
*/
static bool is_typedef_symbol(symbol_t *symbol)
{
- const declaration_t *const declaration =
- get_declaration(symbol, NAMESPACE_NORMAL);
- return
- declaration != NULL &&
- declaration->storage_class == STORAGE_CLASS_TYPEDEF;
+ const entity_t *const entity = get_entity(symbol, NAMESPACE_NORMAL);
+ return entity != NULL && entity->kind == ENTITY_TYPEDEF;
}
static type_t *parse_typeof(void)
static type_t *get_typedef_type(symbol_t *symbol)
{
- declaration_t *declaration = get_declaration(symbol, NAMESPACE_NORMAL);
- if (declaration == NULL ||
- declaration->storage_class != STORAGE_CLASS_TYPEDEF)
+ entity_t *entity = get_entity(symbol, NAMESPACE_NORMAL);
+ if (entity == NULL || entity->kind != ENTITY_TYPEDEF)
return NULL;
- type_t *type = allocate_type_zero(TYPE_TYPEDEF);
- type->typedeft.declaration = declaration;
+ type_t *type = allocate_type_zero(TYPE_TYPEDEF);
+ type->typedeft.typedefe = &entity->typedefe;
return type;
}
next_token();
if (specifiers->deprecated != 0 && warning.other)
warningf(HERE, "deprecated used more than once");
- specifiers->deprecated = 1;
+ specifiers->deprecated = true;
if (token.type == '(') {
next_token();
if (token.type == T_STRING_LITERAL) {
return;
}
-static declaration_t *create_error_declaration(symbol_t *symbol, storage_class_tag_t storage_class)
+static entity_t *create_error_entity(symbol_t *symbol, entity_kind_tag_t kind)
{
- declaration_t *const decl = allocate_declaration_zero();
- decl->source_position = *HERE;
- decl->declared_storage_class = storage_class;
- decl->storage_class =
- storage_class != STORAGE_CLASS_NONE || scope == file_scope ?
- storage_class : STORAGE_CLASS_AUTO;
- decl->symbol = symbol;
- decl->implicit = true;
- record_declaration(decl, false);
- return decl;
+ entity_t *entity = allocate_entity_zero(kind);
+ entity->base.source_position = *HERE;
+ entity->base.symbol = symbol;
+ if (is_declaration(entity)) {
+ entity->declaration.implicit = true;
+ }
+ record_entity(entity, false);
+ return entity;
}
/**
* Finish the construction of a struct type by calculating
* its size, offsets, alignment.
*/
-static void finish_struct_type(compound_type_t *type) {
- if (type->declaration == NULL)
- return;
- declaration_t *struct_decl = type->declaration;
- if (! struct_decl->init.complete)
+static void finish_struct_type(compound_type_t *type)
+{
+ assert(type->compound != NULL);
+
+ compound_t *compound = type->compound;
+ if (!compound->complete)
return;
il_size_t size = 0;
il_alignment_t alignment = 1;
bool need_pad = false;
- declaration_t *entry = struct_decl->scope.declarations;
- for (; entry != NULL; entry = entry->next) {
- if (entry->namespc != NAMESPACE_NORMAL)
+ entity_t *entry = compound->members.entities;
+ for (; entry != NULL; entry = entry->base.next) {
+ if (entry->kind != ENTITY_COMPOUND_MEMBER)
continue;
- type_t *m_type = skip_typeref(entry->type);
+ type_t *m_type = skip_typeref(entry->declaration.type);
if (! is_type_valid(m_type)) {
/* simply ignore errors here */
continue;
if (offset > size)
need_pad = true;
- entry->offset = offset;
+ entry->compound_member.offset = offset;
size = offset + m_type->base.size;
}
if (type->base.alignment != 0) {
need_pad = true;
if (warning.padded && need_pad) {
- warningf(&struct_decl->source_position,
- "'%#T' needs padding", type, struct_decl->symbol);
+ warningf(&compound->base.source_position,
+ "'%#T' needs padding", type, compound->base.symbol);
}
if (warning.packed && !need_pad) {
- warningf(&struct_decl->source_position,
+ warningf(&compound->base.source_position,
"superfluous packed attribute on '%#T'",
- type, struct_decl->symbol);
+ type, compound->base.symbol);
}
type->base.size = offset;
* Finish the construction of an union type by calculating
* its size and alignment.
*/
-static void finish_union_type(compound_type_t *type) {
- if (type->declaration == NULL)
- return;
- declaration_t *union_decl = type->declaration;
- if (! union_decl->init.complete)
+static void finish_union_type(compound_type_t *type)
+{
+ assert(type->compound != NULL);
+
+ compound_t *compound = type->compound;
+ if (! compound->complete)
return;
il_size_t size = 0;
il_alignment_t alignment = 1;
- declaration_t *entry = union_decl->scope.declarations;
- for (; entry != NULL; entry = entry->next) {
- if (entry->namespc != NAMESPACE_NORMAL)
+ entity_t *entry = compound->members.entities;
+ for (; entry != NULL; entry = entry->base.next) {
+ if (entry->kind != ENTITY_COMPOUND_MEMBER)
continue;
- type_t *m_type = skip_typeref(entry->type);
+ type_t *m_type = skip_typeref(entry->declaration.type);
if (! is_type_valid(m_type))
continue;
- entry->offset = 0;
+ entry->compound_member.offset = 0;
if (m_type->base.size > size)
size = m_type->base.size;
if (m_type->base.alignment > alignment)
/* storage class */
#define MATCH_STORAGE_CLASS(token, class) \
case token: \
- if (specifiers->declared_storage_class != STORAGE_CLASS_NONE) { \
+ if (specifiers->storage_class != STORAGE_CLASS_NONE) { \
errorf(HERE, "multiple storage classes in declaration specifiers"); \
} \
- specifiers->declared_storage_class = class; \
+ specifiers->storage_class = class; \
next_token(); \
break;
break;
case T___thread:
- switch (specifiers->declared_storage_class) {
+ switch (specifiers->storage_class) {
case STORAGE_CLASS_NONE:
- specifiers->declared_storage_class = STORAGE_CLASS_THREAD;
+ specifiers->storage_class = STORAGE_CLASS_THREAD;
break;
case STORAGE_CLASS_EXTERN:
- specifiers->declared_storage_class = STORAGE_CLASS_THREAD_EXTERN;
+ specifiers->storage_class = STORAGE_CLASS_THREAD_EXTERN;
break;
case STORAGE_CLASS_STATIC:
- specifiers->declared_storage_class = STORAGE_CLASS_THREAD_STATIC;
+ specifiers->storage_class = STORAGE_CLASS_THREAD_STATIC;
break;
default:
case T_struct: {
type = allocate_type_zero(TYPE_COMPOUND_STRUCT);
- type->compound.declaration = parse_compound_type_specifier(true);
+ type->compound.compound = parse_compound_type_specifier(true);
finish_struct_type(&type->compound);
break;
}
case T_union: {
type = allocate_type_zero(TYPE_COMPOUND_UNION);
- type->compound.declaration = parse_compound_type_specifier(false);
- if (type->compound.declaration->modifiers & DM_TRANSPARENT_UNION)
+ type->compound.compound = parse_compound_type_specifier(false);
+ if (type->compound.compound->modifiers & DM_TRANSPARENT_UNION)
modifiers |= TYPE_MODIFIER_TRANSPARENT_UNION;
finish_union_type(&type->compound);
break;
case '*': {
errorf(HERE, "%K does not name a type", &token);
- declaration_t *const decl =
- create_error_declaration(token.v.symbol, STORAGE_CLASS_TYPEDEF);
+ entity_t *entity =
+ create_error_entity(token.v.symbol, ENTITY_TYPEDEF);
type = allocate_type_zero(TYPE_TYPEDEF);
- type->typedeft.declaration = decl;
+ type->typedeft.typedefe = &entity->typedefe;
next_token();
saw_error = true;
atomic_type_kind_t atomic_type;
/* match valid basic types */
- switch(type_specifiers) {
+ switch (type_specifiers) {
case SPECIFIER_VOID:
atomic_type = ATOMIC_TYPE_VOID;
break;
type_qualifiers_t qualifiers = TYPE_QUALIFIER_NONE;
while (true) {
- switch(token.type) {
+ switch (token.type) {
/* type qualifiers */
MATCH_TYPE_QUALIFIER(T_const, TYPE_QUALIFIER_CONST);
MATCH_TYPE_QUALIFIER(T_restrict, TYPE_QUALIFIER_RESTRICT);
}
/**
- * Parses an K&R identifier list and return a list of declarations.
- *
- * @param last points to the last declaration in the list
- * @return the list of declarations
+ * Parses an K&R identifier list
*/
-static declaration_t *parse_identifier_list(declaration_t **last)
+static void parse_identifier_list(scope_t *scope)
{
- declaration_t *declarations = NULL;
- declaration_t *last_declaration = NULL;
do {
- declaration_t *const declaration = allocate_declaration_zero();
- declaration->type = NULL; /* a K&R parameter list has no types, yet */
- declaration->source_position = token.source_position;
- declaration->symbol = token.v.symbol;
+ entity_t *entity = allocate_entity_zero(ENTITY_VARIABLE);
+ entity->base.source_position = token.source_position;
+ entity->base.namespc = NAMESPACE_NORMAL;
+ entity->base.symbol = token.v.symbol;
+ /* a K&R parameter has no type, yet */
next_token();
- if (last_declaration != NULL) {
- last_declaration->next = declaration;
- } else {
- declarations = declaration;
- }
- last_declaration = declaration;
+ append_entity(scope, entity);
if (token.type != ',') {
break;
}
next_token();
} while (token.type == T_IDENTIFIER);
-
- *last = last_declaration;
- return declarations;
}
static type_t *automatic_type_conversion(type_t *orig_type);
static void semantic_parameter(declaration_t *declaration)
{
/* TODO: improve error messages */
- source_position_t const* const pos = &declaration->source_position;
+ source_position_t const* const pos = &declaration->base.source_position;
+ /* §6.9.1:6 */
switch (declaration->declared_storage_class) {
- case STORAGE_CLASS_TYPEDEF:
- errorf(pos, "typedef not allowed in parameter list");
- break;
-
/* Allowed storage classes */
case STORAGE_CLASS_NONE:
case STORAGE_CLASS_REGISTER:
if (is_type_incomplete(skip_typeref(type))) {
errorf(pos, "parameter '%#T' is of incomplete type",
- orig_type, declaration->symbol);
+ orig_type, declaration->base.symbol);
}
}
-static declaration_t *parse_parameter(void)
+static entity_t *parse_parameter(void)
{
declaration_specifiers_t specifiers;
memset(&specifiers, 0, sizeof(specifiers));
parse_declaration_specifiers(&specifiers);
- declaration_t *declaration = parse_declarator(&specifiers, /*may_be_abstract=*/true);
-
- return declaration;
+ entity_t *entity = parse_declarator(&specifiers, true, false);
+ return entity;
}
/**
- * Parses a function type parameter list and return a list of declarations.
- *
- * @param last point to the last element of the list
- * @return the parameter list
+ * Parses function type parameters (and optionally creates variable_t entities
+ * for them in a scope)
*/
-static declaration_t *parse_parameters(function_type_t *type, declaration_t **last)
+static void parse_parameters(function_type_t *type, scope_t *scope)
{
- declaration_t *declarations = NULL;
-
eat('(');
add_anchor_token(')');
int saved_comma_state = save_and_reset_anchor_state(',');
token_type_t la1_type = (token_type_t)look_ahead(1)->type;
if (la1_type == ',' || la1_type == ')') {
type->kr_style_parameters = true;
- declarations = parse_identifier_list(last);
+ parse_identifier_list(scope);
goto parameters_finished;
}
}
if (token.type == ')') {
/* ISO/IEC 14882:1998(E) §C.1.6:1 */
if (!(c_mode & _CXX))
- type->unspecified_parameters = 1;
+ type->unspecified_parameters = true;
goto parameters_finished;
}
- declaration_t *declaration;
- declaration_t *last_declaration = NULL;
function_parameter_t *parameter;
function_parameter_t *last_parameter = NULL;
while (true) {
- switch(token.type) {
+ switch (token.type) {
case T_DOTDOTDOT:
next_token();
- type->variadic = 1;
+ type->variadic = true;
goto parameters_finished;
case T_IDENTIFIER:
case T___extension__:
DECLARATION_START
- declaration = parse_parameter();
+ {
+ entity_t *entity = parse_parameter();
+ if (entity->kind == ENTITY_TYPEDEF) {
+ errorf(&entity->base.source_position,
+ "typedef not allowed as function parameter");
+ break;
+ }
+ assert(is_declaration(entity));
/* func(void) is not a parameter */
if (last_parameter == NULL
&& token.type == ')'
- && declaration->symbol == NULL
- && skip_typeref(declaration->type) == type_void) {
+ && entity->base.symbol == NULL
+ && skip_typeref(entity->declaration.type) == type_void) {
goto parameters_finished;
}
- semantic_parameter(declaration);
+ semantic_parameter(&entity->declaration);
- parameter = obstack_alloc(type_obst, sizeof(parameter[0]));
+ parameter = obstack_alloc(type_obst, sizeof(parameter[0]));
memset(parameter, 0, sizeof(parameter[0]));
- parameter->type = declaration->type;
+ parameter->type = entity->declaration.type;
+
+ if (scope != NULL) {
+ append_entity(scope, entity);
+ }
if (last_parameter != NULL) {
- last_declaration->next = declaration;
- last_parameter->next = parameter;
+ last_parameter->next = parameter;
} else {
type->parameters = parameter;
- declarations = declaration;
}
last_parameter = parameter;
- last_declaration = declaration;
break;
+ }
default:
goto parameters_finished;
rem_anchor_token(')');
expect(')');
- restore_anchor_state(',', saved_comma_state);
- *last = last_declaration;
- return declarations;
-
end_error:
restore_anchor_state(',', saved_comma_state);
- *last = NULL;
- return NULL;
}
typedef enum construct_type_kind_t {
return (construct_type_t*) array;
}
-static construct_type_t *parse_function_declarator(declaration_t *declaration)
+static construct_type_t *parse_function_declarator(scope_t *scope)
{
- type_t *type;
- if (declaration != NULL) {
- type = allocate_type_zero(TYPE_FUNCTION);
+ type_t *type = allocate_type_zero(TYPE_FUNCTION);
- unsigned mask = declaration->modifiers & (DM_CDECL|DM_STDCALL|DM_FASTCALL|DM_THISCALL);
+ /* TODO: revive this... once we know exactly how to do it */
+#if 0
+ decl_modifiers_t modifiers = entity->declaration.modifiers;
- if (mask & (mask-1)) {
- const char *first = NULL, *second = NULL;
+ unsigned mask = modifiers & (DM_CDECL|DM_STDCALL|DM_FASTCALL|DM_THISCALL);
- /* more than one calling convention set */
- if (declaration->modifiers & DM_CDECL) {
- if (first == NULL) first = "cdecl";
- else if (second == NULL) second = "cdecl";
- }
- if (declaration->modifiers & DM_STDCALL) {
- if (first == NULL) first = "stdcall";
- else if (second == NULL) second = "stdcall";
- }
- if (declaration->modifiers & DM_FASTCALL) {
- if (first == NULL) first = "fastcall";
- else if (second == NULL) second = "fastcall";
- }
- if (declaration->modifiers & DM_THISCALL) {
- if (first == NULL) first = "thiscall";
- else if (second == NULL) second = "thiscall";
- }
- errorf(&declaration->source_position, "%s and %s attributes are not compatible", first, second);
- }
+ if (mask & (mask-1)) {
+ const char *first = NULL, *second = NULL;
- if (declaration->modifiers & DM_CDECL)
- type->function.calling_convention = CC_CDECL;
- else if (declaration->modifiers & DM_STDCALL)
- type->function.calling_convention = CC_STDCALL;
- else if (declaration->modifiers & DM_FASTCALL)
- type->function.calling_convention = CC_FASTCALL;
- else if (declaration->modifiers & DM_THISCALL)
- type->function.calling_convention = CC_THISCALL;
- } else {
- type = allocate_type_zero(TYPE_FUNCTION);
+ /* 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);
}
- declaration_t *last;
- declaration_t *parameters = parse_parameters(&type->function, &last);
- if (declaration != NULL) {
- declaration->scope.declarations = parameters;
- declaration->scope.last_declaration = last;
- }
+ 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);
construct_function_type_t *construct_function_type =
obstack_alloc(&temp_obst, sizeof(construct_function_type[0]));
return &construct_function_type->construct_type;
}
-static void fix_declaration_type(declaration_t *declaration)
-{
- decl_modifiers_t declaration_modifiers = declaration->modifiers;
- type_modifiers_t type_modifiers = declaration->type->base.modifiers;
-
- if (declaration_modifiers & DM_TRANSPARENT_UNION)
- type_modifiers |= TYPE_MODIFIER_TRANSPARENT_UNION;
-
- if (declaration->type->base.modifiers == type_modifiers)
- return;
-
- type_t *copy = duplicate_type(declaration->type);
- copy->base.modifiers = type_modifiers;
-
- type_t *result = typehash_insert(copy);
- if (result != copy) {
- obstack_free(type_obst, copy);
- }
-
- declaration->type = result;
-}
+typedef struct parse_declarator_env_t {
+ decl_modifiers_t modifiers;
+ symbol_t *symbol;
+ source_position_t source_position;
+ scope_t parameters;
+} parse_declarator_env_t;
-static construct_type_t *parse_inner_declarator(declaration_t *declaration,
+static construct_type_t *parse_inner_declarator(parse_declarator_env_t *env,
bool may_be_abstract)
{
/* construct a single linked list of construct_type_t's which describe
* how to construct the final declarator type */
- construct_type_t *first = NULL;
- construct_type_t *last = NULL;
+ construct_type_t *first = NULL;
+ construct_type_t *last = NULL;
gnu_attribute_t *attributes = NULL;
decl_modifiers_t modifiers = parse_attributes(&attributes);
modifiers |= parse_attributes(&attributes);
}
- if (declaration != NULL)
- declaration->modifiers |= modifiers;
+ if (env != NULL)
+ env->modifiers |= modifiers;
construct_type_t *inner_types = NULL;
- switch(token.type) {
+ switch (token.type) {
case T_IDENTIFIER:
- if (declaration == NULL) {
+ if (env == NULL) {
errorf(HERE, "no identifier expected in typename");
} else {
- declaration->symbol = token.v.symbol;
- declaration->source_position = token.source_position;
+ env->symbol = token.v.symbol;
+ env->source_position = token.source_position;
}
next_token();
break;
case '(':
next_token();
add_anchor_token(')');
- inner_types = parse_inner_declarator(declaration, may_be_abstract);
+ inner_types = parse_inner_declarator(env, may_be_abstract);
if (inner_types != NULL) {
- /* All later declarators only modify the return type, not declaration */
- declaration = NULL;
+ /* All later declarators only modify the return type */
+ env = NULL;
}
rem_anchor_token(')');
expect(')');
while(true) {
construct_type_t *type;
- switch(token.type) {
- case '(':
- type = parse_function_declarator(declaration);
+ switch (token.type) {
+ case '(': {
+ scope_t *scope = NULL;
+ if (env != NULL)
+ scope = &env->parameters;
+
+ type = parse_function_declarator(scope);
break;
+ }
case '[':
type = parse_array_declarator();
break;
return NULL;
}
-static void parse_declaration_attributes(declaration_t *declaration)
+static void parse_declaration_attributes(entity_t *entity)
{
gnu_attribute_t *attributes = NULL;
decl_modifiers_t modifiers = parse_attributes(&attributes);
- if (declaration == NULL)
+ if (entity == NULL)
return;
- declaration->modifiers |= modifiers;
- /* check if we have these stupid mode attributes... */
- type_t *old_type = declaration->type;
- if (old_type == NULL)
+ type_t *type;
+ if (entity->kind == ENTITY_TYPEDEF) {
+ modifiers |= entity->typedefe.modifiers;
+ type = entity->typedefe.type;
+ } else {
+ assert(is_declaration(entity));
+ modifiers |= entity->declaration.modifiers;
+ type = entity->declaration.type;
+ }
+ if (type == NULL)
return;
+ /* handle these strange/stupid mode attributes */
gnu_attribute_t *attribute = attributes;
for ( ; attribute != NULL; attribute = attribute->next) {
if (attribute->kind != GNU_AK_MODE || attribute->invalid)
continue;
atomic_type_kind_t akind = attribute->u.akind;
- if (!is_type_signed(old_type)) {
- switch(akind) {
+ if (!is_type_signed(type)) {
+ switch (akind) {
case ATOMIC_TYPE_CHAR: akind = ATOMIC_TYPE_UCHAR; break;
case ATOMIC_TYPE_SHORT: akind = ATOMIC_TYPE_USHORT; break;
case ATOMIC_TYPE_INT: akind = ATOMIC_TYPE_UINT; break;
default:
panic("invalid akind in mode attribute");
}
+ } else {
+ switch (akind) {
+ case ATOMIC_TYPE_CHAR: akind = ATOMIC_TYPE_SCHAR; break;
+ case ATOMIC_TYPE_SHORT: akind = ATOMIC_TYPE_SHORT; break;
+ case ATOMIC_TYPE_INT: akind = ATOMIC_TYPE_INT; break;
+ case ATOMIC_TYPE_LONGLONG: akind = ATOMIC_TYPE_LONGLONG; break;
+ default:
+ panic("invalid akind in mode attribute");
+ }
}
- declaration->type
- = make_atomic_type(akind, old_type->base.qualifiers);
+
+ type = make_atomic_type(akind, type->base.qualifiers);
+ }
+
+ type_modifiers_t type_modifiers = type->base.modifiers;
+ if (modifiers & DM_TRANSPARENT_UNION)
+ modifiers |= TYPE_MODIFIER_TRANSPARENT_UNION;
+
+ if (type->base.modifiers != type_modifiers) {
+ type_t *copy = duplicate_type(type);
+ copy->base.modifiers = type_modifiers;
+
+ type = typehash_insert(copy);
+ if (type != copy) {
+ obstack_free(type_obst, copy);
+ }
+ }
+
+ if (entity->kind == ENTITY_TYPEDEF) {
+ entity->typedefe.type = type;
+ entity->typedefe.modifiers = modifiers;
+ } else {
+ entity->declaration.type = type;
+ entity->declaration.modifiers = modifiers;
}
}
{
construct_type_t *iter = construct_list;
for( ; iter != NULL; iter = iter->next) {
- switch(iter->kind) {
+ switch (iter->kind) {
case CONSTRUCT_INVALID:
internal_errorf(HERE, "invalid type construction found");
case CONSTRUCT_FUNCTION: {
return type;
}
-static declaration_t *parse_declarator(
- const declaration_specifiers_t *specifiers, bool may_be_abstract)
+static entity_t *parse_declarator(const declaration_specifiers_t *specifiers,
+ bool may_be_abstract,
+ bool create_compound_member)
{
- declaration_t *const declaration = allocate_declaration_zero();
- declaration->source_position = specifiers->source_position;
- declaration->declared_storage_class = specifiers->declared_storage_class;
- declaration->modifiers = specifiers->modifiers;
- declaration->deprecated_string = specifiers->deprecated_string;
- declaration->get_property_sym = specifiers->get_property_sym;
- declaration->put_property_sym = specifiers->put_property_sym;
- declaration->is_inline = specifiers->is_inline;
+ parse_declarator_env_t env;
+ memset(&env, 0, sizeof(env));
- declaration->storage_class = specifiers->declared_storage_class;
- if (declaration->storage_class == STORAGE_CLASS_NONE &&
- scope != file_scope) {
- declaration->storage_class = STORAGE_CLASS_AUTO;
- }
+ construct_type_t *construct_type
+ = parse_inner_declarator(&env, may_be_abstract);
+ type_t *type = construct_declarator_type(construct_type, specifiers->type);
- if (specifiers->alignment != 0) {
- /* TODO: add checks here */
- declaration->alignment = specifiers->alignment;
+ if (construct_type != NULL) {
+ obstack_free(&temp_obst, construct_type);
}
- construct_type_t *construct_type
- = parse_inner_declarator(declaration, may_be_abstract);
- type_t *const type = specifiers->type;
- declaration->type = construct_declarator_type(construct_type, type);
+ entity_t *entity;
+ if (specifiers->storage_class == STORAGE_CLASS_TYPEDEF) {
+ entity = allocate_entity_zero(ENTITY_TYPEDEF);
+ entity->base.symbol = env.symbol;
+ entity->base.source_position = env.source_position;
+ entity->typedefe.type = type;
+ } else {
+ if (create_compound_member) {
+ entity = allocate_entity_zero(ENTITY_COMPOUND_MEMBER);
+ } else if (is_type_function(skip_typeref(type))) {
+ entity = allocate_entity_zero(ENTITY_FUNCTION);
+
+ entity->function.is_inline = specifiers->is_inline;
+ entity->function.parameters = env.parameters;
+ } else {
+ entity = allocate_entity_zero(ENTITY_VARIABLE);
- parse_declaration_attributes(declaration);
+ entity->variable.get_property_sym = specifiers->get_property_sym;
+ entity->variable.put_property_sym = specifiers->put_property_sym;
+ if (specifiers->alignment != 0) {
+ /* TODO: add checks here */
+ entity->variable.alignment = specifiers->alignment;
+ }
- fix_declaration_type(declaration);
+ if (warning.other && specifiers->is_inline && is_type_valid(type)) {
+ warningf(&env.source_position,
+ "variable '%Y' declared 'inline'\n", env.symbol);
+ }
+ }
- if (construct_type != NULL) {
- obstack_free(&temp_obst, construct_type);
+ 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->declaration.deprecated_string = specifiers->deprecated_string;
+
+ storage_class_t storage_class = specifiers->storage_class;
+ entity->declaration.declared_storage_class = storage_class;
+
+ if (storage_class == STORAGE_CLASS_NONE && scope != file_scope) {
+ storage_class = STORAGE_CLASS_AUTO;
+ }
+ entity->declaration.storage_class = storage_class;
}
- return declaration;
+ parse_declaration_attributes(entity);
+
+ return entity;
}
static type_t *parse_abstract_declarator(type_t *base_type)
return result;
}
-static declaration_t *append_declaration(declaration_t* const declaration)
-{
- if (last_declaration != NULL) {
- last_declaration->next = declaration;
- } else {
- scope->declarations = declaration;
- }
- last_declaration = declaration;
- return declaration;
-}
-
/**
* Check if the declaration of main is suspicious. main should be a
* function with external linkage, returning int, taking either zero
* @param decl the declaration to check
* @param type the function type of the declaration
*/
-static void check_type_of_main(const declaration_t *const decl, const function_type_t *const func_type)
+static void check_type_of_main(const entity_t *entity)
{
- if (decl->storage_class == STORAGE_CLASS_STATIC) {
- warningf(&decl->source_position,
- "'main' is normally a non-static function");
+ const source_position_t *pos = &entity->base.source_position;
+ if (entity->kind != ENTITY_FUNCTION) {
+ warningf(pos, "'main' is not a function");
+ return;
}
+
+ if (entity->declaration.storage_class == STORAGE_CLASS_STATIC) {
+ warningf(pos, "'main' is normally a non-static function");
+ }
+
+ type_t *type = skip_typeref(entity->declaration.type);
+ assert(is_type_function(type));
+
+ function_type_t *func_type = &type->function;
if (!types_compatible(skip_typeref(func_type->return_type), type_int)) {
- warningf(&decl->source_position,
- "return type of 'main' should be 'int', but is '%T'",
+ warningf(pos, "return type of 'main' should be 'int', but is '%T'",
func_type->return_type);
}
const function_parameter_t *parm = func_type->parameters;
if (parm != NULL) {
type_t *const first_type = parm->type;
if (!types_compatible(skip_typeref(first_type), type_int)) {
- warningf(&decl->source_position,
- "first argument of 'main' should be 'int', but is '%T'", first_type);
+ warningf(pos,
+ "first argument of 'main' should be 'int', but is '%T'",
+ first_type);
}
parm = parm->next;
if (parm != NULL) {
type_t *const second_type = parm->type;
if (!types_compatible(skip_typeref(second_type), type_char_ptr_ptr)) {
- warningf(&decl->source_position,
- "second argument of 'main' should be 'char**', but is '%T'", second_type);
+ warningf(pos, "second argument of 'main' should be 'char**', but is '%T'", second_type);
}
parm = parm->next;
if (parm != NULL) {
type_t *const third_type = parm->type;
if (!types_compatible(skip_typeref(third_type), type_char_ptr_ptr)) {
- warningf(&decl->source_position,
- "third argument of 'main' should be 'char**', but is '%T'", third_type);
+ warningf(pos, "third argument of 'main' should be 'char**', but is '%T'", third_type);
}
parm = parm->next;
if (parm != NULL)
}
} else {
warn_arg_count:
- warningf(&decl->source_position, "'main' takes only zero, two or three arguments");
+ warningf(pos, "'main' takes only zero, two or three arguments");
}
}
}
return strcmp(sym->string, "main") == 0;
}
-static declaration_t *record_declaration(
- declaration_t *const declaration,
- const bool is_definition)
+/**
+ * record entities for the NAMESPACE_NORMAL, and produce error messages/warnings
+ * for various problems that occur for multiple definitions
+ */
+static entity_t *record_entity(entity_t *entity, const bool is_definition)
{
- const symbol_t *const symbol = declaration->symbol;
- const namespace_t namespc = (namespace_t)declaration->namespc;
+ const symbol_t *const symbol = entity->base.symbol;
+ const namespace_t namespc = entity->base.namespc;
+ const source_position_t *pos = &entity->base.source_position;
assert(symbol != NULL);
- declaration_t *previous_declaration = get_declaration(symbol, namespc);
+ entity_t *previous_entity = get_entity(symbol, namespc);
+ /* pushing the same entity twice will break the stack structure */
+ assert(previous_entity != entity);
- type_t *const orig_type = declaration->type;
- type_t *const type = skip_typeref(orig_type);
- if (is_type_function(type) &&
- type->function.unspecified_parameters &&
- warning.strict_prototypes &&
- previous_declaration == NULL) {
- warningf(&declaration->source_position,
- "function declaration '%#T' is not a prototype",
- orig_type, symbol);
- }
-
- if (warning.main && is_type_function(type) && is_sym_main(symbol)) {
- check_type_of_main(declaration, &type->function);
- }
-
- if (warning.nested_externs &&
- declaration->storage_class == STORAGE_CLASS_EXTERN &&
- scope != file_scope) {
- warningf(&declaration->source_position,
- "nested extern declaration of '%#T'", declaration->type, symbol);
- }
-
- assert(declaration != previous_declaration);
- if (previous_declaration != NULL &&
- previous_declaration->parent_scope == ¤t_function->scope &&
- scope->depth == previous_declaration->parent_scope->depth + 1) {
- errorf(&declaration->source_position,
- "declaration '%#T' redeclares the parameter '%#T' (declared %P)",
- orig_type, symbol, previous_declaration->type, symbol,
- &previous_declaration->source_position);
+ if (entity->kind == ENTITY_FUNCTION) {
+ type_t *const orig_type = entity->declaration.type;
+ type_t *const type = skip_typeref(orig_type);
+
+ assert(is_type_function(type));
+ if (type->function.unspecified_parameters &&
+ warning.strict_prototypes &&
+ previous_entity == NULL) {
+ warningf(pos, "function declaration '%#T' is not a prototype",
+ orig_type, symbol);
+ }
+
+ if (warning.main && scope == file_scope && is_sym_main(symbol)) {
+ check_type_of_main(entity);
+ }
+ }
+
+ if (is_declaration(entity)) {
+ if (warning.nested_externs
+ && entity->declaration.storage_class == STORAGE_CLASS_EXTERN
+ && scope != file_scope) {
+ warningf(pos, "nested extern declaration of '%#T'",
+ entity->declaration.type, symbol);
+ }
+ }
+
+ if (previous_entity != NULL
+ && previous_entity->base.parent_scope == ¤t_function->parameters
+ && scope->depth == previous_entity->base.parent_scope->depth + 1) {
+
+ assert(previous_entity->kind == ENTITY_VARIABLE);
+ errorf(pos,
+ "declaration '%#T' redeclares the parameter '%#T' (declared %P)",
+ entity->declaration.type, symbol,
+ previous_entity->declaration.type, symbol,
+ &previous_entity->base.source_position);
goto finish;
}
- if (previous_declaration != NULL &&
- previous_declaration->parent_scope == scope) {
- /* can happen for K&R style declarations */
- if (previous_declaration->type == NULL) {
- previous_declaration->type = declaration->type;
+
+ if (previous_entity != NULL
+ && previous_entity->base.parent_scope == 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);
+ goto finish;
}
+ if (previous_entity->kind == ENTITY_ENUM_VALUE) {
+ errorf(pos,
+ "redeclaration of enum entry '%Y' (declared %P)",
+ symbol, &previous_entity->base.source_position);
+ goto finish;
+ }
+ if (previous_entity->kind == ENTITY_TYPEDEF) {
+ /* TODO: C++ allows this for exactly the same type */
+ errorf(pos,
+ "redefinition of typedef '%Y' (declared %P)",
+ symbol, &previous_entity->base.source_position);
+ goto finish;
+ }
+
+ /* at this point we should have only VARIABLES or FUNCTIONS */
+ assert(is_declaration(previous_entity) && is_declaration(entity));
+
+ /* can happen for K&R style declarations */
+ if (previous_entity->kind == ENTITY_VARIABLE
+ && previous_entity->declaration.type == NULL
+ && entity->kind == ENTITY_VARIABLE) {
+ previous_entity->declaration.type = entity->declaration.type;
+ previous_entity->declaration.storage_class
+ = entity->declaration.storage_class;
+ previous_entity->declaration.declared_storage_class
+ = entity->declaration.declared_storage_class;
+ previous_entity->declaration.modifiers
+ = entity->declaration.modifiers;
+ previous_entity->declaration.deprecated_string
+ = entity->declaration.deprecated_string;
+ }
+ assert(entity->declaration.type != NULL);
+
+ declaration_t *const previous_declaration
+ = &previous_entity->declaration;
+ declaration_t *const declaration = &entity->declaration;
+ type_t *const orig_type = entity->declaration.type;
+ type_t *const type = skip_typeref(orig_type);
+
+ type_t *prev_type = skip_typeref(previous_declaration->type);
- const type_t *prev_type = skip_typeref(previous_declaration->type);
if (!types_compatible(type, prev_type)) {
- errorf(&declaration->source_position,
+ errorf(pos,
"declaration '%#T' is incompatible with '%#T' (declared %P)",
orig_type, symbol, previous_declaration->type, symbol,
- &previous_declaration->source_position);
+ &previous_entity->base.source_position);
} else {
unsigned old_storage_class = previous_declaration->storage_class;
- if (old_storage_class == STORAGE_CLASS_ENUM_ENTRY) {
- errorf(&declaration->source_position,
- "redeclaration of enum entry '%Y' (declared %P)",
- symbol, &previous_declaration->source_position);
- return previous_declaration;
- }
-
- if (warning.redundant_decls &&
- is_definition &&
- previous_declaration->storage_class == STORAGE_CLASS_STATIC &&
- !(previous_declaration->modifiers & DM_USED) &&
- !previous_declaration->used) {
- warningf(&previous_declaration->source_position,
+ if (warning.redundant_decls && is_definition
+ && previous_declaration->storage_class == STORAGE_CLASS_STATIC
+ && !(previous_declaration->modifiers & DM_USED)
+ && !previous_declaration->used) {
+ warningf(&previous_entity->base.source_position,
"unnecessary static forward declaration for '%#T'",
previous_declaration->type, symbol);
}
unsigned new_storage_class = declaration->storage_class;
-
if (is_type_incomplete(prev_type)) {
previous_declaration->type = type;
prev_type = type;
/* pretend no storage class means extern for function
* declarations (except if the previous declaration is neither
* none nor extern) */
- if (is_type_function(type)) {
+ if (entity->kind == ENTITY_FUNCTION) {
if (prev_type->function.unspecified_parameters) {
previous_declaration->type = type;
prev_type = type;
if (warning.missing_prototypes &&
prev_type->function.unspecified_parameters &&
!is_sym_main(symbol)) {
- warningf(&declaration->source_position,
- "no previous prototype for '%#T'",
+ warningf(pos, "no previous prototype for '%#T'",
orig_type, symbol);
}
} else if (new_storage_class == STORAGE_CLASS_NONE) {
if (!is_definition &&
warning.redundant_decls &&
is_type_valid(prev_type) &&
- strcmp(previous_declaration->source_position.input_name, "<builtin>") != 0) {
- warningf(&declaration->source_position,
+ strcmp(previous_entity->base.source_position.input_name, "<builtin>") != 0) {
+ warningf(pos,
"redundant declaration for '%Y' (declared %P)",
- symbol, &previous_declaration->source_position);
+ symbol, &previous_entity->base.source_position);
}
} else if (current_function == NULL) {
if (old_storage_class != STORAGE_CLASS_STATIC &&
new_storage_class == STORAGE_CLASS_STATIC) {
- errorf(&declaration->source_position,
+ errorf(pos,
"static declaration of '%Y' follows non-static declaration (declared %P)",
- symbol, &previous_declaration->source_position);
+ symbol, &previous_entity->base.source_position);
} else if (old_storage_class == STORAGE_CLASS_EXTERN) {
previous_declaration->storage_class = STORAGE_CLASS_NONE;
previous_declaration->declared_storage_class = STORAGE_CLASS_NONE;
} else if (is_type_valid(prev_type)) {
if (old_storage_class == new_storage_class) {
error_redeclaration:
- errorf(&declaration->source_position,
- "redeclaration of '%Y' (declared %P)",
- symbol, &previous_declaration->source_position);
+ errorf(pos, "redeclaration of '%Y' (declared %P)",
+ symbol, &previous_entity->base.source_position);
} else {
- errorf(&declaration->source_position,
+ errorf(pos,
"redeclaration of '%Y' with different linkage (declared %P)",
- symbol, &previous_declaration->source_position);
+ symbol, &previous_entity->base.source_position);
}
}
}
previous_declaration->modifiers |= declaration->modifiers;
- previous_declaration->is_inline |= declaration->is_inline;
- return previous_declaration;
- } else if (is_type_function(type)) {
+ if (entity->kind == ENTITY_FUNCTION) {
+ previous_entity->function.is_inline |= entity->function.is_inline;
+ }
+ return previous_entity;
+ }
+
+ if (entity->kind == ENTITY_FUNCTION) {
if (is_definition &&
- declaration->storage_class != STORAGE_CLASS_STATIC) {
+ entity->declaration.storage_class != STORAGE_CLASS_STATIC) {
if (warning.missing_prototypes && !is_sym_main(symbol)) {
- warningf(&declaration->source_position,
- "no previous prototype for '%#T'", orig_type, symbol);
+ warningf(pos, "no previous prototype for '%#T'",
+ entity->declaration.type, symbol);
} else if (warning.missing_declarations && !is_sym_main(symbol)) {
- warningf(&declaration->source_position,
- "no previous declaration for '%#T'", orig_type,
- symbol);
+ warningf(pos, "no previous declaration for '%#T'",
+ entity->declaration.type, symbol);
}
}
- } else {
- if (warning.missing_declarations &&
- scope == file_scope && (
- declaration->storage_class == STORAGE_CLASS_NONE ||
- declaration->storage_class == STORAGE_CLASS_THREAD
- )) {
- warningf(&declaration->source_position,
- "no previous declaration for '%#T'", orig_type, symbol);
+ } else if (warning.missing_declarations
+ && entity->kind == ENTITY_VARIABLE
+ && scope == file_scope) {
+ declaration_t *declaration = &entity->declaration;
+ if (declaration->storage_class == STORAGE_CLASS_NONE ||
+ declaration->storage_class == STORAGE_CLASS_THREAD) {
+ warningf(pos, "no previous declaration for '%#T'",
+ declaration->type, symbol);
}
}
+
finish:
- assert(declaration->parent_scope == NULL);
+ assert(entity->base.parent_scope == NULL);
assert(scope != NULL);
- declaration->parent_scope = scope;
+ entity->base.parent_scope = scope;
+ entity->base.namespc = NAMESPACE_NORMAL;
+ environment_push(entity);
+ append_entity(scope, entity);
- environment_push(declaration);
- return append_declaration(declaration);
+ return entity;
}
-static void parser_error_multiple_definition(declaration_t *declaration,
+static void parser_error_multiple_definition(entity_t *entity,
const source_position_t *source_position)
{
errorf(source_position, "multiple definition of symbol '%Y' (declared %P)",
- declaration->symbol, &declaration->source_position);
+ entity->base.symbol, &entity->base.source_position);
}
static bool is_declaration_specifier(const token_t *token,
}
}
-static void parse_init_declarator_rest(declaration_t *declaration)
+static void parse_init_declarator_rest(entity_t *entity)
{
+ assert(is_declaration(entity));
+ declaration_t *const declaration = &entity->declaration;
+
eat('=');
type_t *orig_type = declaration->type;
type_t *type = skip_typeref(orig_type);
- if (declaration->init.initializer != NULL) {
- parser_error_multiple_definition(declaration, HERE);
+ if (entity->kind == ENTITY_VARIABLE
+ && entity->variable.initializer != NULL) {
+ parser_error_multiple_definition(entity, HERE);
}
bool must_be_constant = false;
if (declaration->storage_class == STORAGE_CLASS_STATIC ||
declaration->storage_class == STORAGE_CLASS_THREAD_STATIC ||
- declaration->parent_scope == file_scope) {
+ entity->base.parent_scope == file_scope) {
must_be_constant = true;
}
if (is_type_function(type)) {
- errorf(&declaration->source_position,
+ errorf(&entity->base.source_position,
"function '%#T' is initialized like a variable",
- orig_type, declaration->symbol);
+ orig_type, entity->base.symbol);
orig_type = type_error_type;
}
parse_initializer_env_t env;
env.type = orig_type;
env.must_be_constant = must_be_constant;
- env.declaration = current_init_decl = declaration;
+ env.entity = entity;
+ current_init_decl = entity;
initializer_t *initializer = parse_initializer(&env);
current_init_decl = NULL;
- if (!is_type_function(type)) {
- /* § 6.7.5 (22) array initializers for arrays with unknown size determine
- * the array type size */
- declaration->type = env.type;
- declaration->init.initializer = initializer;
+ if (entity->kind == ENTITY_VARIABLE) {
+ /* § 6.7.5 (22) array initializers for arrays with unknown size
+ * determine the array type size */
+ declaration->type = env.type;
+ entity->variable.initializer = initializer;
}
}
eat(';');
if (warning.other) {
- if (specifiers->declared_storage_class != STORAGE_CLASS_NONE) {
+ if (specifiers->storage_class != STORAGE_CLASS_NONE) {
warningf(&specifiers->source_position,
"useless storage class in empty declaration");
}
switch (type->kind) {
case TYPE_COMPOUND_STRUCT:
case TYPE_COMPOUND_UNION: {
- if (type->compound.declaration->symbol == NULL) {
+ if (type->compound.compound->base.symbol == NULL) {
warningf(&specifiers->source_position,
"unnamed struct/union that defines no instances");
}
break;
}
}
-
-#ifdef RECORD_EMPTY_DECLARATIONS
- declaration_t *const declaration = allocate_declaration_zero();
- declaration->type = specifiers->type;
- declaration->declared_storage_class = specifiers->declared_storage_class;
- declaration->source_position = specifiers->source_position;
- declaration->modifiers = specifiers->modifiers;
- declaration->storage_class = STORAGE_CLASS_NONE;
-
- append_declaration(declaration);
-#endif
}
-static void parse_declaration_rest(declaration_t *ndeclaration,
+static void parse_declaration_rest(entity_t *ndeclaration,
const declaration_specifiers_t *specifiers,
parsed_declaration_func finished_declaration)
{
add_anchor_token(';');
add_anchor_token(',');
while(true) {
- declaration_t *declaration =
- finished_declaration(ndeclaration, token.type == '=');
-
- type_t *orig_type = declaration->type;
- type_t *type = skip_typeref(orig_type);
-
- if (warning.other &&
- type->kind != TYPE_FUNCTION &&
- declaration->is_inline &&
- is_type_valid(type)) {
- warningf(&declaration->source_position,
- "variable '%Y' declared 'inline'\n", declaration->symbol);
- }
+ entity_t *entity = finished_declaration(ndeclaration, token.type == '=');
if (token.type == '=') {
- parse_init_declarator_rest(declaration);
+ parse_init_declarator_rest(entity);
}
if (token.type != ',')
eat(',');
add_anchor_token('=');
- ndeclaration = parse_declarator(specifiers, /*may_be_abstract=*/false);
+ ndeclaration = parse_declarator(specifiers, /*may_be_abstract=*/false, false);
rem_anchor_token('=');
}
expect(';');
rem_anchor_token(',');
}
-static declaration_t *finished_kr_declaration(declaration_t *declaration, bool is_definition)
+static entity_t *finished_kr_declaration(entity_t *entity, bool is_definition)
{
- symbol_t *symbol = declaration->symbol;
+ symbol_t *symbol = entity->base.symbol;
if (symbol == NULL) {
errorf(HERE, "anonymous declaration not valid as function parameter");
- return declaration;
- }
- namespace_t namespc = (namespace_t) declaration->namespc;
- if (namespc != NAMESPACE_NORMAL) {
- return record_declaration(declaration, false);
+ return entity;
}
- declaration_t *previous_declaration = get_declaration(symbol, namespc);
- if (previous_declaration == NULL ||
- previous_declaration->parent_scope != scope) {
+ 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) {
errorf(HERE, "expected declaration of a function parameter, found '%Y'",
symbol);
- return declaration;
+ return entity;
}
if (is_definition) {
- errorf(HERE, "parameter %Y is initialised", declaration->symbol);
+ errorf(HERE, "parameter %Y is initialised", entity->base.symbol);
}
- if (previous_declaration->type == NULL) {
- previous_declaration->type = declaration->type;
- previous_declaration->declared_storage_class = declaration->declared_storage_class;
- previous_declaration->storage_class = declaration->storage_class;
- previous_declaration->parent_scope = scope;
- return previous_declaration;
- } else {
- return record_declaration(declaration, false);
- }
+ return record_entity(entity, false);
}
static void parse_declaration(parsed_declaration_func finished_declaration)
if (token.type == ';') {
parse_anonymous_declaration_rest(&specifiers);
} else {
- declaration_t *declaration = parse_declarator(&specifiers, /*may_be_abstract=*/false);
- parse_declaration_rest(declaration, &specifiers, finished_declaration);
+ entity_t *entity = parse_declarator(&specifiers, /*may_be_abstract=*/false, false);
+ parse_declaration_rest(entity, &specifiers, finished_declaration);
}
}
return result;
}
-static void parse_kr_declaration_list(declaration_t *declaration)
+static void parse_kr_declaration_list(entity_t *entity)
{
- type_t *type = skip_typeref(declaration->type);
- if (!is_type_function(type))
+ if (entity->kind != ENTITY_FUNCTION)
return;
+ type_t *type = skip_typeref(entity->declaration.type);
+ assert(is_type_function(type));
if (!type->function.kr_style_parameters)
return;
+
add_anchor_token('{');
/* push function parameters */
size_t const top = environment_top();
- scope_push(&declaration->scope);
+ scope_push(&entity->function.parameters);
- declaration_t *parameter = declaration->scope.declarations;
- for ( ; parameter != NULL; parameter = parameter->next) {
- assert(parameter->parent_scope == NULL);
- parameter->parent_scope = scope;
+ 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;
environment_push(parameter);
}
}
/* pop function parameters */
- assert(scope == &declaration->scope);
+ assert(scope == &entity->function.parameters);
scope_pop();
environment_pop_to(top);
function_parameter_t *parameters = NULL;
function_parameter_t *last_parameter = NULL;
- declaration_t *parameter_declaration = declaration->scope.declarations;
+ entity_t *parameter_declaration = entity->function.parameters.entities;
for( ; parameter_declaration != NULL;
- parameter_declaration = parameter_declaration->next) {
- type_t *parameter_type = parameter_declaration->type;
+ parameter_declaration = parameter_declaration->base.next) {
+ type_t *parameter_type = parameter_declaration->declaration.type;
if (parameter_type == NULL) {
if (strict_mode) {
errorf(HERE, "no type specified for function parameter '%Y'",
- parameter_declaration->symbol);
+ parameter_declaration->base.symbol);
} else {
if (warning.implicit_int) {
warningf(HERE, "no type specified for function parameter '%Y', using 'int'",
- parameter_declaration->symbol);
+ parameter_declaration->base.symbol);
}
- parameter_type = type_int;
- parameter_declaration->type = parameter_type;
+ parameter_type = type_int;
+ parameter_declaration->declaration.type = parameter_type;
}
}
- semantic_parameter(parameter_declaration);
- parameter_type = parameter_declaration->type;
+ semantic_parameter(¶meter_declaration->declaration);
+ parameter_type = parameter_declaration->declaration.type;
/*
* we need the default promoted types for the function type
obstack_free(type_obst, new_type);
}
- declaration->type = type;
+ entity->declaration.type = type;
rem_anchor_token('{');
}
if (first_err) {
first_err = false;
diagnosticf("%s: In function '%Y':\n",
- current_function->source_position.input_name,
- current_function->symbol);
+ current_function->base.base.source_position.input_name,
+ current_function->base.base.symbol);
}
}
if (goto_statement->expression != NULL)
continue;
- declaration_t *label = goto_statement->label;
+ label_t *label = goto_statement->label;
label->used = true;
- if (label->source_position.input_name == NULL) {
+ if (label->base.source_position.input_name == NULL) {
print_in_function();
errorf(&goto_statement->base.source_position,
- "label '%Y' used but not defined", label->symbol);
+ "label '%Y' used but not defined", label->base.symbol);
}
}
- goto_first = goto_last = NULL;
+ goto_first = NULL;
+ goto_last = NULL;
if (warning.unused_label) {
for (const label_statement_t *label_statement = label_first;
label_statement != NULL;
label_statement = label_statement->next) {
- const declaration_t *label = label_statement->label;
+ label_t *label = label_statement->label;
if (! label->used) {
print_in_function();
warningf(&label_statement->base.source_position,
- "label '%Y' defined but not used", label->symbol);
+ "label '%Y' defined but not used", label->base.symbol);
}
}
}
label_first = label_last = NULL;
}
-static void warn_unused_decl(declaration_t *decl, declaration_t *end, char const *const what)
+static void warn_unused_decl(entity_t *entity, entity_t *end,
+ char const *const what)
{
- for (; decl != NULL; decl = decl->next) {
- if (decl->implicit)
+ for (; entity != NULL; entity = entity->base.next) {
+ if (!is_declaration(entity))
+ continue;
+
+ declaration_t *declaration = &entity->declaration;
+ if (declaration->implicit)
continue;
- if (!decl->used) {
+ if (!declaration->used) {
print_in_function();
- warningf(&decl->source_position, "%s '%Y' is unused", what, decl->symbol);
- } else if (!decl->read) {
+ warningf(&entity->base.source_position, "%s '%Y' is unused",
+ what, entity->base.symbol);
+ } else if (entity->kind == ENTITY_VARIABLE && !entity->variable.read) {
print_in_function();
- warningf(&decl->source_position, "%s '%Y' is never read", what, decl->symbol);
+ warningf(&entity->base.source_position, "%s '%Y' is never read",
+ what, entity->base.symbol);
}
- if (decl == end)
+ if (entity == end)
break;
}
}
switch (stmt->kind) {
case STATEMENT_DECLARATION: {
declaration_statement_t const *const decls = &stmt->declaration;
- warn_unused_decl(decls->declarations_begin, decls->declarations_end, "variable");
+ warn_unused_decl(decls->declarations_begin, decls->declarations_end,
+ "variable");
return;
}
case STATEMENT_FOR:
- warn_unused_decl(stmt->fors.scope.declarations, NULL, "variable");
+ warn_unused_decl(stmt->fors.scope.entities, NULL, "variable");
return;
default:
static void check_declarations(void)
{
if (warning.unused_parameter) {
- const scope_t *scope = ¤t_function->scope;
+ const scope_t *scope = ¤t_function->parameters;
/* do not issue unused warnings for main */
- if (!is_sym_main(current_function->symbol)) {
- warn_unused_decl(scope->declarations, NULL, "parameter");
+ if (!is_sym_main(current_function->base.base.symbol)) {
+ warn_unused_decl(scope->entities, NULL, "parameter");
}
}
if (warning.unused_variable) {
- walk_statements(current_function->init.statement, check_unused_variables, NULL);
+ walk_statements(current_function->statement, check_unused_variables,
+ NULL);
}
}
case EXPR_CALL: {
expression_t const *const func = expr->call.function;
if (func->kind == EXPR_REFERENCE) {
- declaration_t const *const decl = func->reference.declaration;
- if (decl != NULL && decl->modifiers & DM_NORETURN)
+ entity_t *entity = func->reference.entity;
+ if (entity->kind == ENTITY_FUNCTION
+ && entity->declaration.modifiers & DM_NORETURN)
return false;
}
}
case EXPR_REFERENCE:
+ case EXPR_REFERENCE_ENUM_VALUE:
case EXPR_CONST:
case EXPR_CHARACTER_CONSTANT:
case EXPR_WIDE_CHARACTER_CONSTANT:
case STATEMENT_INVALID:
case STATEMENT_EMPTY:
case STATEMENT_DECLARATION:
+ case STATEMENT_LOCAL_LABEL:
case STATEMENT_ASM:
next = stmt->base.next;
break;
return;
next = parent;
} else {
- next = stmt->gotos.label->init.statement;
+ next = stmt->gotos.label->statement;
if (next == NULL) /* missing label */
return;
}
if (next == NULL) {
noreturn_candidate = false;
- type_t *const type = current_function->type;
+ type_t *const type = current_function->base.type;
assert(is_type_function(type));
type_t *const ret = skip_typeref(type->function.return_type);
if (warning.return_type &&
!is_type_atomic(ret, ATOMIC_TYPE_VOID) &&
is_type_valid(ret) &&
- !is_sym_main(current_function->symbol)) {
+ !is_sym_main(current_function->base.base.symbol)) {
warningf(&stmt->base.source_position,
"control reaches end of non-void function");
}
case STATEMENT_INVALID:
case STATEMENT_EMPTY:
case STATEMENT_DECLARATION:
+ case STATEMENT_LOCAL_LABEL:
case STATEMENT_EXPRESSION:
case STATEMENT_ASM:
case STATEMENT_RETURN:
add_anchor_token('{');
/* declarator is common to both function-definitions and declarations */
- declaration_t *ndeclaration = parse_declarator(&specifiers, /*may_be_abstract=*/false);
+ entity_t *ndeclaration = parse_declarator(&specifiers, /*may_be_abstract=*/false, false);
rem_anchor_token('{');
rem_anchor_token(';');
case ',':
case ';':
case '=':
- parse_declaration_rest(ndeclaration, &specifiers, record_declaration);
+ parse_declaration_rest(ndeclaration, &specifiers, record_entity);
return;
}
return;
}
- type_t *type = ndeclaration->type;
+ assert(is_declaration(ndeclaration));
+ type_t *type = 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_valid(type)) {
errorf(HERE, "declarator '%#T' has a body but is not a function type",
- type, ndeclaration->symbol);
+ type, ndeclaration->base.symbol);
}
eat_block();
return;
if (warning.aggregate_return &&
is_type_compound(skip_typeref(type->function.return_type))) {
warningf(HERE, "function '%Y' returns an aggregate",
- ndeclaration->symbol);
+ ndeclaration->base.symbol);
}
if (warning.traditional && !type->function.unspecified_parameters) {
warningf(HERE, "traditional C rejects ISO C style function definition of function '%Y'",
- ndeclaration->symbol);
+ ndeclaration->base.symbol);
}
if (warning.old_style_definition && type->function.unspecified_parameters) {
warningf(HERE, "old-style function definition '%Y'",
- ndeclaration->symbol);
+ ndeclaration->base.symbol);
}
/* § 6.7.5.3 (14) a function definition with () means no
if (type != duplicate) {
obstack_free(type_obst, duplicate);
}
- ndeclaration->type = type;
+ ndeclaration->declaration.type = type;
}
- declaration_t *const declaration = record_declaration(ndeclaration, true);
- if (ndeclaration != declaration) {
- declaration->scope = ndeclaration->scope;
+ entity_t *const entity = record_entity(ndeclaration, true);
+ assert(entity->kind == ENTITY_FUNCTION);
+ assert(ndeclaration->kind == ENTITY_FUNCTION);
+
+ function_t *function = &entity->function;
+ if (ndeclaration != entity) {
+ function->parameters = ndeclaration->function.parameters;
}
- type = skip_typeref(declaration->type);
+ assert(is_declaration(entity));
+ type = skip_typeref(entity->declaration.type);
/* push function parameters and switch scope */
size_t const top = environment_top();
- scope_push(&declaration->scope);
-
- declaration_t *parameter = declaration->scope.declarations;
- for( ; parameter != NULL; parameter = parameter->next) {
- if (parameter->parent_scope == &ndeclaration->scope) {
- parameter->parent_scope = scope;
- }
- assert(parameter->parent_scope == NULL
- || parameter->parent_scope == scope);
- parameter->parent_scope = scope;
- if (parameter->symbol == NULL) {
- errorf(¶meter->source_position, "parameter name omitted");
+ scope_push(&function->parameters);
+
+ 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;
+ }
+ assert(parameter->base.parent_scope == NULL
+ || parameter->base.parent_scope == scope);
+ parameter->base.parent_scope = scope;
+ if (parameter->base.symbol == NULL) {
+ errorf(¶meter->base.source_position, "parameter name omitted");
continue;
}
environment_push(parameter);
}
- if (declaration->init.statement != NULL) {
- parser_error_multiple_definition(declaration, HERE);
+ if (function->statement != NULL) {
+ parser_error_multiple_definition(entity, HERE);
eat_block();
} else {
/* parse function body */
- int label_stack_top = label_top();
- declaration_t *old_current_function = current_function;
- current_function = declaration;
- current_parent = NULL;
+ int label_stack_top = label_top();
+ function_t *old_current_function = current_function;
+ current_function = function;
+ current_parent = NULL;
- statement_t *const body = parse_compound_statement(false);
- declaration->init.statement = body;
+ statement_t *const body = parse_compound_statement(false);
+ function->statement = body;
first_err = true;
check_labels();
check_declarations();
if (warning.return_type ||
warning.unreachable_code ||
- (warning.missing_noreturn && !(declaration->modifiers & DM_NORETURN))) {
+ (warning.missing_noreturn
+ && !(function->base.modifiers & DM_NORETURN))) {
noreturn_candidate = true;
check_reachable(body);
if (warning.unreachable_code)
walk_statements(body, check_unreachable, NULL);
if (warning.missing_noreturn &&
noreturn_candidate &&
- !(declaration->modifiers & DM_NORETURN)) {
+ !(function->base.modifiers & DM_NORETURN)) {
warningf(&body->base.source_position,
"function '%#T' is candidate for attribute 'noreturn'",
- type, declaration->symbol);
+ type, entity->base.symbol);
}
}
assert(current_parent == NULL);
- assert(current_function == declaration);
+ assert(current_function == function);
current_function = old_current_function;
label_pop_to(label_stack_top);
}
- assert(scope == &declaration->scope);
+ assert(scope == &function->parameters);
scope_pop();
environment_pop_to(top);
}
return type;
}
-static declaration_t *find_compound_entry(declaration_t *compound_declaration,
- symbol_t *symbol)
+static entity_t *find_compound_entry(compound_t *compound, symbol_t *symbol)
{
- declaration_t *iter = compound_declaration->scope.declarations;
- for( ; iter != NULL; iter = iter->next) {
- if (iter->namespc != NAMESPACE_NORMAL)
+ entity_t *iter = compound->members.entities;
+ for( ; iter != NULL; iter = iter->base.next) {
+ if (iter->kind != ENTITY_COMPOUND_MEMBER)
continue;
- if (iter->symbol == NULL) {
- type_t *type = skip_typeref(iter->type);
+ if (iter->base.symbol == NULL) {
+ type_t *type = skip_typeref(iter->declaration.type);
if (is_type_compound(type)) {
- declaration_t *result
- = find_compound_entry(type->compound.declaration, symbol);
+ entity_t *result
+ = find_compound_entry(type->compound.compound, symbol);
if (result != NULL)
return result;
}
continue;
}
- if (iter->symbol == symbol) {
+ if (iter->base.symbol == symbol) {
return iter;
}
}
return NULL;
}
-static void parse_compound_declarators(declaration_t *struct_declaration,
+static void parse_compound_declarators(compound_t *compound,
const declaration_specifiers_t *specifiers)
{
- declaration_t *last_declaration = struct_declaration->scope.declarations;
- if (last_declaration != NULL) {
- while (last_declaration->next != NULL) {
- last_declaration = last_declaration->next;
- }
- }
-
while (true) {
- declaration_t *declaration;
+ entity_t *entity;
if (token.type == ':') {
source_position_t source_position = *HERE;
type_t *type = make_bitfield_type(base_type, size,
&source_position, sym_anonymous);
- declaration = allocate_declaration_zero();
- declaration->namespc = NAMESPACE_NORMAL;
- declaration->declared_storage_class = STORAGE_CLASS_NONE;
- declaration->storage_class = STORAGE_CLASS_NONE;
- declaration->source_position = source_position;
- declaration->modifiers = specifiers->modifiers;
- declaration->type = type;
+ entity = allocate_entity_zero(ENTITY_COMPOUND_MEMBER);
+ entity->base.namespc = NAMESPACE_NORMAL;
+ entity->base.source_position = source_position;
+ entity->declaration.declared_storage_class = STORAGE_CLASS_NONE;
+ entity->declaration.storage_class = STORAGE_CLASS_NONE;
+ entity->declaration.modifiers = specifiers->modifiers;
+ entity->declaration.type = type;
} else {
- declaration = parse_declarator(specifiers,/*may_be_abstract=*/true);
+ entity = parse_declarator(specifiers,/*may_be_abstract=*/true, true);
- type_t *orig_type = declaration->type;
+ assert(is_declaration(entity));
+ type_t *orig_type = entity->declaration.type;
type_t *type = skip_typeref(orig_type);
if (token.type == ':') {
expression_t *size = parse_constant_expression();
type_t *bitfield_type = make_bitfield_type(orig_type, size,
- &source_position, declaration->symbol);
- declaration->type = bitfield_type;
+ &source_position, entity->base.symbol);
+ entity->declaration.type = bitfield_type;
} else {
/* TODO we ignore arrays for now... what is missing is a check
* that they're at the end of the struct */
if (is_type_incomplete(type) && !is_type_array(type)) {
errorf(HERE,
"compound member '%Y' has incomplete type '%T'",
- declaration->symbol, orig_type);
+ entity->base.symbol, orig_type);
} else if (is_type_function(type)) {
errorf(HERE, "compound member '%Y' must not have function type '%T'",
- declaration->symbol, orig_type);
+ entity->base.symbol, orig_type);
}
}
}
/* make sure we don't define a symbol multiple times */
- symbol_t *symbol = declaration->symbol;
+ symbol_t *symbol = entity->base.symbol;
if (symbol != NULL) {
- declaration_t *prev_decl
- = find_compound_entry(struct_declaration, symbol);
+ entity_t *prev = find_compound_entry(compound, symbol);
- if (prev_decl != NULL) {
- assert(prev_decl->symbol == symbol);
- errorf(&declaration->source_position,
+ if (prev != NULL) {
+ assert(prev->base.symbol == symbol);
+ errorf(&entity->base.source_position,
"multiple declarations of symbol '%Y' (declared %P)",
- symbol, &prev_decl->source_position);
+ symbol, &prev->base.source_position);
}
}
- /* append declaration */
- if (last_declaration != NULL) {
- last_declaration->next = declaration;
- } else {
- struct_declaration->scope.declarations = declaration;
- }
- last_declaration = declaration;
+ append_entity(&compound->members, entity);
if (token.type != ',')
break;
;
}
-static void parse_compound_type_entries(declaration_t *compound_declaration)
+static void parse_compound_type_entries(compound_t *compound)
{
eat('{');
add_anchor_token('}');
memset(&specifiers, 0, sizeof(specifiers));
parse_declaration_specifiers(&specifiers);
- parse_compound_declarators(compound_declaration, &specifiers);
+ parse_compound_declarators(compound, &specifiers);
}
rem_anchor_token('}');
next_token();
declaration_specifiers_t specifiers;
memset(&specifiers, 0, sizeof(specifiers));
parse_declaration_specifiers(&specifiers);
- if (specifiers.declared_storage_class != STORAGE_CLASS_NONE) {
+ if (specifiers.storage_class != STORAGE_CLASS_NONE) {
/* TODO: improve error message, user does probably not know what a
* storage class is...
*/
return cnst;
}
-static declaration_t *create_implicit_function(symbol_t *symbol,
+static entity_t *create_implicit_function(symbol_t *symbol,
const source_position_t *source_position)
{
type_t *ntype = allocate_type_zero(TYPE_FUNCTION);
free_type(ntype);
}
- declaration_t *const declaration = allocate_declaration_zero();
- declaration->storage_class = STORAGE_CLASS_EXTERN;
- declaration->declared_storage_class = STORAGE_CLASS_EXTERN;
- declaration->type = type;
- declaration->symbol = symbol;
- declaration->source_position = *source_position;
- declaration->implicit = true;
+ entity_t *entity = allocate_entity_zero(ENTITY_FUNCTION);
+ entity->declaration.storage_class = STORAGE_CLASS_EXTERN;
+ entity->declaration.declared_storage_class = STORAGE_CLASS_EXTERN;
+ entity->declaration.type = type;
+ entity->declaration.implicit = true;
+ entity->base.symbol = symbol;
+ entity->base.source_position = *source_position;
bool strict_prototypes_old = warning.strict_prototypes;
warning.strict_prototypes = false;
- record_declaration(declaration, false);
+ record_entity(entity, false);
warning.strict_prototypes = strict_prototypes_old;
- return declaration;
+ return entity;
}
/**
*/
static type_t *get_builtin_symbol_type(symbol_t *symbol)
{
- switch(symbol->ID) {
+ switch (symbol->ID) {
case T___builtin_alloca:
return make_function_1_type(type_void_ptr, type_size_t);
case T___builtin_huge_val:
type_t *revert_automatic_type_conversion(const expression_t *expression)
{
switch (expression->kind) {
- case EXPR_REFERENCE: return expression->reference.declaration->type;
+ case EXPR_REFERENCE: {
+ entity_t *entity = expression->reference.entity;
+ if (is_declaration(entity)) {
+ return entity->declaration.type;
+ } else if (entity->kind == ENTITY_ENUM_VALUE) {
+ return entity->enum_value.enum_type;
+ } else {
+ panic("no declaration or enum in reference");
+ }
+ }
- case EXPR_SELECT:
- return get_qualified_type(expression->select.compound_entry->type,
+ case EXPR_SELECT: {
+ entity_t *entity = expression->select.compound_entry;
+ assert(is_declaration(entity));
+ type_t *type = entity->declaration.type;
+ return get_qualified_type(type,
expression->base.type->base.qualifiers);
+ }
case EXPR_UNARY_DEREFERENCE: {
const expression_t *const value = expression->unary.value;
static expression_t *parse_reference(void)
{
- expression_t *expression = allocate_expression_zero(EXPR_REFERENCE);
-
- reference_expression_t *ref = &expression->reference;
symbol_t *const symbol = token.v.symbol;
- declaration_t *declaration = get_declaration(symbol, NAMESPACE_NORMAL);
+ entity_t *entity = get_entity(symbol, NAMESPACE_NORMAL);
- if (declaration == NULL) {
+ if (entity == NULL) {
if (!strict_mode && look_ahead(1)->type == '(') {
/* an implicitly declared function */
if (warning.implicit_function_declaration) {
symbol);
}
- declaration = create_implicit_function(symbol, HERE);
+ entity = create_implicit_function(symbol, HERE);
} else {
errorf(HERE, "unknown symbol '%Y' found.", symbol);
- declaration = create_error_declaration(symbol, STORAGE_CLASS_NONE);
+ entity = create_error_entity(symbol, ENTITY_VARIABLE);
}
}
- type_t *orig_type = declaration->type;
+ type_t *orig_type;
+
+ if (is_declaration(entity)) {
+ orig_type = entity->declaration.type;
+ } else if (entity->kind == ENTITY_ENUM_VALUE) {
+ orig_type = entity->enum_value.enum_type;
+ } else {
+ panic("expected declaration or enum value in reference");
+ }
/* we always do the auto-type conversions; the & and sizeof parser contains
* code to revert this! */
type_t *type = automatic_type_conversion(orig_type);
- ref->declaration = declaration;
- ref->base.type = type;
+ expression_kind_t kind = EXPR_REFERENCE;
+ if (entity->kind == ENTITY_ENUM_VALUE)
+ kind = EXPR_REFERENCE_ENUM_VALUE;
+
+ expression_t *expression = allocate_expression_zero(kind);
+ expression->reference.entity = entity;
+ expression->base.type = type;
/* this declaration is used */
- declaration->used = true;
+ if (is_declaration(entity)) {
+ entity->declaration.used = true;
+ }
- if (declaration->parent_scope != file_scope &&
- declaration->parent_scope->depth < current_function->scope.depth &&
- is_type_valid(orig_type) && !is_type_function(orig_type)) {
- /* access of a variable from an outer function */
- declaration->address_taken = true;
+ if (entity->base.parent_scope != file_scope
+ && entity->base.parent_scope->depth < current_function->parameters.depth
+ && is_type_valid(orig_type) && !is_type_function(orig_type)) {
+ if (entity->kind == ENTITY_VARIABLE) {
+ /* access of a variable from an outer function */
+ entity->variable.address_taken = true;
+ }
current_function->need_closure = true;
}
/* check for deprecated functions */
- if (warning.deprecated_declarations &&
- declaration->modifiers & DM_DEPRECATED) {
- char const *const prefix = is_type_function(declaration->type) ?
+ if (warning.deprecated_declarations
+ && is_declaration(entity)
+ && entity->declaration.modifiers & DM_DEPRECATED) {
+ declaration_t *declaration = &entity->declaration;
+
+ char const *const prefix = entity->kind == ENTITY_FUNCTION ?
"function" : "variable";
if (declaration->deprecated_string != NULL) {
warningf(HERE, "%s '%Y' is deprecated (declared %P): \"%s\"",
- prefix, declaration->symbol, &declaration->source_position,
- declaration->deprecated_string);
+ prefix, entity->base.symbol, &entity->base.source_position,
+ declaration->deprecated_string);
} else {
warningf(HERE, "%s '%Y' is deprecated (declared %P)", prefix,
- declaration->symbol, &declaration->source_position);
+ entity->base.symbol, &entity->base.source_position);
}
}
- if (warning.init_self && declaration == current_init_decl && !in_type_prop) {
+
+ if (warning.init_self && entity == current_init_decl && !in_type_prop
+ && entity->kind == ENTITY_VARIABLE) {
current_init_decl = NULL;
warningf(HERE, "variable '%#T' is initialized by itself",
- declaration->type, declaration->symbol);
+ entity->declaration.type, entity->base.symbol);
}
next_token();
parse_initializer_env_t env;
env.type = type;
- env.declaration = NULL;
+ env.entity = NULL;
env.must_be_constant = false;
initializer_t *initializer = parse_initializer(&env);
type = env.type;
{
eat('(');
- switch(token.type) {
+ switch (token.type) {
case '{':
/* gcc extension: a statement expression */
return parse_statement_expression();
expect(',');
expression_t *const expr = parse_assignment_expression();
if (expr->kind == EXPR_REFERENCE) {
- declaration_t *const decl = expr->reference.declaration;
- if (decl->parent_scope != ¤t_function->scope || decl->next != NULL) {
+ entity_t *const entity = expr->reference.entity;
+ if (entity->base.parent_scope != ¤t_function->parameters
+ || entity->base.next != NULL
+ || entity->kind != ENTITY_VARIABLE) {
errorf(&expr->base.source_position,
"second argument of 'va_start' must be last parameter of the current function");
+ } else {
+ expression->va_starte.parameter = &entity->variable;
}
- expression->va_starte.parameter = decl;
expect(')');
return expression;
}
{
expression_t *expression;
- switch(token.type) {
+ switch (token.type) {
case T___builtin_isgreater:
expression = allocate_expression_zero(EXPR_BINARY_ISGREATER);
break;
*
* @param symbol the symbol of the label
*/
-static declaration_t *get_label(symbol_t *symbol)
+static label_t *get_label(symbol_t *symbol)
{
- declaration_t *candidate;
+ entity_t *label;
assert(current_function != NULL);
- candidate = get_declaration(symbol, NAMESPACE_LOCAL_LABEL);
+ label = get_entity(symbol, NAMESPACE_LOCAL_LABEL);
/* if we found a local label, we already created the declaration */
- if (candidate != NULL) {
- if (candidate->parent_scope != scope) {
- assert(candidate->parent_scope->depth < scope->depth);
+ if (label != NULL && label->kind == ENTITY_LOCAL_LABEL) {
+ if (label->base.parent_scope != scope) {
+ assert(label->base.parent_scope->depth < scope->depth);
current_function->goto_to_outer = true;
}
- return candidate;
+ return &label->label;
}
- candidate = get_declaration(symbol, NAMESPACE_LABEL);
+ label = get_entity(symbol, NAMESPACE_LABEL);
/* if we found a label in the same function, then we already created the
* declaration */
- if (candidate != NULL
- && candidate->parent_scope == ¤t_function->scope) {
- return candidate;
+ if (label != NULL
+ && label->base.parent_scope == ¤t_function->parameters) {
+ return &label->label;
}
/* otherwise we need to create a new one */
- declaration_t *const declaration = allocate_declaration_zero();
- declaration->namespc = NAMESPACE_LABEL;
- declaration->symbol = symbol;
+ label = allocate_entity_zero(ENTITY_LABEL);
+ label->base.namespc = NAMESPACE_LABEL;
+ label->base.symbol = symbol;
- label_push(declaration);
+ label_push(label);
- return declaration;
+ return &label->label;
}
/**
symbol_t *symbol = token.v.symbol;
next_token();
- declaration_t *label = get_label(symbol);
-
+ label_t *label = get_label(symbol);
label->used = true;
label->address_taken = true;
expression->base.source_position = source_position;
/* label address is threaten as a void pointer */
- expression->base.type = type_void_ptr;
- expression->label_address.declaration = label;
+ expression->base.type = type_void_ptr;
+ expression->label_address.label = label;
return expression;
end_error:
return create_invalid_expression();
type_left = type;
}
- declaration_t *entry;
+ entity_t *entry;
if (type_left->kind == TYPE_COMPOUND_STRUCT ||
type_left->kind == TYPE_COMPOUND_UNION) {
- declaration_t *const declaration = type_left->compound.declaration;
+ compound_t *compound = type_left->compound.compound;
- if (!declaration->init.complete) {
+ if (!compound->complete) {
errorf(HERE, "request for member '%Y' of incomplete type '%T'",
symbol, type_left);
goto create_error_entry;
}
- entry = find_compound_entry(declaration, symbol);
+ entry = find_compound_entry(compound, symbol);
if (entry == NULL) {
errorf(HERE, "'%T' has no member named '%Y'", orig_type, symbol);
goto create_error_entry;
symbol, type_left);
}
create_error_entry:
- entry = allocate_declaration_zero();
- entry->symbol = symbol;
+ return create_invalid_expression();
}
+ assert(is_declaration(entry));
select->select.compound_entry = entry;
- type_t *const res_type =
- get_qualified_type(entry->type, type_left->base.qualifiers);
+ type_t *entry_type = entry->declaration.type;
+ type_t *res_type
+ = get_qualified_type(entry_type, type_left->base.qualifiers);
/* we always do the auto-type conversions; the & and sizeof parser contains
* code to revert this! */
if (is_type_union(expected_type_skip)
&& (expected_type_skip->base.modifiers
& TYPE_MODIFIER_TRANSPARENT_UNION)) {
- declaration_t *union_decl = expected_type_skip->compound.declaration;
-
- declaration_t *declaration = union_decl->scope.declarations;
- type_t *best_type = NULL;
- for ( ; declaration != NULL; declaration = declaration->next) {
- type_t *decl_type = declaration->type;
+ compound_t *union_decl = expected_type_skip->compound.compound;
+ type_t *best_type = NULL;
+ entity_t *entry = union_decl->members.entities;
+ for ( ; entry != NULL; entry = entry->base.next) {
+ assert(is_declaration(entry));
+ type_t *decl_type = entry->declaration.type;
error = semantic_assign(decl_type, arg_expr);
if (error == ASSIGN_ERROR_INCOMPATIBLE
|| error == ASSIGN_ERROR_POINTER_QUALIFIER_MISSING)
return
is_type_compound(type1) &&
type1->kind == type2->kind &&
- type1->compound.declaration == type2->compound.declaration;
+ type1->compound.compound == type2->compound.compound;
}
/**
static bool is_lvalue(const expression_t *expression)
{
+ /* TODO: doesn't seem to be consistent with §6.3.2.1 (1) */
switch (expression->kind) {
case EXPR_REFERENCE:
case EXPR_ARRAY_ACCESS:
expr = expr->unary.value;
}
- if (expr->kind != EXPR_REFERENCE)
- return NULL;
-
- if (!regular_take_address &&
- !is_type_function(skip_typeref(expr->reference.declaration->type))) {
- return NULL;
+ /* special case for functions which are automatically converted to a
+ * pointer to function without an extra TAKE_ADDRESS operation */
+ if (!regular_take_address && expr->kind == EXPR_REFERENCE
+ && expr->reference.entity->kind == ENTITY_FUNCTION) {
+ return expr;
}
- return expr;
+ return NULL;
}
static void warn_function_address_as_bool(expression_t const* expr)
expr = get_reference_address(expr);
if (expr != NULL) {
warningf(&expr->base.source_position,
- "the address of '%Y' will always evaluate as 'true'",
- expr->reference.declaration->symbol);
+ "the address of '%Y' will always evaluate as 'true'",
+ expr->reference.entity->base.symbol);
}
}
if (expression->kind != EXPR_REFERENCE)
return;
- declaration_t *const declaration = expression->reference.declaration;
- /* happens for parse errors */
- if (declaration == NULL)
+ entity_t *const entity = expression->reference.entity;
+
+ if (entity->kind != ENTITY_VARIABLE)
return;
- if (declaration->storage_class == STORAGE_CLASS_REGISTER && !may_be_register) {
+ if (entity->declaration.storage_class == STORAGE_CLASS_REGISTER
+ && !may_be_register) {
errorf(&expression->base.source_position,
"address of register variable '%Y' requested",
- declaration->symbol);
- } else {
- declaration->address_taken = 1;
+ entity->base.symbol);
}
+
+ entity->variable.address_taken = true;
}
/**
value->base.type = revert_automatic_type_conversion(value);
type_t *orig_type = value->base.type;
- if (!is_type_valid(skip_typeref(orig_type)))
+ type_t *type = skip_typeref(orig_type);
+ if (!is_type_valid(type))
return;
+ /* §6.5.3.2 */
+ if (value->kind != EXPR_ARRAY_ACCESS
+ && value->kind != EXPR_UNARY_DEREFERENCE
+ && !is_lvalue(value)) {
+ errorf(&expression->base.source_position,
+ "'&' requires an lvalue");
+ }
+ if (type->kind == TYPE_BITFIELD) {
+ errorf(&expression->base.source_position,
+ "'&' not allowed on object with bitfield type '%T'",
+ type);
+ }
+
set_address_taken(value, false);
expression->base.type = make_pointer_type(orig_type, TYPE_QUALIFIER_NONE);
expression_t const* const func_left = get_reference_address(left);
if (func_left != NULL && is_null_pointer_constant(right)) {
warningf(&expression->base.source_position,
- "the address of '%Y' will never be NULL",
- func_left->reference.declaration->symbol);
+ "the address of '%Y' will never be NULL",
+ func_left->reference.entity->base.symbol);
}
expression_t const* const func_right = get_reference_address(right);
if (func_right != NULL && is_null_pointer_constant(right)) {
warningf(&expression->base.source_position,
- "the address of '%Y' will never be NULL",
- func_right->reference.declaration->symbol);
+ "the address of '%Y' will never be NULL",
+ func_right->reference.entity->base.symbol);
}
}
*/
static bool has_const_fields(const compound_type_t *type)
{
- const scope_t *scope = &type->declaration->scope;
- const declaration_t *declaration = scope->declarations;
+ compound_t *compound = type->compound;
+ entity_t *entry = compound->members.entities;
- for (; declaration != NULL; declaration = declaration->next) {
- if (declaration->namespc != NAMESPACE_NORMAL)
+ for (; entry != NULL; entry = entry->base.next) {
+ if (!is_declaration(entry))
continue;
- const type_t *decl_type = skip_typeref(declaration->type);
+ const type_t *decl_type = skip_typeref(entry->declaration.type);
if (decl_type->base.qualifiers & TYPE_QUALIFIER_CONST)
return true;
}
- /* TODO */
+
return false;
}
case EXPR_UNKNOWN: break;
case EXPR_INVALID: return true; /* do NOT warn */
case EXPR_REFERENCE: return false;
+ case EXPR_REFERENCE_ENUM_VALUE: return false;
/* suppress the warning for microsoft __noop operations */
case EXPR_CONST: return expr->conste.is_ms_noop;
case EXPR_CHARACTER_CONSTANT: return false;
}
if (argument->constraints.begin[0] == '+')
- mark_decls_read(expression, NULL);
+ mark_vars_read(expression, NULL);
} else {
- mark_decls_read(expression, NULL);
+ mark_vars_read(expression, NULL);
}
argument->expression = expression;
expect(')');
static statement_t *parse_label_statement(void)
{
assert(token.type == T_IDENTIFIER);
- symbol_t *symbol = token.v.symbol;
- declaration_t *label = get_label(symbol);
+ symbol_t *symbol = token.v.symbol;
+ label_t *label = get_label(symbol);
statement_t *const statement = allocate_statement_zero(STATEMENT_LABEL);
statement->label.label = label;
PUSH_PARENT(statement);
/* if statement is already set then the label is defined twice,
- * otherwise it was just mentioned in a goto/local label declaration so far */
- if (label->init.statement != NULL) {
+ * otherwise it was just mentioned in a goto/local label declaration so far
+ */
+ if (label->statement != NULL) {
errorf(HERE, "duplicate label '%Y' (declared %P)",
- symbol, &label->source_position);
+ symbol, &label->base.source_position);
} else {
- label->source_position = token.source_position;
- label->init.statement = statement;
+ label->base.source_position = token.source_position;
+ label->statement = statement;
}
eat(':');
add_anchor_token(')');
expression_t *const expr = parse_expression();
statement->ifs.condition = expr;
- mark_decls_read(expr, NULL);
+ mark_vars_read(expr, NULL);
rem_anchor_token(')');
expect(')');
return;
/* FIXME: calculation of value should be done while parsing */
- const declaration_t *declaration;
- long last_value = -1;
- for (declaration = enumt->declaration->next;
- declaration != NULL && declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY;
- declaration = declaration->next) {
- const expression_t *expression = declaration->init.enum_value;
+ /* TODO: quadratic algorithm here. Change to an n log n one */
+ long last_value = -1;
+ const entity_t *entry = enumt->enume->base.next;
+ for (; entry != NULL && entry->kind == ENTITY_ENUM_VALUE;
+ entry = entry->base.next) {
+ const expression_t *expression = entry->enum_value.value;
long value = expression != NULL ? fold_constant(expression) : last_value + 1;
bool found = false;
for (const case_label_statement_t *l = statement->first_case; l != NULL; l = l->next) {
}
if (! found) {
warningf(&statement->base.source_position,
- "enumeration value '%Y' not handled in switch", declaration->symbol);
+ "enumeration value '%Y' not handled in switch",
+ entry->base.symbol);
}
last_value = value;
}
expect('(');
add_anchor_token(')');
expression_t *const expr = parse_expression();
- mark_decls_read(expr, NULL);
+ mark_vars_read(expr, NULL);
type_t * type = skip_typeref(expr->base.type);
if (is_type_integer(type)) {
type = promote_integer(type);
add_anchor_token(')');
expression_t *const cond = parse_expression();
statement->whiles.condition = cond;
- mark_decls_read(cond, NULL);
+ mark_vars_read(cond, NULL);
rem_anchor_token(')');
expect(')');
add_anchor_token(')');
expression_t *const cond = parse_expression();
statement->do_while.condition = cond;
- mark_decls_read(cond, NULL);
+ mark_vars_read(cond, NULL);
rem_anchor_token(')');
expect(')');
expect(';');
if (token.type != ';') {
if (is_declaration_specifier(&token, false)) {
- parse_declaration(record_declaration);
+ parse_declaration(record_entity);
} else {
add_anchor_token(';');
expression_t *const init = parse_expression();
statement->fors.initialisation = init;
- mark_decls_read(init, DECL_ANY);
+ mark_vars_read(init, VAR_ANY);
if (warning.unused_value && !expression_has_effect(init)) {
warningf(&init->base.source_position,
"initialisation of 'for'-statement has no effect");
add_anchor_token(';');
expression_t *const cond = parse_expression();
statement->fors.condition = cond;
- mark_decls_read(cond, NULL);
+ mark_vars_read(cond, NULL);
rem_anchor_token(';');
}
expect(';');
if (token.type != ')') {
expression_t *const step = parse_expression();
statement->fors.step = step;
- mark_decls_read(step, DECL_ANY);
+ mark_vars_read(step, VAR_ANY);
if (warning.unused_value && !expression_has_effect(step)) {
warningf(&step->base.source_position,
"step of 'for'-statement has no effect");
if (GNU_MODE && token.type == '*') {
next_token();
expression_t *expression = parse_expression();
- mark_decls_read(expression, NULL);
+ 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 */
}
/**
- * Check if a given declaration represents a local variable.
+ * Check if a given entity represents a local variable.
*/
-static bool is_local_var_declaration(const declaration_t *declaration)
+static bool is_local_variable(const entity_t *entity)
{
- switch ((storage_class_tag_t) declaration->storage_class) {
+ if (entity->kind != ENTITY_VARIABLE)
+ return false;
+
+ switch ((storage_class_tag_t) entity->declaration.storage_class) {
case STORAGE_CLASS_AUTO:
case STORAGE_CLASS_REGISTER: {
- const type_t *type = skip_typeref(declaration->type);
+ const type_t *type = skip_typeref(entity->declaration.type);
if (is_type_function(type)) {
return false;
} else {
}
}
-/**
- * Check if a given declaration represents a variable.
- */
-static bool is_var_declaration(const declaration_t *declaration)
-{
- if (declaration->storage_class == STORAGE_CLASS_TYPEDEF)
- return false;
-
- const type_t *type = skip_typeref(declaration->type);
- return !is_type_function(type);
-}
-
/**
* Check if a given expression represents a local variable.
*/
-static bool is_local_variable(const expression_t *expression)
+static bool expression_is_local_variable(const expression_t *expression)
{
if (expression->base.kind != EXPR_REFERENCE) {
return false;
}
- const declaration_t *declaration = expression->reference.declaration;
- return is_local_var_declaration(declaration);
+ const entity_t *entity = expression->reference.entity;
+ return is_local_variable(entity);
}
/**
* Check if a given expression represents a local variable and
* return its declaration then, else return NULL.
*/
-declaration_t *expr_is_variable(const expression_t *expression)
+entity_t *expression_is_variable(const expression_t *expression)
{
if (expression->base.kind != EXPR_REFERENCE) {
return NULL;
}
- declaration_t *declaration = expression->reference.declaration;
- if (is_var_declaration(declaration))
- return declaration;
- return NULL;
+ entity_t *entity = expression->reference.entity;
+ if (entity->kind != ENTITY_VARIABLE)
+ return NULL;
+
+ return entity;
}
/**
expression_t *return_value = NULL;
if (token.type != ';') {
return_value = parse_expression();
- mark_decls_read(return_value, NULL);
+ mark_vars_read(return_value, NULL);
}
- const type_t *const func_type = current_function->type;
+ const type_t *const func_type = current_function->base.type;
assert(is_type_function(func_type));
type_t *const return_type = skip_typeref(func_type->function.return_type);
return_value = create_implicit_cast(return_value, return_type);
}
/* check for returning address of a local var */
- if (warning.other &&
- return_value != NULL &&
- return_value->base.kind == EXPR_UNARY_TAKE_ADDRESS) {
+ if (warning.other && return_value != NULL
+ && return_value->base.kind == EXPR_UNARY_TAKE_ADDRESS) {
const expression_t *expression = return_value->unary.value;
- if (is_local_variable(expression)) {
+ if (expression_is_local_variable(expression)) {
warningf(&statement->base.source_position,
"function returns address of local variable");
}
{
statement_t *statement = allocate_statement_zero(STATEMENT_DECLARATION);
- declaration_t *before = last_declaration;
+ entity_t *before = scope->last_entity;
if (GNU_MODE)
parse_external_declaration();
else
- parse_declaration(record_declaration);
+ parse_declaration(record_entity);
if (before == NULL) {
- statement->declaration.declarations_begin = scope->declarations;
+ statement->declaration.declarations_begin = scope->entities;
} else {
- statement->declaration.declarations_begin = before->next;
+ statement->declaration.declarations_begin = before->base.next;
}
- statement->declaration.declarations_end = last_declaration;
+ statement->declaration.declarations_end = scope->last_entity;
return statement;
}
expression_t *const expr = parse_expression();
statement->expression.expression = expr;
- mark_decls_read(expr, DECL_ANY);
+ mark_vars_read(expr, VAR_ANY);
expect(';');
expect('(');
add_anchor_token(')');
expression_t *const expr = parse_expression();
- mark_decls_read(expr, NULL);
+ mark_vars_read(expr, NULL);
type_t * type = skip_typeref(expr->base.type);
if (is_type_integer(type)) {
type = promote_integer(type);
return statement;
}
-static statement_t *parse_local_label_declaration(void) {
+static statement_t *parse_local_label_declaration(void)
+{
statement_t *statement = allocate_statement_zero(STATEMENT_DECLARATION);
eat(T___label__);
- declaration_t *begin = NULL, *end = NULL;
+ entity_t *begin = NULL, *end = NULL;
while (true) {
if (token.type != T_IDENTIFIER) {
T_IDENTIFIER, NULL);
goto end_error;
}
- symbol_t *symbol = token.v.symbol;
- declaration_t *declaration = get_declaration(symbol, NAMESPACE_LOCAL_LABEL);
- if (declaration != NULL) {
+ symbol_t *symbol = token.v.symbol;
+ entity_t *entity = get_entity(symbol, NAMESPACE_LOCAL_LABEL);
+ if (entity != NULL) {
errorf(HERE, "multiple definitions of '__label__ %Y' (previous definition at %P)",
- symbol, &declaration->source_position);
+ symbol, &entity->base.source_position);
} else {
- declaration = allocate_declaration_zero();
- declaration->namespc = NAMESPACE_LOCAL_LABEL;
- declaration->source_position = token.source_position;
- declaration->symbol = symbol;
- declaration->parent_scope = scope;
- declaration->init.statement = NULL;
+ entity = allocate_entity_zero(ENTITY_LOCAL_LABEL);
+
+ entity->base.namespc = NAMESPACE_LOCAL_LABEL;
+ entity->base.source_position = token.source_position;
+ entity->base.symbol = symbol;
if (end != NULL)
- end->next = declaration;
- end = declaration;
+ end->base.next = entity;
+ end = entity;
if (begin == NULL)
- begin = declaration;
+ begin = entity;
- local_label_push(declaration);
+ local_label_push(entity);
}
next_token();
statement = parse_label_statement();
} else if (is_typedef_symbol(token.v.symbol)) {
statement = parse_declaration_statement();
- } else switch (la1_type) {
+ } else {
+ /* it's an identifier, the grammar says this must be an
+ * expression statement. However it is common that users mistype
+ * declaration types, so we guess a bit here to improve robustness
+ * for incorrect programs */
+ switch (la1_type) {
case '*':
- if (get_declaration(token.v.symbol, NAMESPACE_NORMAL) != NULL)
+ if (get_entity(token.v.symbol, NAMESPACE_NORMAL) != NULL)
goto expression_statment;
/* FALLTHROUGH */
expression_statment:
statement = parse_expression_statement();
break;
+ }
}
break;
}
/* const version of wchar_t */
type_const_wchar_t = allocate_type_zero(TYPE_TYPEDEF);
- type_const_wchar_t->typedeft.declaration = type_wchar_t->typedeft.declaration;
- type_const_wchar_t->base.qualifiers |= TYPE_QUALIFIER_CONST;
+ type_const_wchar_t->typedeft.typedefe = type_wchar_t->typedeft.typedefe;
+ type_const_wchar_t->base.qualifiers |= TYPE_QUALIFIER_CONST;
type_const_wchar_t_ptr = make_pointer_type(type_const_wchar_t, TYPE_QUALIFIER_NONE);
}
if (!warning.unused_function && !warning.unused_variable)
return;
- for (const declaration_t *decl = file_scope->declarations; decl != NULL; decl = decl->next) {
- if (decl->used ||
- decl->modifiers & DM_UNUSED ||
- decl->modifiers & DM_USED ||
- decl->storage_class != STORAGE_CLASS_STATIC)
+ for (const entity_t *entity = file_scope->entities; entity != NULL;
+ entity = entity->base.next) {
+ if (!is_declaration(entity))
continue;
- type_t *const type = decl->type;
+ const declaration_t *declaration = &entity->declaration;
+ if (declaration->used ||
+ declaration->modifiers & DM_UNUSED ||
+ declaration->modifiers & DM_USED ||
+ declaration->storage_class != STORAGE_CLASS_STATIC)
+ continue;
+
+ type_t *const type = declaration->type;
const char *s;
- if (is_type_function(skip_typeref(type))) {
- if (!warning.unused_function || decl->is_inline)
+ if (entity->kind == ENTITY_FUNCTION) {
+ /* inhibit warning for static inline functions */
+ if (entity->function.is_inline)
continue;
- s = (decl->init.statement != NULL ? "defined" : "declared");
+ s = entity->function.statement != NULL ? "defined" : "declared";
} else {
- if (!warning.unused_variable)
- continue;
-
s = "defined";
}
- warningf(&decl->source_position, "'%#T' %s but not used",
- type, decl->symbol, s);
+ warningf(&declaration->base.source_position, "'%#T' %s but not used",
+ type, declaration->base.symbol, s);
}
}
/* do NOT use scope_pop() here, this will crash, will it by hand */
assert(scope == &unit->scope);
scope = NULL;
- last_declaration = NULL;
assert(file_scope == &unit->scope);
check_unused_globals();
void parse(void);
translation_unit_t *finish_parsing(void);
-type_t *revert_automatic_type_conversion(const expression_t *expression);
-declaration_t *expr_is_variable(const expression_t *expression);
+type_t *revert_automatic_type_conversion(const expression_t *expression);
+entity_t *expression_is_variable(const expression_t *expression);
#endif
CPARSER_FLAGS="-O3 -fno-inline"
rm -f messages.cparser messages.gcc
-for i in *.c shouldpass/*.c; do
+for i in *.c should_pass/*.c; do
echo -n "Compile $i..."
"$CPARSER" $i $CPARSER_FLAGS -std=c99 -o prog.cparser >> messages.cparser 2>&1 || echo -n " CPARSER COMPILE FAILED"
gcc -m32 -std=c99 $i -O3 -o prog.gcc >> messages.gcc 2>&1 || echo -n " GCC COMPILE FAILED"
fi
done
-for i in shouldfail/*.c; do
+for i in should_fail/*.c; do
echo -n "Compile $i..."
"$CPARSER" $CPARSER_FLAGS $i -std=c99 -o prog.cparser >> messages.cparser 2>&1 && echo -n " CPARSER COMPILED"
gcc -m32 -std=c99 $i -O3 -o prog.gcc >> messages.gcc 2>&1 && echo -n " GCC COMPILED"
#include <stdbool.h>
#include "symbol.h"
-#include "ast.h"
+#include "entity.h"
#include "token_t.h"
struct pp_definition_t {
const char *string;
unsigned short ID;
unsigned short pp_ID;
- declaration_t *declaration;
+ entity_t *entity;
pp_definition_t *pp_definition;
};
static inline
void init_symbol_table_entry(symbol_t *entry, const char *string)
{
- entry->string = string;
- entry->ID = T_IDENTIFIER;
- entry->pp_ID = TP_IDENTIFIER;
- entry->declaration = NULL;
+ entry->string = string;
+ entry->ID = T_IDENTIFIER;
+ entry->pp_ID = TP_IDENTIFIER;
+ entry->entity = NULL;
}
#define HashSet symbol_table_t
#include <assert.h>
#include "type_t.h"
+#include "entity_t.h"
#include "symbol_t.h"
#include "type_hash.h"
#include "adt/error.h"
* @param top true, if this is the top type, false if it's an embedded type.
*/
static void print_function_type_post(const function_type_t *type,
- const scope_t *scope, bool top)
+ const scope_t *parameters, bool top)
{
/* don't emit parenthesis if we're the toplevel type... */
if (!top)
fputc('(', out);
bool first = true;
- if (scope == NULL) {
+ if (parameters == NULL) {
function_parameter_t *parameter = type->parameters;
for( ; parameter != NULL; parameter = parameter->next) {
if (first) {
print_type(parameter->type);
}
} else {
- declaration_t *parameter = scope->declarations;
- for( ; parameter != NULL; parameter = parameter->next) {
+ entity_t *parameter = parameters->entities;
+ for( ; parameter != NULL; parameter = parameter->base.next) {
if (first) {
first = false;
} else {
fputs(", ", out);
}
- print_type_ext(parameter->type, parameter->symbol,
- ¶meter->scope);
+ assert(is_declaration(parameter));
+ print_type_ext(parameter->declaration.type, parameter->base.symbol,
+ NULL);
}
}
if (type->variadic) {
*
* @param declaration The enum's type declaration.
*/
-void print_enum_definition(const declaration_t *declaration)
+void print_enum_definition(const enum_t *enume)
{
fputs("{\n", out);
change_indent(1);
- declaration_t *entry = declaration->next;
- for( ; entry != NULL && entry->storage_class == STORAGE_CLASS_ENUM_ENTRY;
- entry = entry->next) {
+ entity_t *entry = enume->base.next;
+ for( ; entry != NULL && entry->kind == ENTITY_ENUM_VALUE;
+ entry = entry->base.next) {
print_indent();
- fprintf(out, "%s", entry->symbol->string);
- if (entry->init.initializer != NULL) {
+ fprintf(out, "%s", entry->base.symbol->string);
+ if (entry->enum_value.value != NULL) {
fprintf(out, " = ");
/* skip the implicit cast */
- expression_t *expression = entry->init.enum_value;
+ expression_t *expression = entry->enum_value.value;
if (expression->kind == EXPR_UNARY_CAST_IMPLICIT) {
expression = expression->unary.value;
}
print_type_qualifiers(type->base.qualifiers);
fputs(" enum " + empty, out);
- declaration_t *declaration = type->declaration;
- symbol_t *symbol = declaration->symbol;
+ enum_t *enume = type->enume;
+ symbol_t *symbol = enume->base.symbol;
if (symbol != NULL) {
fputs(symbol->string, out);
} else {
- print_enum_definition(declaration);
+ print_enum_definition(enume);
}
}
/**
* Print the compound part of a compound type.
- *
- * @param declaration The declaration of the compound type.
*/
-void print_compound_definition(const declaration_t *declaration)
+void print_compound_definition(const compound_t *compound)
{
fputs("{\n", out);
change_indent(1);
- declaration_t *iter = declaration->scope.declarations;
- for( ; iter != NULL; iter = iter->next) {
+ entity_t *entity = compound->members.entities;
+ for( ; entity != NULL; entity = entity->base.next) {
+ if (entity->kind != ENTITY_COMPOUND_MEMBER)
+ continue;
+
print_indent();
- print_declaration(iter);
+ print_entity(entity);
fputc('\n', out);
}
fputs(" union " + empty, out);
}
- declaration_t *declaration = type->declaration;
- symbol_t *symbol = declaration->symbol;
+ compound_t *compound = type->compound;
+ symbol_t *symbol = compound->base.symbol;
if (symbol != NULL) {
fputs(symbol->string, out);
} else {
- print_compound_definition(declaration);
+ print_compound_definition(compound);
}
}
print_type_qualifiers(type->base.qualifiers);
if (type->base.qualifiers != 0)
fputc(' ', out);
- fputs(type->declaration->symbol->string, out);
+ fputs(type->typedefe->base.symbol->string, out);
}
/**
}
void print_type_ext(const type_t *const type, const symbol_t *symbol,
- const scope_t *scope)
+ const scope_t *parameters)
{
if (type == NULL) {
fputs("nil type", out);
fputs(symbol->string, out);
}
if (type->kind == TYPE_FUNCTION) {
- print_function_type_post(&type->function, scope, true);
+ print_function_type_post(&type->function, parameters, true);
} else {
intern_print_type_post(type, true);
}
case TYPE_COMPOUND_STRUCT:
case TYPE_COMPOUND_UNION: {
const compound_type_t *compound_type = &type->compound;
- declaration_t *declaration = compound_type->declaration;
- return !declaration->init.complete;
- }
- case TYPE_ENUM: {
- const enum_type_t *enum_type = &type->enumt;
- declaration_t *declaration = enum_type->declaration;
- return !declaration->init.complete;
+ return !compound_type->compound->complete;
}
+ case TYPE_ENUM:
+ return false;
case TYPE_ARRAY:
return type->array.size_expression == NULL
type = typedef_type->resolved_type;
break;
}
- type = typedef_type->declaration->type;
+ type = typedef_type->typedefe->type;
continue;
}
case TYPE_TYPEOF: {
if (typedef_type->resolved_type != NULL)
type = typedef_type->resolved_type;
else
- type = typedef_type->declaration->type;
+ type = typedef_type->typedefe->type;
continue;
case TYPE_TYPEOF: {
const typeof_type_t *typeof_type = &type->typeoft;
* if symbol is NULL
*/
void print_type_ext(const type_t *type, const symbol_t *symbol,
- const scope_t *scope);
+ const scope_t *parameters);
void print_type_qualifiers(type_qualifiers_t qualifiers);
-void print_enum_definition(const declaration_t *declaration);
-void print_compound_definition(const declaration_t *declaration);
+void print_enum_definition(const enum_t *enume);
+void print_compound_definition(const compound_t *compound);
/**
* set output stream for the type printer
static unsigned hash_compound_type(const compound_type_t *type)
{
- return hash_ptr(type->declaration);
+ return hash_ptr(type->compound);
}
static unsigned hash_type(const type_t *type);
static unsigned hash_enum_type(const enum_type_t *type)
{
- return hash_ptr(type->declaration);
+ return hash_ptr(type->enume);
}
static unsigned hash_typeof_type(const typeof_type_t *type)
hash = hash_ptr(type->builtin.symbol);
break;
case TYPE_TYPEDEF:
- hash = hash_ptr(type->typedeft.declaration);
+ hash = hash_ptr(type->typedeft.typedefe);
break;
case TYPE_TYPEOF:
hash = hash_typeof_type(&type->typeoft);
static bool compound_types_equal(const compound_type_t *type1,
const compound_type_t *type2)
{
- return type1->declaration == type2->declaration;
+ return type1->compound == type2->compound;
}
static bool enum_types_equal(const enum_type_t *type1,
const enum_type_t *type2)
{
- return type1->declaration == type2->declaration;
+ return type1->enume == type2->enume;
}
static bool typedef_types_equal(const typedef_type_t *type1,
const typedef_type_t *type2)
{
- return type1->declaration == type2->declaration;
+ return type1->typedefe == type2->typedefe;
}
static bool typeof_types_equal(const typeof_type_t *type1,
ir_node *size_node; /**< used by ast2firm phase */
- unsigned is_static : 1; /**< a [static] type */
- unsigned is_variable : 1; /**< a [*] type */
- unsigned has_implicit_size : 1;
- unsigned size_constant : 1; /**< size expression is constant */
- unsigned is_vla : 1; /**< it's a variable length array */
+ bool is_static : 1; /**< a [static] type */
+ bool is_variable : 1; /**< a [*] type */
+ bool has_implicit_size : 1;
+ bool size_constant : 1; /**< size expression is constant */
+ bool is_vla : 1; /**< it's a variable length array */
};
/**
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. */
- unsigned variadic : 1;
- unsigned unspecified_parameters : 1;
- unsigned kr_style_parameters : 1;
+ bool variadic : 1;
+ bool unspecified_parameters : 1;
+ bool kr_style_parameters : 1;
};
struct compound_type_t {
- type_base_t base;
- unsigned packed:1; /** Set if packed was specified. */
+ type_base_t base;
+ bool packed : 1; /** Set if packed was specified. */
/** the declaration of the compound type, the scope of the declaration
* contains the compound entries. */
- declaration_t *declaration;
+ compound_t *compound;
};
struct enum_type_t {
- type_base_t base;
- /** the declaration of the enum type. You can find the enum entries by
- * walking the declaration->next list until you don't find
- * STORAGE_CLASS_ENUM_ENTRY declarations anymore */
- declaration_t *declaration;
+ type_base_t base;
+ /** the enum entity. You can find the enum entries by walking the
+ * enum->base.next list until you don't find ENTITY_ENUM_VALUE entities
+ * anymore */
+ enum_t *enume;
};
struct typedef_type_t {
- type_base_t base;
- declaration_t *declaration;
- type_t *resolved_type;
+ type_base_t base;
+ typedef_t *typedefe;
+ type_t *resolved_type;
};
struct typeof_type_t {
+#include <config.h>
+
#include "adt/error.h"
#include "ast_t.h"
+#include "entity_t.h"
#include "walk_statements.h"
case EXPR_OFFSETOF:
case EXPR_REFERENCE:
+ case EXPR_REFERENCE_ENUM_VALUE:
case EXPR_CONST:
case EXPR_CHARACTER_CONSTANT:
case EXPR_WIDE_CHARACTER_CONSTANT:
/* TODO FIXME: implement all the missing expressions here */
}
+static void walk_initializer(const initializer_t *initializer,
+ statement_callback callback,
+ void *env)
+{
+ switch(initializer->kind) {
+ case INITIALIZER_VALUE:
+ walk_expression(initializer->value.value, callback, env);
+ return;
+ default:
+ /* FIXME: should walk initializer hierarchies... */
+ break;
+ }
+}
-static void walk_declarations(const declaration_t * decl,
- const declaration_t *const end,
+static void walk_declarations(const entity_t* entity,
+ const entity_t* const end,
statement_callback const callback,
void *const env)
{
- for (; decl != end; decl = decl->next) {
- if (decl->namespc != NAMESPACE_NORMAL)
+ for (; entity != end; entity = entity->base.next) {
+ /* we only look at variables */
+ if (entity->kind != ENTITY_VARIABLE)
continue;
- const initializer_t *initializer = decl->init.initializer;
- /* FIXME: should walk initializer hierarchies... */
- if (initializer != NULL && initializer->kind == INITIALIZER_VALUE) {
- walk_expression(initializer->value.value, callback, env);
+ const variable_t *variable = &entity->variable;
+ const initializer_t *initializer = variable->initializer;
+ if (initializer != NULL) {
+ walk_initializer(initializer, callback, env);
}
}
}
return;
case STATEMENT_FOR:
- walk_declarations(stmt->fors.scope.declarations, NULL, callback, env);
+ walk_declarations(stmt->fors.scope.entities, NULL, callback, env);
if (stmt->fors.initialisation != NULL)
walk_expression(stmt->fors.initialisation, callback, env);
if (stmt->fors.condition != NULL)
case STATEMENT_DECLARATION:
walk_declarations(stmt->declaration.declarations_begin,
- stmt->declaration.declarations_end->next,
+ stmt->declaration.declarations_end->base.next,
callback, env);
return;
walk_statements(stmt->ms_try.final_statement, callback, env);
return;
+ case STATEMENT_LOCAL_LABEL:
case STATEMENT_INVALID:
case STATEMENT_EMPTY:
case STATEMENT_CONTINUE:
#include "symbol_t.h"
#include "ast_t.h"
#include "type_t.h"
+#include "entity_t.h"
#include "type.h"
#include "adt/error.h"
fputc('*', out);
}
-static declaration_t *find_typedef(const type_t *type)
+static entity_t *find_typedef(const type_t *type)
{
/* first: search for a matching typedef in the global type... */
- declaration_t *declaration = global_scope->declarations;
- while(declaration != NULL) {
- if (! (declaration->storage_class == STORAGE_CLASS_TYPEDEF)) {
- declaration = declaration->next;
+ entity_t *entity = global_scope->entities;
+ for ( ; entity != NULL; entity = entity->base.next) {
+ if (entity->kind != ENTITY_TYPEDEF)
continue;
- }
- if (declaration->type == type)
+ if (entity->typedefe.type == type)
break;
- declaration = declaration->next;
}
- return declaration;
+ return entity;
}
static void write_compound_type(const compound_type_t *type)
{
- declaration_t *declaration = find_typedef((const type_t*) type);
- if (declaration != NULL) {
- fprintf(out, "%s", declaration->symbol->string);
+ const entity_t *entity = find_typedef((const type_t*) type);
+ if (entity != NULL) {
+ fprintf(out, "%s", entity->base.symbol->string);
return;
}
/* does the struct have a name? */
- symbol_t *symbol = type->declaration->symbol;
+ symbol_t *symbol = type->compound->base.symbol;
if (symbol != NULL) {
/* TODO: make sure we create a struct for it... */
fprintf(out, "%s", symbol->string);
static void write_enum_type(const enum_type_t *type)
{
- declaration_t *declaration = find_typedef((const type_t*) type);
- if (declaration != NULL) {
- fprintf(out, "%s", declaration->symbol->string);
+ const entity_t *entity = find_typedef((const type_t*) type);
+ if (entity != NULL) {
+ fprintf(out, "%s", entity->base.symbol->string);
return;
}
/* does the enum have a name? */
- symbol_t *symbol = type->declaration->symbol;
+ symbol_t *symbol = type->enume->base.symbol;
if (symbol != NULL) {
/* TODO: make sure we create an enum for it... */
fprintf(out, "%s", symbol->string);
}
}
-#if 0
-static void write_struct_entry(const declaration_t *declaration)
-{
- fprintf(out, "\t%s : ", declaration->symbol->string);
- write_type(declaration->type);
- fprintf(out, "\n");
-}
-
-static void write_struct(const symbol_t *symbol, const compound_type_t *type)
-{
- fprintf(out, "struct %s:\n", symbol->string);
-
- const declaration_t *declaration = type->declaration->scope.declarations;
- while(declaration != NULL) {
- write_struct_entry(declaration);
- declaration = declaration->next;
- }
-
- fprintf(out, "\n");
-}
-
-static void write_union(const symbol_t *symbol, const compound_type_t *type)
-{
- fprintf(out, "union %s:\n", symbol->string);
-
- const declaration_t *declaration = type->declaration->scope.declarations;
- while(declaration != NULL) {
- write_struct_entry(declaration);
- declaration = declaration->next;
- }
-
- fprintf(out, "\n");
-}
-
-static void write_expression(const expression_t *expression);
-
-static void write_unary_expression(const unary_expression_t *expression)
-{
- switch(expression->base.kind) {
- case EXPR_UNARY_NEGATE:
- fputc('-', out);
- break;
- case EXPR_UNARY_NOT:
- fputc('!', out);
- break;
- default:
- panic("unimeplemented unary expression found");
- }
- write_expression(expression->value);
-}
-
-static void write_expression(const expression_t *expression)
-{
- const const_expression_t *constant;
- /* TODO */
- switch(expression->kind) {
- case EXPR_CONST:
- constant = &expression->conste;
- if (is_type_integer(expression->base.type)) {
- fprintf(out, "%lld", constant->v.int_value);
- } else {
- fprintf(out, "%Lf", constant->v.float_value);
- }
- break;
- EXPR_UNARY_CASES
- write_unary_expression((const unary_expression_t*) expression);
- break;
- default:
- panic("not implemented expression");
- }
-}
-
-static void write_enum(const symbol_t *symbol, const enum_type_t *type)
-{
- fprintf(out, "enum %s:\n", symbol->string);
-
- declaration_t *entry = type->declaration->next;
- for ( ; entry != NULL && entry->storage_class == STORAGE_CLASS_ENUM_ENTRY;
- entry = entry->next) {
- fprintf(out, "\t%s", entry->symbol->string);
- if (entry->init.initializer != NULL) {
- fprintf(out, " <- ");
- write_expression(entry->init.enum_value);
- }
- fputc('\n', out);
- }
- fprintf(out, "typealias %s <- int\n", symbol->string);
- fprintf(out, "\n");
-}
-
-static void write_variable(const declaration_t *declaration)
-{
- fprintf(out, "var %s : ", declaration->symbol->string);
- write_type(declaration->type);
- /* TODO: initializers */
- fprintf(out, "\n");
-}
-#endif
-
-static void write_function(const declaration_t *declaration)
+static void write_function(const entity_t *entity)
{
- if (declaration->init.statement != NULL) {
+ if (entity->function.statement != NULL) {
fprintf(stderr, "Warning: can't convert function bodies (at %s)\n",
- declaration->symbol->string);
+ entity->base.symbol->string);
}
- fprintf(out, "external %s: ", declaration->symbol->string);
+ fprintf(out, "external %s: ", entity->base.symbol->string);
const function_type_t *function_type
- = (const function_type_t*) declaration->type;
+ = (const function_type_t*) entity->declaration.type;
- declaration_t *parameter = declaration->scope.declarations;
- for( ; parameter != NULL; parameter = parameter->next) {
- write_type(parameter->type);
+ entity_t *parameter = entity->function.parameters.entities;
+ for( ; parameter != NULL; parameter = parameter->base.next) {
+ assert(parameter->kind == ENTITY_VARIABLE);
+ write_type(parameter->declaration.type);
fputs(" -> ", out);
}
if (function_type->variadic) {
write_type(return_type);
fputs(" = \"", out);
- fputs(declaration->symbol->string, out);
+ fputs(entity->base.symbol->string, out);
fputs("\"", out);
fputc('\n', out);
ast_set_output(out);
fprintf(out, "(* WARNING: Automatically generated file - chaning is useless *)\n");
-#if 0
- /* write structs,unions + enums */
- declaration_t *declaration = unit->scope.declarations;
- for( ; declaration != NULL; declaration = declaration->next) {
- //fprintf(out, "// Decl: %s\n", declaration->symbol->string);
- if (! (declaration->storage_class == STORAGE_CLASS_TYPEDEF)) {
- continue;
- }
- type_t *type = declaration->type;
- if (type->kind == TYPE_COMPOUND_STRUCT) {
- write_struct(declaration->symbol, &type->compound);
- } else if (type->kind == TYPE_COMPOUND_UNION) {
- write_union(declaration->symbol, &type->compound);
- } else if (type->kind == TYPE_ENUM) {
- write_enum(declaration->symbol, &type->enumt);
- }
- }
-
- /* write global variables */
- declaration = unit->scope.declarations;
- for( ; declaration != NULL; declaration = declaration->next) {
- if (declaration->namespc != NAMESPACE_NORMAL)
- continue;
- if (declaration->storage_class == STORAGE_CLASS_TYPEDEF
- || declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
- continue;
-
- type_t *type = declaration->type;
- if (type->kind == TYPE_FUNCTION)
- continue;
-
- write_variable(declaration);
- }
-#endif
-
/* write functions */
- declaration_t *declaration = unit->scope.declarations;
- for( ; declaration != NULL; declaration = declaration->next) {
- if (declaration->namespc != NAMESPACE_NORMAL)
- continue;
- if (declaration->storage_class == STORAGE_CLASS_TYPEDEF
- || declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
- continue;
-
- type_t *type = declaration->type;
- if (type->kind != TYPE_FUNCTION)
+ entity_t *entity = unit->scope.entities;
+ for( ; entity != NULL; entity = entity->base.next) {
+ if (entity->kind != ENTITY_FUNCTION)
continue;
- write_function(declaration);
+ write_function(entity);
}
}
#include "symbol_t.h"
#include "ast_t.h"
#include "type_t.h"
+#include "entity_t.h"
#include "type.h"
#include "adt/error.h"
fputc('*', out);
}
-static declaration_t *find_typedef(const type_t *type)
+static entity_t *find_typedef(const type_t *type)
{
/* first: search for a matching typedef in the global type... */
- declaration_t *declaration = global_scope->declarations;
- while(declaration != NULL) {
- if(! (declaration->storage_class == STORAGE_CLASS_TYPEDEF)) {
- declaration = declaration->next;
+ entity_t *entity = global_scope->entities;
+ for ( ; entity != NULL; entity = entity->base.next) {
+ if (entity->kind != ENTITY_TYPEDEF)
continue;
- }
- if(declaration->type == type)
+ if (entity->typedefe.type == type)
break;
- declaration = declaration->next;
}
- return declaration;
+ return entity;
}
static void write_compound_type(const compound_type_t *type)
{
- declaration_t *declaration = find_typedef((const type_t*) type);
- if(declaration != NULL) {
- fprintf(out, "%s", declaration->symbol->string);
+ entity_t *entity = find_typedef((const type_t*) type);
+ if(entity != NULL) {
+ fprintf(out, "%s", entity->base.symbol->string);
return;
}
/* does the struct have a name? */
- symbol_t *symbol = type->declaration->symbol;
+ symbol_t *symbol = type->compound->base.symbol;
if(symbol != NULL) {
/* TODO: make sure we create a struct for it... */
fprintf(out, "%s", symbol->string);
static void write_enum_type(const enum_type_t *type)
{
- declaration_t *declaration = find_typedef((const type_t*) type);
- if(declaration != NULL) {
- fprintf(out, "%s", declaration->symbol->string);
+ entity_t *entity = find_typedef((const type_t*) type);
+ if (entity != NULL) {
+ fprintf(out, "%s", entity->base.symbol->string);
return;
}
/* does the enum have a name? */
- symbol_t *symbol = type->declaration->symbol;
- if(symbol != NULL) {
+ symbol_t *symbol = type->enume->base.symbol;
+ if (symbol != NULL) {
/* TODO: make sure we create an enum for it... */
fprintf(out, "%s", symbol->string);
return;
}
}
-static void write_struct_entry(const declaration_t *declaration)
-{
- fprintf(out, "\t%s : ", declaration->symbol->string);
- write_type(declaration->type);
- fprintf(out, "\n");
-}
-
-static void write_struct(const symbol_t *symbol, const compound_type_t *type)
+static void write_compound_entry(const entity_t *entity)
{
- fprintf(out, "struct %s:\n", symbol->string);
-
- const declaration_t *declaration = type->declaration->scope.declarations;
- while(declaration != NULL) {
- write_struct_entry(declaration);
- declaration = declaration->next;
- }
-
+ fprintf(out, "\t%s : ", entity->base.symbol->string);
+ write_type(entity->declaration.type);
fprintf(out, "\n");
}
-static void write_union(const symbol_t *symbol, const compound_type_t *type)
+static void write_compound(const symbol_t *symbol, const compound_type_t *type)
{
- fprintf(out, "union %s:\n", symbol->string);
+ fprintf(out, "%s %s:\n",
+ type->base.kind == TYPE_COMPOUND_STRUCT ? "struct" : "union",
+ symbol->string);
- const declaration_t *declaration = type->declaration->scope.declarations;
- while(declaration != NULL) {
- write_struct_entry(declaration);
- declaration = declaration->next;
+ const entity_t *entity = type->compound->members.entities;
+ for ( ; entity != NULL; entity = entity->base.next) {
+ write_compound_entry(entity);
}
fprintf(out, "\n");
{
fprintf(out, "enum %s:\n", symbol->string);
- declaration_t *entry = type->declaration->next;
- for ( ; entry != NULL && entry->storage_class == STORAGE_CLASS_ENUM_ENTRY;
- entry = entry->next) {
- fprintf(out, "\t%s", entry->symbol->string);
- if(entry->init.initializer != NULL) {
+ entity_t *entry = type->enume->base.next;
+ for ( ; entry != NULL && entry->kind == ENTITY_ENUM_VALUE;
+ entry = entry->base.next) {
+ fprintf(out, "\t%s", entry->base.symbol->string);
+ if(entry->enum_value.value != NULL) {
fprintf(out, " <- ");
- write_expression(entry->init.enum_value);
+ write_expression(entry->enum_value.value);
}
fputc('\n', out);
}
fprintf(out, "\n");
}
-static void write_variable(const declaration_t *declaration)
+static void write_variable(const entity_t *entity)
{
- fprintf(out, "var %s : ", declaration->symbol->string);
- write_type(declaration->type);
- /* TODO: initializers */
+ fprintf(out, "var %s : ", entity->base.symbol->string);
+ write_type(entity->declaration.type);
fprintf(out, "\n");
}
-static void write_function(const declaration_t *declaration)
+static void write_function(const entity_t *entity)
{
- if(declaration->init.statement != NULL) {
+ if (entity->function.statement != NULL) {
fprintf(stderr, "Warning: can't convert function bodies (at %s)\n",
- declaration->symbol->string);
+ entity->base.symbol->string);
}
- fprintf(out, "func extern %s(",
- declaration->symbol->string);
+ fprintf(out, "func extern %s(", entity->base.symbol->string);
const function_type_t *function_type
- = (const function_type_t*) declaration->type;
+ = (const function_type_t*) entity->declaration.type;
- declaration_t *parameter = declaration->scope.declarations;
- int first = 1;
- for( ; parameter != NULL; parameter = parameter->next) {
+ entity_t *parameter = entity->function.parameters.entities;
+ int first = 1;
+ for( ; parameter != NULL; parameter = parameter->base.next) {
+ assert(parameter->kind == ENTITY_VARIABLE);
if(!first) {
fprintf(out, ", ");
} else {
first = 0;
}
- if(parameter->symbol != NULL) {
- fprintf(out, "%s : ", parameter->symbol->string);
+ if(parameter->base.symbol != NULL) {
+ fprintf(out, "%s : ", parameter->base.symbol->string);
} else {
fputs("_ : ", out);
}
- write_type(parameter->type);
+ write_type(parameter->declaration.type);
}
if(function_type->variadic) {
if(!first) {
fprintf(out, "/* WARNING: Automatically generated file */\n");
/* write structs,unions + enums */
- declaration_t *declaration = unit->scope.declarations;
- for( ; declaration != NULL; declaration = declaration->next) {
- //fprintf(out, "// Decl: %s\n", declaration->symbol->string);
- if(! (declaration->storage_class == STORAGE_CLASS_TYPEDEF)) {
+ entity_t *entity = unit->scope.entities;
+ for( ; entity != NULL; entity = entity->base.next) {
+ if (entity->kind != ENTITY_TYPEDEF)
continue;
- }
- type_t *type = declaration->type;
- if(type->kind == TYPE_COMPOUND_STRUCT) {
- write_struct(declaration->symbol, &type->compound);
- } else if(type->kind == TYPE_COMPOUND_UNION) {
- write_union(declaration->symbol, &type->compound);
+
+ type_t *type = entity->typedefe.type;
+ if(type->kind == TYPE_COMPOUND_STRUCT
+ || type->kind == TYPE_COMPOUND_UNION) {
+ write_compound(entity->base.symbol, &type->compound);
} else if(type->kind == TYPE_ENUM) {
- write_enum(declaration->symbol, &type->enumt);
+ write_enum(entity->base.symbol, &type->enumt);
}
}
/* write global variables */
- declaration = unit->scope.declarations;
- for( ; declaration != NULL; declaration = declaration->next) {
- if(declaration->namespc != NAMESPACE_NORMAL)
- continue;
- if(declaration->storage_class == STORAGE_CLASS_TYPEDEF
- || declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
+ entity = unit->scope.entities;
+ for( ; entity != NULL; entity = entity->base.next) {
+ if (entity->kind != ENTITY_VARIABLE)
continue;
- type_t *type = declaration->type;
- if(type->kind == TYPE_FUNCTION)
- continue;
-
- write_variable(declaration);
+ write_variable(entity);
}
/* write functions */
- declaration = unit->scope.declarations;
- for( ; declaration != NULL; declaration = declaration->next) {
- if(declaration->namespc != NAMESPACE_NORMAL)
- continue;
- if(declaration->storage_class == STORAGE_CLASS_TYPEDEF
- || declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
- continue;
-
- type_t *type = declaration->type;
- if(type->kind != TYPE_FUNCTION)
+ entity = unit->scope.entities;
+ for( ; entity != NULL; entity = entity->base.next) {
+ if (entity->kind != ENTITY_FUNCTION)
continue;
- write_function(declaration);
+ write_function(entity);
}
}