diff --git a/boot/ast.cc b/boot/ast.cc
index 14e4230..ac0b57e 100644
--- a/boot/ast.cc
+++ b/boot/ast.cc
@@ -86,6 +86,24 @@ namespace boot
         }
     }
 
+    void empty_visitor::visit(return_statement *statement)
+    {
+        expression *return_expression = statement->return_expression();
+
+        if (return_expression != nullptr)
+        {
+            return_expression->accept(this);
+        }
+    }
+
+    void empty_visitor::visit(defer_statement *defer)
+    {
+        for (statement *const body_statement : defer->statements)
+        {
+            body_statement->accept(this);
+        }
+    }
+
     void empty_visitor::visit(block *block)
     {
         for (constant_definition *const constant : block->constants)
@@ -370,9 +388,8 @@ namespace boot
     }
 
     procedure_definition::procedure_definition(const struct position position, const std::string& identifier,
-            const bool exported, std::shared_ptr<procedure_type> heading,
-            block *const body, expression *const returning)
-        : definition(position, identifier, exported), m_heading(heading), body(body), returning(returning)
+            const bool exported, std::shared_ptr<procedure_type> heading, block *body)
+        : definition(position, identifier, exported), m_heading(heading), body(body)
     {
     }
 
@@ -389,7 +406,6 @@ namespace boot
     procedure_definition::~procedure_definition()
     {
         delete body;
-        delete returning;
     }
 
     type_definition::type_definition(const struct position position, const std::string& identifier,
@@ -460,6 +476,24 @@ namespace boot
     {
     }
 
+    defer_statement::defer_statement(const struct position position)
+        : node(position)
+    {
+    }
+
+    void defer_statement::accept(parser_visitor *visitor)
+    {
+        visitor->visit(this);
+    }
+
+    defer_statement::~defer_statement()
+    {
+        for (statement *body_statement : statements)
+        {
+            delete body_statement;
+        }
+    }
+
     designator_expression::designator_expression()
     {
     }
@@ -711,6 +745,26 @@ namespace boot
         }
     }
 
