declaration_t -> entity_t
authorMatthias Braun <matze@braunis.de>
Sat, 1 Nov 2008 17:00:35 +0000 (17:00 +0000)
committerMatthias Braun <matze@braunis.de>
Sat, 1 Nov 2008 17:00:35 +0000 (17:00 +0000)
This breaks up the monotolithic declaration_t monster in a bunch of different
structs like variable_t, function_t or label_t
Not everything back to the way it was, but SPEC seems to work now. Just some obscure gnu extensions missing.

[r23351]

20 files changed:
Makefile
ast.c
ast.h
ast2firm.c
ast_t.h
entity.h [new file with mode: 0644]
entity_t.h [new file with mode: 0644]
format_check.c
parser.c
parser.h
parsetest/do_tests.sh
symbol_t.h
symbol_table.c
type.c
type.h
type_hash.c
type_t.h
walk_statements.c
write_caml.c
write_fluffy.c

index f7be9fb..1ddff63 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -29,13 +29,11 @@ SOURCES := \
        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 \
@@ -43,6 +41,8 @@ SOURCES := \
        types.c \
        type_hash.c \
        warning.c \
+       parser.c \
+       ast2firm.c \
        write_fluffy.c \
        write_caml.c \
        driver/firm_cmdline.c \
diff --git a/ast.c b/ast.c
index 8b4ebf4..21f8028 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -24,6 +24,7 @@
 #include "type_t.h"
 #include "parser.h"
 #include "lang_features.h"
+#include "entity_t.h"
 
 #include <assert.h>
 #include <stdio.h>
@@ -241,7 +242,7 @@ static void print_quoted_string(const string_t *const string, char border, int s
                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;
@@ -358,7 +359,7 @@ static void print_funcname(
                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;
@@ -476,7 +477,7 @@ static void print_binary_expression(const binary_expression_t *binexpr)
 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;
@@ -529,7 +530,7 @@ static void print_unary_expression(const unary_expression_t *unexpr)
  */
 static void print_reference_expression(const reference_expression_t *ref)
 {
-       fputs(ref->declaration->symbol->string, out);
+       fputs(ref->entity->base.symbol->string, out);
 }
 
 /**
@@ -539,7 +540,7 @@ static void print_reference_expression(const reference_expression_t *ref)
  */
 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);
 }
 
 /**
@@ -658,7 +659,7 @@ static void print_va_start(const va_start_expression_t *const expression)
        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);
 }
 
@@ -690,7 +691,7 @@ static void print_select(const select_expression_t *expression)
        } else {
                fputc('.', out);
        }
-       fputs(expression->compound_entry->symbol->string, out);
+       fputs(expression->compound_entry->base.symbol->string, out);
 }
 
 /**
@@ -768,7 +769,7 @@ static void print_expression_prec(const expression_t *expression, unsigned top_p
                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);
@@ -917,7 +918,7 @@ static void print_goto_statement(const goto_statement_t *statement)
                fputc('*', out);
                print_expression(statement->expression);
        } else {
-               fputs(statement->label->symbol->string, out);
+               fputs(statement->label->base.symbol->string, out);
        }
        fputs(";\n", out);
 }
@@ -929,7 +930,7 @@ static void print_goto_statement(const goto_statement_t *statement)
  */
 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);
 }
@@ -994,6 +995,47 @@ static void print_case_label(const case_label_statement_t *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.
  *
@@ -1003,38 +1045,29 @@ static void print_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);
        }
 }
 
@@ -1074,13 +1107,15 @@ static void print_do_while_statement(const do_while_statement_t *statement)
 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);
@@ -1228,6 +1263,9 @@ void print_statement(const statement_t *statement)
        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;
@@ -1280,8 +1318,7 @@ void print_statement(const statement_t *statement)
  */
 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;
@@ -1307,7 +1344,7 @@ void print_initializer(const initializer_t *initializer)
                return;
        }
 
