diff --git a/boot/semantic.cc b/boot/semantic.cc
new file mode 100644
index 0000000..6735976
--- /dev/null
+++ b/boot/semantic.cc
@@ -0,0 +1,73 @@
+/* Name analysis.
+   Copyright (C) 2025 Free Software Foundation, Inc.
+
+GCC 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 3, or (at your option)
+any later version.
+
+GCC 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 GCC; see the file COPYING3.  If not see
+.  */
+
+#include "elna/boot/semantic.h"
+
+namespace elna
+{
+namespace boot
+{
+    alias_type *type::is_alias()
+    {
+        return nullptr;
+    }
+
+    primitive_type *type::is_primitive()
+    {
+        return nullptr;
+    }
+
+    record_type *type::is_record()
+    {
+        return nullptr;
+    }
+
+    union_type *type::is_union()
+    {
+        return nullptr;
+    }
+
+    type::~type()
+    {
+    }
+
+    alias_type *alias_type::is_alias()
+    {
+        return this;
+    }
+
+    primitive_type::primitive_type(const std::string& identifier)
+        : identifier(identifier)
+    {
+    }
+
+    primitive_type *primitive_type::is_primitive()
+    {
+        return this;
+    }
+
+    record_type *record_type::is_record()
+    {
+        return this;
+    }
+
+    union_type *union_type::is_union()
+    {
+        return this;
+    }
+}
+}
diff --git a/gcc/Make-lang.in b/gcc/Make-lang.in
index f8f8385..54a2807 100644
--- a/gcc/Make-lang.in
+++ b/gcc/Make-lang.in
@@ -46,6 +46,7 @@ elna_OBJS = \
 	elna/driver.o \
 	elna/lexer.o \
 	elna/parser.o \
+	elna/semantic.o \
 	elna/result.o \
 	$(END)
 
diff --git a/gcc/elna-generic.cc b/gcc/elna-generic.cc
index 497c92a..3ee4f94 100644
--- a/gcc/elna-generic.cc
+++ b/gcc/elna-generic.cc
@@ -41,25 +41,65 @@ namespace gcc
     declaration_visitor::declaration_visitor(std::shared_ptr symbol_table)
         : symbols(symbol_table)
     {
-        this->unresolved.insert({ "Int", std::make_shared(elna_int_type_node) });
-        this->unresolved.insert({ "Word", std::make_shared(elna_word_type_node) });
-        this->unresolved.insert({ "Char", std::make_shared(elna_char_type_node) });
-        this->unresolved.insert({ "Bool", std::make_shared(elna_bool_type_node) });
-        this->unresolved.insert({ "Byte", std::make_shared(elna_byte_type_node) });
-        this->unresolved.insert({ "Float", std::make_shared(elna_float_type_node) });
-        this->unresolved.insert({ "String", std::make_shared(elna_string_type_node) });
+        this->symbols->enter("Int", elna_int_type_node);
+        this->symbols->enter("Word", elna_word_type_node);
+        this->symbols->enter("Char", elna_char_type_node);
+        this->symbols->enter("Bool", elna_bool_type_node);
+        this->symbols->enter("Byte", elna_byte_type_node);
+        this->symbols->enter("Float", elna_float_type_node);
+        this->symbols->enter("String", elna_string_type_node);
     }
 
-    tree get_inner_alias(const type& t)
+    tree declaration_visitor::get_inner_alias(const boot::alias_type& t)
     {
         if (t.reference == nullptr)
         {
-            return t.resolved;
+            return NULL_TREE;
         }
-        else
+        else if (auto reference = t.reference->is_primitive())
         {
-            return get_inner_alias(*t.reference);
+            return this->symbols->lookup(reference->identifier);
         }
+        else if (auto reference = t.reference->is_alias())
+        {
+            return get_inner_alias(*reference);
+        }
+        else if (auto reference = t.reference->is_record())
+        {
+            return make_node(RECORD_TYPE);
+        }
+        else if (auto reference = t.reference->is_union())
+        {
+            return make_node(UNION_TYPE);
+        }
+        return NULL_TREE;
+    }
+
+    boot::type *declaration_visitor::build_type(boot::type_expression *type_expression)
+    {
+        if (auto alias_node = type_expression->is_primitive())
+        {
+            return this->unresolved.at(alias_node->name);
+        }
+        else if (auto alias_node = type_expression->is_record())
+        {
+            return build_record(alias_node.get());
+        }
+        else if (auto alias_node = type_expression->is_union())
+        {
+            return build_union(alias_node.get());
+        }
+        return nullptr;
+    }
+
+    boot::record_type *declaration_visitor::build_record(boot::record_type_expression *type_expression)
+    {
+        return new boot::record_type();
+    }
+
+    boot::union_type *declaration_visitor::build_union(boot::union_type_expression *type_expression)
+    {
+        return new boot::union_type();
     }
 
     void declaration_visitor::visit(boot::program *program)