+    return_statement::return_statement(const struct position position, expression *return_expression)
+        : node(position), m_return_expression(return_expression)
+    {
+    }
+
+    void return_statement::accept(parser_visitor *visitor)
+    {
+        visitor->visit(this);
+    }
+
+    expression *return_statement::return_expression()
+    {
+        return m_return_expression;
+    }
+
+    return_statement::~return_statement()
+    {
+        delete m_return_expression;
+    }
+
     void assign_statement::accept(parser_visitor *visitor)
     {
         visitor->visit(this);
diff --git a/boot/lexer.ll b/boot/lexer.ll
index 0019f8d..bb7ca06 100644
--- a/boot/lexer.ll
+++ b/boot/lexer.ll
@@ -125,6 +125,9 @@ return                  {
 cast                    {
                             return yy::parser::make_CAST(this->location);
                         }
+defer                   {
+                            return yy::parser::make_DEFER(this->location);
+                        }
 [A-Za-z_][A-Za-z0-9_]*  {
                             return yy::parser::make_IDENTIFIER(yytext, this->location);
                         }
diff --git a/boot/parser.yy b/boot/parser.yy
index 8adc80b..b740b70 100644
--- a/boot/parser.yy
+++ b/boot/parser.yy
@@ -106,6 +106,7 @@ along with GCC; see the file COPYING3.  If not see
     RETURN "return"
     BEGIN_BLOCK "begin"
     END_BLOCK "end"
+    DEFER "defer"
 %token OR "or" AND "and" XOR "xor"
     EQUALS "=" NOT_EQUAL "<>" LESS_THAN "<" GREATER_THAN ">" LESS_EQUAL "<=" GREATER_EQUAL ">="
     SHIFT_LEFT "<<" SHIFT_RIGHT ">>"
@@ -135,12 +136,12 @@ along with GCC; see the file COPYING3.  If not see
 %type <elna::boot::procedure_call*> call_expression;
 %type <elna::boot::while_statement *> while_statement;
 %type <elna::boot::if_statement *> if_statement;
-%type <elna::boot::expression *> return_statement;
+%type <elna::boot::return_statement *> return_statement;
 %type <elna::boot::statement *> statement;
-%type <std::vector<elna::boot::statement *>> statements statement_part;
+%type <std::vector<elna::boot::statement *>> statements;
 %type <elna::boot::procedure_definition *> procedure_definition;
 %type <std::shared_ptr<elna::boot::procedure_type>> procedure_heading;
-%type <std::vector<elna::boot::procedure_definition *>> procedure_definitions;
+%type <std::vector<elna::boot::procedure_definition *>> procedure_definitions procedure_part;
 %type <elna::boot::type_definition *> type_definition;
 %type <std::vector<elna::boot::type_definition *>> type_definitions type_part;
 %type <elna::boot::block *> block;
@@ -148,11 +149,12 @@ along with GCC; see the file COPYING3.  If not see
 %type <std::vector<std::pair<std::string, std::shared_ptr<elna::boot::top_type>>>> optional_fields required_fields;
 %type <std::vector<elna::boot::conditional_statements *>> elsif_then_statements elsif_do_statements;
 %type <elna::boot::cast_expression *> cast_expression;
+%type <elna::boot::defer_statement *> defer_statement;
 %type <std::pair<std::string, bool>> identifier_definition;
 %type <std::vector<std::pair<std::string, bool>>> identifier_definitions;
 %%
 program:
-    constant_part type_part variable_part procedure_definitions "begin" statements "end" "."
+    constant_part type_part variable_part procedure_part "begin" statements "end" "."
         {
             auto tree = new elna::boot::program(elna::boot::make_position(@5));
 
@@ -164,13 +166,13 @@ program:
 
             driver.tree.reset(tree);
         }
-block: constant_part variable_part statement_part
+block: constant_part variable_part "begin" statements "end"
         {
-            $$ = new elna::boot::block(elna::boot::make_position(@1));
+            $$ = new elna::boot::block(elna::boot::make_position(@3));
 
             std::swap($$->constants, $1);
             std::swap($$->variables, $2);
-            std::swap($$->body, $3);
+            std::swap($$->body, $4);
         }
 identifier_definition:
     IDENTIFIER "*"
@@ -205,10 +207,9 @@ procedure_heading:
             std::swap($1, $$->parameters);
         }
 procedure_definition:
-    "proc" identifier_definition procedure_heading ";" block return_statement "end"
+    "proc" identifier_definition procedure_heading ";" block
         {
-            $$ = new elna::boot::procedure_definition(elna::boot::make_position(@1), $2.first, $2.second,
-                $3, $5, $6);
+            $$ = new elna::boot::procedure_definition(elna::boot::make_position(@1), $2.first, $2.second, $3, $5);
         }
     | "proc" identifier_definition procedure_heading ";" "extern"
         {
@@ -220,7 +221,10 @@ procedure_definitions:
             std::swap($$, $2);
             $$.emplace($$.cbegin(), std::move($1));
         }
-    | /* no procedure definitions */ {}
+    | procedure_definition { $$.emplace_back(std::move($1)); }
+procedure_part:
+    /* no procedure definitions */ {}
+    | procedure_definitions { std::swap($$, $1); }
 assign_statement: designator_expression ":=" expression
         {
             $$ = new elna::boot::assign_statement(elna::boot::make_position(@1), $1, $3);
@@ -275,12 +279,15 @@ if_statement:
             $$ = new elna::boot::if_statement(elna::boot::make_position(@1), then, _else);
             std::swap($5, $$->branches);
         }
-return_statement:
-    "return" expression
+return_statement: "return" expression
         {
-            $$ = $2;
+            $$ = new elna::boot::return_statement(elna::boot::make_position(@1), $2);
+        }
+defer_statement: DEFER statements "end"
+        {
+            $$ = new elna::boot::defer_statement(elna::boot::make_position(@1));
+            std::swap($2, $$->statements);
         }
-    | /* no return statement */ { $$ = nullptr; }
 literal:
     INTEGER
         {
@@ -451,21 +458,17 @@ statement:
     assign_statement { $$ = $1; }
     | while_statement { $$ = $1; }
     | if_statement { $$ = $1; }
+    | return_statement { $$ = $1; }
     | call_expression { $$ = $1; }
+    | defer_statement { $$ = $1; }
 statements:
     statement ";" statements
         {
             std::swap($$, $3);
-            $$.emplace($$.cbegin(), $1);
-        }
-    | statement
-        {
-            $$.push_back($1);
+            $$.insert($$.cbegin(), $1);
         }
+    | statement { $$.push_back($1); }
     | /* no statements */ {}
-statement_part:
-    "begin" statements { std::swap($$, $2); }
-    | {}
 field_declaration:
     IDENTIFIER ":" type_expression { $$ = std::make_pair($1, $3); }
 required_fields:
diff --git a/gcc/elna-generic.cc b/gcc/elna-generic.cc
index ad2d9d5..aa32df6 100644
--- a/gcc/elna-generic.cc
+++ b/gcc/elna-generic.cc
@@ -294,7 +294,6 @@ namespace gcc
         if (definition->body != nullptr)
         {
             definition->body->accept(this);
-            visit_return(definition->returning);
             tree mapping = leave_scope();
 
             BLOCK_SUPERCONTEXT(BIND_EXPR_BLOCK(mapping)) = fndecl;
@@ -335,7 +334,7 @@ namespace gcc
         {
             BLOCK_SUPERCONTEXT(it) = new_block;
         }
-        tree bind_expr = build3(BIND_EXPR, void_type_node, variables, f_binding_level->statement_list, new_block);
+        tree bind_expr = build3(BIND_EXPR, void_type_node, variables, chain_defer(), new_block);
         this->symbol_map = this->symbol_map->scope();
 
         f_binding_level = f_binding_level->level_chain;
@@ -1085,8 +1084,10 @@ namespace gcc
         }
     }
 
-    void generic_visitor::visit_return(boot::expression *const return_expression)
+    void generic_visitor::visit(boot::return_statement *statement)
     {
+        boot::expression *return_expression = statement->return_expression();
+
         if (return_expression == nullptr)
         {
             return;
@@ -1206,5 +1207,11 @@ namespace gcc
         this->current_expression = build_pointer_type_for_mode(procedure_type_node, VOIDmode, true);
     }
 
+    void generic_visitor::visit(boot::defer_statement *statement)
+    {
+        enter_scope();
+        visit_statements(statement->statements);
+        defer(leave_scope());
+    }
 }
 }