-       switch(initializer->kind) {
+       switch (initializer->kind) {
        case INITIALIZER_VALUE: {
                const initializer_value_t *value = &initializer->value;
                print_expression(value->value);
@@ -1347,20 +1384,50 @@ void print_initializer(const initializer_t *initializer)
 /**
  * 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);
                }
@@ -1391,10 +1458,8 @@ static void print_ms_modifiers(const declaration_t *declaration) {
                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);
@@ -1402,52 +1467,52 @@ static void print_ms_modifiers(const declaration_t *declaration) {
                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);
 }
@@ -1467,44 +1532,53 @@ void print_expression(const expression_t *expression)
  *
  * @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");
 }
 
 /**
@@ -1516,25 +1590,25 @@ void print_ast(const translation_unit_t *unit)
 {
        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:
@@ -1556,7 +1630,7 @@ bool is_constant_initializer(const initializer_t *initializer)
 
 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);
 
@@ -1575,15 +1649,24 @@ static bool is_object_with_linker_constant_address(const expression_t *expressio
                        && 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:
@@ -1593,7 +1676,7 @@ static bool is_object_with_linker_constant_address(const expression_t *expressio
 
 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);
 
@@ -1636,8 +1719,11 @@ bool is_address_constant(const expression_t *expression)
        }
 
        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)) {
@@ -1701,7 +1787,7 @@ static bool is_constant_pointer(const expression_t *expression)
 
 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;
@@ -1745,6 +1831,7 @@ bool is_constant_expression(const expression_t *expression)
        case EXPR_ALIGNOF:
        case EXPR_BUILTIN_CONSTANT_P:
        case EXPR_LABEL_ADDRESS:
+       case EXPR_REFERENCE_ENUM_VALUE:
                return true;
 
        case EXPR_SIZEOF: {
@@ -1764,6 +1851,7 @@ bool is_constant_expression(const expression_t *expression)
        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:
@@ -1848,14 +1936,6 @@ bool is_constant_expression(const expression_t *expression)
                        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;
 
diff --git a/ast.h b/ast.h
index 1de96dc..3eda9ce 100644 (file)
--- a/ast.h
+++ b/ast.h
@@ -22,8 +22,7 @@
 
 #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;
@@ -65,8 +64,6 @@ typedef struct initializer_wide_string_t    initializer_wide_string_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;
@@ -75,6 +72,7 @@ typedef struct return_statement_t           return_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;
@@ -99,7 +97,8 @@ void  print_expression(const expression_t *expression);
 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);
 
index c0a0d98..dbe3434 100644 (file)
@@ -36,6 +36,7 @@
 #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"
@@ -55,24 +56,23 @@ static ir_type *ir_type_wchar_t;
 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;
 
@@ -80,51 +80,43 @@ static struct obstack asm_obst;
 
 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);
 }
@@ -160,7 +152,7 @@ static ir_mode *mode_int, *mode_uint;
 static ir_node *_expression_to_firm(const expression_t *expression);
 static ir_node *expression_to_firm(const expression_t *expression);
 static inline ir_mode *get_ir_mode(type_t *type);
-static void create_local_declaration(declaration_t *declaration);
+static void create_local_declaration(entity_t *entity);
 
 static ir_mode *init_atomic_ir_mode(atomic_type_kind_t kind)
 {
@@ -200,7 +192,7 @@ 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];
@@ -368,8 +360,8 @@ static type_t *get_parameter_type(type_t *type)
 {
        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;
@@ -377,7 +369,7 @@ static type_t *get_parameter_type(type_t *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);
@@ -576,13 +568,11 @@ static ir_type *create_compound_type(compound_type_t *type, ir_type *irtype,
                                      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;
@@ -590,7 +580,7 @@ static ir_type *create_compound_type(compound_type_t *type, ir_type *irtype,
        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);
@@ -601,7 +591,7 @@ static ir_type *create_compound_type(compound_type_t *type, ir_type *irtype,
                                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);
@@ -609,10 +599,8 @@ static ir_type *create_compound_type(compound_type_t *type, ir_type *irtype,
                        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;
@@ -621,18 +609,18 @@ static ir_type *create_compound_type(compound_type_t *type, ir_type *irtype,
        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) {
@@ -708,9 +696,9 @@ static ir_type *create_compound_type(compound_type_t *type, ir_type *irtype,
                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) {
@@ -765,14 +753,13 @@ static ir_type *create_enum_type(enum_type_t *const type)
        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)) {
@@ -780,7 +767,7 @@ static ir_type *create_enum_type(enum_type_t *const type)
                        }
                        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);
        }
 
@@ -980,18 +967,19 @@ static ident *rts_idents[sizeof(rts_data) / sizeof(rts_data[0])];
  * @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);
@@ -1005,11 +993,10 @@ static ident *create_ld_ident_win32(ir_entity *ent, declaration_t *declaration)
  * @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);
 }
 
 /**
@@ -1018,16 +1005,15 @@ static ident *create_ld_ident_linux_elf(ir_entity *entity,
  * @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
@@ -1035,21 +1021,23 @@ create_ld_ident_func  create_ld_ident = create_ld_ident_linux_elf;
  * @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);
        }
 }
 
@@ -1058,58 +1046,58 @@ static void handle_gnu_attributes_ent(ir_entity *ent, declaration_t *decl)
  *
  * @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. */
@@ -1123,17 +1111,17 @@ static ir_entity *get_function_entity(declaration_t *declaration)
                        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;
 }
 
 /**
@@ -1252,7 +1240,7 @@ static ir_node *string_to_firm(const source_position_t *const src_pos,
        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);
        }
 
@@ -1305,7 +1293,7 @@ static ir_node *wide_string_literal_to_firm(
        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);
        }
 
@@ -1363,22 +1351,23 @@ static ir_node *do_strict_conv(dbg_info *dbgi, ir_node *node)
 }
 
 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);
        }
 }
 
@@ -1427,63 +1416,67 @@ static void keep_all_memory(ir_node *block) {
        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");
        }
 
@@ -1492,11 +1485,11 @@ static ir_node *reference_expression_to_firm(const reference_expression_t *ref)
 
 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:
@@ -1504,34 +1497,28 @@ static ir_node *reference_addr(const reference_expression_t *ref)
                 * 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");
        }
 
@@ -1615,27 +1602,26 @@ static ir_node *call_expression_to_firm(const call_expression_t *call)
                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);
@@ -1652,7 +1638,7 @@ static ir_node *call_expression_to_firm(const call_expression_t *call)
        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;
                }
 
@@ -1669,12 +1655,12 @@ static ir_node *call_expression_to_firm(const call_expression_t *call)
                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);
@@ -1687,7 +1673,7 @@ static ir_node *call_expression_to_firm(const call_expression_t *call)
        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);
 
@@ -1719,7 +1705,7 @@ static ir_node *call_expression_to_firm(const call_expression_t *call)
        }
 
        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);
@@ -1840,7 +1826,8 @@ static ir_node *bitfield_extract_to_firm(const select_expression_t *expression,
        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));
@@ -1864,6 +1851,16 @@ static ir_node *bitfield_extract_to_firm(const select_expression_t *expression,
        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)
 {
@@ -1873,10 +1870,11 @@ static void set_value_for_expression_addr(const expression_t *expression,
        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;
                }
        }
@@ -1889,12 +1887,15 @@ static void set_value_for_expression_addr(const expression_t *expression,
        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;
                }
        }
@@ -1914,12 +1915,13 @@ static ir_node *get_value_from_lvalue(const expression_t *expression,
        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);
                }
        }
 
@@ -1928,7 +1930,8 @@ static ir_node *get_value_from_lvalue(const expression_t *expression,
 
        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);
@@ -1989,9 +1992,12 @@ static bool is_local_variable(expression_t *expression)
 {
        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)
@@ -2032,50 +2038,50 @@ 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;
 }
@@ -2508,7 +2514,7 @@ static long get_offsetof_offset(const offsetof_expression_t *expression)
        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);
@@ -2517,19 +2523,20 @@ static long get_offsetof_offset(const offsetof_expression_t *expression)
                        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);
@@ -2619,9 +2626,10 @@ static ir_node *alignof_to_firm(const typeprop_expression_t *expression)
                /* 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);
@@ -2739,22 +2747,18 @@ static ir_node *select_addr(const select_expression_t *expression)
 {
        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;
 }
@@ -2767,8 +2771,9 @@ static ir_node *select_to_firm(const select_expression_t *expression)
                        (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);
@@ -2884,7 +2889,7 @@ static ir_node *function_name_to_firm(
        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);
                }
@@ -2913,7 +2918,8 @@ static ir_node *statement_expression_to_firm(const statement_expression_t *expr)
 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);
@@ -2922,7 +2928,7 @@ static ir_node *va_start_expression_to_firm(
        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);
 
@@ -2998,14 +3004,10 @@ static ir_node *builtin_prefetch_to_firm(
        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. */
@@ -3016,10 +3018,9 @@ static ir_node *get_label_block(declaration_t *label)
        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;
@@ -3032,7 +3033,7 @@ static ir_node *get_label_block(declaration_t *label)
 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) {
@@ -3071,6 +3072,8 @@ static ir_node *_expression_to_firm(const expression_t *expression)
                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
@@ -3246,35 +3249,30 @@ static ir_node *create_condition_evaluation(const expression_t *expression,
 }
 
 
-
-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);
        }
 }
 