@@ -80,26 +120,30 @@ namespace gcc
                 {
                     unresolved_declaration->reference = unresolved_alias->second;
                 }
+                else
+                {
+                    unresolved_declaration->reference = new boot::primitive_type(alias_node->name);
+                }
             }
             else if (auto alias_node = type->body().is_record())
             {
-                unresolved_declaration->resolved = make_node(RECORD_TYPE);
+                unresolved_declaration->reference = build_record(alias_node.get());
             }
             else if (auto alias_node = type->body().is_union())
             {
-                unresolved_declaration->resolved = make_node(UNION_TYPE);
+                unresolved_declaration->reference = build_union(alias_node.get());
             }
         }
         for (auto unresolved : this->unresolved)
         {
-            auto inner_alias = get_inner_alias(unresolved.second);
+            auto inner_alias = get_inner_alias(*unresolved.second);
             this->symbols->enter(unresolved.first, inner_alias);
         }
     }
 
     void declaration_visitor::visit(boot::type_definition *definition)
     {
-        this->unresolved.insert({ definition->identifier, std::make_shared() });
+        this->unresolved.insert({ definition->identifier, new boot::alias_type() });
     }
 
     generic_visitor::generic_visitor(std::shared_ptr symbol_table)
diff --git a/include/elna/boot/semantic.h b/include/elna/boot/semantic.h
new file mode 100644
index 0000000..de6030a
--- /dev/null
+++ b/include/elna/boot/semantic.h
@@ -0,0 +1,75 @@
+/* Name analysis.
+   Copyright (C) 2025 Free Software Foundation, Inc.
+
+GCC 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 3, or (at your option)
+any later version.
+
+GCC 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 GCC; see the file COPYING3.  If not see
+.  */
+
+#include 
+#include 
+
+namespace elna
+{
+namespace boot
+{
+    class alias_type;
+    class record_type;
+    class union_type;
+    class primitive_type;
+
+    class type
+    {
+    public:
+        virtual alias_type *is_alias();
+        virtual primitive_type *is_primitive();
+        virtual record_type *is_record();
+        virtual union_type *is_union();
+
+        virtual ~type() = 0;
+    };
+
+    class alias_type : public type
+    {
+    public:
+        alias_type *is_alias() override;
+
+        type *reference{ nullptr };
+    };
+
+    class primitive_type : public type
+    {
+    public:
+        std::string identifier;
+
+        primitive_type(const std::string& identifier);
+
+        primitive_type *is_primitive() override;
+    };
+
+    class record_type : public type
+    {
+    public:
+        std::vector> fields;
+
+        record_type *is_record() override;
+    };
+
+    class union_type : public type
+    {
+    public:
+        std::vector> fields;
+
+        union_type *is_union() override;
+    };
+}
+}
diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h
index 921236f..4f4c635 100644
--- a/include/elna/gcc/elna-generic.h
+++ b/include/elna/gcc/elna-generic.h
@@ -19,6 +19,7 @@ along with GCC; see the file COPYING3.  If not see
 
 #include "elna/boot/ast.h"
 #include "elna/boot/symbol.h"
+#include "elna/boot/semantic.h"
 #include "elna/gcc/elna-tree.h"
 
 #include "config.h"
@@ -34,20 +35,15 @@ namespace elna
 {
 namespace gcc
 {
-    struct type
-    {
-        type() {}
-        type(tree resolved): resolved(resolved) {}
-        type(std::shared_ptr reference): reference(reference) {}
-
-        tree resolved{ NULL_TREE };
-        std::shared_ptr reference;
-    };
-
     class declaration_visitor final : public boot::empty_visitor
     {
         std::shared_ptr symbols;
-        std::unordered_map> unresolved;
+        std::unordered_map unresolved;
+
+        boot::type *build_type(boot::type_expression *type_expression);
+        boot::record_type *build_record(boot::record_type_expression *type_expression);
+        boot::union_type *build_union(boot::union_type_expression *type_expression);
+        tree get_inner_alias(const boot::alias_type& t);
 
     public:
         declaration_visitor(std::shared_ptr symbol_table);