diff --git a/gcc/elna-tree.cc b/gcc/elna-tree.cc
index 569e0b9..c8262df 100644
--- a/gcc/elna-tree.cc
+++ b/gcc/elna-tree.cc
@@ -91,7 +91,40 @@ namespace gcc
 
     void append_statement(tree statement_tree)
     {
-        append_to_statement_list(statement_tree, &f_binding_level->statement_list);
+        if (!vec_safe_is_empty(f_binding_level->defers))
+        {
+            append_to_statement_list(statement_tree, &f_binding_level->defers->begin()->try_statements);
+        }
+        else
+        {
+            append_to_statement_list(statement_tree, &f_binding_level->statement_list);
+        }
+    }
+
+    void defer(tree statement_tree)
+    {
+        defer_scope new_defer{ statement_tree, alloc_stmt_list() };
+        vec_safe_insert(f_binding_level->defers, 0, new_defer);
+    }
+
+    tree chain_defer()
+    {
+        if (vec_safe_is_empty(f_binding_level->defers))
+        {
+            return f_binding_level->statement_list;
+        }
+        defer_scope *defer_iterator = f_binding_level->defers->begin();
+        tree defer_tree = build2(TRY_FINALLY_EXPR, void_type_node,
+                defer_iterator->try_statements, defer_iterator->defer_block);
+        int i;
+
+        FOR_EACH_VEC_ELT_FROM(*f_binding_level->defers, i, defer_iterator, 1)
+        {
+            append_to_statement_list(defer_tree, &defer_iterator->try_statements);
+            defer_tree = build2(TRY_FINALLY_EXPR, void_type_node,
+                    defer_iterator->try_statements, defer_iterator->defer_block);
+        }
+        return build2(COMPOUND_EXPR, TREE_TYPE(defer_tree), f_binding_level->statement_list, defer_tree);
     }
 
     tree build_field(location_t location, tree record_type, const std::string name, tree type)
diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h
index 3002cbe..9bc523f 100644
--- a/include/elna/boot/ast.h
+++ b/include/elna/boot/ast.h
@@ -63,6 +63,7 @@ namespace boot
     class assign_statement;
     class if_statement;
     class while_statement;