@@ -3284,7 +3282,7 @@ struct type_path_entry_t {
        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;
@@ -3298,12 +3296,12 @@ static __attribute__((unused)) void debug_print_type_path(const type_path_t *pat
 {
        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 {
@@ -3332,17 +3330,16 @@ static type_path_entry_t *append_to_type_path(type_path_t *path)
        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)
@@ -3376,14 +3373,16 @@ static void descend_into_subtype(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);
@@ -3423,7 +3422,7 @@ static void walk_designator(type_path_t *path, const designator_t *designator)
        /* 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);
@@ -3433,10 +3432,11 @@ static void walk_designator(type_path_t *path, const designator_t *designator)
                        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;
                                }
                        }
@@ -3445,7 +3445,7 @@ static void walk_designator(type_path_t *path, const designator_t *designator)
                        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);
@@ -3488,13 +3488,14 @@ static void advance_current_object(type_path_t *path)
        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 {
@@ -3542,7 +3543,7 @@ static ir_initializer_t *create_ir_initializer_list(
 
        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) {
@@ -3597,7 +3598,7 @@ static ir_initializer_t *create_ir_initializer_string(
        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];
@@ -3623,7 +3624,7 @@ static ir_initializer_t *create_ir_initializer_wide_string(
        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];
@@ -3684,7 +3685,7 @@ static void create_dynamic_null_initializer(ir_type *type, dbg_info *dbgi,
                        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)) {
@@ -3767,7 +3768,7 @@ static void create_dynamic_initializer_sub(ir_initializer_t *initializer,
                                != (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;
@@ -3863,90 +3864,91 @@ static void create_local_initializer(initializer_t *initializer, dbg_info *dbgi,
        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 */
@@ -3959,24 +3961,24 @@ static void allocate_variable_length_array(declaration_t *declaration)
        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;
@@ -3986,48 +3988,50 @@ static void create_local_variable(declaration_t *declaration)
 
        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;
@@ -4041,7 +4045,8 @@ static void return_statement_to_firm(return_statement_t *statement)
                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];
@@ -4090,14 +4095,17 @@ static ir_node *expression_statement_to_firm(expression_statement_t *statement)
 
 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(
@@ -4110,11 +4118,13 @@ static ir_node *compound_statement_to_firm(compound_statement_t *compound)
        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;
@@ -4148,66 +4158,68 @@ 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:
@@ -4216,29 +4228,24 @@ static void create_local_declaration(declaration_t *declaration)
        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;
 
@@ -4250,12 +4257,12 @@ static void initialize_local_declaration(declaration_t *declaration)
 
 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);
        }
 }
 
@@ -4438,15 +4445,21 @@ static void for_statement_to_firm(for_statement_t *statement)
        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) {
@@ -4731,7 +4744,7 @@ static void asm_statement_to_firm(const asm_statement_t *statement)
 
        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)) {
@@ -4867,7 +4880,7 @@ static void asm_statement_to_firm(const asm_statement_t *statement)
                     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);
@@ -4984,7 +4997,7 @@ static void statement_to_firm(statement_t *statement)
        statement->base.transformed = true;
 #endif
 
-       switch(statement->kind) {
+       switch (statement->kind) {
        case STATEMENT_INVALID:
                panic("invalid statement found");
                return;
@@ -5030,6 +5043,10 @@ static void statement_to_firm(statement_t *statement)
        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;
@@ -5046,68 +5063,71 @@ static void statement_to_firm(statement_t *statement)
        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;
@@ -5115,12 +5135,12 @@ static void initialize_function_parameters(declaration_t *declaration)
 
                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;
                }
 
@@ -5134,12 +5154,13 @@ static void initialize_function_parameters(declaration_t *declaration)
                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*) &parameter->variable);
                ++next_value_number_function;
 
-               set_value(parameter->v.value_number, value);
+               set_value(parameter->variable.v.value_number, value);
        }
 }
 