+    class return_statement;
     class traits_expression;
     class block;
     class program;
@@ -80,6 +81,7 @@ namespace boot
     class dereference_expression;
     template<typename T>
     class number_literal;
+    class defer_statement;
 
     /**
      * Interface for AST visitors.
@@ -96,6 +98,8 @@ namespace boot
         virtual void visit(assign_statement *) = 0;
         virtual void visit(if_statement *) = 0;
         virtual void visit(while_statement *) = 0;
+        virtual void visit(return_statement *) = 0;
+        virtual void visit(defer_statement *) = 0;
         virtual void visit(block *) = 0;
         virtual void visit(program *) = 0;
         virtual void visit(binary_expression *) = 0;
@@ -134,6 +138,8 @@ namespace boot
         virtual void visit(assign_statement *statement) override;
         virtual void visit(if_statement *) override;
         virtual void visit(while_statement *) override;
+        virtual void visit(return_statement *) override;
+        virtual void visit(defer_statement *defer) override;
         virtual void visit(block *block) override;
         virtual void visit(program *program) override;
         virtual void visit(binary_expression *expression) override;
@@ -360,11 +366,9 @@ namespace boot
 
     public:
         block *const body;
-        expression *const returning;
 
         procedure_definition(const struct position position, const std::string& identifier,
-                const bool exported, std::shared_ptr<procedure_type> heading,
-                block *const body = nullptr, expression *const returning = nullptr);
+                const bool exported, std::shared_ptr<procedure_type> heading, block *body = nullptr);
         virtual void accept(parser_visitor *visitor) override;
 
         procedure_type& heading();
@@ -435,6 +439,19 @@ namespace boot
         virtual ~conditional_statements();
     };
 
+    class return_statement : public statement
+    {
+        expression *m_return_expression{ nullptr };
+
+    public:
+        return_statement(const struct position position, expression *return_expression);
+        virtual void accept(parser_visitor *visitor) override;
+
+        expression *return_expression();
+
+        virtual ~return_statement() override;
+    };
+
     class designator_expression : public expression
     {
     public:
@@ -627,6 +644,17 @@ namespace boot
         }
     };
 
+    class defer_statement : public statement
+    {
+    public:
+        std::vector<statement *> statements;
+
+        defer_statement(const struct position position);
+        virtual void accept(parser_visitor *visitor) override;
+
+        virtual ~defer_statement() override;
+    };
+
     class binary_expression : public expression
     {
         expression *m_lhs;
diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h
index 668b759..d3ddde9 100644
--- a/include/elna/gcc/elna-generic.h
+++ b/include/elna/gcc/elna-generic.h
@@ -60,42 +60,43 @@ namespace gcc
         void build_record_call(location_t call_location,
                 tree symbol, const std::vector<boot::expression *>& arguments);
         void visit_statements(const std::vector<boot::statement *>& statements);
-        void visit_return(boot::expression *const return_expression);
 
     public:
         generic_visitor(std::shared_ptr<symbol_table> symbol_table);
 
-        virtual void visit(boot::program *program) override;
-        virtual void visit(boot::procedure_definition *definition) override;
-        virtual void visit(boot::procedure_call *call) override;
-        virtual void visit(boot::cast_expression *expression) override;
-        virtual void visit(boot::traits_expression *trait) override;
-        virtual void visit(boot::number_literal<std::int32_t> *literal) override;
-        virtual void visit(boot::number_literal<std::uint32_t> *literal) override;
-        virtual void visit(boot::number_literal<double> *literal) override;
-        virtual void visit(boot::number_literal<bool> *boolean) override;
-        virtual void visit(boot::number_literal<unsigned char> *character) override;
-        virtual void visit(boot::number_literal<std::nullptr_t> *) override;
-        virtual void visit(boot::number_literal<std::string> *string) override;
-        virtual void visit(boot::binary_expression *expression) override;
-        virtual void visit(boot::unary_expression *expression) override;
-        virtual void visit(boot::constant_definition *definition) override;
-        virtual void visit(boot::type_definition *definition) override;
-        virtual void visit(boot::variable_declaration *declaration) override;
-        virtual void visit(boot::variable_expression *expression) override;
-        virtual void visit(boot::array_access_expression *expression) override;
-        virtual void visit(boot::field_access_expression *expression) override;
-        virtual void visit(boot::dereference_expression *expression) override;
-        virtual void visit(boot::block *block) override;
-        virtual void visit(boot::assign_statement *statement) override;
-        virtual void visit(boot::if_statement *statement) override;
-        virtual void visit(boot::while_statement *statement) override;
-        virtual void visit(boot::basic_type *type) override;
-        virtual void visit(boot::array_type *type) override;
-        virtual void visit(boot::pointer_type *type) override;
-        virtual void visit(boot::record_type *type) override;
-        virtual void visit(boot::union_type *type) override;
-        virtual void visit(boot::procedure_type *type) override;
+        void visit(boot::program *program) override;
+        void visit(boot::procedure_definition *definition) override;
+        void visit(boot::procedure_call *call) override;
+        void visit(boot::cast_expression *expression) override;
+        void visit(boot::traits_expression *trait) override;
+        void visit(boot::number_literal<std::int32_t> *literal) override;
+        void visit(boot::number_literal<std::uint32_t> *literal) override;
+        void visit(boot::number_literal<double> *literal) override;
+        void visit(boot::number_literal<bool> *boolean) override;
+        void visit(boot::number_literal<unsigned char> *character) override;
+        void visit(boot::number_literal<std::nullptr_t> *) override;
+        void visit(boot::number_literal<std::string> *string) override;
+        void visit(boot::binary_expression *expression) override;
+        void visit(boot::unary_expression *expression) override;
+        void visit(boot::constant_definition *definition) override;
+        void visit(boot::type_definition *definition) override;
+        void visit(boot::variable_declaration *declaration) override;
+        void visit(boot::variable_expression *expression) override;
+        void visit(boot::array_access_expression *expression) override;
+        void visit(boot::field_access_expression *expression) override;
+        void visit(boot::dereference_expression *expression) override;
+        void visit(boot::block *block) override;
+        void visit(boot::assign_statement *statement) override;
+        void visit(boot::if_statement *statement) override;
+        void visit(boot::while_statement *statement) override;
+        void visit(boot::basic_type *type) override;
+        void visit(boot::array_type *type) override;
+        void visit(boot::pointer_type *type) override;
+        void visit(boot::record_type *type) override;
+        void visit(boot::union_type *type) override;
+        void visit(boot::procedure_type *type) override;
+        void visit(boot::return_statement *statement) override;
+        void visit(boot::defer_statement *statement) override;
     };
 }
 }
diff --git a/include/elna/gcc/elna-tree.h b/include/elna/gcc/elna-tree.h
index d1ffd30..1f83b05 100644
--- a/include/elna/gcc/elna-tree.h
+++ b/include/elna/gcc/elna-tree.h
@@ -72,6 +72,8 @@ namespace gcc
     bool is_assignable_from(tree assignee, tree assignment);
 
     void append_statement(tree statement_tree);
+    void defer(tree statement_tree);
+    tree chain_defer();
 
     tree do_pointer_arithmetic(boot::binary_operator binary_operator, tree left, tree right);
     tree build_binary_operation(bool condition, boot::binary_expression *expression,
diff --git a/include/elna/gcc/elna1.h b/include/elna/gcc/elna1.h
index d65440c..418c832 100644
--- a/include/elna/gcc/elna1.h
+++ b/include/elna/gcc/elna1.h
@@ -58,6 +58,12 @@ struct GTY (()) lang_decl
 {
 };
 
+struct GTY (()) defer_scope
+{
+    tree defer_block;
+    tree try_statements;
+};
+
 struct GTY ((chain_next ("%h.level_chain"))) binding_level
 {
     // A block chain is needed to call defer statements beloning to each block.
@@ -68,6 +74,9 @@ struct GTY ((chain_next ("%h.level_chain"))) binding_level
 
     // Statements before the first defer has been seen.
     tree statement_list;
+
+    // Defer statement coupled with statements following it.
+    vec<defer_scope, va_gc> *defers;
 };
 
 struct GTY (()) language_function
diff --git a/source.elna b/source.elna
index 5ba30ee..aae4bc6 100644
--- a/source.elna
+++ b/source.elna
@@ -140,6 +140,7 @@ proc exit(code: Int) -> !; extern
   Standard procedures.
 *)
 proc reallocarray(ptr: ^Byte, n: Word, size: Word) -> ^Byte;
+begin
   return realloc(ptr, n * size)
 end
 
@@ -197,26 +198,32 @@ begin
 end
 
 proc is_digit(c: Char) -> Bool;
+begin
   return cast(c: Int) >= cast('0': Int) and cast(c: Int) <= cast('9': Int)
 end
 
 proc is_alpha(c: Char) -> Bool;
+begin
   return cast(c: Int) >= cast('A': Int) and cast(c: Int) <= cast('z': Int)
 end
 
 proc is_alnum(c: Char) -> Bool;
+begin
   return is_digit(c) or is_alpha(c)
 end
 
 proc is_space(c: Char) -> Bool;
+begin
   return c = ' ' or c = '\n' or c = '\t'
 end
 
 proc substring(string: String, start: Word, count: Word) -> String;
+begin
   return String(string.ptr + start, count)
 end
 
 proc open_substring(string: String, start: Word) -> String;
+begin
   return substring(string, start, string.length - start)
 end
 
@@ -270,6 +277,7 @@ end
 *)
 
 proc make_position() -> Position;
+begin
   return Position(1u, 1u)
 end
 
@@ -285,7 +293,7 @@ begin
     result^.handle := file_handle;
     result^.size := 0u;
     result^.index := 1u
-  end
+  end;
   return result
 end
 
@@ -344,7 +352,7 @@ begin
   if source_file^.index > source_file^.size then
     source_file^.size := fread(cast(@source_file^.buffer: ^Byte), 1u, 1024u, source_file^.handle);
 	source_file^.index := 1u
-  end
+  end;
 
   return source_file^.size = 0u
 end
@@ -368,10 +376,12 @@ begin
 end
 
 proc source_code_empty(source_code: ^SourceCode) -> Bool;
+begin
   return source_code^.empty(source_code^.input)
 end
 
 proc source_code_head(source_code: SourceCode) -> Char;
+begin
   return source_code.head(source_code.input)
 end
 
@@ -388,6 +398,7 @@ begin
 end
 
 proc source_code_expect(source_code: ^SourceCode, expected: Char) -> Bool;
+begin
   return not source_code_empty(source_code) and source_code_head(source_code^) = expected
 end
 
@@ -402,6 +413,7 @@ begin
 end
 
 proc is_ident(char: Char) -> Bool;
+begin
   return is_alnum(char) or char = '_'
 end
 
@@ -433,7 +445,7 @@ begin
 	  trailing := 0u
 	end;
     source_code_advance(source_code)
-  end
+  end;
 
   return trailing = 2u
 end
@@ -456,7 +468,7 @@ begin
   end;
   if successful then
     source_code_advance(source_code)
-  end
+  end;
   return successful
 end
 
@@ -481,7 +493,7 @@ begin
     source_code_advance(source_code)
   else
     is_valid := false
-  end
+  end;
   return is_valid
 end
 
@@ -710,7 +722,7 @@ begin
   else
 	current_token.kind := TOKEN_IDENTIFIER;
 	current_token.value.string := string_dup(token_content)
-  end
+  end;
 
   return current_token
 end
@@ -887,7 +899,7 @@ begin
 	  write_c(first_char);
 	  write_s("\".\n")
 	end
-  end
+  end;
 
   return tokens
 end
@@ -904,7 +916,7 @@ begin
   result^.syntax_tree := false;
   result^.input := nil;
 
-  while i < argc and result <> nil do
+  while i < argc do
     parameter := argv + i;
 
     if strcmp(parameter^, "--tokenize\0".ptr) = 0 then
@@ -920,15 +932,15 @@ begin
       write_z(parameter^);
       write_s(".\n");
 
-      result := nil
+      return nil
     end;
 
     i := i + 1
   end;
-  if result <> nil and result^.input = nil then
+  if result^.input = nil then
     write_s("Fatal error: no input files.\n");
-	result := nil
-  end
+	return nil
+  end;
 
   return result
 end
@@ -969,7 +981,7 @@ begin
     if command_line^.tokenize then
       print_tokens(tokens, tokens_size)
     end
-  end
+  end;
   return return_code
 end