@@ -5209,31 +5230,32 @@ static void gen_ijmp_branches(ir_node *block) {
 /**
  * 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;
@@ -5246,20 +5268,20 @@ static void create_function(declaration_t *declaration)
        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
@@ -5278,7 +5300,7 @@ static void create_function(declaration_t *declaration)
 
                        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);
@@ -5290,19 +5312,19 @@ static void create_function(declaration_t *declaration)
 
        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);
        }
@@ -5320,7 +5342,7 @@ static void create_function(declaration_t *declaration)
        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);
 
@@ -5343,52 +5365,43 @@ static void create_function(declaration_t *declaration)
 
        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);
                }
        }
 }
@@ -5477,9 +5490,13 @@ void translation_unit_to_firm(translation_unit_t *unit)
        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;
 }
diff --git a/ast_t.h b/ast_t.h
index 583e040..eefd350 100644 (file)
--- a/ast_t.h
+++ b/ast_t.h
@@ -27,6 +27,7 @@
 #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. */
@@ -64,6 +65,7 @@ typedef enum expression_kind_t {
        EXPR_UNKNOWN = 0,
        EXPR_INVALID,
        EXPR_REFERENCE,
+       EXPR_REFERENCE_ENUM_VALUE,
        EXPR_CONST,
        EXPR_CHARACTER_CONSTANT,
        EXPR_WIDE_CHARACTER_CONSTANT,
@@ -230,10 +232,10 @@ typedef enum funcname_kind_t {
  * 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 {
@@ -298,7 +300,7 @@ struct builtin_prefetch_expression_t {
 
 struct reference_expression_t {
        expression_base_t  base;
-       declaration_t     *declaration;
+       entity_t          *entity;
 };
 
 struct call_argument_t {
@@ -326,7 +328,7 @@ struct binary_expression_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 {
@@ -358,7 +360,7 @@ struct offsetof_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 {
@@ -385,7 +387,7 @@ struct classify_type_expression_t {
 
 struct label_address_expression_t {
        expression_base_t  base;
-       declaration_t     *declaration;
+       label_t           *label;
 };
 
 union expression_t {
@@ -415,28 +417,6 @@ 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,
@@ -557,92 +537,13 @@ typedef enum gnu_attribute_kind_t {
        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,
@@ -691,8 +592,14 @@ struct compound_statement_t {
 
 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 {
@@ -713,7 +620,7 @@ struct switch_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 */
 };
@@ -732,7 +639,7 @@ struct case_label_statement_t {
 
 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 */
 };
@@ -803,6 +710,7 @@ union statement_t {
        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;
diff --git a/entity.h b/entity.h
new file mode 100644 (file)
index 0000000..f7d4375
--- /dev/null
+++ b/entity.h
@@ -0,0 +1,37 @@
+/*
+ * 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
diff --git a/entity_t.h b/entity_t.h
new file mode 100644 (file)
index 0000000..821fd18
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * 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
index 3ac9110..06e0f7a 100644 (file)
@@ -23,6 +23,7 @@
 #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"
@@ -636,8 +637,8 @@ void check_format(const call_expression_t *const call)
        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 */
@@ -646,7 +647,7 @@ void check_format(const call_expression_t *const call)
                 * 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) {
index df1a6b6..686912f 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -33,6 +33,7 @@
 #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"
@@ -52,9 +53,9 @@ bool opt_short_wchar_t =
 #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;
@@ -81,10 +82,10 @@ struct gnu_attribute_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. */
@@ -97,14 +98,14 @@ struct declaration_specifiers_t {
  * 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;
@@ -119,10 +120,9 @@ static stack_entry_t      *local_label_stack = NULL;
 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;
@@ -186,10 +186,11 @@ static expression_t *parse_sub_expression(precedence_t);
 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);
 
@@ -310,12 +311,31 @@ static void *allocate_ast_zero(size_t size)
        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;
 }
 
 /**
@@ -331,6 +351,7 @@ static size_t get_statement_struct_size(statement_kind_t kind)
                [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),
@@ -361,6 +382,7 @@ static size_t get_expression_struct_size(expression_kind_t kind)
        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),
@@ -760,81 +782,73 @@ static void type_error_incompatible(const char *msg,
 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);
 }
 
 /**
@@ -842,10 +856,11 @@ static void environment_push(declaration_t *declaration)
  *
  * @param declaration  the declaration
  */
-static void label_push(declaration_t *declaration)
+static void label_push(entity_t *label)
 {
-       declaration->parent_scope = &current_function->scope;
-       stack_push(&label_stack, declaration);
+       /* we abuse the parameters scope as parent for the labels */
+       label->base.parent_scope = &current_function->parameters;
+       stack_push(&label_stack, label);
 }
 
 /**
@@ -853,10 +868,11 @@ static void label_push(declaration_t *declaration)
  *
  * @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);
 }
 
 /**
@@ -875,28 +891,28 @@ static void stack_pop_to(stack_entry_t **stack_ptr, size_t new_top)
        for(i = top; i > new_top; --i) {
                stack_entry_t *entry = &stack[i - 1];
 
-               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;
                }
        }
 
@@ -1180,21 +1196,19 @@ static expression_t *parse_assignment_expression(void)
 
 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;
 }
@@ -1717,7 +1731,7 @@ static decl_modifiers_t parse_gnu_attribute(gnu_attribute_t **attributes)
                                                attribute->have_arguments = true;
                                }
 
-                               switch(kind) {
+                               switch (kind) {
                                case GNU_AK_VOLATILE:
                                case GNU_AK_NAKED:
                                case GNU_AK_MALLOC:
@@ -1892,7 +1906,7 @@ static decl_modifiers_t parse_attributes(gnu_attribute_t **attributes)
        decl_modifiers_t modifiers = 0;
 
        while (true) {
-               switch(token.type) {
+               switch (token.type) {
                case T___attribute__:
                        modifiers |= parse_gnu_attribute(attributes);
                        continue;
@@ -1929,34 +1943,39 @@ end_error:
        }
 }
 
-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;
                        }
                }
@@ -1965,20 +1984,20 @@ static declaration_t *determine_lhs_decl(expression_t *const expr, declaration_t
                        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
@@ -1992,54 +2011,59 @@ static declaration_t *determine_lhs_decl(expression_t *const expr, declaration_t
  *   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;
 
 
@@ -2050,8 +2074,8 @@ static void mark_decls_read(expression_t *const expr, declaration_t *lhs_decl)
                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:
@@ -2066,7 +2090,7 @@ static void mark_decls_read(expression_t *const expr, declaration_t *lhs_decl)
                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:
@@ -2094,8 +2118,8 @@ unary:
                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:
@@ -2109,15 +2133,15 @@ unary:
                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:
@@ -2139,6 +2163,7 @@ unary:
                case EXPR_STATEMENT: // TODO
                case EXPR_LABEL_ADDRESS:
                case EXPR_BINARY_BUILTIN_EXPECT:
+               case EXPR_REFERENCE_ENUM_VALUE:
                        return;
        }
 
@@ -2152,7 +2177,7 @@ static designator_t *parse_designation(void)
 
        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;
@@ -2303,7 +2328,7 @@ static initializer_t *parse_scalar_initializer(type_t *type,
        }
 
        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",
@@ -2378,7 +2403,8 @@ static __attribute__((unused)) void debug_print_type_path(
                                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 {
@@ -2417,8 +2443,7 @@ static type_path_entry_t *append_to_type_path(type_path_t *path)
 }
 
 /**
- * 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)
 {
@@ -2429,14 +2454,15 @@ 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;
@@ -2496,10 +2522,10 @@ static bool walk_designator(type_path_t *path, const designator_t *designator,
                                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;
                                        }
                                }
@@ -2508,8 +2534,9 @@ static bool walk_designator(type_path_t *path, const designator_t *designator,
                                               "'%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",
@@ -2519,8 +2546,8 @@ static bool walk_designator(type_path_t *path, const designator_t *designator,
                                }
 
                                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;
@@ -2577,7 +2604,14 @@ static void advance_current_object(type_path_t *path, size_t top_path_level)
        } 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;
@@ -2707,9 +2741,10 @@ finish_designator:
                        } 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");
                                        }
@@ -2743,7 +2778,7 @@ finish_designator:
                                /* 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;
@@ -2806,9 +2841,9 @@ finish_designator:
                } 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");
                                }
@@ -2936,9 +2971,18 @@ end_error:
        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;
@@ -2948,8 +2992,8 @@ static declaration_t *parse_compound_type_specifier(bool is_struct)
                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);
@@ -2961,18 +3005,22 @@ static declaration_t *parse_compound_type_specifier(bool is_struct)
 
                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 != '{') {
@@ -2987,28 +3035,31 @@ static declaration_t *parse_compound_type_specifier(bool is_struct)
                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)
@@ -3030,11 +3081,10 @@ 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 == '=') {
@@ -3042,12 +3092,12 @@ static void parse_enum_entries(type_t *const enum_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;
@@ -3064,7 +3114,7 @@ end_error:
 static type_t *parse_enum_specifier(void)
 {
        gnu_attribute_t *attributes = NULL;
-       declaration_t   *declaration;
+       entity_t        *entity;
        symbol_t        *symbol;
 
        eat(T_enum);
@@ -3072,39 +3122,44 @@ static type_t *parse_enum_specifier(void)
                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;
@@ -3115,11 +3170,8 @@ static type_t *parse_enum_specifier(void)
  */
 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)
@@ -3214,13 +3266,12 @@ static type_t *create_builtin_type(symbol_t *const symbol,
 
 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;
 }
@@ -3356,7 +3407,7 @@ static void parse_microsoft_extended_decl_modifier(declaration_specifiers_t *spe
                        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) {
@@ -3385,29 +3436,28 @@ end_error:
        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;
@@ -3415,12 +3465,12 @@ static void finish_struct_type(compound_type_t *type) {
        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;
@@ -3433,7 +3483,7 @@ static void finish_struct_type(compound_type_t *type) {
 
                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) {
@@ -3445,13 +3495,13 @@ static void finish_struct_type(compound_type_t *type) {
                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;
@@ -3462,26 +3512,27 @@ static void finish_struct_type(compound_type_t *type) {
  * 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)
@@ -3518,10 +3569,10 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
                /* 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;
 
@@ -3541,17 +3592,17 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
                        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:
@@ -3634,14 +3685,14 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
                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;
@@ -3694,11 +3745,11 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
                                        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;
@@ -3730,7 +3781,7 @@ finish_specifiers:
                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;
@@ -3926,7 +3977,7 @@ static type_qualifiers_t parse_type_qualifiers(void)
        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);
@@ -3945,37 +3996,25 @@ static type_qualifiers_t parse_type_qualifiers(void)
 }
 
 /**
- * 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);
@@ -3983,13 +4022,10 @@ 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:
@@ -4011,32 +4047,27 @@ static void semantic_parameter(declaration_t *declaration)
 
        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(',');
@@ -4046,7 +4077,7 @@ static declaration_t *parse_parameters(function_type_t *type, declaration_t **la
                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;
                }
        }
@@ -4054,50 +4085,57 @@ static declaration_t *parse_parameters(function_type_t *type, declaration_t **la
        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;
@@ -4113,14 +4151,8 @@ 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 {
@@ -4212,55 +4244,51 @@ end_error:
        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]));
@@ -4271,35 +4299,20 @@ static construct_type_t *parse_function_declarator(declaration_t *declaration)
        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);
@@ -4320,28 +4333,28 @@ static construct_type_t *parse_inner_declarator(declaration_t *declaration,
                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(')');
@@ -4358,10 +4371,15 @@ static construct_type_t *parse_inner_declarator(declaration_t *declaration,
 
        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;
@@ -4397,28 +4415,35 @@ end_error:
        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;
@@ -4426,9 +4451,40 @@ static void parse_declaration_attributes(declaration_t *declaration)
                        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;
        }
 }
 
@@ -4437,7 +4493,7 @@ static type_t *construct_declarator_type(construct_type_t *construct_list,
 {
        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: {
@@ -4523,43 +4579,70 @@ static type_t *construct_declarator_type(construct_type_t *construct_list,
        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)
@@ -4574,17 +4657,6 @@ 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
@@ -4595,37 +4667,45 @@ static declaration_t *append_declaration(declaration_t* const declaration)
  * @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)
@@ -4633,7 +4713,7 @@ static void check_type_of_main(const declaration_t *const decl, const function_t
                        }
                } 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");
                }
        }
 }
@@ -4646,82 +4726,127 @@ static bool is_sym_main(const symbol_t *const sym)
        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 == &current_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 == &current_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;
@@ -4730,7 +4855,7 @@ static declaration_t *record_declaration(
                        /* 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;
@@ -4746,8 +4871,7 @@ static declaration_t *record_declaration(
                                                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) {
@@ -4766,17 +4890,17 @@ warn_redundant_declaration:
                                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;
@@ -4789,57 +4913,62 @@ warn_redundant_declaration:
                        } 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,
@@ -4861,44 +4990,49 @@ 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;
        }
 }
 
@@ -4909,7 +5043,7 @@ static void parse_anonymous_declaration_rest(
        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");
                }
@@ -4918,7 +5052,7 @@ static void parse_anonymous_declaration_rest(
                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");
                                }
@@ -4933,42 +5067,19 @@ static void parse_anonymous_declaration_rest(
                                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 != ',')
@@ -4976,7 +5087,7 @@ static void parse_declaration_rest(declaration_t *ndeclaration,
                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(';');
@@ -4986,39 +5097,28 @@ end_error:
        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)
@@ -5033,8 +5133,8 @@ 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);
        }
 }
 
@@ -5052,25 +5152,27 @@ static type_t *get_default_promoted_type(type_t *orig_type)
        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);
        }
 
@@ -5080,7 +5182,7 @@ static void parse_kr_declaration_list(declaration_t *declaration)
        }
 
        /* pop function parameters */
-       assert(scope == &declaration->scope);
+       assert(scope == &entity->function.parameters);
        scope_pop();
        environment_pop_to(top);
 
@@ -5090,26 +5192,26 @@ static void parse_kr_declaration_list(declaration_t *declaration)
        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(&parameter_declaration->declaration);
+               parameter_type = parameter_declaration->declaration.type;
 
                /*
                 * we need the default promoted types for the function type
@@ -5139,7 +5241,7 @@ static void parse_kr_declaration_list(declaration_t *declaration)
                obstack_free(type_obst, new_type);
        }
 
-       declaration->type = type;
+       entity->declaration.type = type;
 
        rem_anchor_token('{');
 }
@@ -5155,8 +5257,8 @@ static void print_in_function(void)
        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);
        }
 }
 
@@ -5173,48 +5275,56 @@ static void check_labels(void)
                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;
        }
 }
@@ -5226,12 +5336,13 @@ static void check_unused_variables(statement_t *const stmt, void *const env)
        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:
@@ -5245,15 +5356,16 @@ static void check_unused_variables(statement_t *const stmt, void *const env)
 static void check_declarations(void)
 {
        if (warning.unused_parameter) {
-               const scope_t *scope = &current_function->scope;
+               const scope_t *scope = &current_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);
        }
 }
 
@@ -5271,8 +5383,9 @@ static bool expression_returns(expression_t const *const expr)
                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;
                        }
 
@@ -5288,6 +5401,7 @@ static bool expression_returns(expression_t const *const expr)
                }
 
                case EXPR_REFERENCE:
+               case EXPR_REFERENCE_ENUM_VALUE:
                case EXPR_CONST:
                case EXPR_CHARACTER_CONSTANT:
                case EXPR_WIDE_CHARACTER_CONSTANT:
@@ -5363,6 +5477,7 @@ static void check_reachable(statement_t *const stmt)
                case STATEMENT_INVALID:
                case STATEMENT_EMPTY:
                case STATEMENT_DECLARATION:
+               case STATEMENT_LOCAL_LABEL:
                case STATEMENT_ASM:
                        next = stmt->base.next;
                        break;
@@ -5492,7 +5607,7 @@ found_break_parent:
                                        return;
                                next = parent;
                        } else {
-                               next = stmt->gotos.label->init.statement;
+                               next = stmt->gotos.label->statement;
                                if (next == NULL) /* missing label */
                                        return;
                        }
@@ -5574,13 +5689,13 @@ found_break_parent:
                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");
                        }
@@ -5591,6 +5706,7 @@ found_break_parent:
                        case STATEMENT_INVALID:
                        case STATEMENT_EMPTY:
                        case STATEMENT_DECLARATION:
+                       case STATEMENT_LOCAL_LABEL:
                        case STATEMENT_EXPRESSION:
                        case STATEMENT_ASM:
                        case STATEMENT_RETURN:
@@ -5759,7 +5875,7 @@ static void parse_external_declaration(void)
        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(';');
@@ -5771,7 +5887,7 @@ static void parse_external_declaration(void)
                case ',':
                case ';':
                case '=':
-                       parse_declaration_rest(ndeclaration, &specifiers, record_declaration);
+                       parse_declaration_rest(ndeclaration, &specifiers, record_entity);
                        return;
        }
 
@@ -5784,14 +5900,15 @@ static void parse_external_declaration(void)
                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;
@@ -5800,15 +5917,15 @@ static void parse_external_declaration(void)
        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
@@ -5823,72 +5940,78 @@ static void parse_external_declaration(void)
                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(&parameter->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(&parameter->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);
 }
@@ -5932,26 +6055,25 @@ static type_t *make_bitfield_type(type_t *base_type, expression_t *size,
        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;
                }
        }
@@ -5959,18 +6081,11 @@ static declaration_t *find_compound_entry(declaration_t *compound_declaration,
        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;
@@ -5982,17 +6097,18 @@ static void parse_compound_declarators(declaration_t *struct_declaration,
                        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 == ':') {
@@ -6001,43 +6117,36 @@ static void parse_compound_declarators(declaration_t *struct_declaration,
                                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;
@@ -6049,7 +6158,7 @@ end_error:
        ;
 }
 
-static void parse_compound_type_entries(declaration_t *compound_declaration)
+static void parse_compound_type_entries(compound_t *compound)
 {
        eat('{');
        add_anchor_token('}');
@@ -6063,7 +6172,7 @@ static void parse_compound_type_entries(declaration_t *compound_declaration)
                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();
@@ -6074,7 +6183,7 @@ static type_t *parse_typename(void)
        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...
                 */
@@ -6240,7 +6349,7 @@ static expression_t *parse_float_const(void)
        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);
@@ -6252,20 +6361,20 @@ static declaration_t *create_implicit_function(symbol_t *symbol,
                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;
 }
 
 /**
@@ -6345,7 +6454,7 @@ static type_t *make_function_0_type(type_t *return_type)
  */
 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:
@@ -6401,11 +6510,24 @@ static type_t *automatic_type_conversion(type_t *orig_type)
 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;
@@ -6447,14 +6569,11 @@ type_t *revert_automatic_type_conversion(const expression_t *expression)
 
 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) {
@@ -6462,52 +6581,74 @@ static expression_t *parse_reference(void)
                                        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();
@@ -6568,7 +6709,7 @@ static expression_t *parse_compound_literal(type_t *type)
 
        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;
@@ -6656,7 +6797,7 @@ static expression_t *parse_parenthesized_expression(void)
 {
        eat('(');
 
-       switch(token.type) {
+       switch (token.type) {
        case '{':
                /* gcc extension: a statement expression */
                return parse_statement_expression();
@@ -6852,12 +6993,15 @@ static expression_t *parse_va_start(void)
        expect(',');
        expression_t *const expr = parse_assignment_expression();
        if (expr->kind == EXPR_REFERENCE) {
-               declaration_t *const decl = expr->reference.declaration;
-               if (decl->parent_scope != &current_function->scope || decl->next != NULL) {
+               entity_t *const entity = expr->reference.entity;
+               if (entity->base.parent_scope != &current_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;
        }
@@ -6959,7 +7103,7 @@ static expression_t *parse_compare_builtin(void)
 {
        expression_t *expression;
 
-       switch(token.type) {
+       switch (token.type) {
        case T___builtin_isgreater:
                expression = allocate_expression_zero(EXPR_BINARY_ISGREATER);
                break;
@@ -7061,37 +7205,37 @@ end_error:
  *
  * @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 == &current_function->scope) {
-               return candidate;
+       if (label != NULL
+                       && label->base.parent_scope == &current_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;
 }
 
 /**
@@ -7108,8 +7252,7 @@ static expression_t *parse_label_address(void)
        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;
 
@@ -7117,8 +7260,8 @@ static expression_t *parse_label_address(void)
        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();
@@ -7390,18 +7533,18 @@ static expression_t *parse_select_expression(expression_t *compound)
                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;
@@ -7413,14 +7556,15 @@ static expression_t *parse_select_expression(expression_t *compound)
                               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! */
@@ -7447,12 +7591,12 @@ static void check_call_argument(const function_parameter_t *parameter,
        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)
@@ -7598,7 +7742,7 @@ static bool same_compound_type(const type_t *type1, const type_t *type2)
        return
                is_type_compound(type1) &&
                type1->kind == type2->kind &&
-               type1->compound.declaration == type2->compound.declaration;
+               type1->compound.compound == type2->compound.compound;
 }
 
 /**
@@ -7891,6 +8035,7 @@ static bool check_pointer_arithmetic(const source_position_t *source_position,
 
 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:
@@ -7968,15 +8113,14 @@ static expression_t const *get_reference_address(expression_t const *expr)
                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)
@@ -7987,8 +8131,8 @@ 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);
        }
 }
 
@@ -8049,18 +8193,19 @@ static void set_address_taken(expression_t *expression, bool may_be_register)
        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;
 }
 
 /**
@@ -8072,9 +8217,23 @@ static void semantic_take_addr(unary_expression_t *expression)
        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);
@@ -8380,15 +8539,15 @@ static void semantic_comparison(binary_expression_t *expression)
                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);
                }
        }
 
@@ -8459,18 +8618,18 @@ static void semantic_comparison(binary_expression_t *expression)
  */
 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;
 }
 
@@ -8639,6 +8798,7 @@ static bool expression_has_effect(const expression_t *const expr)
                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;
@@ -9048,9 +9208,9 @@ static asm_argument_t *parse_asm_arguments(bool is_out)
                        }
 
                        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(')');
@@ -9307,8 +9467,8 @@ end_error:
 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;
@@ -9318,13 +9478,14 @@ static statement_t *parse_label_statement(void)
        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(':');
@@ -9381,7 +9542,7 @@ static statement_t *parse_if(void)
        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(')');
 
@@ -9417,12 +9578,12 @@ static void check_enum_cases(const switch_statement_t *statement) {
                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) {
@@ -9435,7 +9596,8 @@ static void check_enum_cases(const switch_statement_t *statement) {
                }
                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;
        }
@@ -9455,7 +9617,7 @@ static statement_t *parse_switch(void)
        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);
@@ -9520,7 +9682,7 @@ static statement_t *parse_while(void)
        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(')');
 
@@ -9553,7 +9715,7 @@ static statement_t *parse_do(void)
        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(';');
@@ -9584,12 +9746,12 @@ static statement_t *parse_for(void)
 
        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");
@@ -9605,14 +9767,14 @@ static statement_t *parse_for(void)
                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");
@@ -9650,7 +9812,7 @@ static statement_t *parse_goto(void)
        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 */
@@ -9753,14 +9915,17 @@ end_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 {
@@ -9772,43 +9937,32 @@ static bool is_local_var_declaration(const declaration_t *declaration)
        }
 }
 
-/**
- * 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;
 }
 
 /**
@@ -9823,10 +9977,10 @@ static statement_t *parse_return(void)
        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);
 
@@ -9847,11 +10001,10 @@ static statement_t *parse_return(void)
                        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");
                        }
@@ -9875,18 +10028,18 @@ static statement_t *parse_declaration_statement(void)
 {
        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;
 }
@@ -9900,7 +10053,7 @@ static statement_t *parse_expression_statement(void)
 
        expression_t *const expr         = parse_expression();
        statement->expression.expression = expr;
-       mark_decls_read(expr, DECL_ANY);
+       mark_vars_read(expr, VAR_ANY);
 
        expect(';');
 
@@ -9931,7 +10084,7 @@ static statement_t *parse_ms_try_statment(void)
                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);
@@ -9966,12 +10119,13 @@ static statement_t *parse_empty_statement(void)
        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) {
@@ -9979,26 +10133,25 @@ static statement_t *parse_local_label_declaration(void) {
                                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();
 
@@ -10031,9 +10184,14 @@ static statement_t *intern_parse_statement(void)
                        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 */
 
@@ -10046,6 +10204,7 @@ static statement_t *intern_parse_statement(void)
 expression_statment:
                                statement = parse_expression_statement();
                                break;
+                       }
                }
                break;
        }
@@ -10228,8 +10387,8 @@ static void initialize_builtin_types(void)
 
        /* 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);
 }
@@ -10242,29 +10401,32 @@ static void check_unused_globals(void)
        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);
        }
 }
 
@@ -10383,7 +10545,6 @@ translation_unit_t *finish_parsing(void)
        /* do NOT use scope_pop() here, this will crash, will it by hand */
        assert(scope == &unit->scope);
        scope            = NULL;
-       last_declaration = NULL;
 
        assert(file_scope == &unit->scope);
        check_unused_globals();
index b6ee305..1bc004d 100644 (file)
--- a/parser.h
+++ b/parser.h
@@ -32,7 +32,7 @@ void start_parsing(void);
 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
index c5dc403..1f5a341 100755 (executable)
@@ -4,7 +4,7 @@ CPARSER=../build/cparser
 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"
@@ -44,7 +44,7 @@ for i in should_warn/*.c; do
        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"
index 1fe4054..42fe92c 100644 (file)
@@ -22,7 +22,7 @@
 
 #include <stdbool.h>
 #include "symbol.h"
-#include "ast.h"
+#include "entity.h"
 #include "token_t.h"
 
 struct pp_definition_t {
@@ -41,7 +41,7 @@ struct symbol_t {
        const char       *string;
        unsigned short    ID;
        unsigned short    pp_ID;
-       declaration_t    *declaration;
+       entity_t         *entity;
        pp_definition_t  *pp_definition;
 };
 
index 00b38ad..5a448e9 100644 (file)
@@ -30,10 +30,10 @@ struct obstack symbol_obstack;
 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
diff --git a/type.c b/type.c
index 5b7006f..9ea8d41 100644 (file)
--- a/type.c
+++ b/type.c
@@ -23,6 +23,7 @@
 #include <assert.h>
 
 #include "type_t.h"
+#include "entity_t.h"
 #include "symbol_t.h"
 #include "type_hash.h"
 #include "adt/error.h"
@@ -327,7 +328,7 @@ static void print_function_type_pre(const function_type_t *type, bool top)
  * @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)
@@ -335,7 +336,7 @@ static void print_function_type_post(const function_type_t *type,
 
        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) {
@@ -346,15 +347,16 @@ static void print_function_type_post(const function_type_t *type,
                        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,
-                                      &parameter->scope);
+                       assert(is_declaration(parameter));
+                       print_type_ext(parameter->declaration.type, parameter->base.symbol,
+                                      NULL);
                }
        }
        if (type->variadic) {
@@ -446,23 +448,23 @@ static void print_bitfield_type_post(const bitfield_type_t *type)
  *
  * @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;
                        }
@@ -487,29 +489,30 @@ static void print_type_enum(const enum_type_t *type)
        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);
        }
 
@@ -535,12 +538,12 @@ static void print_compound_type(const compound_type_t *type)
                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);
        }
 }
 
@@ -554,7 +557,7 @@ static void print_typedef_type_pre(const typedef_type_t *const type)
        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);
 }
 
 /**
@@ -677,7 +680,7 @@ void print_type(const type_t *const type)
 }
 
 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);
@@ -690,7 +693,7 @@ void print_type_ext(const type_t *const type, const symbol_t *symbol,
                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);
        }
@@ -972,14 +975,10 @@ bool is_type_incomplete(const type_t *type)
        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
@@ -1161,7 +1160,7 @@ type_t *skip_typeref(type_t *type)
                                type = typedef_type->resolved_type;
                                break;
                        }
-                       type = typedef_type->declaration->type;
+                       type = typedef_type->typedefe->type;
                        continue;
                }
                case TYPE_TYPEOF: {
@@ -1217,7 +1216,7 @@ type_qualifiers_t get_type_qualifier(const type_t *type, bool skip_array_type) {
                        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;
diff --git a/type.h b/type.h
index 3304c1e..50c9cf7 100644 (file)
--- a/type.h
+++ b/type.h
@@ -102,12 +102,12 @@ void print_type(const type_t *type);
  * 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
index 49fd88e..d20759f 100644 (file)
@@ -84,7 +84,7 @@ static unsigned hash_array_type(const array_type_t *type)
 
 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);
@@ -105,7 +105,7 @@ static unsigned hash_function_type(const function_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)
@@ -163,7 +163,7 @@ static unsigned hash_type(const 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);
@@ -262,19 +262,19 @@ static bool builtin_types_equal(const builtin_type_t *type1,
 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,
index 24fec3a..3f84f0c 100644 (file)
--- a/type_t.h
+++ b/type_t.h
@@ -101,11 +101,11 @@ struct array_type_t {
 
        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 */
 };
 
 /**
@@ -133,31 +133,31 @@ struct function_type_t {
        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 {
index a0337a0..242b6f3 100644 (file)
@@ -1,5 +1,8 @@
+#include <config.h>
+
 #include "adt/error.h"
 #include "ast_t.h"
+#include "entity_t.h"
 #include "walk_statements.h"
 
 
@@ -77,6 +80,7 @@ static void walk_expression(expression_t const *const expr, statement_callback c
 
                case EXPR_OFFSETOF:
                case EXPR_REFERENCE:
+               case EXPR_REFERENCE_ENUM_VALUE:
                case EXPR_CONST:
                case EXPR_CHARACTER_CONSTANT:
                case EXPR_WIDE_CHARACTER_CONSTANT:
@@ -93,20 +97,34 @@ static void walk_expression(expression_t const *const expr, statement_callback c
        /* 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);
                }
        }
 }
@@ -124,7 +142,7 @@ void walk_statements(statement_t *const stmt, statement_callback const callback,
                        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)
@@ -175,7 +193,7 @@ void walk_statements(statement_t *const stmt, statement_callback const callback,
 
                case STATEMENT_DECLARATION:
                        walk_declarations(stmt->declaration.declarations_begin,
-                                         stmt->declaration.declarations_end->next,
+                                         stmt->declaration.declarations_end->base.next,
                                          callback, env);
                        return;
 
@@ -184,6 +202,7 @@ void walk_statements(statement_t *const stmt, statement_callback const callback,
                        walk_statements(stmt->ms_try.final_statement, callback, env);
                        return;
 
+               case STATEMENT_LOCAL_LABEL:
                case STATEMENT_INVALID:
                case STATEMENT_EMPTY:
                case STATEMENT_CONTINUE:
index b688cc6..612ca15 100644 (file)
@@ -26,6 +26,7 @@
 #include "symbol_t.h"
 #include "ast_t.h"
 #include "type_t.h"
+#include "entity_t.h"
 #include "type.h"
 #include "adt/error.h"
 
@@ -75,33 +76,30 @@ static void write_pointer_type(const pointer_type_t *type)
        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);
@@ -113,14 +111,14 @@ static void write_compound_type(const compound_type_t *type)
 
 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);
@@ -192,120 +190,22 @@ static void write_type(const type_t *type)
        }
 }
 
-#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) {
@@ -318,7 +218,7 @@ static void write_function(const declaration_t *declaration)
        write_type(return_type);
 
        fputs(" = \"", out);
-       fputs(declaration->symbol->string, out);
+       fputs(entity->base.symbol->string, out);
        fputs("\"", out);
 
        fputc('\n', out);
@@ -332,54 +232,12 @@ void write_caml_decls(FILE *output, const translation_unit_t *unit)
        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);
        }
 }
index 5379aee..63dbe9a 100644 (file)
@@ -26,6 +26,7 @@
 #include "symbol_t.h"
 #include "ast_t.h"
 #include "type_t.h"
+#include "entity_t.h"
 #include "type.h"
 #include "adt/error.h"
 
@@ -68,33 +69,30 @@ static void write_pointer_type(const pointer_type_t *type)
        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);
@@ -106,15 +104,15 @@ static void write_compound_type(const compound_type_t *type)
 
 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;
@@ -185,34 +183,22 @@ static void write_type(const type_t *type)
        }
 }
 
-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");
@@ -260,13 +246,13 @@ 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) {
+       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);
        }
@@ -274,41 +260,40 @@ static void write_enum(const symbol_t *symbol, const enum_type_t *type)
        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) {
@@ -338,51 +323,35 @@ void write_fluffy_decls(FILE *output, const translation_unit_t *unit)
        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);
        }
 }