[vala] Rework header file generation



commit 2d4a4a264677b42710914907f63e1624e25e560f
Author: Jürg Billeter <j bitron ch>
Date:   Tue Mar 31 00:31:07 2009 +0200

    Rework header file generation
    
    Generate single C header file for public API, do not use header
    files for internal API. Fixes bug 471244, bug 571037, bug 572536,
    and bug 575629.
---
 gobject/valaccodearraymodule.vala        |   12 +-
 gobject/valaccodeassignmentmodule.vala   |   12 +
 gobject/valaccodebasemodule.vala         |  762 +++++++++++++++---------------
 gobject/valaccodedeclarationspace.vala   |   31 +-
 gobject/valaccodedelegatemodule.vala     |   63 ++--
 gobject/valaccodegenerator.vala          |    8 -
 gobject/valaccodememberaccessmodule.vala |   31 ++-
 gobject/valaccodemethodcallmodule.vala   |    1 +
 gobject/valaccodemethodmodule.vala       |  150 +++++--
 gobject/valaccodemodule.vala             |   12 -
 gobject/valaccodestructmodule.vala       |   93 +++--
 gobject/valadbusclientmodule.vala        |   13 +-
 gobject/valadbusservermodule.vala        |   12 +-
 gobject/valagasyncmodule.vala            |   35 +-
 gobject/valagerrormodule.vala            |   48 ++-
 gobject/valagobjectmodule.vala           |  466 +++++++++++++-----
 gobject/valagtypemodule.vala             |  133 ++++--
 vala/Makefile.am                         |    1 -
 vala/valacastexpression.vala             |    4 +-
 vala/valacatchclause.vala                |    6 +-
 vala/valaclass.vala                      |    2 -
 vala/valacodecontext.vala                |  139 ------
 vala/valaenumvalue.vala                  |    6 -
 vala/valafield.vala                      |   10 -
 vala/valaflowanalyzer.vala               |    8 +-
 vala/valaforeachstatement.vala           |    4 +-
 vala/valaformalparameter.vala            |    9 -
 vala/valainterface.vala                  |    2 -
 vala/valalocalvariable.vala              |    2 -
 vala/valamemberaccess.vala               |    2 -
 vala/valamethod.vala                     |    9 -
 vala/valaobjectcreationexpression.vala   |    4 -
 vala/valaproperty.vala                   |    9 -
 vala/valasemanticanalyzer.vala           |    3 -
 vala/valasizeofexpression.vala           |    4 +-
 vala/valasourcefile.vala                 |  204 +--------
 vala/valasourcefilecycle.vala            |   39 --
 vala/valasymbol.vala                     |   13 +-
 vala/valatypecheck.vala                  |    4 +-
 vala/valatypeofexpression.vala           |    4 +-
 40 files changed, 1169 insertions(+), 1201 deletions(-)

diff --git a/gobject/valaccodearraymodule.vala b/gobject/valaccodearraymodule.vala
index 06ad8b9..d9f5c55 100644
--- a/gobject/valaccodearraymodule.vala
+++ b/gobject/valaccodearraymodule.vala
@@ -693,12 +693,20 @@ internal class Vala.CCodeArrayModule : CCodeMethodCallModule {
 		assignment.ccodenode = ccall;
 	}
 
-	public override void generate_parameter (FormalParameter param, Map<int,CCodeFormalParameter> cparam_map, Map<int,CCodeExpression>? carg_map) {
+	public override void generate_parameter (FormalParameter param, CCodeDeclarationSpace decl_space, Map<int,CCodeFormalParameter> cparam_map, Map<int,CCodeExpression>? carg_map) {
 		if (!(param.parameter_type is ArrayType)) {
-			base.generate_parameter (param, cparam_map, carg_map);
+			base.generate_parameter (param, decl_space, cparam_map, carg_map);
 			return;
 		}
 
+		string ctypename = param.parameter_type.get_cname ();
+
+		if (param.direction != ParameterDirection.IN) {
+			ctypename += "*";
+		}
+
+		param.ccodenode = new CCodeFormalParameter (param.name, ctypename);
+
 		var array_type = (ArrayType) param.parameter_type;
 
 		cparam_map.set (get_param_pos (param.cparameter_position), (CCodeFormalParameter) param.ccodenode);
diff --git a/gobject/valaccodeassignmentmodule.vala b/gobject/valaccodeassignmentmodule.vala
index 332bb4f..eb2a1fd 100644
--- a/gobject/valaccodeassignmentmodule.vala
+++ b/gobject/valaccodeassignmentmodule.vala
@@ -38,6 +38,18 @@ internal class Vala.CCodeAssignmentModule : CCodeMemberAccessModule {
 
 		var prop = (Property) assignment.left.symbol_reference;
 
+		if (!(prop is DynamicProperty)) {
+			generate_property_accessor_declaration (prop.set_accessor, source_declarations);
+
+			if (!prop.external && prop.external_package) {
+				// internal VAPI properties
+				// only add them once per source file
+				if (add_generated_external_symbol (prop)) {
+					visit_property (prop);
+				}
+			}
+		}
+
 		if (prop.set_accessor.construction && current_type_symbol is Class && current_class.is_subtype_of (gobject_type) && in_creation_method) {
 			return head.get_construct_property_assignment (prop.get_canonical_cconstant (), prop.property_type, (CCodeExpression) assignment.right.ccodenode);
 		} else {
diff --git a/gobject/valaccodebasemodule.vala b/gobject/valaccodebasemodule.vala
index 9bfa75c..f7803c9 100644
--- a/gobject/valaccodebasemodule.vala
+++ b/gobject/valaccodebasemodule.vala
@@ -54,13 +54,8 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 	public CCodeFragment module_init_fragment;
 	
 	public CCodeStruct param_spec_struct;
-	public CCodeStruct instance_struct;
-	public CCodeStruct type_struct;
-	public CCodeStruct instance_priv_struct;
-	public CCodeStruct type_priv_struct;
 	public CCodeStruct closure_struct;
 	public CCodeEnum prop_enum;
-	public CCodeEnum cenum;
 	public CCodeFunction function;
 
 	// code nodes to be inserted before the current statement
@@ -127,7 +122,6 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 	public bool string_h_needed;
 	public bool gvaluecollector_h_needed;
 	public bool gio_h_needed;
-	public bool requires_free_checked;
 	public bool requires_array_free;
 	public bool requires_array_move;
 	public bool requires_array_length;
@@ -136,9 +130,12 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 	public bool dbus_glib_h_needed_in_header;
 
 	public Set<string> wrappers;
+	Set<Symbol> generated_external_symbols;
 
 	public Map<string,string> variable_name_map = new HashMap<string,string> (str_hash, str_equal);
 
+	string? legacy_header_define;
+
 	public CCodeBaseModule (CCodeGenerator codegen, CCodeModule? next) {
 		base (codegen, next);
 
@@ -207,6 +204,148 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 		c_keywords.add ("cdecl");
 	}
 
+	public override void emit (CodeContext context) {
+		this.context = context;
+
+		root_symbol = context.root;
+
+		bool_type = new BooleanType ((Struct) root_symbol.scope.lookup ("bool"));
+		char_type = new IntegerType ((Struct) root_symbol.scope.lookup ("char"));
+		uchar_type = new IntegerType ((Struct) root_symbol.scope.lookup ("uchar"));
+		unichar_type = new IntegerType ((Struct) root_symbol.scope.lookup ("unichar"));
+		short_type = new IntegerType ((Struct) root_symbol.scope.lookup ("short"));
+		ushort_type = new IntegerType ((Struct) root_symbol.scope.lookup ("ushort"));
+		int_type = new IntegerType ((Struct) root_symbol.scope.lookup ("int"));
+		uint_type = new IntegerType ((Struct) root_symbol.scope.lookup ("uint"));
+		long_type = new IntegerType ((Struct) root_symbol.scope.lookup ("long"));
+		ulong_type = new IntegerType ((Struct) root_symbol.scope.lookup ("ulong"));
+		int8_type = new IntegerType ((Struct) root_symbol.scope.lookup ("int8"));
+		uint8_type = new IntegerType ((Struct) root_symbol.scope.lookup ("uint8"));
+		int16_type = new IntegerType ((Struct) root_symbol.scope.lookup ("int16"));
+		uint16_type = new IntegerType ((Struct) root_symbol.scope.lookup ("uint16"));
+		int32_type = new IntegerType ((Struct) root_symbol.scope.lookup ("int32"));
+		uint32_type = new IntegerType ((Struct) root_symbol.scope.lookup ("uint32"));
+		int64_type = new IntegerType ((Struct) root_symbol.scope.lookup ("int64"));
+		uint64_type = new IntegerType ((Struct) root_symbol.scope.lookup ("uint64"));
+		float_type = new FloatingType ((Struct) root_symbol.scope.lookup ("float"));
+		double_type = new FloatingType ((Struct) root_symbol.scope.lookup ("double"));
+		string_type = new ObjectType ((Class) root_symbol.scope.lookup ("string"));
+
+		var glib_ns = root_symbol.scope.lookup ("GLib");
+
+		gtype_type = (TypeSymbol) glib_ns.scope.lookup ("Type");
+		gobject_type = (TypeSymbol) glib_ns.scope.lookup ("Object");
+		gerror_type = new ErrorType (null, null);
+		glist_type = (Class) glib_ns.scope.lookup ("List");
+		gslist_type = (Class) glib_ns.scope.lookup ("SList");
+		gstringbuilder_type = (TypeSymbol) glib_ns.scope.lookup ("StringBuilder");
+		garray_type = (TypeSymbol) glib_ns.scope.lookup ("Array");
+		gbytearray_type = (TypeSymbol) glib_ns.scope.lookup ("ByteArray");
+		gptrarray_type = (TypeSymbol) glib_ns.scope.lookup ("PtrArray");
+
+		gquark_type = new IntegerType ((Struct) glib_ns.scope.lookup ("Quark"));
+		gvalue_type = (Struct) glib_ns.scope.lookup ("Value");
+		mutex_type = (Struct) glib_ns.scope.lookup ("StaticRecMutex");
+
+		type_module_type = (TypeSymbol) glib_ns.scope.lookup ("TypeModule");
+
+		if (context.module_init_method != null) {
+			module_init_fragment = new CCodeFragment ();
+			foreach (FormalParameter parameter in context.module_init_method.get_parameters ()) {
+				if (parameter.parameter_type.data_type == type_module_type) {
+					in_plugin = true;
+					module_init_param_name = parameter.name;
+					break;
+				}
+			}
+		}
+
+		var dbus_ns = root_symbol.scope.lookup ("DBus");
+		if (dbus_ns != null) {
+			dbus_object_type = (TypeSymbol) dbus_ns.scope.lookup ("Object");
+		}
+
+		header_declarations = new CCodeDeclarationSpace ();
+
+		/* we're only interested in non-pkg source files */
+		var source_files = context.get_source_files ();
+		foreach (SourceFile file in source_files) {
+			if (!file.external_package) {
+				file.accept (codegen);
+			}
+		}
+
+		// generate C header file for public API
+		if (context.header_filename != null) {
+			var writer = new CCodeWriter (context.header_filename);
+			if (!writer.open ()) {
+				Report.error (null, "unable to open `%s' for writing".printf (writer.filename));
+				return;
+			}
+			writer.write_newline ();
+
+			var once = new CCodeOnceSection (get_define_for_filename (writer.filename));
+			once.append (new CCodeNewline ());
+			once.append (header_declarations.include_directives);
+			once.append (new CCodeNewline ());
+			once.append (new CCodeIdentifier ("G_BEGIN_DECLS"));
+			once.append (new CCodeNewline ());
+			once.append (new CCodeNewline ());
+			once.append (header_declarations.type_declaration);
+			once.append (new CCodeNewline ());
+			once.append (header_declarations.type_definition);
+			once.append (new CCodeNewline ());
+			once.append (header_declarations.type_member_declaration);
+			once.append (new CCodeNewline ());
+			once.append (header_declarations.constant_declaration);
+			once.append (new CCodeNewline ());
+			once.append (new CCodeIdentifier ("G_END_DECLS"));
+			once.append (new CCodeNewline ());
+			once.append (new CCodeNewline ());
+			once.write (writer);
+			writer.close ();
+		} else if (context.legacy_headers) {
+			foreach (SourceFile file in source_files) {
+				if (file.external_package) {
+					continue;
+				}
+
+				if (legacy_header_define == null) {
+					// share the same define for all legacy headers
+					legacy_header_define = get_define_for_filename (file.get_cinclude_filename ());
+				}
+
+				var writer = new CCodeWriter (file.get_cheader_filename ());
+				if (!writer.open ()) {
+					Report.error (null, "unable to open `%s' for writing".printf (writer.filename));
+					return;
+				}
+				writer.write_newline ();
+
+				var once = new CCodeOnceSection (legacy_header_define);
+				once.append (new CCodeNewline ());
+				once.append (header_declarations.include_directives);
+				once.append (new CCodeNewline ());
+				once.append (new CCodeIdentifier ("G_BEGIN_DECLS"));
+				once.append (new CCodeNewline ());
+				once.append (new CCodeNewline ());
+				once.append (header_declarations.type_declaration);
+				once.append (new CCodeNewline ());
+				once.append (header_declarations.type_definition);
+				once.append (new CCodeNewline ());
+				once.append (header_declarations.type_member_declaration);
+				once.append (new CCodeNewline ());
+				once.append (header_declarations.constant_declaration);
+				once.append (new CCodeNewline ());
+				once.append (new CCodeIdentifier ("G_END_DECLS"));
+				once.append (new CCodeNewline ());
+				once.append (new CCodeNewline ());
+				once.write (writer);
+				writer.close ();
+			}
+		}
+	}
+
 	public override CCodeIdentifier get_value_setter_function (DataType type_reference) {
 		if (type_reference.data_type != null) {
 			return new CCodeIdentifier (type_reference.data_type.get_set_value_function ());
@@ -261,7 +400,6 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 	}
 
 	public override void visit_source_file (SourceFile source_file) {
-		header_declarations = new CCodeDeclarationSpace ();
 		source_declarations = new CCodeDeclarationSpace ();
 		source_type_member_definition = new CCodeFragment ();
 		source_signal_marshaller_definition = new CCodeFragment ();
@@ -277,80 +415,16 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 		gio_h_needed = false;
 		dbus_glib_h_needed = false;
 		dbus_glib_h_needed_in_header = false;
-		requires_free_checked = false;
 		requires_array_free = false;
 		requires_array_move = false;
 		requires_array_length = false;
 		requires_strcmp0 = false;
 
 		wrappers = new HashSet<string> (str_hash, str_equal);
+		generated_external_symbols = new HashSet<Symbol> ();
 
-		header_declarations.add_include ("glib.h");
-		header_declarations.add_include ("glib-object.h");
-
-		if (context.legacy_headers) {
-			if (context.basedir != null || context.library != null) {
-				source_declarations.add_include (source_file.get_cinclude_filename ());
-			} else {
-				source_declarations.add_include (source_file.get_cinclude_filename (), true);
-			}
-		}
-		
-		Gee.List<string> used_includes = new ArrayList<string> (str_equal);
-		used_includes.add ("glib.h");
-		used_includes.add ("glib-object.h");
-
-		if (context.legacy_headers) {
-			used_includes.add (source_file.get_cinclude_filename ());
-		
-			foreach (string filename in source_file.get_header_external_includes ()) {
-				if (!used_includes.contains (filename)) {
-					header_declarations.add_include (filename);
-					used_includes.add (filename);
-				}
-			}
-			foreach (string filename in source_file.get_header_internal_includes ()) {
-				if (!used_includes.contains (filename)) {
-					header_declarations.add_include (filename, (context.library == null));
-					used_includes.add (filename);
-				}
-			}
-			foreach (string filename in source_file.get_source_external_includes ()) {
-				if (!used_includes.contains (filename)) {
-					source_declarations.add_include (filename);
-					used_includes.add (filename);
-				}
-			}
-			foreach (string filename in source_file.get_source_internal_includes ()) {
-				if (!used_includes.contains (filename)) {
-					source_declarations.add_include (filename, (context.library == null));
-					used_includes.add (filename);
-				}
-			}
-			if (source_file.is_cycle_head) {
-				foreach (SourceFile cycle_file in source_file.cycle.files) {
-					foreach (CodeNode node in cycle_file.get_nodes ()) {
-						if (node is Struct) {
-							var st = (Struct) node;
-							header_declarations.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (st.get_cname ()), new CCodeVariableDeclarator (st.get_cname ())));
-						} else if (node is Class) {
-							var cl = (Class) node;
-							header_declarations.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (cl.get_cname ()), new CCodeVariableDeclarator (cl.get_cname ())));
-							header_declarations.add_type_declaration (new CCodeTypeDefinition ("struct _%sClass".printf (cl.get_cname ()), new CCodeVariableDeclarator ("%sClass".printf (cl.get_cname ()))));
-						} else if (node is Interface) {
-							var iface = (Interface) node;
-							header_declarations.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (iface.get_cname ()), new CCodeVariableDeclarator (iface.get_cname ())));
-							header_declarations.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (iface.get_type_cname ()), new CCodeVariableDeclarator (iface.get_type_cname ())));
-						}
-					}
-				}
-			}
-		}
-		foreach (Symbol symbol in source_file.get_source_symbol_dependencies ()) {
-			if (!symbol.external && symbol.external_package) {
-				symbol.accept (codegen);
-			}
-		}
+		source_declarations.add_include ("glib.h");
+		source_declarations.add_include ("glib-object.h");
 
 		source_file.accept_children (codegen);
 
@@ -358,12 +432,6 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 			return;
 		}
 
-		var header_define = get_define_for_filename (source_file.get_cinclude_filename ());
-		
-		/* generate hardcoded "well-known" macros */
-		if (requires_free_checked) {
-			source_declarations.add_begin (new CCodeMacroReplacement ("VALA_FREE_CHECKED(o,f)", "((o) == NULL ? NULL : ((o) = (f (o), NULL)))"));
-		}
 		if (requires_array_free) {
 			append_vala_array_free ();
 		}
@@ -385,15 +453,7 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 			source_declarations.add_include ("gobject/gvaluecollector.h");
 		}
 
-		if (gio_h_needed) {
-			header_declarations.add_include ("gio/gio.h");
-		}
-
-		if (dbus_glib_h_needed_in_header) {
-			header_declarations.add_include ("dbus/dbus.h");
-			header_declarations.add_include ("dbus/dbus-glib.h");
-			header_declarations.add_include ("dbus/dbus-glib-lowlevel.h");
-		} else if (dbus_glib_h_needed) {
+		if (dbus_glib_h_needed) {
 			source_declarations.add_include ("dbus/dbus.h");
 			source_declarations.add_include ("dbus/dbus-glib.h");
 			source_declarations.add_include ("dbus/dbus-glib-lowlevel.h");
@@ -484,38 +544,6 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 		if (source_file.comment != null) {
 			comment = new CCodeComment (source_file.comment);
 		}
-
-		if (context.legacy_headers) {
-			var writer = new CCodeWriter (source_file.get_cheader_filename ());
-			if (!writer.open ()) {
-				Report.error (null, "unable to open `%s' for writing".printf (writer.filename));
-				return;
-			}
-			if (comment != null) {
-				comment.write (writer);
-			}
-			writer.write_newline ();
-			var once = new CCodeOnceSection (header_define);
-			once.append (new CCodeNewline ());
-			once.append (header_declarations.include_directives);
-			once.append (new CCodeNewline ());
-			once.append (new CCodeIdentifier ("G_BEGIN_DECLS"));
-			once.append (new CCodeNewline ());
-			once.append (new CCodeNewline ());
-			once.append (header_declarations.type_declaration);
-			once.append (new CCodeNewline ());
-			once.append (header_declarations.type_definition);
-			once.append (new CCodeNewline ());
-			once.append (header_declarations.type_member_declaration);
-			once.append (new CCodeNewline ());
-			once.append (header_declarations.constant_declaration);
-			once.append (new CCodeNewline ());
-			once.append (new CCodeIdentifier ("G_END_DECLS"));
-			once.append (new CCodeNewline ());
-			once.append (new CCodeNewline ());
-			once.write (writer);
-			writer.close ();
-		}
 		
 		var writer = new CCodeWriter (source_file.get_csource_filename ());
 		if (!writer.open ()) {
@@ -526,7 +554,6 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 		if (comment != null) {
 			comment.write (writer);
 		}
-		source_declarations.begin.write (writer);
 		writer.write_newline ();
 		source_declarations.include_directives.write (writer);
 		writer.write_newline ();
@@ -549,7 +576,6 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 		writer.write_newline ();
 		writer.close ();
 
-		header_declarations = null;
 		source_declarations = null;
 		source_type_member_definition = null;
 		source_signal_marshaller_definition = null;
@@ -576,108 +602,20 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 		return define.str;
 	}
 
-	public override void emit (CodeContext context) {
-		this.context = context;
-
-		if (context.legacy_headers) {
-			context.find_header_cycles ();
-		}
-
-		root_symbol = context.root;
-
-		bool_type = new BooleanType ((Struct) root_symbol.scope.lookup ("bool"));
-		char_type = new IntegerType ((Struct) root_symbol.scope.lookup ("char"));
-		uchar_type = new IntegerType ((Struct) root_symbol.scope.lookup ("uchar"));
-		unichar_type = new IntegerType ((Struct) root_symbol.scope.lookup ("unichar"));
-		short_type = new IntegerType ((Struct) root_symbol.scope.lookup ("short"));
-		ushort_type = new IntegerType ((Struct) root_symbol.scope.lookup ("ushort"));
-		int_type = new IntegerType ((Struct) root_symbol.scope.lookup ("int"));
-		uint_type = new IntegerType ((Struct) root_symbol.scope.lookup ("uint"));
-		long_type = new IntegerType ((Struct) root_symbol.scope.lookup ("long"));
-		ulong_type = new IntegerType ((Struct) root_symbol.scope.lookup ("ulong"));
-		int8_type = new IntegerType ((Struct) root_symbol.scope.lookup ("int8"));
-		uint8_type = new IntegerType ((Struct) root_symbol.scope.lookup ("uint8"));
-		int16_type = new IntegerType ((Struct) root_symbol.scope.lookup ("int16"));
-		uint16_type = new IntegerType ((Struct) root_symbol.scope.lookup ("uint16"));
-		int32_type = new IntegerType ((Struct) root_symbol.scope.lookup ("int32"));
-		uint32_type = new IntegerType ((Struct) root_symbol.scope.lookup ("uint32"));
-		int64_type = new IntegerType ((Struct) root_symbol.scope.lookup ("int64"));
-		uint64_type = new IntegerType ((Struct) root_symbol.scope.lookup ("uint64"));
-		float_type = new FloatingType ((Struct) root_symbol.scope.lookup ("float"));
-		double_type = new FloatingType ((Struct) root_symbol.scope.lookup ("double"));
-		string_type = new ObjectType ((Class) root_symbol.scope.lookup ("string"));
-
-		var glib_ns = root_symbol.scope.lookup ("GLib");
-
-		gtype_type = (TypeSymbol) glib_ns.scope.lookup ("Type");
-		gobject_type = (TypeSymbol) glib_ns.scope.lookup ("Object");
-		gerror_type = new ErrorType (null, null);
-		glist_type = (Class) glib_ns.scope.lookup ("List");
-		gslist_type = (Class) glib_ns.scope.lookup ("SList");
-		gstringbuilder_type = (TypeSymbol) glib_ns.scope.lookup ("StringBuilder");
-		garray_type = (TypeSymbol) glib_ns.scope.lookup ("Array");
-		gbytearray_type = (TypeSymbol) glib_ns.scope.lookup ("ByteArray");
-		gptrarray_type = (TypeSymbol) glib_ns.scope.lookup ("PtrArray");
-
-		gquark_type = new IntegerType ((Struct) glib_ns.scope.lookup ("Quark"));
-		gvalue_type = (Struct) glib_ns.scope.lookup ("Value");
-		mutex_type = (Struct) glib_ns.scope.lookup ("StaticRecMutex");
-		
-		type_module_type = (TypeSymbol) glib_ns.scope.lookup ("TypeModule");
-
-		if (context.module_init_method != null) {
-			module_init_fragment = new CCodeFragment ();
-			foreach (FormalParameter parameter in context.module_init_method.get_parameters ()) {
-				if (parameter.parameter_type.data_type == type_module_type) {
-					in_plugin = true;
-					module_init_param_name = parameter.name;
-					break;
-				}
-			}
+	public void generate_enum_declaration (Enum en, CCodeDeclarationSpace decl_space) {
+		if (decl_space.add_symbol_declaration (en, en.get_cname ())) {
+			return;
 		}
 
-		var dbus_ns = root_symbol.scope.lookup ("DBus");
-		if (dbus_ns != null) {
-			dbus_object_type = (TypeSymbol) dbus_ns.scope.lookup ("Object");
-		}
-	
-		/* we're only interested in non-pkg source files */
-		var source_files = context.get_source_files ();
-		foreach (SourceFile file in source_files) {
-			if (!file.external_package) {
-				file.accept (codegen);
-			}
-		}
+		var cenum = new CCodeEnum (en.get_cname ());
 
-		// generate C header file for public API
-		if (context.header_filename != null) {
-			var writer = new CCodeWriter (context.header_filename);
-			if (!writer.open ()) {
-				Report.error (null, "unable to open `%s' for writing".printf (writer.filename));
-				return;
+		foreach (EnumValue ev in en.get_values ()) {
+			if (ev.value == null) {
+				cenum.add_value (new CCodeEnumValue (ev.get_cname ()));
+			} else {
+				ev.value.accept (codegen);
+				cenum.add_value (new CCodeEnumValue (ev.get_cname (), (CCodeExpression) ev.value.ccodenode));
 			}
-			writer.write_newline ();
-			var once = new CCodeOnceSection (get_define_for_filename (writer.filename));
-			once.append (new CCodeNewline ());
-			once.append (new CCodeIdentifier ("G_BEGIN_DECLS"));
-			once.append (new CCodeNewline ());
-			once.append (new CCodeNewline ());
-			once.append (new CCodeIdentifier ("G_END_DECLS"));
-			once.append (new CCodeNewline ());
-			once.append (new CCodeNewline ());
-			once.write (writer);
-			writer.close ();
-		}
-	}
-
-	public override void visit_enum (Enum en) {
-		cenum = new CCodeEnum (en.get_cname ());
-
-		CCodeDeclarationSpace decl_space;
-		if (en.access != SymbolAccessibility.PRIVATE) {
-			decl_space = header_declarations;
-		} else {
-			decl_space = source_declarations;
 		}
 		
 		if (en.source_reference.comment != null) {
@@ -687,8 +625,6 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 		decl_space.add_type_definition (cenum);
 		decl_space.add_type_definition (new CCodeNewline ());
 
-		en.accept_children (codegen);
-
 		if (!en.has_type_id) {
 			return;
 		}
@@ -698,6 +634,29 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 		var macro = "(%s_get_type ())".printf (en.get_lower_case_cname (null));
 		decl_space.add_type_declaration (new CCodeMacroReplacement (en.get_type_id (), macro));
 
+		var fun_name = "%s_get_type".printf (en.get_lower_case_cname (null));
+		var regfun = new CCodeFunction (fun_name, "GType");
+
+		if (en.access == SymbolAccessibility.PRIVATE) {
+			regfun.modifiers = CCodeModifiers.STATIC;
+		}
+
+		decl_space.add_type_member_declaration (regfun);
+	}
+
+	public override void visit_enum (Enum en) {
+		en.accept_children (codegen);
+
+		generate_enum_declaration (en, source_declarations);
+
+		if (!en.is_internal_symbol ()) {
+			generate_enum_declaration (en, header_declarations);
+		}
+
+		if (!en.has_type_id) {
+			return;
+		}
+
 		var clist = new CCodeInitializerList (); /* or during visit time? */
 		CCodeInitializerList clist_ev = null;
 		foreach (EnumValue ev in en.get_values ()) {
@@ -759,10 +718,8 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 
 		regblock.add_statement (new CCodeReturnStatement (new CCodeConstant (type_id_name)));
 
-		if (en.access != SymbolAccessibility.PRIVATE) {
-			header_declarations.add_type_member_declaration (regfun.copy ());
-		} else {
-			source_declarations.add_type_member_declaration (regfun.copy ());
+		if (en.access == SymbolAccessibility.PRIVATE) {
+			regfun.modifiers = CCodeModifiers.STATIC;
 		}
 		regfun.block = regblock;
 
@@ -770,44 +727,29 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 		source_type_member_definition.append (regfun);
 	}
 
-	public override void visit_enum_value (EnumValue ev) {
-		if (ev.value == null) {
-			cenum.add_value (new CCodeEnumValue (ev.get_cname ()));
-		} else {
-			ev.value.accept (codegen);
-			cenum.add_value (new CCodeEnumValue (ev.get_cname (), (CCodeExpression) ev.value.ccodenode));
-		}
-	}
-	
 	public override void visit_member (Member m) {
 		/* stuff meant for all lockable members */
-		if (m is Lockable && ((Lockable)m).get_lock_used ()) {
+		if (m is Lockable && ((Lockable) m).get_lock_used ()) {
 			CCodeExpression l = new CCodeIdentifier ("self");
-			l = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (l, "priv"), get_symbol_lock_name (m));	
-
-			instance_priv_struct.add_field (mutex_type.get_cname (), get_symbol_lock_name (m));
-
-			var initf = new CCodeFunctionCall (
-				new CCodeIdentifier (mutex_type.default_construction_method.get_cname ()));
-
-			initf.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l));		
+			l = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (l, "priv"), get_symbol_lock_name (m));
 
+			var initf = new CCodeFunctionCall (new CCodeIdentifier (mutex_type.default_construction_method.get_cname ()));
+			initf.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l));
 			instance_init_fragment.append (new CCodeExpressionStatement (initf));
-		
-			requires_free_checked = true;
-
-
-			var fc = new CCodeFunctionCall (new CCodeIdentifier ("g_static_rec_mutex_free"));
-
-			fc.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l));
 
 			if (instance_finalize_fragment != null) {
+				var fc = new CCodeFunctionCall (new CCodeIdentifier ("g_static_rec_mutex_free"));
+				fc.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l));
 				instance_finalize_fragment.append (new CCodeExpressionStatement (fc));
 			}
 		}
 	}
 
-	public override void visit_constant (Constant c) {
+	public void generate_constant_declaration (Constant c, CCodeDeclarationSpace decl_space) {
+		if (decl_space.add_symbol_declaration (c, c.get_cname ())) {
+			return;
+		}
+
 		c.accept_children (codegen);
 
 		if (c.initializer is InitializerList) {
@@ -819,17 +761,60 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 			cdecl.add_declarator (new CCodeVariableDeclarator ("%s%s".printf (c.get_cname (), arr), (CCodeExpression) c.initializer.ccodenode));
 			cdecl.modifiers = CCodeModifiers.STATIC;
 		
-			if (!c.is_internal_symbol ()) {
-				header_declarations.add_constant_declaration (cdecl);
-			} else {
-				source_declarations.add_constant_declaration (cdecl);
-			}
+			decl_space.add_constant_declaration (cdecl);
 		} else {
 			var cdefine = new CCodeMacroReplacement.with_expression (c.get_cname (), (CCodeExpression) c.initializer.ccodenode);
-			if (!c.is_internal_symbol ()) {
-				header_declarations.add_type_member_declaration (cdefine);
-			} else {
-				source_declarations.add_type_member_declaration (cdefine);
+			decl_space.add_type_member_declaration (cdefine);
+		}
+	}
+
+	public override void visit_constant (Constant c) {
+		generate_constant_declaration (c, source_declarations);
+	}
+
+	void generate_field_declaration (Field f, CCodeDeclarationSpace decl_space) {
+		string field_ctype = f.field_type.get_cname ();
+		if (f.is_volatile) {
+			field_ctype = "volatile " + field_ctype;
+		}
+
+		var cdecl = new CCodeDeclaration (field_ctype);
+		cdecl.add_declarator (new CCodeVariableDeclarator (f.get_cname ()));
+		if (f.is_private_symbol ()) {
+			cdecl.modifiers = CCodeModifiers.STATIC;
+		} else {
+			cdecl.modifiers = CCodeModifiers.EXTERN;
+		}
+		decl_space.add_type_member_declaration (cdecl);
+
+		if (f.field_type is ArrayType && !f.no_array_length) {
+			var array_type = (ArrayType) f.field_type;
+
+			for (int dim = 1; dim <= array_type.rank; dim++) {
+				var len_type = int_type.copy ();
+
+				cdecl = new CCodeDeclaration (len_type.get_cname ());
+				cdecl.add_declarator (new CCodeVariableDeclarator (head.get_array_length_cname (f.get_cname (), dim)));
+				if (f.is_private_symbol ()) {
+					cdecl.modifiers = CCodeModifiers.STATIC;
+				} else {
+					cdecl.modifiers = CCodeModifiers.EXTERN;
+				}
+				decl_space.add_type_member_declaration (cdecl);
+			}
+		} else if (f.field_type is DelegateType) {
+			var delegate_type = (DelegateType) f.field_type;
+			if (delegate_type.delegate_symbol.has_target) {
+				// create field to store delegate target
+
+				cdecl = new CCodeDeclaration ("gpointer");
+				cdecl.add_declarator (new CCodeVariableDeclarator (get_delegate_target_cname  (f.get_cname ())));
+				if (f.is_private_symbol ()) {
+					cdecl.modifiers = CCodeModifiers.STATIC;
+				} else {
+					cdecl.modifiers = CCodeModifiers.EXTERN;
+				}
+				decl_space.add_type_member_declaration (cdecl);
 			}
 		}
 	}
@@ -843,8 +828,7 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 		bool is_gtypeinstance = (cl != null && !cl.is_compact);
 
 		CCodeExpression lhs = null;
-		CCodeStruct st = null;
-		
+
 		string field_ctype = f.field_type.get_cname ();
 		if (f.is_volatile) {
 			field_ctype = "volatile " + field_ctype;
@@ -852,34 +836,11 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 
 		if (f.binding == MemberBinding.INSTANCE)  {
 			if (is_gtypeinstance && f.access == SymbolAccessibility.PRIVATE) {
-				st = instance_priv_struct;
 				lhs = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), f.get_cname ());
 			} else {
-				st = instance_struct;
 				lhs = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), f.get_cname ());
 			}
 
-			st.add_field (field_ctype, f.get_cname ());
-			if (f.field_type is ArrayType && !f.no_array_length) {
-				// create fields to store array dimensions
-				var array_type = (ArrayType) f.field_type;
-				var len_type = int_type.copy ();
-				
-				for (int dim = 1; dim <= array_type.rank; dim++) {
-					st.add_field (len_type.get_cname (), head.get_array_length_cname (f.name, dim));
-				}
-
-				if (array_type.rank == 1 && f.is_internal_symbol ()) {
-					st.add_field (len_type.get_cname (), head.get_array_size_cname (f.name));
-				}
-			} else if (f.field_type is DelegateType) {
-				var delegate_type = (DelegateType) f.field_type;
-				if (delegate_type.delegate_symbol.has_target) {
-					// create field to store delegate target
-					st.add_field ("gpointer", get_delegate_target_cname (f.name));
-				}
-			}
-
 			if (f.initializer != null) {
 				var rhs = (CCodeExpression) f.initializer.ccodenode;
 
@@ -927,24 +888,15 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 				f.error = true;
 				return;
 			}
-
-			if (f.access != SymbolAccessibility.PRIVATE) {
-				st = type_struct;
-			} else {
-				st = type_priv_struct;
-			}
-
-			st.add_field (field_ctype, f.get_cname ());
 		} else {
-			lhs = new CCodeIdentifier (f.get_cname ());
+			generate_field_declaration (f, source_declarations);
 
 			if (!f.is_internal_symbol ()) {
-				var cdecl = new CCodeDeclaration (field_ctype);
-				cdecl.add_declarator (new CCodeVariableDeclarator (f.get_cname ()));
-				cdecl.modifiers = CCodeModifiers.EXTERN;
-				header_declarations.add_type_member_declaration (cdecl);
+				generate_field_declaration (f, header_declarations);
 			}
 
+			lhs = new CCodeIdentifier (f.get_cname ());
+
 			var var_decl = new CCodeVariableDeclarator (f.get_cname ());
 			var_decl.initializer = default_value_for_type (f.field_type, true);
 
@@ -957,7 +909,7 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 
 			var var_def = new CCodeDeclaration (field_ctype);
 			var_def.add_declarator (var_decl);
-			if (!f.is_internal_symbol ()) {
+			if (!f.is_private_symbol ()) {
 				var_def.modifiers = CCodeModifiers.EXTERN;
 			} else {
 				var_def.modifiers = CCodeModifiers.STATIC;
@@ -971,16 +923,9 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 				for (int dim = 1; dim <= array_type.rank; dim++) {
 					var len_type = int_type.copy ();
 
-					if (!f.is_internal_symbol ()) {
-						var cdecl = new CCodeDeclaration (len_type.get_cname ());
-						cdecl.add_declarator (new CCodeVariableDeclarator (head.get_array_length_cname (f.get_cname (), dim)));
-						cdecl.modifiers = CCodeModifiers.EXTERN;
-						header_declarations.add_type_member_declaration (cdecl);
-					}
-
 					var len_def = new CCodeDeclaration (len_type.get_cname ());
 					len_def.add_declarator (new CCodeVariableDeclarator (head.get_array_length_cname (f.get_cname (), dim), new CCodeConstant ("0")));
-					if (!f.is_internal_symbol ()) {
+					if (!f.is_private_symbol ()) {
 						len_def.modifiers = CCodeModifiers.EXTERN;
 					} else {
 						len_def.modifiers = CCodeModifiers.STATIC;
@@ -1001,16 +946,9 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 				if (delegate_type.delegate_symbol.has_target) {
 					// create field to store delegate target
 
-					if (!f.is_internal_symbol ()) {
-						var cdecl = new CCodeDeclaration ("gpointer");
-						cdecl.add_declarator (new CCodeVariableDeclarator (get_delegate_target_cname  (f.get_cname ())));
-						cdecl.modifiers = CCodeModifiers.EXTERN;
-						header_declarations.add_type_member_declaration (cdecl);
-					}
-
 					var target_def = new CCodeDeclaration ("gpointer");
 					target_def.add_declarator (new CCodeVariableDeclarator (get_delegate_target_cname  (f.get_cname ()), new CCodeConstant ("NULL")));
-					if (!f.is_internal_symbol ()) {
+					if (!f.is_private_symbol ()) {
 						target_def.modifiers = CCodeModifiers.EXTERN;
 					} else {
 						target_def.modifiers = CCodeModifiers.STATIC;
@@ -1105,33 +1043,6 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 		check_type (p.parameter_type);
 
 		p.accept_children (codegen);
-
-		if (!p.ellipsis) {
-			string ctypename = p.parameter_type.get_cname ();
-			string cname = p.name;
-
-			// pass non-simple structs always by reference
-			if (p.parameter_type.data_type is Struct) {
-				var st = (Struct) p.parameter_type.data_type;
-				if (!st.is_simple_type () && p.direction == ParameterDirection.IN) {
-					if (st.use_const) {
-						ctypename = "const " + ctypename;
-					}
-
-					if (!p.parameter_type.nullable) {
-						ctypename += "*";
-					}
-				}
-			}
-
-			if (p.direction != ParameterDirection.IN) {
-				ctypename += "*";
-			}
-
-			p.ccodenode = new CCodeFormalParameter (cname, ctypename);
-		} else {
-			p.ccodenode = new CCodeFormalParameter.with_ellipsis ();
-		}
 	}
 
 	public override void visit_property (Property prop) {
@@ -1148,6 +1059,82 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 		variable_name_map = old_variable_name_map;
 	}
 
+	public void generate_type_declaration (DataType type, CCodeDeclarationSpace decl_space) {
+		if (type is ObjectType) {
+			var object_type = (ObjectType) type;
+			if (object_type.type_symbol is Class) {
+				generate_class_declaration ((Class) object_type.type_symbol, decl_space);
+			} else if (object_type.type_symbol is Interface) {
+				generate_interface_declaration ((Interface) object_type.type_symbol, decl_space);
+			}
+		} else if (type is DelegateType) {
+			var deleg_type = (DelegateType) type;
+			var d = deleg_type.delegate_symbol;
+			generate_delegate_declaration (d, decl_space);
+		} else if (type.data_type is Enum) {
+			var en = (Enum) type.data_type;
+			generate_enum_declaration (en, decl_space);
+		} else if (type is StructValueType) {
+			var struct_type = (StructValueType) type;
+			generate_struct_declaration ((Struct) struct_type.type_symbol, decl_space);
+		}
+
+		foreach (DataType type_arg in type.get_type_arguments ()) {
+			generate_type_declaration (type_arg, decl_space);
+		}
+	}
+
+	public virtual void generate_class_struct_declaration (Class cl, CCodeDeclarationSpace decl_space) {
+	}
+
+	public virtual void generate_struct_declaration (Struct st, CCodeDeclarationSpace decl_space) {
+	}
+
+	public virtual void generate_delegate_declaration (Delegate d, CCodeDeclarationSpace decl_space) {
+	}
+
+	public virtual void generate_cparameters (Method m, CCodeDeclarationSpace decl_space, Map<int,CCodeFormalParameter> cparam_map, CCodeFunction func, CCodeFunctionDeclarator? vdeclarator = null, Map<int,CCodeExpression>? carg_map = null, CCodeFunctionCall? vcall = null, int direction = 3) {
+	}
+
+	public void generate_property_accessor_declaration (PropertyAccessor acc, CCodeDeclarationSpace decl_space) {
+		if (decl_space.add_symbol_declaration (acc.prop, acc.get_cname ())) {
+			return;
+		}
+
+		var prop = (Property) acc.prop;
+
+		bool returns_real_struct = prop.property_type.is_real_struct_type ();
+
+		var t = (ObjectTypeSymbol) prop.parent_symbol;
+
+		var this_type = new ObjectType (t);
+		generate_type_declaration (this_type, decl_space);
+		var cselfparam = new CCodeFormalParameter ("self", this_type.get_cname ());
+
+		CCodeFormalParameter cvalueparam;
+		if (returns_real_struct) {
+			cvalueparam = new CCodeFormalParameter ("value", acc.value_type.get_cname () + "*");
+		} else {
+			cvalueparam = new CCodeFormalParameter ("value", acc.value_type.get_cname ());
+		}
+		generate_type_declaration (acc.value_type, decl_space);
+
+		if (acc.readable && !returns_real_struct) {
+			function = new CCodeFunction (acc.get_cname (), acc.value_type.get_cname ());
+		} else {
+			function = new CCodeFunction (acc.get_cname (), "void");
+		}
+		function.add_parameter (cselfparam);
+		if (acc.writable || acc.construction || returns_real_struct) {
+			function.add_parameter (cvalueparam);
+		}
+
+		if (prop.is_private_symbol () || (!acc.readable && !acc.writable) || acc.access == SymbolAccessibility.PRIVATE) {
+			function.modifiers |= CCodeModifiers.STATIC;
+		}
+		decl_space.add_type_member_declaration (function);
+	}
+
 	public override void visit_property_accessor (PropertyAccessor acc) {
 		current_property_accessor = acc;
 		current_method_inner_error = false;
@@ -1156,6 +1143,7 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 
 		bool returns_real_struct = prop.property_type.is_real_struct_type ();
 
+		var old_return_type = current_return_type;
 		if (acc.readable && !returns_real_struct) {
 			current_return_type = prop.property_type;
 		} else {
@@ -1164,7 +1152,7 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 
 		acc.accept_children (codegen);
 
-		var t = (TypeSymbol) prop.parent_symbol;
+		var t = (ObjectTypeSymbol) prop.parent_symbol;
 
 		if (acc.construction && !t.is_subtype_of (gobject_type)) {
 			Report.error (acc.source_reference, "construct properties require GLib.Object");
@@ -1172,12 +1160,19 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 			return;
 		}
 
-		ReferenceType this_type;
-		if (t is Class) {
-			this_type = new ObjectType ((Class) t);
-		} else {
-			this_type = new ObjectType ((Interface) t);
+		// do not declare overriding properties and interface implementations
+		if (prop.is_abstract || prop.is_virtual
+		    || (prop.base_property == null && prop.base_interface_property == null)) {
+			generate_property_accessor_declaration (acc, source_declarations);
+
+			if (!prop.is_internal_symbol ()
+			    && (acc.access == SymbolAccessibility.PUBLIC
+				|| acc.access == SymbolAccessibility.PROTECTED)) {
+				generate_property_accessor_declaration (acc, header_declarations);
+			}
 		}
+
+		var this_type = new ObjectType (t);
 		var cselfparam = new CCodeFormalParameter ("self", this_type.get_cname ());
 		CCodeFormalParameter cvalueparam;
 		if (returns_real_struct) {
@@ -1187,38 +1182,21 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 		}
 
 		if (prop.is_abstract || prop.is_virtual) {
-			CCodeFunctionDeclarator vdeclarator;
-
 			if (acc.readable) {
 				function = new CCodeFunction (acc.get_cname (), current_return_type.get_cname ());
-
-				var vdecl = new CCodeDeclaration (current_return_type.get_cname ());
-				vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (prop.name));
-				vdecl.add_declarator (vdeclarator);
-				type_struct.add_declaration (vdecl);
 			} else {
 				function = new CCodeFunction (acc.get_cname (), "void");
-
-				var vdecl = new CCodeDeclaration ("void");
-				vdeclarator = new CCodeFunctionDeclarator ("set_%s".printf (prop.name));
-				vdecl.add_declarator (vdeclarator);
-				type_struct.add_declaration (vdecl);
 			}
 			function.add_parameter (cselfparam);
-			vdeclarator.add_parameter (cselfparam);
 			if (acc.writable || acc.construction || returns_real_struct) {
 				function.add_parameter (cvalueparam);
-				vdeclarator.add_parameter (cvalueparam);
 			}
-			
-			if (!prop.is_internal_symbol () && (acc.readable || acc.writable) && acc.access != SymbolAccessibility.PRIVATE) {
-				// accessor function should be public if the property is a public symbol and it's not a construct-only setter
-				header_declarations.add_type_member_declaration (function.copy ());
-			} else {
+
+			if (prop.is_private_symbol () || !(acc.readable || acc.writable) || acc.access == SymbolAccessibility.PRIVATE) {
+				// accessor function should be private if the property is an internal symbol or it's a construct-only setter
 				function.modifiers |= CCodeModifiers.STATIC;
-				source_declarations.add_type_member_declaration (function.copy ());
 			}
-			
+
 			var block = new CCodeBlock ();
 			function.block = block;
 
@@ -1292,12 +1270,9 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 			}
 
 			if (!is_virtual) {
-				if (!prop.is_internal_symbol () && (acc.readable || acc.writable) && acc.access != SymbolAccessibility.PRIVATE) {
-					// accessor function should be public if the property is a public symbol and it's not a construct-only setter
-					header_declarations.add_type_member_declaration (function.copy ());
-				} else {
+				if (prop.is_private_symbol () || !(acc.readable || acc.writable) || acc.access == SymbolAccessibility.PRIVATE) {
+					// accessor function should be private if the property is an internal symbol or it's a construct-only setter
 					function.modifiers |= CCodeModifiers.STATIC;
-					source_declarations.add_type_member_declaration (function.copy ());
 				}
 			}
 
@@ -1346,7 +1321,7 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 		}
 
 		current_property_accessor = null;
-		current_return_type = null;
+		current_return_type = old_return_type;
 	}
 
 	public override void visit_destructor (Destructor d) {
@@ -1475,6 +1450,8 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 
 		local.accept_children (codegen);
 
+		generate_type_declaration (local.variable_type, source_declarations);
+
 		if (local.variable_type is ArrayType) {
 			// create variables to store array dimensions
 			var array_type = (ArrayType) local.variable_type;
@@ -2331,7 +2308,7 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 		}
 	}
 
-	private string get_symbol_lock_name (Symbol sym) {
+	public string get_symbol_lock_name (Symbol sym) {
 		return "__lock_%s".printf (sym.name);
 	}
 
@@ -2776,6 +2753,18 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 		}
 	}
 
+	public virtual void generate_class_declaration (Class cl, CCodeDeclarationSpace decl_space) {
+	}
+
+	public virtual void generate_interface_declaration (Interface iface, CCodeDeclarationSpace decl_space) {
+	}
+
+	public virtual void generate_method_declaration (Method m, CCodeDeclarationSpace decl_space) {
+	}
+
+	public virtual void generate_error_domain_declaration (ErrorDomain edomain, CCodeDeclarationSpace decl_space) {
+	}
+
 	public override void visit_object_creation_expression (ObjectCreationExpression expr) {
 		expr.accept_children (codegen);
 
@@ -2802,6 +2791,8 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 				// NULL is an empty list
 				expr.ccodenode = new CCodeConstant ("NULL");
 			} else if (expr.type_reference.data_type is Class && expr.type_reference.data_type.is_subtype_of (gobject_type)) {
+				generate_class_declaration ((Class) expr.type_reference.data_type, source_declarations);
+
 				creation_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_new"));
 				creation_call.add_argument (new CCodeConstant (expr.type_reference.data_type.get_type_id ()));
 				creation_call.add_argument (new CCodeConstant ("NULL"));
@@ -2825,12 +2816,16 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 			var params = m.get_parameters ();
 			CCodeFunctionCall creation_call;
 
+			generate_method_declaration (m, source_declarations);
+
 			creation_call = new CCodeFunctionCall (new CCodeIdentifier (m.get_cname ()));
 
 			if ((st != null && !st.is_simple_type ()) && !(m.cinstance_parameter_position < 0)) {
 				creation_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, instance));
 			}
 
+			generate_type_declaration (expr.type_reference, source_declarations);
+
 			var cl = expr.type_reference.data_type as Class;
 			if (cl != null && !cl.is_compact) {
 				foreach (DataType type_arg in expr.type_reference.get_type_arguments ()) {
@@ -2962,6 +2957,8 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 			var edomain = (ErrorDomain) ecode.parent_symbol;
 			CCodeFunctionCall creation_call;
 
+			generate_error_domain_declaration (edomain, source_declarations);
+
 			if (expr.get_argument_list ().size == 1) {
 				// must not be a format argument
 				creation_call = new CCodeFunctionCall (new CCodeIdentifier ("g_error_new_literal"));
@@ -3324,6 +3321,8 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 	}
 
 	public override void visit_type_check (TypeCheck expr) {
+		generate_type_declaration (expr.type_reference, source_declarations);
+
 		expr.ccodenode = create_type_check (expr.expression.ccodenode, expr.type_reference);
 	}
 
@@ -3540,6 +3539,9 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 			} else if (prop.base_interface_property != null) {
 				base_property = prop.base_interface_property;
 			}
+
+			generate_property_accessor_declaration (base_property.set_accessor, source_declarations);
+
 			set_func = base_property.set_accessor.get_cname ();
 			if (prop is DynamicProperty) {
 				set_func = head.get_dynamic_property_setter_cname ((DynamicProperty) prop);
@@ -3612,6 +3614,10 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 		return wrappers.add (wrapper_name);
 	}
 
+	public bool add_generated_external_symbol (Symbol external_symbol) {
+		return generated_external_symbols.add (external_symbol);
+	}
+
 	public static DataType get_data_type_for_symbol (TypeSymbol sym) {
 		DataType type = null;
 
diff --git a/gobject/valaccodedeclarationspace.vala b/gobject/valaccodedeclarationspace.vala
index 008321b..696b0a4 100644
--- a/gobject/valaccodedeclarationspace.vala
+++ b/gobject/valaccodedeclarationspace.vala
@@ -23,14 +23,39 @@
 using Gee;
 
 class Vala.CCodeDeclarationSpace {
+	Set<string> declarations = new HashSet<string> (str_hash, str_equal);
 	Set<string> includes = new HashSet<string> (str_hash, str_equal);
-	internal CCodeFragment begin = new CCodeFragment ();
 	internal CCodeFragment include_directives = new CCodeFragment ();
 	internal CCodeFragment type_declaration = new CCodeFragment ();
 	internal CCodeFragment type_definition = new CCodeFragment ();
 	internal CCodeFragment type_member_declaration = new CCodeFragment ();
 	internal CCodeFragment constant_declaration = new CCodeFragment ();
 
+	public bool add_declaration (string name) {
+		if (name in declarations) {
+			return true;
+		}
+		declarations.add (name);
+		return false;
+	}
+
+	public bool add_symbol_declaration (Symbol sym, string name) {
+		if (add_declaration (name)) {
+			return true;
+		}
+		if (sym.external_package) {
+			// add appropriate include file
+			foreach (string header_filename in sym.get_cheader_filenames ()) {
+				add_include (header_filename);
+			}
+			// declaration complete
+			return true;
+		} else {
+			// require declaration
+			return false;
+		}
+	}
+
 	public void add_include (string filename, bool local = false) {
 		if (!(filename in includes)) {
 			include_directives.append (new CCodeIncludeDirective (filename, local));
@@ -38,10 +63,6 @@ class Vala.CCodeDeclarationSpace {
 		}
 	}
 
-	public void add_begin (CCodeNode node) {
-		begin.append (node);
-	}
-
 	public void add_type_declaration (CCodeNode node) {
 		type_declaration.append (node);
 	}
diff --git a/gobject/valaccodedelegatemodule.vala b/gobject/valaccodedelegatemodule.vala
index a5a22b4..f7fae0e 100644
--- a/gobject/valaccodedelegatemodule.vala
+++ b/gobject/valaccodedelegatemodule.vala
@@ -32,11 +32,15 @@ internal class Vala.CCodeDelegateModule : CCodeArrayModule {
 		base (codegen, next);
 	}
 
-	public override void visit_delegate (Delegate d) {
-		d.accept_children (codegen);
+	public override void generate_delegate_declaration (Delegate d, CCodeDeclarationSpace decl_space) {
+		if (decl_space.add_symbol_declaration (d, d.get_cname ())) {
+			return;
+		}
 
 		var cfundecl = new CCodeFunctionDeclarator (d.get_cname ());
 		foreach (FormalParameter param in d.get_parameters ()) {
+			generate_parameter (param, decl_space, new HashMap<int,CCodeFormalParameter> (), null);
+
 			cfundecl.add_parameter ((CCodeFormalParameter) param.ccodenode);
 
 			// handle array parameters
@@ -74,17 +78,16 @@ internal class Vala.CCodeDelegateModule : CCodeArrayModule {
 
 		var ctypedef = new CCodeTypeDefinition (d.return_type.get_cname (), cfundecl);
 
-		if (!d.is_internal_symbol ()) {
-			if (d.source_reference != null && d.source_reference.comment != null) {
-				header_declarations.add_type_declaration (new CCodeComment (d.source_reference.comment));
-			}
-			header_declarations.add_type_declaration (ctypedef);
-		} else {
-			if (d.source_reference != null && d.source_reference.comment != null) {
-				source_declarations.add_type_declaration (new CCodeComment (d.source_reference.comment));
-			}
-			source_declarations.add_type_declaration (ctypedef);
+		if (d.source_reference != null && d.source_reference.comment != null) {
+			decl_space.add_type_declaration (new CCodeComment (d.source_reference.comment));
 		}
+		decl_space.add_type_declaration (ctypedef);
+	}
+
+	public override void visit_delegate (Delegate d) {
+		d.accept_children (codegen);
+
+		generate_delegate_declaration (d, source_declarations);
 	}
 
 	public override string get_delegate_target_cname (string delegate_cname) {
@@ -238,26 +241,7 @@ internal class Vala.CCodeDelegateModule : CCodeArrayModule {
 
 		var d_params = d.get_parameters ();
 		foreach (FormalParameter param in d_params) {
-			// ensure that C code node has been generated
-			param.accept (codegen);
-
-			cparam_map.set (get_param_pos (param.cparameter_position), (CCodeFormalParameter) param.ccodenode);
-
-			// handle array parameters
-			if (!param.no_array_length && param.parameter_type is ArrayType) {
-				var array_type = (ArrayType) param.parameter_type;
-				
-				var length_ctype = "int";
-				if (param.direction != ParameterDirection.IN) {
-					length_ctype = "int*";
-				}
-				
-				for (int dim = 1; dim <= array_type.rank; dim++) {
-					var cparam = new CCodeFormalParameter (head.get_array_length_cname (param.name, dim), length_ctype);
-					cparam_map.set (get_param_pos (param.carray_length_parameter_position + 0.01 * dim), cparam);
-				}
-			}
-
+			generate_parameter (param, source_declarations, cparam_map, null);
 		}
 		if (!d.no_array_length && d.return_type is ArrayType) {
 			// return array length if appropriate
@@ -387,12 +371,20 @@ internal class Vala.CCodeDelegateModule : CCodeArrayModule {
 		return wrapper_name;
 	}
 
-	public override void generate_parameter (FormalParameter param, Map<int,CCodeFormalParameter> cparam_map, Map<int,CCodeExpression>? carg_map) {
+	public override void generate_parameter (FormalParameter param, CCodeDeclarationSpace decl_space, Map<int,CCodeFormalParameter> cparam_map, Map<int,CCodeExpression>? carg_map) {
 		if (!(param.parameter_type is DelegateType || param.parameter_type is MethodType)) {
-			base.generate_parameter (param, cparam_map, carg_map);
+			base.generate_parameter (param, decl_space, cparam_map, carg_map);
 			return;
 		}
 
+		string ctypename = param.parameter_type.get_cname ();
+
+		if (param.direction != ParameterDirection.IN) {
+			ctypename += "*";
+		}
+
+		param.ccodenode = new CCodeFormalParameter (param.name, ctypename);
+
 		cparam_map.set (get_param_pos (param.cparameter_position), (CCodeFormalParameter) param.ccodenode);
 		if (carg_map != null) {
 			carg_map.set (get_param_pos (param.cparameter_position), new CCodeIdentifier (param.name));
@@ -401,6 +393,9 @@ internal class Vala.CCodeDelegateModule : CCodeArrayModule {
 		if (param.parameter_type is DelegateType) {
 			var deleg_type = (DelegateType) param.parameter_type;
 			var d = deleg_type.delegate_symbol;
+
+			generate_delegate_declaration (d, decl_space);
+
 			if (d.has_target) {
 				var cparam = new CCodeFormalParameter (get_delegate_target_cname (param.name), "void*");
 				cparam_map.set (get_param_pos (param.cdelegate_target_parameter_position), cparam);
diff --git a/gobject/valaccodegenerator.vala b/gobject/valaccodegenerator.vala
index 0ada7db..9d9b3c8 100644
--- a/gobject/valaccodegenerator.vala
+++ b/gobject/valaccodegenerator.vala
@@ -76,18 +76,10 @@ public class Vala.CCodeGenerator : CodeGenerator {
 		head.visit_enum (en);
 	}
 
-	public override void visit_enum_value (EnumValue ev) {
-		head.visit_enum_value (ev);
-	}
-
 	public override void visit_error_domain (ErrorDomain edomain) {
 		head.visit_error_domain (edomain);
 	}
 
-	public override void visit_error_code (ErrorCode ecode) {
-		head.visit_error_code (ecode);
-	}
-
 	public override void visit_delegate (Delegate d) {
 		head.visit_delegate (d);
 	}
diff --git a/gobject/valaccodememberaccessmodule.vala b/gobject/valaccodememberaccessmodule.vala
index d2731e8..8b618ac 100644
--- a/gobject/valaccodememberaccessmodule.vala
+++ b/gobject/valaccodememberaccessmodule.vala
@@ -45,7 +45,19 @@ internal class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
 
 		if (expr.symbol_reference is Method) {
 			var m = (Method) expr.symbol_reference;
-			
+
+			if (!(m is DynamicMethod || m is ArrayMoveMethod || m is ArrayResizeMethod)) {
+				generate_method_declaration (m, source_declarations);
+
+				if (!m.external && m.external_package) {
+					// internal VAPI methods
+					// only add them once per source file
+					if (add_generated_external_symbol (m)) {
+						visit_method (m);
+					}
+				}
+			}
+
 			if (expr.inner is BaseAccess) {
 				if (m.base_method != null) {
 					var base_class = (Class) m.base_method.parent_symbol;
@@ -103,6 +115,9 @@ internal class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
 				if (is_gtypeinstance && f.access == SymbolAccessibility.PRIVATE) {
 					inst = new CCodeMemberAccess.pointer (pub_inst, "priv");
 				} else {
+					if (cl != null) {
+						generate_class_struct_declaration (cl, source_declarations);
+					}
 					inst = pub_inst;
 				}
 				if (instance_target_type.data_type.is_reference_type () || (expr.inner != null && expr.inner.value_type is PointerType)) {
@@ -149,6 +164,8 @@ internal class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
 		} else if (expr.symbol_reference is Constant) {
 			var c = (Constant) expr.symbol_reference;
 
+			generate_constant_declaration (c, source_declarations);
+
 			string fn = c.get_full_name ();
 			if (fn == "GLib.Log.FILE") {
 				string s = Path.get_basename (expr.source_reference.file.filename);
@@ -168,6 +185,18 @@ internal class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
 		} else if (expr.symbol_reference is Property) {
 			var prop = (Property) expr.symbol_reference;
 
+			if (!(prop is DynamicProperty)) {
+				generate_property_accessor_declaration (prop.get_accessor, source_declarations);
+
+				if (!prop.external && prop.external_package) {
+					// internal VAPI properties
+					// only add them once per source file
+					if (add_generated_external_symbol (prop)) {
+						visit_property (prop);
+					}
+				}
+			}
+
 			if (expr.inner is BaseAccess) {
 				if (prop.base_property != null) {
 					var base_class = (Class) prop.base_property.parent_symbol;
diff --git a/gobject/valaccodemethodcallmodule.vala b/gobject/valaccodemethodcallmodule.vala
index f77aaaf..4785120 100644
--- a/gobject/valaccodemethodcallmodule.vala
+++ b/gobject/valaccodemethodcallmodule.vala
@@ -60,6 +60,7 @@ internal class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
 			// constructor
 			var cl = (Class) ((ObjectType) itype).type_symbol;
 			m = cl.default_construction_method;
+			generate_method_declaration (m, source_declarations);
 			ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_real_cname ()));
 		}
 
diff --git a/gobject/valaccodemethodmodule.vala b/gobject/valaccodemethodmodule.vala
index 5096111..3aab9ec 100644
--- a/gobject/valaccodemethodmodule.vala
+++ b/gobject/valaccodemethodmodule.vala
@@ -66,10 +66,10 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
 		return result;
 	}
 
-	public virtual void generate_method_result_declaration (Method m, CCodeFunction cfunc, Map<int,CCodeFormalParameter> cparam_map, Map<int,CCodeExpression>? carg_map) {
+	public virtual void generate_method_result_declaration (Method m, CCodeDeclarationSpace decl_space, CCodeFunction cfunc, Map<int,CCodeFormalParameter> cparam_map, Map<int,CCodeExpression>? carg_map) {
 		var creturn_type = m.return_type;
 		if (m is CreationMethod) {
-			var cl = current_type_symbol as Class;
+			var cl = m.parent_symbol as Class;
 			if (cl != null) {
 				// object creation methods return the new object in C
 				// in Vala they have no return type
@@ -78,6 +78,8 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
 		}
 		cfunc.return_type = get_creturn_type (m, creturn_type.get_cname ());
 
+		generate_type_declaration (m.return_type, decl_space);
+
 		if (!m.no_array_length && m.return_type is ArrayType) {
 			// return array length if appropriate
 			var array_type = (ArrayType) m.return_type;
@@ -140,6 +142,42 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
 		return complete_block;
 	}
 
+	public override void generate_method_declaration (Method m, CCodeDeclarationSpace decl_space) {
+		if (decl_space.add_symbol_declaration (m, m.get_cname ())) {
+			return;
+		}
+
+		var function = new CCodeFunction (m.get_cname ());
+
+		if (m.is_private_symbol ()) {
+			function.modifiers |= CCodeModifiers.STATIC;
+			if (m.is_inline) {
+				function.modifiers |= CCodeModifiers.INLINE;
+			}
+		}
+
+		var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
+		var carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
+
+		generate_cparameters (m, decl_space, cparam_map, function, null, carg_map, new CCodeFunctionCall (new CCodeIdentifier ("fake")));
+
+		decl_space.add_type_member_declaration (function);
+
+		if (m is CreationMethod && m.parent_symbol is Class) {
+			// _construct function
+			function = new CCodeFunction (m.get_real_cname ());
+
+			if (m.is_private_symbol ()) {
+				function.modifiers |= CCodeModifiers.STATIC;
+			}
+
+			cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
+			generate_cparameters (m, decl_space, cparam_map, function);
+
+			decl_space.add_type_member_declaration (function);
+		}
+	}
+
 	public override void visit_method (Method m) {
 		var old_type_symbol = current_type_symbol;
 		var old_symbol = current_symbol;
@@ -249,6 +287,16 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
 		variable_name_map = old_variable_name_map;
 		current_try = old_try;
 
+		// do not declare overriding methods and interface implementations
+		if (m.is_abstract || m.is_virtual
+		    || (m.base_method == null && m.base_interface_method == null)) {
+			generate_method_declaration (m, source_declarations);
+
+			if (!m.is_internal_symbol ()) {
+				generate_method_declaration (m, header_declarations);
+			}
+		}
+
 		function = new CCodeFunction (m.get_real_cname ());
 		m.ccodenode = function;
 
@@ -258,30 +306,17 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
 
 		var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
 
-		CCodeFunctionDeclarator vdeclarator = null;
-		if ((m.is_abstract || m.is_virtual) && !m.coroutine) {
-			var vdecl = new CCodeDeclaration (get_creturn_type (m, creturn_type.get_cname ()));
-			vdeclarator = new CCodeFunctionDeclarator (m.vfunc_name);
-			vdecl.add_declarator (vdeclarator);
-			type_struct.add_declaration (vdecl);
-		}
-
-		generate_cparameters (m, cparam_map, function, vdeclarator);
-
-		bool visible = !m.is_internal_symbol ();
+		generate_cparameters (m, source_declarations, cparam_map, function);
 
 		// generate *_real_* functions for virtual methods
 		// also generate them for abstract methods of classes to prevent faulty subclassing
 		if (!m.is_abstract || (m.is_abstract && current_type_symbol is Class)) {
-			if (visible && m.base_method == null && m.base_interface_method == null) {
-				/* public methods need function declaration in
-				 * header file except virtual/overridden methods */
-				header_declarations.add_type_member_declaration (function.copy ());
-			} else {
-				/* declare all other functions in source file to
-				 * avoid dependency on order within source file */
+			if (m.base_method != null || m.base_interface_method != null) {
+				// declare *_real_* function
 				function.modifiers |= CCodeModifiers.STATIC;
 				source_declarations.add_type_member_declaration (function.copy ());
+			} else if (m.is_private_symbol ()) {
+				function.modifiers |= CCodeModifiers.STATIC;
 			}
 		
 			/* Methods imported from a plain C file don't
@@ -583,14 +618,43 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
 		}
 	}
 
-	public virtual void generate_parameter (FormalParameter param, Map<int,CCodeFormalParameter> cparam_map, Map<int,CCodeExpression>? carg_map) {
+	public virtual void generate_parameter (FormalParameter param, CCodeDeclarationSpace decl_space, Map<int,CCodeFormalParameter> cparam_map, Map<int,CCodeExpression>? carg_map) {
+		if (!param.ellipsis) {
+			string ctypename = param.parameter_type.get_cname ();
+
+			generate_type_declaration (param.parameter_type, decl_space);
+
+			// pass non-simple structs always by reference
+			if (param.parameter_type.data_type is Struct) {
+				var st = (Struct) param.parameter_type.data_type;
+				generate_struct_declaration (st, decl_space);
+				if (!st.is_simple_type () && param.direction == ParameterDirection.IN) {
+					if (st.use_const) {
+						ctypename = "const " + ctypename;
+					}
+
+					if (!param.parameter_type.nullable) {
+						ctypename += "*";
+					}
+				}
+			}
+
+			if (param.direction != ParameterDirection.IN) {
+				ctypename += "*";
+			}
+
+			param.ccodenode = new CCodeFormalParameter (param.name, ctypename);
+		} else {
+			param.ccodenode = new CCodeFormalParameter.with_ellipsis ();
+		}
+
 		cparam_map.set (get_param_pos (param.cparameter_position), (CCodeFormalParameter) param.ccodenode);
-		if (carg_map != null) {
+		if (carg_map != null && !param.ellipsis) {
 			carg_map.set (get_param_pos (param.cparameter_position), new CCodeIdentifier (param.name));
 		}
 	}
 
-	public override void generate_cparameters (Method m, Map<int,CCodeFormalParameter> cparam_map, CCodeFunction func, CCodeFunctionDeclarator? vdeclarator = null, Map<int,CCodeExpression>? carg_map = null, CCodeFunctionCall? vcall = null, int direction = 3) {
+	public override void generate_cparameters (Method m, CCodeDeclarationSpace decl_space, Map<int,CCodeFormalParameter> cparam_map, CCodeFunction func, CCodeFunctionDeclarator? vdeclarator = null, Map<int,CCodeExpression>? carg_map = null, CCodeFunctionCall? vcall = null, int direction = 3) {
 		if (m.parent_symbol is Class && m is CreationMethod) {
 			var cl = (Class) m.parent_symbol;
 			if (!cl.is_compact && vcall == null) {
@@ -611,6 +675,8 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
 				assert_not_reached ();
 			}
 
+			generate_type_declaration (this_type, decl_space);
+
 			CCodeFormalParameter instance_param = null;
 			if (m.base_interface_method != null && !m.is_abstract && !m.is_virtual) {
 				var base_type = new ObjectType ((Interface) m.base_interface_method.parent_symbol);
@@ -637,7 +703,8 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
 		if (is_gtypeinstance_creation_method (m)) {
 			// memory management for generic types
 			int type_param_index = 0;
-			foreach (TypeParameter type_param in current_class.get_type_parameters ()) {
+			var cl = (Class) m.parent_symbol;
+			foreach (TypeParameter type_param in cl.get_type_parameters ()) {
 				cparam_map.set (get_param_pos (0.1 * type_param_index + 0.01), new CCodeFormalParameter ("%s_type".printf (type_param.name.down ()), "GType"));
 				cparam_map.set (get_param_pos (0.1 * type_param_index + 0.02), new CCodeFormalParameter ("%s_dup_func".printf (type_param.name.down ()), "GBoxedCopyFunc"));
 				cparam_map.set (get_param_pos (0.1 * type_param_index + 0.03), new CCodeFormalParameter ("%s_destroy_func".printf (type_param.name.down ()), "GDestroyNotify"));
@@ -663,11 +730,11 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
 				}
 			}
 
-			generate_parameter (param, cparam_map, carg_map);
+			generate_parameter (param, source_declarations, cparam_map, carg_map);
 		}
 
 		if ((direction & 2) != 0) {
-			generate_method_result_declaration (m, func, cparam_map, carg_map);
+			generate_method_result_declaration (m, decl_space, func, cparam_map, carg_map);
 		}
 
 		// append C parameters in the right order
@@ -688,15 +755,16 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
 				vdeclarator.add_parameter (cparam_map.get (min_pos));
 			}
 			if (vcall != null) {
-				vcall.add_argument (carg_map.get (min_pos));
+				var arg = carg_map.get (min_pos);
+				if (arg != null) {
+					vcall.add_argument (arg);
+				}
 			}
 			last_pos = min_pos;
 		}
 	}
 
 	public void generate_vfunc (Method m, DataType return_type, Map<int,CCodeFormalParameter> cparam_map, Map<int,CCodeExpression> carg_map, string suffix = "", int direction = 3) {
-		bool visible = !m.is_internal_symbol ();
-
 		var vfunc = new CCodeFunction (m.get_cname () + suffix);
 		vfunc.line = function.line;
 
@@ -724,7 +792,7 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
 		var vcall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (vcast, m.vfunc_name + suffix));
 		carg_map.set (get_param_pos (m.cinstance_parameter_position), new CCodeIdentifier ("self"));
 
-		generate_cparameters (m, cparam_map, vfunc, null, carg_map, vcall, direction);
+		generate_cparameters (m, source_declarations, cparam_map, vfunc, null, carg_map, vcall, direction);
 
 		CCodeStatement cstmt;
 		if (return_type is VoidType) {
@@ -753,13 +821,6 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
 			}
 		}
 
-		if (visible) {
-			header_declarations.add_type_member_declaration (vfunc.copy ());
-		} else {
-			vfunc.modifiers |= CCodeModifiers.STATIC;
-			source_declarations.add_type_member_declaration (vfunc.copy ());
-		}
-		
 		vfunc.block = vblock;
 
 		if (m.is_abstract && m.source_reference != null && m.source_reference.comment != null) {
@@ -838,6 +899,8 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
 
 		var cdecl = new CCodeVariableDeclarator ("self");
 		if (chain_up) {
+			generate_method_declaration (cm, source_declarations);
+
 			var ccall = new CCodeFunctionCall (new CCodeIdentifier (cm.get_real_cname ()));
 			ccall.add_argument (new CCodeIdentifier ("object_type"));
 			cdecl.initializer = new CCodeCastExpression (ccall, "%s*".printf (cl.get_cname ()));
@@ -861,7 +924,7 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
 	}
 
 	public override void visit_creation_method (CreationMethod m) {
-		bool visible = !m.is_internal_symbol ();
+		bool visible = !m.is_private_symbol ();
 
 		if (m.body != null && current_type_symbol is Class && current_class.is_subtype_of (gobject_type)) {
 			int n_params = 0;
@@ -898,18 +961,17 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
 			var vcall = new CCodeFunctionCall (new CCodeIdentifier (m.get_real_cname ()));
 			vcall.add_argument (new CCodeIdentifier (current_class.get_type_id ()));
 
-			generate_cparameters (m, cparam_map, vfunc, null, carg_map, vcall);
+			generate_cparameters (m, source_declarations, cparam_map, vfunc, null, carg_map, vcall);
 			CCodeStatement cstmt = new CCodeReturnStatement (vcall);
 			cstmt.line = vfunc.line;
 			vblock.add_statement (cstmt);
 
-			if (visible) {
-				header_declarations.add_type_member_declaration (vfunc.copy ());
-			} else {
+			if (!visible) {
 				vfunc.modifiers |= CCodeModifiers.STATIC;
-				source_declarations.add_type_member_declaration (vfunc.copy ());
 			}
-		
+
+			source_declarations.add_type_member_declaration (vfunc.copy ());
+
 			vfunc.block = vblock;
 
 			source_type_member_definition.append (vfunc);
diff --git a/gobject/valaccodemodule.vala b/gobject/valaccodemodule.vala
index 85415b0..8dff9bf 100644
--- a/gobject/valaccodemodule.vala
+++ b/gobject/valaccodemodule.vala
@@ -72,18 +72,10 @@ public abstract class Vala.CCodeModule {
 		next.visit_enum (en);
 	}
 
-	public virtual void visit_enum_value (EnumValue ev) {
-		next.visit_enum_value (ev);
-	}
-
 	public virtual void visit_error_domain (ErrorDomain edomain) {
 		next.visit_error_domain (edomain);
 	}
 
-	public virtual void visit_error_code (ErrorCode ecode) {
-		next.visit_error_code (ecode);
-	}
-
 	public virtual void visit_delegate (Delegate d) {
 		next.visit_delegate (d);
 	}
@@ -328,10 +320,6 @@ public abstract class Vala.CCodeModule {
 		next.visit_assignment (a);
 	}
 
-	public virtual void generate_cparameters (Method m, Map<int,CCodeFormalParameter> cparam_map, CCodeFunction func, CCodeFunctionDeclarator? vdeclarator = null, Map<int,CCodeExpression>? carg_map = null, CCodeFunctionCall? vcall = null, int direction = 3) {
-		next.generate_cparameters (m, cparam_map, func, vdeclarator, carg_map, vcall, direction);
-	}
-
 	public virtual string? get_custom_creturn_type (Method m) {
 		return next.get_custom_creturn_type (m);
 	}
diff --git a/gobject/valaccodestructmodule.vala b/gobject/valaccodestructmodule.vala
index 5802608..00a60af 100644
--- a/gobject/valaccodestructmodule.vala
+++ b/gobject/valaccodestructmodule.vala
@@ -1,6 +1,7 @@
 /* valaccodestructmodule.vala
  *
- * Copyright (C) 2006-2008  Jürg Billeter, Raffaele Sandrini
+ * Copyright (C) 2006-2009  Jürg Billeter
+ * Copyright (C) 2006-2008  Raffaele Sandrini
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -28,31 +29,62 @@ internal class Vala.CCodeStructModule : CCodeBaseModule {
 		base (codegen, next);
 	}
 
-	public override void visit_struct (Struct st) {
-		var old_type_symbol = current_type_symbol;
-		var old_instance_struct = instance_struct;
-		var old_instance_finalize_fragment = instance_finalize_fragment;
-		current_type_symbol = st;
-		instance_struct = new CCodeStruct ("_%s".printf (st.get_cname ()));
-		instance_finalize_fragment = new CCodeFragment ();
-
-		CCodeDeclarationSpace decl_space;
-		if (st.access != SymbolAccessibility.PRIVATE) {
-			decl_space = header_declarations;
-		} else {
-			decl_space = source_declarations;
+	public override void generate_struct_declaration (Struct st, CCodeDeclarationSpace decl_space) {
+		if (decl_space.add_symbol_declaration (st, st.get_cname ())) {
+			return;
 		}
 
-		if (st.access == SymbolAccessibility.PRIVATE
-		    || st.source_reference.file.cycle == null) {
-			// no file dependency cycle for private symbols
-			decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (st.get_cname ()), new CCodeVariableDeclarator (st.get_cname ())));
+		var instance_struct = new CCodeStruct ("_%s".printf (st.get_cname ()));
+
+		foreach (Field f in st.get_fields ()) {
+			string field_ctype = f.field_type.get_cname ();
+			if (f.is_volatile) {
+				field_ctype = "volatile " + field_ctype;
+			}
+
+			if (f.binding == MemberBinding.INSTANCE)  {
+				instance_struct.add_field (field_ctype, f.get_cname ());
+				if (f.field_type is ArrayType && !f.no_array_length) {
+					// create fields to store array dimensions
+					var array_type = (ArrayType) f.field_type;
+					var len_type = int_type.copy ();
+
+					for (int dim = 1; dim <= array_type.rank; dim++) {
+						instance_struct.add_field (len_type.get_cname (), head.get_array_length_cname (f.name, dim));
+					}
+
+					if (array_type.rank == 1 && f.is_internal_symbol ()) {
+						instance_struct.add_field (len_type.get_cname (), head.get_array_size_cname (f.name));
+					}
+				} else if (f.field_type is DelegateType) {
+					var delegate_type = (DelegateType) f.field_type;
+					if (delegate_type.delegate_symbol.has_target) {
+						// create field to store delegate target
+						instance_struct.add_field ("gpointer", get_delegate_target_cname (f.name));
+					}
+				}
+			}
 		}
 
+		decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (st.get_cname ()), new CCodeVariableDeclarator (st.get_cname ())));
+
 		if (st.source_reference.comment != null) {
 			decl_space.add_type_definition (new CCodeComment (st.source_reference.comment));
 		}
 		decl_space.add_type_definition (instance_struct);
+	}
+
+	public override void visit_struct (Struct st) {
+		var old_type_symbol = current_type_symbol;
+		var old_instance_finalize_fragment = instance_finalize_fragment;
+		current_type_symbol = st;
+		instance_finalize_fragment = new CCodeFragment ();
+
+		generate_struct_declaration (st, source_declarations);
+
+		if (!st.is_internal_symbol ()) {
+			generate_struct_declaration (st, header_declarations);
+		}
 
 		st.accept_children (codegen);
 
@@ -65,7 +97,6 @@ internal class Vala.CCodeStructModule : CCodeBaseModule {
 		add_struct_free_function (st);
 
 		current_type_symbol = old_type_symbol;
-		instance_struct = old_instance_struct;
 		instance_finalize_fragment = old_instance_finalize_fragment;
 	}
 
@@ -77,11 +108,7 @@ internal class Vala.CCodeStructModule : CCodeBaseModule {
 
 		function.add_parameter (new CCodeFormalParameter ("self", "const " + st.get_cname () + "*"));
 
-		if (st.access != SymbolAccessibility.PRIVATE) {
-			header_declarations.add_type_member_declaration (function.copy ());
-		} else {
-			source_declarations.add_type_member_declaration (function.copy ());
-		}
+		source_declarations.add_type_member_declaration (function.copy ());
 
 		var cblock = new CCodeBlock ();
 
@@ -125,11 +152,7 @@ internal class Vala.CCodeStructModule : CCodeBaseModule {
 
 		function.add_parameter (new CCodeFormalParameter ("self", st.get_cname () + "*"));
 
-		if (st.access != SymbolAccessibility.PRIVATE) {
-			header_declarations.add_type_member_declaration (function.copy ());
-		} else {
-			source_declarations.add_type_member_declaration (function.copy ());
-		}
+		source_declarations.add_type_member_declaration (function.copy ());
 
 		var cblock = new CCodeBlock ();
 
@@ -157,11 +180,7 @@ internal class Vala.CCodeStructModule : CCodeBaseModule {
 		function.add_parameter (new CCodeFormalParameter ("self", "const " + st.get_cname () + "*"));
 		function.add_parameter (new CCodeFormalParameter ("dest", st.get_cname () + "*"));
 
-		if (st.access != SymbolAccessibility.PRIVATE) {
-			header_declarations.add_type_member_declaration (function.copy ());
-		} else {
-			source_declarations.add_type_member_declaration (function.copy ());
-		}
+		source_declarations.add_type_member_declaration (function.copy ());
 
 		var cblock = new CCodeBlock ();
 		var cfrag = new CCodeFragment ();
@@ -208,11 +227,7 @@ internal class Vala.CCodeStructModule : CCodeBaseModule {
 
 		function.add_parameter (new CCodeFormalParameter ("self", st.get_cname () + "*"));
 
-		if (st.access != SymbolAccessibility.PRIVATE) {
-			header_declarations.add_type_member_declaration (function.copy ());
-		} else {
-			source_declarations.add_type_member_declaration (function.copy ());
-		}
+		source_declarations.add_type_member_declaration (function.copy ());
 
 		var cblock = new CCodeBlock ();
 
diff --git a/gobject/valadbusclientmodule.vala b/gobject/valadbusclientmodule.vala
index 77e986d..5a5214d 100644
--- a/gobject/valadbusclientmodule.vala
+++ b/gobject/valadbusclientmodule.vala
@@ -52,7 +52,7 @@ internal class Vala.DBusClientModule : DBusModule {
 
 		var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
 
-		generate_cparameters (method, cparam_map, func);
+		generate_cparameters (method, source_declarations, cparam_map, func);
 
 		var block = new CCodeBlock ();
 		if (dynamic_method.dynamic_type.data_type == dbus_object_type) {
@@ -840,12 +840,9 @@ internal class Vala.DBusClientModule : DBusModule {
 		string cname = iface.get_cname () + "DBusProxy";
 		string lower_cname = iface.get_lower_case_cprefix () + "dbus_proxy";
 
-		CCodeDeclarationSpace decl_space;
 		if (iface.access != SymbolAccessibility.PRIVATE) {
-			decl_space = header_declarations;
 			dbus_glib_h_needed_in_header = true;
 		} else {
-			decl_space = source_declarations;
 			dbus_glib_h_needed = true;
 		}
 
@@ -922,7 +919,7 @@ internal class Vala.DBusClientModule : DBusModule {
 
 		new_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("self")));
 
-		decl_space.add_type_member_declaration (proxy_new.copy ());
+		source_declarations.add_type_member_declaration (proxy_new.copy ());
 		proxy_new.block = new_block;
 		source_type_member_definition.append (proxy_new);
 
@@ -1272,7 +1269,7 @@ internal class Vala.DBusClientModule : DBusModule {
 
 		var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
 
-		generate_cparameters (m, cparam_map, function);
+		generate_cparameters (m, source_declarations, cparam_map, function);
 
 		var block = new CCodeBlock ();
 		var prefragment = new CCodeFragment ();
@@ -1368,7 +1365,7 @@ internal class Vala.DBusClientModule : DBusModule {
 		cparam_map.set (get_param_pos (-1), new CCodeFormalParameter ("callback", "GAsyncReadyCallback"));
 		cparam_map.set (get_param_pos (-0.9), new CCodeFormalParameter ("user_data", "gpointer"));
 
-		generate_cparameters (m, cparam_map, function, null, null, null, 1);
+		generate_cparameters (m, source_declarations, cparam_map, function, null, null, null, 1);
 
 		var block = new CCodeBlock ();
 		var prefragment = new CCodeFragment ();
@@ -1496,7 +1493,7 @@ internal class Vala.DBusClientModule : DBusModule {
 
 		cparam_map.set (get_param_pos (0.1), new CCodeFormalParameter ("res", "GAsyncResult*"));
 
-		generate_cparameters (m, cparam_map, function, null, null, null, 2);
+		generate_cparameters (m, source_declarations, cparam_map, function, null, null, null, 2);
 
 		var block = new CCodeBlock ();
 		var prefragment = new CCodeFragment ();
diff --git a/gobject/valadbusservermodule.vala b/gobject/valadbusservermodule.vala
index 26d032b..caede6a 100644
--- a/gobject/valadbusservermodule.vala
+++ b/gobject/valadbusservermodule.vala
@@ -324,15 +324,14 @@ internal class Vala.DBusServerModule : DBusClientModule {
 
 		if (!sym.is_internal_symbol ()) {
 			dbus_glib_h_needed_in_header = true;
-
-			header_declarations.add_type_member_declaration (cfunc.copy ());
 		} else {
 			dbus_glib_h_needed = true;
 
 			cfunc.modifiers |= CCodeModifiers.STATIC;
-			source_declarations.add_type_member_declaration (cfunc.copy ());
 		}
 
+		source_declarations.add_type_member_declaration (cfunc.copy ());
+
 		var block = new CCodeBlock ();
 		cfunc.block = block;
 
@@ -1129,13 +1128,12 @@ internal class Vala.DBusServerModule : DBusClientModule {
 		cfunc.add_parameter (new CCodeFormalParameter ("message", "DBusMessage*"));
 		cfunc.add_parameter (new CCodeFormalParameter ("object", "void*"));
 
-		if (!sym.is_internal_symbol ()) {
-			header_declarations.add_type_member_declaration (cfunc.copy ());
-		} else {
+		if (sym.is_internal_symbol ()) {
 			cfunc.modifiers |= CCodeModifiers.STATIC;
-			source_declarations.add_type_member_declaration (cfunc.copy ());
 		}
 
+		source_declarations.add_type_member_declaration (cfunc.copy ());
+
 		var block = new CCodeBlock ();
 		cfunc.block = block;
 
diff --git a/gobject/valagasyncmodule.vala b/gobject/valagasyncmodule.vala
index c6d863a..af2c96f 100644
--- a/gobject/valagasyncmodule.vala
+++ b/gobject/valagasyncmodule.vala
@@ -159,7 +159,7 @@ internal class Vala.GAsyncModule : GSignalModule {
 		cparam_map.set (get_param_pos (-1), new CCodeFormalParameter ("callback", "GAsyncReadyCallback"));
 		cparam_map.set (get_param_pos (-0.9), new CCodeFormalParameter ("user_data", "gpointer"));
 
-		generate_cparameters (m, cparam_map, asyncfunc, null, null, null, 1);
+		generate_cparameters (m, source_declarations, cparam_map, asyncfunc, null, null, null, 1);
 
 		if (!m.is_internal_symbol () && m.base_method == null && m.base_interface_method == null) {
 			asyncfunc.modifiers |= CCodeModifiers.STATIC;
@@ -181,11 +181,7 @@ internal class Vala.GAsyncModule : GSignalModule {
 		var block = function.block;
 		function.block = null;
  
-		if ((function.modifiers & CCodeModifiers.STATIC) != 0) {
-			source_declarations.add_type_member_declaration (function.copy ());
-		} else {
-			header_declarations.add_type_member_declaration (function.copy ());
-		}
+		source_declarations.add_type_member_declaration (function.copy ());
 
 		function.block = block;
 		source_type_member_definition.append (function);
@@ -214,11 +210,6 @@ internal class Vala.GAsyncModule : GSignalModule {
 				base.visit_method (m);
 				closure_struct = null;
 			}
-
-			if (m.is_abstract || m.is_virtual) {
-				append_async_virtual_function (m);
-				append_finish_virtual_function (m);
-			}
 		} else {
 			base.visit_method (m);
 		}
@@ -234,7 +225,7 @@ internal class Vala.GAsyncModule : GSignalModule {
 
 		cparam_map.set (get_param_pos (0.1), new CCodeFormalParameter ("res", "GAsyncResult*"));
 
-		generate_cparameters (m, cparam_map, finishfunc, null, null, null, 2);
+		generate_cparameters (m, source_declarations, cparam_map, finishfunc, null, null, null, 2);
 
 		finishfunc.block = finishblock;
 
@@ -271,7 +262,19 @@ internal class Vala.GAsyncModule : GSignalModule {
 		return readyfunc;
 	}
 
-	void append_async_virtual_function (Method m) {
+	public override void generate_virtual_method_declaration (Method m, CCodeDeclarationSpace decl_space, CCodeStruct type_struct) {
+		if (!m.coroutine) {
+			base.generate_virtual_method_declaration (m, decl_space, type_struct);
+			return;
+		}
+
+		if (m.is_abstract || m.is_virtual) {
+			append_async_virtual_function (m, decl_space, type_struct);
+			append_finish_virtual_function (m, decl_space, type_struct);
+		}
+	}
+
+	void append_async_virtual_function (Method m, CCodeDeclarationSpace decl_space, CCodeStruct type_struct) {
 		var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
 		var carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
 
@@ -288,10 +291,10 @@ internal class Vala.GAsyncModule : GSignalModule {
 		type_struct.add_declaration (vdecl);
 
 		var fake = new CCodeFunction ("fake", "void");
-		generate_cparameters (m, cparam_map, fake, vdeclarator, null, null, 1);
+		generate_cparameters (m, decl_space, cparam_map, fake, vdeclarator, null, null, 1);
 	}
 
-	void append_finish_virtual_function (Method m) {
+	void append_finish_virtual_function (Method m, CCodeDeclarationSpace decl_space, CCodeStruct type_struct) {
 		var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
 		var carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
 
@@ -306,7 +309,7 @@ internal class Vala.GAsyncModule : GSignalModule {
 		type_struct.add_declaration (vdecl);
 
 		var fake = new CCodeFunction ("fake", "void");
-		generate_cparameters (m, cparam_map, fake, vdeclarator, null, null, 2);
+		generate_cparameters (m, decl_space, cparam_map, fake, vdeclarator, null, null, 2);
 	}
 
 	public override void visit_yield_statement (YieldStatement stmt) {
diff --git a/gobject/valagerrormodule.vala b/gobject/valagerrormodule.vala
index 01b6e14..5d1201c 100644
--- a/gobject/valagerrormodule.vala
+++ b/gobject/valagerrormodule.vala
@@ -1,6 +1,6 @@
 /* valagerrormodule.vala
  *
- * Copyright (C) 2008  Jürg Billeter
+ * Copyright (C) 2008-2009  Jürg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -32,20 +32,41 @@ internal class Vala.GErrorModule : CCodeDelegateModule {
 		base (codegen, next);
 	}
 
-	public override void visit_error_domain (ErrorDomain edomain) {
-		cenum = new CCodeEnum (edomain.get_cname ());
+	public override void generate_error_domain_declaration (ErrorDomain edomain, CCodeDeclarationSpace decl_space) {
+		if (decl_space.add_symbol_declaration (edomain, edomain.get_cname ())) {
+			return;
+		}
 
-		if (edomain.source_reference.comment != null) {
-			header_declarations.add_type_definition (new CCodeComment (edomain.source_reference.comment));
+		var cenum = new CCodeEnum (edomain.get_cname ());
+
+		foreach (ErrorCode ecode in edomain.get_codes ()) {
+			if (ecode.value == null) {
+				cenum.add_value (new CCodeEnumValue (ecode.get_cname ()));
+			} else {
+				ecode.value.accept (codegen);
+				cenum.add_value (new CCodeEnumValue (ecode.get_cname (), (CCodeExpression) ecode.value.ccodenode));
+			}
 		}
-		header_declarations.add_type_definition (cenum);
 
-		edomain.accept_children (codegen);
+		if (edomain.source_reference.comment != null) {
+			decl_space.add_type_definition (new CCodeComment (edomain.source_reference.comment));
+		}
+		decl_space.add_type_definition (cenum);
 
 		string quark_fun_name = edomain.get_lower_case_cprefix () + "quark";
 
 		var error_domain_define = new CCodeMacroReplacement (edomain.get_upper_case_cname (), quark_fun_name + " ()");
-		header_declarations.add_type_definition (error_domain_define);
+		decl_space.add_type_definition (error_domain_define);
+
+		var cquark_fun = new CCodeFunction (quark_fun_name, gquark_type.data_type.get_cname ());
+
+		decl_space.add_type_member_declaration (cquark_fun);
+	}
+
+	public override void visit_error_domain (ErrorDomain edomain) {
+		generate_error_domain_declaration (edomain, source_declarations);
+
+		string quark_fun_name = edomain.get_lower_case_cprefix () + "quark";
 
 		var cquark_fun = new CCodeFunction (quark_fun_name, gquark_type.data_type.get_cname ());
 		var cquark_block = new CCodeBlock ();
@@ -55,21 +76,10 @@ internal class Vala.GErrorModule : CCodeDelegateModule {
 
 		cquark_block.add_statement (new CCodeReturnStatement (cquark_call));
 
-		header_declarations.add_type_member_declaration (cquark_fun.copy ());
-
 		cquark_fun.block = cquark_block;
 		source_type_member_definition.append (cquark_fun);
 	}
 
-	public override void visit_error_code (ErrorCode ecode) {
-		if (ecode.value == null) {
-			cenum.add_value (new CCodeEnumValue (ecode.get_cname ()));
-		} else {
-			ecode.value.accept (codegen);
-			cenum.add_value (new CCodeEnumValue (ecode.get_cname (), (CCodeExpression) ecode.value.ccodenode));
-		}
-	}
-
 	public override void visit_throw_statement (ThrowStatement stmt) {
 		stmt.accept_children (codegen);
 
diff --git a/gobject/valagobjectmodule.vala b/gobject/valagobjectmodule.vala
index 030c18b..39810a4 100644
--- a/gobject/valagobjectmodule.vala
+++ b/gobject/valagobjectmodule.vala
@@ -32,70 +32,42 @@ internal class Vala.GObjectModule : GTypeModule {
 		base (codegen, next);
 	}
 
-	public override void generate_parameter (FormalParameter param, Map<int,CCodeFormalParameter> cparam_map, Map<int,CCodeExpression>? carg_map) {
+	public override void generate_parameter (FormalParameter param, CCodeDeclarationSpace decl_space, Map<int,CCodeFormalParameter> cparam_map, Map<int,CCodeExpression>? carg_map) {
 		if (!(param.parameter_type is ObjectType)) {
-			base.generate_parameter (param, cparam_map, carg_map);
+			base.generate_parameter (param, decl_space, cparam_map, carg_map);
 			return;
 		}
 
+		generate_type_declaration (param.parameter_type, decl_space);
+
+		string ctypename = param.parameter_type.get_cname ();
+
+		if (param.direction != ParameterDirection.IN) {
+			ctypename += "*";
+		}
+
+		param.ccodenode = new CCodeFormalParameter (param.name, ctypename);
+
 		cparam_map.set (get_param_pos (param.cparameter_position), (CCodeFormalParameter) param.ccodenode);
 		if (carg_map != null) {
 			carg_map.set (get_param_pos (param.cparameter_position), new CCodeIdentifier (param.name));
 		}
 	}
 
-	public override void visit_class (Class cl) {
-		var old_symbol = current_symbol;
-		var old_type_symbol = current_type_symbol;
-		var old_class = current_class;
-		var old_instance_struct = instance_struct;
-		var old_param_spec_struct = param_spec_struct;
-		var old_type_struct = type_struct;
-		var old_instance_priv_struct = instance_priv_struct;
-		var old_type_priv_struct = type_priv_struct;
-		var old_prop_enum = prop_enum;
-		var old_class_init_fragment = class_init_fragment;
-		var old_base_init_fragment = base_init_fragment;
-		var old_class_finalize_fragment = class_finalize_fragment;
-		var old_base_finalize_fragment = base_finalize_fragment;
-		var old_instance_init_fragment = instance_init_fragment;
-		var old_instance_finalize_fragment = instance_finalize_fragment;
-		current_symbol = cl;
-		current_type_symbol = cl;
-		current_class = cl;
-		
-		bool is_gtypeinstance = !cl.is_compact;
-		bool is_gobject = cl.is_subtype_of (gobject_type);
-		bool is_fundamental = is_gtypeinstance && cl.base_class == null;
-
-		if (cl.get_cname().len () < 3) {
-			cl.error = true;
-			Report.error (cl.source_reference, "Class name `%s' is too short".printf (cl.get_cname ()));
+	public override void generate_class_declaration (Class cl, CCodeDeclarationSpace decl_space) {
+		if (decl_space.add_symbol_declaration (cl, cl.get_cname ())) {
 			return;
 		}
 
-
-		instance_struct = new CCodeStruct ("_%s".printf (cl.get_cname ()));
-		type_struct = new CCodeStruct ("_%sClass".printf (cl.get_cname ()));
-		instance_priv_struct = new CCodeStruct ("_%sPrivate".printf (cl.get_cname ()));
-		type_priv_struct = new CCodeStruct ("_%sClassPrivate".printf (cl.get_cname ()));
-		prop_enum = new CCodeEnum ();
-		prop_enum.add_value (new CCodeEnumValue ("%s_DUMMY_PROPERTY".printf (cl.get_upper_case_cname (null))));
-		class_init_fragment = new CCodeFragment ();
-		base_init_fragment = new CCodeFragment ();
-		class_finalize_fragment = new CCodeFragment ();
-		base_finalize_fragment = new CCodeFragment ();
-		instance_init_fragment = new CCodeFragment ();
-		instance_finalize_fragment = new CCodeFragment ();
-
-
-		CCodeDeclarationSpace decl_space;
-		if (cl.access != SymbolAccessibility.PRIVATE) {
-			decl_space = header_declarations;
-		} else {
-			decl_space = source_declarations;
+		if (cl.base_class != null) {
+			// base class declaration
+			// necessary for ref and unref function declarations
+			generate_class_declaration (cl.base_class, decl_space);
 		}
 
+		bool is_gtypeinstance = !cl.is_compact;
+		bool is_fundamental = is_gtypeinstance && cl.base_class == null;
+
 		if (is_gtypeinstance) {
 			decl_space.add_type_declaration (new CCodeNewline ());
 			var macro = "(%s_get_type ())".printf (cl.get_lower_case_cname (null));
@@ -118,14 +90,94 @@ internal class Vala.GObjectModule : GTypeModule {
 			decl_space.add_type_declaration (new CCodeNewline ());
 		}
 
+		decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (cl.get_cname ()), new CCodeVariableDeclarator (cl.get_cname ())));
+
+		if (is_fundamental) {
+			var ref_fun = new CCodeFunction (cl.get_lower_case_cprefix () + "ref", "gpointer");
+			var unref_fun = new CCodeFunction (cl.get_lower_case_cprefix () + "unref", "void");
+			if (cl.access == SymbolAccessibility.PRIVATE) {
+				ref_fun.modifiers = CCodeModifiers.STATIC;
+				unref_fun.modifiers = CCodeModifiers.STATIC;
+			}
+
+			ref_fun.add_parameter (new CCodeFormalParameter ("instance", "gpointer"));
+			unref_fun.add_parameter (new CCodeFormalParameter ("instance", "gpointer"));
+
+			decl_space.add_type_member_declaration (ref_fun.copy ());
+			decl_space.add_type_member_declaration (unref_fun.copy ());
+
+			// GParamSpec and GValue functions
+			var function_name = cl.get_lower_case_cname ("param_spec_");
+
+			var function = new CCodeFunction (function_name, "GParamSpec*");
+			function.add_parameter (new CCodeFormalParameter ("name", "const gchar*"));
+			function.add_parameter (new CCodeFormalParameter ("nick", "const gchar*"));
+			function.add_parameter (new CCodeFormalParameter ("blurb", "const gchar*"));
+			function.add_parameter (new CCodeFormalParameter ("object_type", "GType"));
+			function.add_parameter (new CCodeFormalParameter ("flags", "GParamFlags"));
 
-		if (cl.access == SymbolAccessibility.PRIVATE
-		    || cl.source_reference.file.cycle == null) {
-			// no file dependency cycle for private symbols
-			decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (instance_struct.name), new CCodeVariableDeclarator (cl.get_cname ())));
+			cl.set_param_spec_function (function_name);
+
+			if (cl.access == SymbolAccessibility.PRIVATE) {
+				function.modifiers = CCodeModifiers.STATIC;
+			}
+
+			decl_space.add_type_member_declaration (function);
+
+			function = new CCodeFunction (cl.get_set_value_function (), "void");
+			function.add_parameter (new CCodeFormalParameter ("value", "GValue*"));
+			function.add_parameter (new CCodeFormalParameter ("v_object", "gpointer"));
+
+			if (cl.access == SymbolAccessibility.PRIVATE) {
+				function.modifiers = CCodeModifiers.STATIC;
+			}
+
+			decl_space.add_type_member_declaration (function);
+
+			function = new CCodeFunction (cl.get_get_value_function (), "gpointer");
+			function.add_parameter (new CCodeFormalParameter ("value", "const GValue*"));
+
+			if (cl.access == SymbolAccessibility.PRIVATE) {
+				function.modifiers = CCodeModifiers.STATIC;
+			}
+
+			decl_space.add_type_member_declaration (function);
+		}
+
+		if (is_gtypeinstance) {
+			decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%sClass".printf (cl.get_cname ()), new CCodeVariableDeclarator ("%sClass".printf (cl.get_cname ()))));
+
+			var type_fun = new ClassRegisterFunction (cl, context);
+			type_fun.init_from_type (in_plugin);
+			decl_space.add_type_member_declaration (type_fun.get_declaration ());
+		}
+	}
+
+	public override void generate_class_struct_declaration (Class cl, CCodeDeclarationSpace decl_space) {
+		if (decl_space.add_symbol_declaration (cl, "struct _" + cl.get_cname ())) {
+			return;
 		}
 
 		if (cl.base_class != null) {
+			// base class declaration
+			generate_class_struct_declaration (cl.base_class, decl_space);
+		}
+		foreach (DataType base_type in cl.get_base_types ()) {
+			var iface = base_type.data_type as Interface;
+			if (iface != null) {
+				generate_interface_declaration (iface, decl_space);
+			}
+		}
+
+		generate_class_declaration (cl, decl_space);
+
+		bool is_gtypeinstance = !cl.is_compact;
+		bool is_fundamental = is_gtypeinstance && cl.base_class == null;
+
+		var instance_struct = new CCodeStruct ("_%s".printf (cl.get_cname ()));
+		var type_struct = new CCodeStruct ("_%sClass".printf (cl.get_cname ()));
+
+		if (cl.base_class != null) {
 			instance_struct.add_field (cl.base_class.get_cname (), "parent_instance");
 		} else if (is_fundamental) {
 			instance_struct.add_field ("GTypeInstance", "parent_instance");
@@ -138,19 +190,7 @@ internal class Vala.GObjectModule : GTypeModule {
 		}
 
 		if (is_gtypeinstance) {
-			if (cl.access == SymbolAccessibility.PRIVATE
-			    || cl.source_reference.file.cycle == null) {
-				// no file dependency cycle for private symbols
-				decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (type_struct.name), new CCodeVariableDeclarator ("%sClass".printf (cl.get_cname ()))));
-			}
-			decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (instance_priv_struct.name), new CCodeVariableDeclarator ("%sPrivate".printf (cl.get_cname ()))));
-			if (cl.has_class_private_fields) {
-				decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (type_priv_struct.name), new CCodeVariableDeclarator ("%sClassPrivate".printf (cl.get_cname ()))));
-				var cdecl = new CCodeDeclaration ("GQuark");
-				cdecl.add_declarator (new CCodeVariableDeclarator ("_vala_%s_class_private_quark".printf (cl.get_lower_case_cname ()), new CCodeConstant ("0")));
-				cdecl.modifiers = CCodeModifiers.STATIC;
-				decl_space.add_type_declaration (cdecl);
-			}
+			decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %sPrivate".printf (instance_struct.name), new CCodeVariableDeclarator ("%sPrivate".printf (cl.get_cname ()))));
 
 			instance_struct.add_field ("%sPrivate *".printf (cl.get_cname ()), "priv");
 			if (is_fundamental) {
@@ -171,20 +211,246 @@ internal class Vala.GObjectModule : GTypeModule {
 
 		if (is_gtypeinstance) {
 			decl_space.add_type_definition (type_struct);
+		}
+
+		foreach (Method m in cl.get_methods ()) {
+			generate_virtual_method_declaration (m, decl_space, type_struct);
+		}
+
+		foreach (Property prop in cl.get_properties ()) {
+			if (!prop.is_abstract && !prop.is_virtual) {
+				continue;
+			}
+
+			var t = (ObjectTypeSymbol) prop.parent_symbol;
+
+			bool returns_real_struct = prop.property_type.is_real_struct_type ();
+
+			var this_type = new ObjectType (t);
+			var cselfparam = new CCodeFormalParameter ("self", this_type.get_cname ());
+			CCodeFormalParameter cvalueparam;
+			if (returns_real_struct) {
+				cvalueparam = new CCodeFormalParameter ("value", prop.property_type.get_cname () + "*");
+			} else {
+				cvalueparam = new CCodeFormalParameter ("value", prop.property_type.get_cname ());
+			}
+
+			if (prop.get_accessor != null) {
+				var vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (prop.name));
+				vdeclarator.add_parameter (cselfparam);
+				string creturn_type;
+				if (returns_real_struct) {
+					vdeclarator.add_parameter (cvalueparam);
+					creturn_type = "void";
+				} else {
+					creturn_type = prop.property_type.get_cname ();
+				}
+				var vdecl = new CCodeDeclaration (creturn_type);
+				vdecl.add_declarator (vdeclarator);
+				type_struct.add_declaration (vdecl);
+			}
+			if (prop.set_accessor != null) {
+				var vdeclarator = new CCodeFunctionDeclarator ("set_%s".printf (prop.name));
+				vdeclarator.add_parameter (cselfparam);
+				vdeclarator.add_parameter (cvalueparam);
+				var vdecl = new CCodeDeclaration ("void");
+				vdecl.add_declarator (vdeclarator);
+				type_struct.add_declaration (vdecl);
+			}
+		}
+
+		foreach (Field f in cl.get_fields ()) {
+			string field_ctype = f.field_type.get_cname ();
+			if (f.is_volatile) {
+				field_ctype = "volatile " + field_ctype;
+			}
+
+			if (f.binding == MemberBinding.INSTANCE && f.access != SymbolAccessibility.PRIVATE)  {
+				generate_type_declaration (f.field_type, decl_space);
+
+				instance_struct.add_field (field_ctype, f.get_cname ());
+				if (f.field_type is ArrayType && !f.no_array_length) {
+					// create fields to store array dimensions
+					var array_type = (ArrayType) f.field_type;
+					var len_type = int_type.copy ();
+
+					for (int dim = 1; dim <= array_type.rank; dim++) {
+						instance_struct.add_field (len_type.get_cname (), head.get_array_length_cname (f.name, dim));
+					}
+
+					if (array_type.rank == 1 && f.is_internal_symbol ()) {
+						instance_struct.add_field (len_type.get_cname (), head.get_array_size_cname (f.name));
+					}
+				} else if (f.field_type is DelegateType) {
+					var delegate_type = (DelegateType) f.field_type;
+					if (delegate_type.delegate_symbol.has_target) {
+						// create field to store delegate target
+						instance_struct.add_field ("gpointer", get_delegate_target_cname (f.name));
+					}
+				}
+			} else if (f.binding == MemberBinding.CLASS && f.access != SymbolAccessibility.PRIVATE)  {
+				type_struct.add_field (field_ctype, f.get_cname ());
+			}
+		}
+	}
+
+	public virtual void generate_virtual_method_declaration (Method m, CCodeDeclarationSpace decl_space, CCodeStruct type_struct) {
+		if (!m.is_abstract && !m.is_virtual) {
+			return;
+		}
+
+		// add vfunc field to the type struct
+		var vdeclarator = new CCodeFunctionDeclarator (m.vfunc_name);
+		var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
+
+		generate_cparameters (m, decl_space, cparam_map, new CCodeFunction ("fake"), vdeclarator);
+
+		var vdecl = new CCodeDeclaration (m.return_type.get_cname ());
+		vdecl.add_declarator (vdeclarator);
+		type_struct.add_declaration (vdecl);
+	}
+
+	void generate_class_private_declaration (Class cl, CCodeDeclarationSpace decl_space) {
+		if (decl_space.add_symbol_declaration (cl, cl.get_cname () + "Private")) {
+			return;
+		}
+
+		bool is_gtypeinstance = !cl.is_compact;
+
+		var instance_priv_struct = new CCodeStruct ("_%sPrivate".printf (cl.get_cname ()));
+		var type_priv_struct = new CCodeStruct ("_%sClassPrivate".printf (cl.get_cname ()));
+
+		if (is_gtypeinstance) {
+			/* create type, dup_func, and destroy_func fields for generic types */
+			foreach (TypeParameter type_param in cl.get_type_parameters ()) {
+				string func_name;
+
+				func_name = "%s_type".printf (type_param.name.down ());
+				instance_priv_struct.add_field ("GType", func_name);
+
+				func_name = "%s_dup_func".printf (type_param.name.down ());
+				instance_priv_struct.add_field ("GBoxedCopyFunc", func_name);
+
+				func_name = "%s_destroy_func".printf (type_param.name.down ());
+				instance_priv_struct.add_field ("GDestroyNotify", func_name);
+			}
+		}
+
+		foreach (Field f in cl.get_fields ()) {
+			string field_ctype = f.field_type.get_cname ();
+			if (f.is_volatile) {
+				field_ctype = "volatile " + field_ctype;
+			}
+
+			if (f.binding == MemberBinding.INSTANCE && f.access == SymbolAccessibility.PRIVATE)  {
+				generate_type_declaration (f.field_type, decl_space);
+
+				instance_priv_struct.add_field (field_ctype, f.get_cname ());
+				if (f.field_type is ArrayType && !f.no_array_length) {
+					// create fields to store array dimensions
+					var array_type = (ArrayType) f.field_type;
+					var len_type = int_type.copy ();
+
+					for (int dim = 1; dim <= array_type.rank; dim++) {
+						instance_priv_struct.add_field (len_type.get_cname (), head.get_array_length_cname (f.name, dim));
+					}
+
+					if (array_type.rank == 1 && f.is_internal_symbol ()) {
+						instance_priv_struct.add_field (len_type.get_cname (), head.get_array_size_cname (f.name));
+					}
+				} else if (f.field_type is DelegateType) {
+					var delegate_type = (DelegateType) f.field_type;
+					if (delegate_type.delegate_symbol.has_target) {
+						// create field to store delegate target
+						instance_priv_struct.add_field ("gpointer", get_delegate_target_cname (f.name));
+					}
+				}
+
+				if (f.get_lock_used ()) {
+					// add field for mutex
+					instance_priv_struct.add_field (mutex_type.get_cname (), get_symbol_lock_name (f));
+				}
+			} else if (f.binding == MemberBinding.CLASS && f.access == SymbolAccessibility.PRIVATE)  {
+				type_priv_struct.add_field (field_ctype, f.get_cname ());
+			}
+		}
+
+		if (is_gtypeinstance) {
+			if (cl.has_class_private_fields) {
+				decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (type_priv_struct.name), new CCodeVariableDeclarator ("%sClassPrivate".printf (cl.get_cname ()))));
+				var cdecl = new CCodeDeclaration ("GQuark");
+				cdecl.add_declarator (new CCodeVariableDeclarator ("_vala_%s_class_private_quark".printf (cl.get_lower_case_cname ()), new CCodeConstant ("0")));
+				cdecl.modifiers = CCodeModifiers.STATIC;
+				decl_space.add_type_declaration (cdecl);
+			}
+
 			/* only add the *Private struct if it is not empty, i.e. we actually have private data */
 			if (cl.has_private_fields || cl.get_type_parameters ().size > 0) {
-				source_declarations.add_type_member_declaration (instance_priv_struct);
+				decl_space.add_type_definition (instance_priv_struct);
 				var macro = "(G_TYPE_INSTANCE_GET_PRIVATE ((o), %s, %sPrivate))".printf (cl.get_type_id (), cl.get_cname ());
-				source_declarations.add_type_member_declaration (new CCodeMacroReplacement ("%s_GET_PRIVATE(o)".printf (cl.get_upper_case_cname (null)), macro));
+				decl_space.add_type_member_declaration (new CCodeMacroReplacement ("%s_GET_PRIVATE(o)".printf (cl.get_upper_case_cname (null)), macro));
 			}
 
 			if (cl.has_class_private_fields) {
-				source_declarations.add_type_member_declaration (type_priv_struct);
-				
+				decl_space.add_type_member_declaration (type_priv_struct);
+
 				var macro = "((%sClassPrivate *) g_type_get_qdata (type, _vala_%s_class_private_quark))".printf (cl.get_cname(), cl.get_lower_case_cname ());
-				source_declarations.add_type_member_declaration (new CCodeMacroReplacement ("%s_GET_CLASS_PRIVATE(type)".printf (cl.get_upper_case_cname (null)), macro));
+				decl_space.add_type_member_declaration (new CCodeMacroReplacement ("%s_GET_CLASS_PRIVATE(type)".printf (cl.get_upper_case_cname (null)), macro));
+			}
+			decl_space.add_type_member_declaration (prop_enum);
+		} else {
+			var function = new CCodeFunction (cl.get_lower_case_cprefix () + "free", "void");
+			if (cl.access == SymbolAccessibility.PRIVATE) {
+				function.modifiers = CCodeModifiers.STATIC;
 			}
-			source_declarations.add_type_member_declaration (prop_enum);
+
+			function.add_parameter (new CCodeFormalParameter ("self", cl.get_cname () + "*"));
+
+			decl_space.add_type_member_declaration (function);
+		}
+	}
+
+	public override void visit_class (Class cl) {
+		var old_symbol = current_symbol;
+		var old_type_symbol = current_type_symbol;
+		var old_class = current_class;
+		var old_param_spec_struct = param_spec_struct;
+		var old_prop_enum = prop_enum;
+		var old_class_init_fragment = class_init_fragment;
+		var old_base_init_fragment = base_init_fragment;
+		var old_class_finalize_fragment = class_finalize_fragment;
+		var old_base_finalize_fragment = base_finalize_fragment;
+		var old_instance_init_fragment = instance_init_fragment;
+		var old_instance_finalize_fragment = instance_finalize_fragment;
+		current_symbol = cl;
+		current_type_symbol = cl;
+		current_class = cl;
+
+		bool is_gtypeinstance = !cl.is_compact;
+		bool is_gobject = cl.is_subtype_of (gobject_type);
+		bool is_fundamental = is_gtypeinstance && cl.base_class == null;
+
+		if (cl.get_cname().len () < 3) {
+			cl.error = true;
+			Report.error (cl.source_reference, "Class name `%s' is too short".printf (cl.get_cname ()));
+			return;
+		}
+
+		prop_enum = new CCodeEnum ();
+		prop_enum.add_value (new CCodeEnumValue ("%s_DUMMY_PROPERTY".printf (cl.get_upper_case_cname (null))));
+		class_init_fragment = new CCodeFragment ();
+		base_init_fragment = new CCodeFragment ();
+		class_finalize_fragment = new CCodeFragment ();
+		base_finalize_fragment = new CCodeFragment ();
+		instance_init_fragment = new CCodeFragment ();
+		instance_finalize_fragment = new CCodeFragment ();
+
+
+		generate_class_struct_declaration (cl, source_declarations);
+		generate_class_private_declaration (cl, source_declarations);
+
+		if (!cl.is_internal_symbol ()) {
+			generate_class_struct_declaration (cl, header_declarations);
 		}
 
 		cl.accept_children (codegen);
@@ -193,9 +459,9 @@ internal class Vala.GObjectModule : GTypeModule {
 			if (is_fundamental) {
 				param_spec_struct = new CCodeStruct ( "_%sParamSpec%s".printf(cl.parent_symbol.get_cprefix (), cl.name));
 				param_spec_struct.add_field ("GParamSpec", "parent_instance");
-				decl_space.add_type_definition (param_spec_struct);
+				source_declarations.add_type_definition (param_spec_struct);
 
-				decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (param_spec_struct.name), new CCodeVariableDeclarator ( "%sParamSpec%s".printf(cl.parent_symbol.get_cprefix (), cl.name))));
+				source_declarations.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (param_spec_struct.name), new CCodeVariableDeclarator ( "%sParamSpec%s".printf(cl.parent_symbol.get_cprefix (), cl.name))));
 
 
 				gvaluecollector_h_needed = true;
@@ -249,11 +515,6 @@ internal class Vala.GObjectModule : GTypeModule {
 
 			var type_fun = new ClassRegisterFunction (cl, context);
 			type_fun.init_from_type (in_plugin);
-			if (cl.access != SymbolAccessibility.PRIVATE) {
-				header_declarations.add_type_member_declaration (type_fun.get_declaration ());
-			} else {
-				source_declarations.add_type_member_declaration (type_fun.get_declaration ());
-			}
 			source_type_member_definition.append (type_fun.get_definition ());
 			
 			if (in_plugin) {
@@ -274,14 +535,6 @@ internal class Vala.GObjectModule : GTypeModule {
 				ref_fun.add_parameter (new CCodeFormalParameter ("instance", "gpointer"));
 				unref_fun.add_parameter (new CCodeFormalParameter ("instance", "gpointer"));
 
-				if (cl.access != SymbolAccessibility.PRIVATE) {
-					header_declarations.add_type_member_declaration (ref_fun.copy ());
-					header_declarations.add_type_member_declaration (unref_fun.copy ());
-				} else {
-					source_declarations.add_type_member_declaration (ref_fun.copy ());
-					source_declarations.add_type_member_declaration (unref_fun.copy ());
-				}
-
 				var ref_block = new CCodeBlock ();
 				var unref_block = new CCodeBlock ();
 
@@ -334,12 +587,6 @@ internal class Vala.GObjectModule : GTypeModule {
 
 			function.add_parameter (new CCodeFormalParameter ("self", cl.get_cname () + "*"));
 
-			if (cl.access != SymbolAccessibility.PRIVATE) {
-				header_declarations.add_type_member_declaration (function.copy ());
-			} else {
-				source_declarations.add_type_member_declaration (function.copy ());
-			}
-
 			var cblock = new CCodeBlock ();
 
 			cblock.add_statement (instance_finalize_fragment);
@@ -361,11 +608,7 @@ internal class Vala.GObjectModule : GTypeModule {
 		current_symbol = old_symbol;
 		current_type_symbol = old_type_symbol;
 		current_class = old_class;
-		instance_struct = old_instance_struct;
 		param_spec_struct = old_param_spec_struct;
-		type_struct = old_type_struct;
-		instance_priv_struct = old_instance_priv_struct;
-		type_priv_struct = old_type_priv_struct;
 		prop_enum = old_prop_enum;
 		class_init_fragment = old_class_init_fragment;
 		base_init_fragment = old_base_init_fragment;
@@ -594,9 +837,6 @@ internal class Vala.GObjectModule : GTypeModule {
 
 		if (cl.access == SymbolAccessibility.PRIVATE) {
 			function.modifiers = CCodeModifiers.STATIC;
-			source_declarations.add_type_member_declaration (function.copy ());
-		} else {
-			header_declarations.add_type_member_declaration (function.copy ());
 		}
 
 		var init_block = new CCodeBlock ();
@@ -639,9 +879,6 @@ internal class Vala.GObjectModule : GTypeModule {
 
 		if (cl.access == SymbolAccessibility.PRIVATE) {
 			function.modifiers = CCodeModifiers.STATIC;
-			source_declarations.add_type_member_declaration (function.copy ());
-		} else {
-			header_declarations.add_type_member_declaration (function.copy ());
 		}
 
 		var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
@@ -715,9 +952,6 @@ internal class Vala.GObjectModule : GTypeModule {
 
 		if (cl.access == SymbolAccessibility.PRIVATE) {
 			function.modifiers = CCodeModifiers.STATIC;
-			source_declarations.add_type_member_declaration (function.copy ());
-		} else {
-			header_declarations.add_type_member_declaration (function.copy ());
 		}
 
 		var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
@@ -967,8 +1201,6 @@ internal class Vala.GObjectModule : GTypeModule {
 				init_block.add_statement (new CCodeExpressionStatement (cinst));
 				prop_enum.add_value (new CCodeEnumValue (enum_value));
 
-				instance_priv_struct.add_field ("GType", func_name);
-
 
 				func_name = "%s_dup_func".printf (type_param.name.down ());
 				func_name_constant = new CCodeConstant ("\"%s-dup-func\"".printf (type_param.name.down ()));
@@ -985,8 +1217,6 @@ internal class Vala.GObjectModule : GTypeModule {
 				init_block.add_statement (new CCodeExpressionStatement (cinst));
 				prop_enum.add_value (new CCodeEnumValue (enum_value));
 
-				instance_priv_struct.add_field ("GBoxedCopyFunc", func_name);
-
 
 				func_name = "%s_destroy_func".printf (type_param.name.down ());
 				func_name_constant = new CCodeConstant ("\"%s-destroy-func\"".printf (type_param.name.down ()));
@@ -1002,8 +1232,6 @@ internal class Vala.GObjectModule : GTypeModule {
 				cinst.add_argument (cspec);
 				init_block.add_statement (new CCodeExpressionStatement (cinst));
 				prop_enum.add_value (new CCodeEnumValue (enum_value));
-
-				instance_priv_struct.add_field ("GDestroyNotify", func_name);
 			}
 
 			/* create properties */
@@ -1035,20 +1263,6 @@ internal class Vala.GObjectModule : GTypeModule {
 					init_block.add_statement (new CCodeExpressionStatement (cinst));
 				}
 			}
-		} else if (!cl.is_compact) {
-			/* create type, dup_func, and destroy_func fields for generic types */
-			foreach (TypeParameter type_param in cl.get_type_parameters ()) {
-				string func_name;
-
-				func_name = "%s_type".printf (type_param.name.down ());
-				instance_priv_struct.add_field ("GType", func_name);
-
-				func_name = "%s_dup_func".printf (type_param.name.down ());
-				instance_priv_struct.add_field ("GBoxedCopyFunc", func_name);
-
-				func_name = "%s_destroy_func".printf (type_param.name.down ());
-				instance_priv_struct.add_field ("GDestroyNotify", func_name);
-			}
 		}
 
 		if (!cl.is_compact) {
diff --git a/gobject/valagtypemodule.vala b/gobject/valagtypemodule.vala
index 42afdbb..4e13ccc 100644
--- a/gobject/valagtypemodule.vala
+++ b/gobject/valagtypemodule.vala
@@ -1,6 +1,7 @@
 /* valagtypemodule.vala
  *
- * Copyright (C) 2006-2008  Jürg Billeter, Raffaele Sandrini
+ * Copyright (C) 2006-2009  Jürg Billeter
+ * Copyright (C) 2006-2008  Raffaele Sandrini
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -21,31 +22,29 @@
  *	Raffaele Sandrini <raffaele sandrini ch>
  */
 
-using GLib;
+using Gee;
 
 internal class Vala.GTypeModule : GErrorModule {
 	public GTypeModule (CCodeGenerator codegen, CCodeModule? next) {
 		base (codegen, next);
 	}
 
-	public override void visit_interface (Interface iface) {
-		current_symbol = iface;
-		current_type_symbol = iface;
-
-		if (iface.get_cname().len () < 3) {
-			iface.error = true;
-			Report.error (iface.source_reference, "Interface name `%s' is too short".printf (iface.get_cname ()));
+	public override void generate_interface_declaration (Interface iface, CCodeDeclarationSpace decl_space) {
+		if (decl_space.add_symbol_declaration (iface, iface.get_cname ())) {
 			return;
 		}
 
-		CCodeDeclarationSpace decl_space;
-		if (iface.access != SymbolAccessibility.PRIVATE) {
-			decl_space = header_declarations;
-		} else {
-			decl_space = source_declarations;
+		foreach (DataType prerequisite in iface.get_prerequisites ()) {
+			var prereq_cl = prerequisite.data_type as Class;
+			var prereq_iface = prerequisite.data_type as Interface;
+			if (prereq_cl != null) {
+				generate_class_declaration (prereq_cl, decl_space);
+			} else if (prereq_iface != null) {
+				generate_interface_declaration (prereq_iface, decl_space);
+			}
 		}
 
-		type_struct = new CCodeStruct ("_%s".printf (iface.get_type_cname ()));
+		var type_struct = new CCodeStruct ("_%s".printf (iface.get_type_cname ()));
 		
 		decl_space.add_type_declaration (new CCodeNewline ());
 		var macro = "(%s_get_type ())".printf (iface.get_lower_case_cname (null));
@@ -61,12 +60,9 @@ internal class Vala.GTypeModule : GErrorModule {
 		decl_space.add_type_declaration (new CCodeMacroReplacement ("%s_GET_INTERFACE(obj)".printf (iface.get_upper_case_cname (null)), macro));
 		decl_space.add_type_declaration (new CCodeNewline ());
 
+		decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (iface.get_cname ()), new CCodeVariableDeclarator (iface.get_cname ())));
+		decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (type_struct.name), new CCodeVariableDeclarator (iface.get_type_cname ())));
 
-		if (iface.source_reference.file.cycle == null) {
-			decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (iface.get_cname ()), new CCodeVariableDeclarator (iface.get_cname ())));
-			decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (type_struct.name), new CCodeVariableDeclarator (iface.get_type_cname ())));
-		}
-		
 		type_struct.add_field ("GTypeInterface", "parent_iface");
 
 		if (iface.source_reference.comment != null) {
@@ -74,17 +70,87 @@ internal class Vala.GTypeModule : GErrorModule {
 		}
 		decl_space.add_type_definition (type_struct);
 
+		foreach (Method m in iface.get_methods ()) {
+			if ((!m.is_abstract && !m.is_virtual) || m.coroutine) {
+				continue;
+			}
+
+			// add vfunc field to the type struct
+			var vdeclarator = new CCodeFunctionDeclarator (m.vfunc_name);
+			var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
+
+			generate_cparameters (m, decl_space, cparam_map, new CCodeFunction ("fake"), vdeclarator);
+
+			var vdecl = new CCodeDeclaration (m.return_type.get_cname ());
+			vdecl.add_declarator (vdeclarator);
+			type_struct.add_declaration (vdecl);
+		}
+
+		foreach (Property prop in iface.get_properties ()) {
+			if (!prop.is_abstract && !prop.is_virtual) {
+				continue;
+			}
+
+			var t = (ObjectTypeSymbol) prop.parent_symbol;
+
+			bool returns_real_struct = prop.property_type.is_real_struct_type ();
+
+			var this_type = new ObjectType (t);
+			var cselfparam = new CCodeFormalParameter ("self", this_type.get_cname ());
+			CCodeFormalParameter cvalueparam;
+			if (returns_real_struct) {
+				cvalueparam = new CCodeFormalParameter ("value", prop.property_type.get_cname () + "*");
+			} else {
+				cvalueparam = new CCodeFormalParameter ("value", prop.property_type.get_cname ());
+			}
+
+			if (prop.get_accessor != null) {
+				var vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (prop.name));
+				vdeclarator.add_parameter (cselfparam);
+				string creturn_type;
+				if (returns_real_struct) {
+					vdeclarator.add_parameter (cvalueparam);
+					creturn_type = "void";
+				} else {
+					creturn_type = prop.property_type.get_cname ();
+				}
+				var vdecl = new CCodeDeclaration (creturn_type);
+				vdecl.add_declarator (vdeclarator);
+				type_struct.add_declaration (vdecl);
+			}
+			if (prop.set_accessor != null) {
+				var vdeclarator = new CCodeFunctionDeclarator ("set_%s".printf (prop.name));
+				vdeclarator.add_parameter (cselfparam);
+				vdeclarator.add_parameter (cvalueparam);
+				var vdecl = new CCodeDeclaration ("void");
+				vdecl.add_declarator (vdeclarator);
+				type_struct.add_declaration (vdecl);
+			}
+		}
+
+		var type_fun = new InterfaceRegisterFunction (iface, context);
+		type_fun.init_from_type ();
+		decl_space.add_type_member_declaration (type_fun.get_declaration ());
+	}
+
+	public override void visit_interface (Interface iface) {
+		current_symbol = iface;
+		current_type_symbol = iface;
+
+		if (iface.get_cname().len () < 3) {
+			iface.error = true;
+			Report.error (iface.source_reference, "Interface name `%s' is too short".printf (iface.get_cname ()));
+			return;
+		}
+
+		generate_interface_declaration (iface, source_declarations);
+
 		iface.accept_children (codegen);
 
 		add_interface_base_init_function (iface);
 
 		var type_fun = new InterfaceRegisterFunction (iface, context);
 		type_fun.init_from_type ();
-		if (iface.access != SymbolAccessibility.PRIVATE) {
-			header_declarations.add_type_member_declaration (type_fun.get_declaration ());
-		} else {
-			source_declarations.add_type_member_declaration (type_fun.get_declaration ());
-		}
 		source_type_member_definition.append (type_fun.get_definition ());
 
 		current_type_symbol = null;
@@ -143,24 +209,13 @@ internal class Vala.GTypeModule : GErrorModule {
 	public override void visit_struct (Struct st) {
 		base.visit_struct (st);
 
-		CCodeDeclarationSpace decl_space;
-		if (st.access != SymbolAccessibility.PRIVATE) {
-			decl_space = header_declarations;
-		} else {
-			decl_space = source_declarations;
-		}
-
-		decl_space.add_type_declaration (new CCodeNewline ());
+		source_declarations.add_type_declaration (new CCodeNewline ());
 		var macro = "(%s_get_type ())".printf (st.get_lower_case_cname (null));
-		decl_space.add_type_declaration (new CCodeMacroReplacement (st.get_type_id (), macro));
+		source_declarations.add_type_declaration (new CCodeMacroReplacement (st.get_type_id (), macro));
 
 		var type_fun = new StructRegisterFunction (st, context);
 		type_fun.init_from_type (false);
-		if (st.access != SymbolAccessibility.PRIVATE) {
-			header_declarations.add_type_member_declaration (type_fun.get_declaration ());
-		} else {
-			source_declarations.add_type_member_declaration (type_fun.get_declaration ());
-		}
+		source_declarations.add_type_member_declaration (type_fun.get_declaration ());
 		source_type_member_definition.append (type_fun.get_definition ());
 	}
 }
diff --git a/vala/Makefile.am b/vala/Makefile.am
index 93e6f51..dac7d44 100644
--- a/vala/Makefile.am
+++ b/vala/Makefile.am
@@ -120,7 +120,6 @@ libvalacore_la_VALASOURCES = \
 	valasignaltype.vala \
 	valasizeofexpression.vala \
 	valasourcefile.vala \
-	valasourcefilecycle.vala \
 	valasourcelocation.vala \
 	valasourcereference.vala \
 	valastatement.vala \
diff --git a/vala/valacastexpression.vala b/vala/valacastexpression.vala
index 4f94832..f75c9ff 100644
--- a/vala/valacastexpression.vala
+++ b/vala/valacastexpression.vala
@@ -1,6 +1,6 @@
 /* valacastexpression.vala
  *
- * Copyright (C) 2006-2008  Jürg Billeter
+ * Copyright (C) 2006-2009  Jürg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -114,8 +114,6 @@ public class Vala.CastExpression : Expression {
 
 		// FIXME: check whether cast is allowed
 
-		analyzer.current_source_file.add_type_dependency (type_reference, SourceFileDependencyType.SOURCE);
-
 		value_type = type_reference;
 		value_type.value_owned = inner.value_type.value_owned;
 
diff --git a/vala/valacatchclause.vala b/vala/valacatchclause.vala
index 039ea6b..8d3d412 100644
--- a/vala/valacatchclause.vala
+++ b/vala/valacatchclause.vala
@@ -1,6 +1,6 @@
-/* valacatchvala
+/* valacatchclause.vala
  *
- * Copyright (C) 2007-2008  Jürg Billeter
+ * Copyright (C) 2007-2009  Jürg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -115,8 +115,6 @@ public class Vala.CatchClause : CodeNode {
 
 		error_type.check (analyzer);
 
-		analyzer.current_source_file.add_type_dependency (error_type, SourceFileDependencyType.SOURCE);
-
 		body.check (analyzer);
 
 		return !error;
diff --git a/vala/valaclass.vala b/vala/valaclass.vala
index a32abfc..2511d1a 100644
--- a/vala/valaclass.vala
+++ b/vala/valaclass.vala
@@ -916,8 +916,6 @@ public class Vala.Class : ObjectTypeSymbol {
 				Report.error (source_reference, "base type `%s` is less accessible than class `%s`".printf (base_type_reference.to_string (), get_full_name ()));
 				return false;
 			}
-
-			analyzer.current_source_file.add_type_dependency (base_type_reference, SourceFileDependencyType.HEADER_FULL);
 		}
 
 		foreach (DataType type in base_types) {
diff --git a/vala/valacodecontext.vala b/vala/valacodecontext.vala
index 1841528..e040630 100644
--- a/vala/valacodecontext.vala
+++ b/vala/valacodecontext.vala
@@ -163,8 +163,6 @@ public class Vala.CodeContext {
 	private Gee.List<SourceFile> source_files = new ArrayList<SourceFile> ();
 	private Gee.List<string> c_source_files = new ArrayList<string> ();
 	private Namespace _root = new Namespace (null);
-	
-	private Gee.List<SourceFileCycle> cycles = new ArrayList<SourceFileCycle> ();
 
 	private Gee.List<string> packages = new ArrayList<string> (str_equal);
 
@@ -294,143 +292,6 @@ public class Vala.CodeContext {
 			file.accept (visitor);
 		}
 	}
-	
-	/**
-	 * Find and resolve cycles in source file dependencies.
-	 */
-	public void find_header_cycles () {
-		/* find cycles in dependencies between source files */
-		foreach (SourceFile file in source_files) {
-			/* we're only interested in internal source files */
-			if (file.external_package) {
-				continue;
-			}
-			
-			if (file.mark == 0) {
-				visit (file, new ArrayList<SourceFile> ());
-			}
-		}
-		
-		/* find one head for each cycle, it must not have any
-		 * hard dependencies on other files in the cycle
-		 */
-		foreach (SourceFileCycle cycle in cycles) {
-			cycle.head = find_cycle_head (cycle.files.get (0));
-			cycle.head.is_cycle_head = true;
-		}
-
-		/* connect the source files in a non-cyclic way
-		 * cycle members connect to the head of their cycle
-		 */
-		foreach (SourceFile file2 in source_files) {
-			/* we're only interested in internal source files */
-			if (file2.external_package) {
-				continue;
-			}
-
-			foreach (SourceFile dep in file2.get_header_internal_dependencies ()) {
-				if (file2.cycle != null && dep.cycle == file2.cycle) {
-					/* in the same cycle */
-					if (!file2.is_cycle_head) {
-						/* include header of cycle head */
-						file2.add_header_internal_include (file2.cycle.head.get_cinclude_filename ());
-					}
-				} else {
-					/* we can just include the headers if they are not in a cycle or not in the same cycle as the current file */
-					file2.add_header_internal_include (dep.get_cinclude_filename ());
-				}
-			}
-		}
-		
-	}
-	
-	private weak SourceFile find_cycle_head (SourceFile file) {
-		foreach (SourceFile dep in file.get_header_internal_full_dependencies ()) {
-			if (dep == file) {
-				/* ignore file-internal dependencies */
-				continue;
-			}
-			
-			foreach (SourceFile cycle_file in file.cycle.files) {
-				if (dep == cycle_file) {
-					return find_cycle_head (dep);
-				}
-			}
-		}
-		/* no hard dependencies on members of the same cycle found
-		 * source file suitable as cycle head
-		 */
-		return file;
-	}
-	
-	private void visit (SourceFile file, Gee.List<SourceFile> chain) {
-		Gee.List<SourceFile> l = new ArrayList<SourceFile> ();
-		foreach (SourceFile chain_file in chain) {
-			l.add (chain_file);
-		}
-		l.add (file);
-
-		/* mark file as currently being visited */
-		file.mark = 1;
-		
-		foreach (SourceFile dep in file.get_header_internal_dependencies ()) {
-			if (file == dep) {
-				continue;
-			}
-			
-			if (dep.mark == 1) {
-				/* found cycle */
-				
-				var cycle = new SourceFileCycle ();
-				cycles.add (cycle);
-				
-				bool cycle_start_found = false;
-				foreach (SourceFile cycle_file in l) {
-					SourceFileCycle ref_cycle_file_cycle = cycle_file.cycle;
-					if (!cycle_start_found) {
-						if (cycle_file == dep) {
-							cycle_start_found = true;
-						}
-					}
-					
-					if (!cycle_start_found) {
-						continue;
-					}
-					
-					if (ref_cycle_file_cycle != null) {
-						/* file already in a cycle */
-						
-						if (cycle_file.cycle == cycle) {
-							/* file is in the same cycle, nothing to do */
-							continue;
-						}
-						
-						/* file is in an other cycle, merge the two cycles */
-						
-						cycles.remove (cycle_file.cycle);
-						
-						foreach (SourceFile inner_cycle_file in cycle_file.cycle.files) {
-							if (inner_cycle_file.cycle != cycle) {
-								/* file in inner cycle not yet added to outer cycle */
-								cycle.files.add (inner_cycle_file);
-								inner_cycle_file.cycle = cycle;
-							}
-						}
-					} else {
-						cycle.files.add (cycle_file);
-						cycle_file.cycle = cycle;
-					}
-				}
-			} else if (dep.mark == 0) {
-				/* found not yet visited file */
-				
-				visit (dep, l);
-			}
-		}
-		
-		/* mark file as successfully visited */
-		file.mark = 2;
-	}
 
 	public string? get_package_path (string pkg, string[] vapi_directories) {
 		string basename = "%s.vapi".printf (pkg);
diff --git a/vala/valaenumvalue.vala b/vala/valaenumvalue.vala
index e77d7af..8fbcc57 100644
--- a/vala/valaenumvalue.vala
+++ b/vala/valaenumvalue.vala
@@ -140,12 +140,6 @@ public class Vala.EnumValue : Symbol {
 
 		if (value != null) {
 			value.check (analyzer);
-
-			// ensure to include dependency in header file as well if necessary
-			if (!parent_symbol.is_internal_symbol ()
-			    &&value is MemberAccess && value.symbol_reference != null) {
-				analyzer.current_source_file.add_symbol_dependency (value.symbol_reference, SourceFileDependencyType.HEADER_SHALLOW);
-			}
 		}
 
 		return !error;
diff --git a/vala/valafield.vala b/vala/valafield.vala
index 24ac796..f43e83b 100644
--- a/vala/valafield.vala
+++ b/vala/valafield.vala
@@ -325,16 +325,6 @@ public class Vala.Field : Member, Lockable {
 			Report.warning (source_reference, "%s hides inherited field `%s'. Use the `new' keyword if hiding was intentional".printf (get_full_name (), get_hidden_member ().get_full_name ()));
 		}
 
-		if (field_in_header) {
-			if (field_type is ValueType) {
-				analyzer.current_source_file.add_type_dependency (field_type, SourceFileDependencyType.HEADER_FULL);
-			} else {
-				analyzer.current_source_file.add_type_dependency (field_type, SourceFileDependencyType.HEADER_SHALLOW);
-			}
-		} else {
-			analyzer.current_source_file.add_type_dependency (field_type, SourceFileDependencyType.SOURCE);
-		}
-
 		analyzer.current_source_file = old_source_file;
 		analyzer.current_symbol = old_symbol;
 
diff --git a/vala/valaflowanalyzer.vala b/vala/valaflowanalyzer.vala
index 621ce4b..dde5446 100644
--- a/vala/valaflowanalyzer.vala
+++ b/vala/valaflowanalyzer.vala
@@ -123,15 +123,15 @@ public class Vala.FlowAnalyzer : CodeVisitor {
 	}
 
 	public override void visit_field (Field f) {
-		if (f.is_library_internal_symbol () && !f.used) {
+		if (f.is_internal_symbol () && !f.used) {
 			Report.warning (f.source_reference, "field `%s' never used".printf (f.get_full_name ()));
 		}
 	}
 
 	public override void visit_method (Method m) {
-		if (m.is_library_internal_symbol () && !m.used && !m.entry_point
-			 && !m.overrides && (m.base_interface_method == null || m.base_interface_method == m)
-			 && !(m is CreationMethod)) {
+		if (m.is_internal_symbol () && !m.used && !m.entry_point
+		    && !m.overrides && (m.base_interface_method == null || m.base_interface_method == m)
+		    && !(m is CreationMethod)) {
 			Report.warning (m.source_reference, "method `%s' never used".printf (m.get_full_name ()));
 		}
 
diff --git a/vala/valaforeachstatement.vala b/vala/valaforeachstatement.vala
index f69f38f..91bbd85 100644
--- a/vala/valaforeachstatement.vala
+++ b/vala/valaforeachstatement.vala
@@ -1,6 +1,6 @@
 /* valaforeachstatement.vala
  *
- * Copyright (C) 2006-2008  Jürg Billeter
+ * Copyright (C) 2006-2009  Jürg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -278,8 +278,6 @@ public class Vala.ForeachStatement : Block {
 			return false;
 		}
 
-		analyzer.current_source_file.add_type_dependency (type_reference, SourceFileDependencyType.SOURCE);
-
 		element_variable = new LocalVariable (type_reference, variable_name);
 
 		body.scope.add (variable_name, element_variable);
diff --git a/vala/valaformalparameter.vala b/vala/valaformalparameter.vala
index e24592a..021ecbe 100644
--- a/vala/valaformalparameter.vala
+++ b/vala/valaformalparameter.vala
@@ -234,15 +234,6 @@ public class Vala.FormalParameter : Symbol {
 		}
 
 		if (!ellipsis) {
-			if (!is_internal_symbol ()) {
-				if (parameter_type is ValueType && !parameter_type.is_real_struct_type ()) {
-					analyzer.current_source_file.add_type_dependency (parameter_type, SourceFileDependencyType.HEADER_FULL);
-				} else {
-					analyzer.current_source_file.add_type_dependency (parameter_type, SourceFileDependencyType.HEADER_SHALLOW);
-				}
-			}
-			analyzer.current_source_file.add_type_dependency (parameter_type, SourceFileDependencyType.SOURCE);
-
 			// check whether parameter type is at least as accessible as the method
 			if (!analyzer.is_type_accessible (this, parameter_type)) {
 				error = true;
diff --git a/vala/valainterface.vala b/vala/valainterface.vala
index 66e3068..c048c9e 100644
--- a/vala/valainterface.vala
+++ b/vala/valainterface.vala
@@ -546,8 +546,6 @@ public class Vala.Interface : ObjectTypeSymbol {
 				Report.error (source_reference, "prerequisite `%s` is less accessible than interface `%s`".printf (prerequisite_reference.to_string (), get_full_name ()));
 				return false;
 			}
-
-			analyzer.current_source_file.add_type_dependency (prerequisite_reference, SourceFileDependencyType.HEADER_FULL);
 		}
 
 		/* check prerequisites */
diff --git a/vala/valalocalvariable.vala b/vala/valalocalvariable.vala
index cdc9b3a..9fce2c2 100644
--- a/vala/valalocalvariable.vala
+++ b/vala/valalocalvariable.vala
@@ -198,8 +198,6 @@ public class Vala.LocalVariable : Symbol {
 			}
 		}
 
-		analyzer.current_source_file.add_type_dependency (variable_type, SourceFileDependencyType.SOURCE);
-
 		analyzer.current_symbol.scope.add (name, this);
 
 		// current_symbol is a Method if this is the `result'
diff --git a/vala/valamemberaccess.vala b/vala/valamemberaccess.vala
index 1ddb39d..4f99208 100644
--- a/vala/valamemberaccess.vala
+++ b/vala/valamemberaccess.vala
@@ -565,8 +565,6 @@ public class Vala.MemberAccess : Expression {
 			}
 		}
 
-		analyzer.current_source_file.add_symbol_dependency (symbol_reference, SourceFileDependencyType.SOURCE);
-
 		return !error;
 	}
 
diff --git a/vala/valamethod.vala b/vala/valamethod.vala
index fc8ad15..19e6c08 100644
--- a/vala/valamethod.vala
+++ b/vala/valamethod.vala
@@ -688,15 +688,6 @@ public class Vala.Method : Member {
 			source_reference.file.context.module_init_method = this;
 		}
 
-		if (!is_internal_symbol ()) {
-			if (return_type is ValueType) {
-				analyzer.current_source_file.add_type_dependency (return_type, SourceFileDependencyType.HEADER_FULL);
-			} else {
-				analyzer.current_source_file.add_type_dependency (return_type, SourceFileDependencyType.HEADER_SHALLOW);
-			}
-		}
-		analyzer.current_source_file.add_type_dependency (return_type, SourceFileDependencyType.SOURCE);
-
 		if (return_type != null) {
 			return_type.check (analyzer);
 		}
diff --git a/vala/valaobjectcreationexpression.vala b/vala/valaobjectcreationexpression.vala
index 9d1126d..20b829b 100644
--- a/vala/valaobjectcreationexpression.vala
+++ b/vala/valaobjectcreationexpression.vala
@@ -216,15 +216,11 @@ public class Vala.ObjectCreationExpression : Expression {
 
 			foreach (DataType type_arg in type_args) {
 				type_reference.add_type_argument (type_arg);
-
-				analyzer.current_source_file.add_type_dependency (type_arg, SourceFileDependencyType.SOURCE);
 			}
 		} else {
 			type = type_reference.data_type;
 		}
 
-		analyzer.current_source_file.add_symbol_dependency (type, SourceFileDependencyType.SOURCE);
-
 		value_type = type_reference.copy ();
 		value_type.value_owned = true;
 
diff --git a/vala/valaproperty.vala b/vala/valaproperty.vala
index b138c54..241fd36 100644
--- a/vala/valaproperty.vala
+++ b/vala/valaproperty.vala
@@ -435,15 +435,6 @@ public class Vala.Property : Member, Lockable {
 			Report.error (source_reference, "property type `%s` is less accessible than property `%s`".printf (property_type.to_string (), get_full_name ()));
 		}
 
-		if (!is_internal_symbol ()) {
-			if (property_type is ValueType && !property_type.is_real_struct_type ()) {
-				analyzer.current_source_file.add_type_dependency (property_type, SourceFileDependencyType.HEADER_FULL);
-			} else {
-				analyzer.current_source_file.add_type_dependency (property_type, SourceFileDependencyType.HEADER_SHALLOW);
-			}
-		}
-		analyzer.current_source_file.add_type_dependency (property_type, SourceFileDependencyType.SOURCE);
-
 		if (overrides && base_property == null) {
 			Report.error (source_reference, "%s: no suitable property found to override".printf (get_full_name ()));
 		}
diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala
index 7f45cc1..fcfdd30 100644
--- a/vala/valasemanticanalyzer.vala
+++ b/vala/valasemanticanalyzer.vala
@@ -287,9 +287,6 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
 				break;
 			}
 
-			/* header file necessary if we need to cast argument */
-			current_source_file.add_type_dependency (param.parameter_type, SourceFileDependencyType.SOURCE);
-
 			if (param.params_array) {
 				while (arg_it.next ()) {
 					var arg = arg_it.get ();
diff --git a/vala/valasizeofexpression.vala b/vala/valasizeofexpression.vala
index 041ba4a..57866e3 100644
--- a/vala/valasizeofexpression.vala
+++ b/vala/valasizeofexpression.vala
@@ -1,6 +1,6 @@
 /* valasizeofexpression.vala
  *
- * Copyright (C) 2006-2008  Jürg Billeter
+ * Copyright (C) 2006-2009  Jürg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -80,8 +80,6 @@ public class Vala.SizeofExpression : Expression {
 
 		value_type = analyzer.ulong_type;
 
-		analyzer.current_source_file.add_type_dependency (type_reference, SourceFileDependencyType.SOURCE);
-
 		return !error;
 	}
 }
diff --git a/vala/valasourcefile.vala b/vala/valasourcefile.vala
index 51466a6..65a0e4c 100644
--- a/vala/valasourcefile.vala
+++ b/vala/valasourcefile.vala
@@ -41,29 +41,7 @@ public class Vala.SourceFile {
 	 * Specifies whether this file is a VAPI package file.
 	 */
 	public bool external_package { get; set; }
-	
-	/**
-	 * Specifies the dependency cycle this source file is member of. If this
-	 * source file is in a cycle, all type definitions of that cycle will
-	 * only be written to the C header file of the cycle head.
-	 */
-	public SourceFileCycle cycle { get; set; }
-	
-	/**
-	 * Specifies whether this source file is the head of the cycle, if it is
-	 * in a cycle at all.
-	 */
-	public bool is_cycle_head { get; set; }
-	
-	/**
-	 * Mark used for cycle detection.
-	 *
-	 * 0: not yet visited
-	 * 1: currently visiting
-	 * 2: already visited
-	 */
-	public int mark { get; set; }
-	
+
 	/**
 	 * The context this source file belongs to.
 	 */
@@ -84,16 +62,6 @@ public class Vala.SourceFile {
 	private string cheader_filename = null;
 	private string csource_filename = null;
 	private string cinclude_filename = null;
-	
-	private Gee.List<string> header_external_includes = new ArrayList<string> ();
-	private Gee.List<string> header_internal_includes = new ArrayList<string> ();
-	private Gee.List<string> source_external_includes = new ArrayList<string> ();
-	private Gee.List<string> source_internal_includes = new ArrayList<string> ();
-	
-	private Gee.List<weak SourceFile> header_internal_full_dependencies = new ArrayList<weak SourceFile> ();
-	private Gee.List<weak SourceFile> header_internal_dependencies = new ArrayList<weak SourceFile> ();
-
-	private Gee.Set<Symbol> source_symbol_dependencies = new HashSet<Symbol> ();
 
 	private Gee.ArrayList<string> source_array = null;
 
@@ -260,170 +228,13 @@ public class Vala.SourceFile {
 	 */
 	public string get_cinclude_filename () {
 		if (cinclude_filename == null) {
-			cinclude_filename = "%s%s.h".printf (get_subdir (), get_basename ());
-		}
-		return cinclude_filename;
-	}
-	
-	/**
-	 * Adds the specified symbol to the list of symbols code in this source
-	 * file depends on.
-	 *
-	 * TODO Move source and header file dependency analysis to
-	 * code generator.
-	 *
-	 * @param sym      a symbol
-	 * @param dep_type type of dependency
-	 */
-	public void add_symbol_dependency (Symbol? sym, SourceFileDependencyType dep_type) {
-		if (external_package) {
-			return;
-		}
-
-		Symbol s;
-		
-		if (sym is ErrorCode || sym is EnumValue) {
-			s = sym.parent_symbol;
-		} else if (sym is TypeSymbol ||
-		    sym is Method ||
-		    sym is Field ||
-		    sym is Property ||
-		    sym is Constant) {
-			s = sym;
-		} else if (sym is FormalParameter) {
-			var fp = (FormalParameter) sym;
-			s = fp.parameter_type.data_type;
-			if (s == null) {
-				/* generic type parameter */
-				return;
-			}
-		} else {
-			return;
-		}
-		
-		if (dep_type == SourceFileDependencyType.SOURCE) {
-			source_symbol_dependencies.add (s);
-			if (s.external_package) {
-				foreach (string fn in s.get_cheader_filenames ()) {
-					source_external_includes.add (fn);
-				}
+			if (context.header_filename != null) {
+				cinclude_filename = Path.get_basename (context.header_filename);
 			} else {
-				foreach (string fn in s.get_cheader_filenames ()) {
-					source_internal_includes.add (fn);
-				}
-			}
-			return;
-		}
-
-		if (s.external_package) {
-			/* external package */
-			foreach (string fn in s.get_cheader_filenames ()) {
-				header_external_includes.add (fn);
+				cinclude_filename = "%s%s.h".printf (get_subdir (), get_basename ());
 			}
-			return;
-		}
-		
-		if (dep_type == SourceFileDependencyType.HEADER_FULL) {
-			foreach (string fn in s.get_cheader_filenames ()) {
-				header_internal_includes.add (fn);
-			}
-			header_internal_full_dependencies.add (s.source_reference.file);
-		}
-
-		header_internal_dependencies.add (s.source_reference.file);
-	}
-
-	/**
-	 * Adds the symbols that define the specified type to the list of
-	 * symbols code in this source file depends on.
-	 *
-	 * TODO Move source and header file dependency analysis to
-	 * code generator.
-	 *
-	 * @param type     a data type
-	 * @param dep_type type of dependency
-	 */
-	public void add_type_dependency (DataType type, SourceFileDependencyType dep_type) {
-		foreach (Symbol type_symbol in type.get_symbols ()) {
-			add_symbol_dependency (type_symbol, dep_type);
-		}
-	}
-
-	/**
-	 * Returns the list of external includes the generated C header file
-	 * requires.
-	 *
-	 * @return external include list for C header file
-	 */
-	public Gee.List<string> get_header_external_includes () {
-		return new ReadOnlyList<string> (header_external_includes);
-	}
-	
-	/**
-	 * Adds the specified filename to the list of package-internal includes
-	 * the generated C header file requires.
-	 *
-	 * @param include internal include for C header file
-	 */
-	public void add_header_internal_include (string include) {
-		/* skip includes to self */
-		if (include != get_cinclude_filename ()) {
-			header_internal_includes.add (include);
 		}
-	}
-	
-	/**
-	 * Returns the list of package-internal includes the generated C header
-	 * file requires.
-	 *
-	 * @return internal include list for C header file
-	 */
-	public Gee.List<string> get_header_internal_includes () {
-		return new ReadOnlyList<string> (header_internal_includes);
-	}
-	
-	/**
-	 * Returns the list of external includes the generated C source file
-	 * requires.
-	 *
-	 * @return include list for C source file
-	 */
-	public Gee.List<string> get_source_external_includes () {
-		return new ReadOnlyList<string> (source_external_includes);
-	}
-	
-	/**
-	 * Returns the list of package-internal includes the generated C source
-	 * file requires.
-	 *
-	 * @return include list for C source file
-	 */
-	public Gee.List<string> get_source_internal_includes () {
-		return new ReadOnlyList<string> (source_internal_includes);
-	}
-	
-	/**
-	 * Returns the list of source files the generated C header file requires
-	 * definitely.
-	 *
-	 * @return definite source file dependencies
-	 */
-	public Gee.List<weak SourceFile> get_header_internal_full_dependencies () {
-		return new ReadOnlyList<weak SourceFile> (header_internal_full_dependencies);
-	}
-	
-	/**
-	 * Returns the list of source files the generated C header file loosely
-	 * depends on.
-	 *
-	 * @return loose source file dependencies
-	 */
-	public Gee.List<weak SourceFile> get_header_internal_dependencies () {
-		return new ReadOnlyList<weak SourceFile> (header_internal_dependencies);
-	}
-
-	public Gee.Set<Symbol> get_source_symbol_dependencies () {
-		return new ReadOnlySet<Symbol> (source_symbol_dependencies);
+		return cinclude_filename;
 	}
 
 	/**
@@ -502,8 +313,3 @@ public class Vala.SourceFile {
 	}
 }
 
-public enum Vala.SourceFileDependencyType {
-	HEADER_FULL,
-	HEADER_SHALLOW,
-	SOURCE
-}
diff --git a/vala/valasourcefilecycle.vala b/vala/valasourcefilecycle.vala
deleted file mode 100644
index b3fd4ad..0000000
--- a/vala/valasourcefilecycle.vala
+++ /dev/null
@@ -1,39 +0,0 @@
-/* valasourcefilecycle.vala
- *
- * Copyright (C) 2006-2008  Jürg Billeter
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
-
- * This library 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
- * Lesser General Public License for more details.
-
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
- *
- * Author:
- * 	Jürg Billeter <j bitron ch>
- */
-
-using GLib;
-using Gee;
-
-/**
- * Represents a dependency cycle of source files.
- */
-public class Vala.SourceFileCycle {
-	/**
-	 * The members of this source file cycle.
-	 */
-	public Gee.List<weak SourceFile> files = new ArrayList<weak SourceFile> ();
-	
-	/**
-	 * The head of this source file cycle.
-	 */
-	public weak SourceFile head;
-}
diff --git a/vala/valasymbol.vala b/vala/valasymbol.vala
index 2478b14..61a1c0a 100644
--- a/vala/valasymbol.vala
+++ b/vala/valasymbol.vala
@@ -93,7 +93,8 @@ public abstract class Vala.Symbol : CodeNode {
 		}
 
 		for (Symbol sym = this; null != sym; sym = sym.parent_symbol) {
-			if (SymbolAccessibility.PRIVATE == sym.access) {
+			if (sym.access == SymbolAccessibility.PRIVATE
+			    || sym.access == SymbolAccessibility.INTERNAL) {
 				return true;
 			}
 		}
@@ -101,10 +102,14 @@ public abstract class Vala.Symbol : CodeNode {
 		return false;
 	}
 
-	public bool is_library_internal_symbol () {
+	public bool is_private_symbol () {
+		if (!external && external_package) {
+			// non-external symbols in VAPI files are private symbols
+			return true;
+		}
+
 		for (Symbol sym = this; null != sym; sym = sym.parent_symbol) {
-			if (sym.access == SymbolAccessibility.PRIVATE
-			    || sym.access == SymbolAccessibility.INTERNAL) {
+			if (sym.access == SymbolAccessibility.PRIVATE) {
 				return true;
 			}
 		}
diff --git a/vala/valatypecheck.vala b/vala/valatypecheck.vala
index 2dee142..1f626ae 100644
--- a/vala/valatypecheck.vala
+++ b/vala/valatypecheck.vala
@@ -1,6 +1,6 @@
 /* valatypecheck.vala
  *
- * Copyright (C) 2006-2008  Jürg Billeter
+ * Copyright (C) 2006-2009  Jürg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -95,8 +95,6 @@ public class Vala.TypeCheck : Expression {
 			return false;
 		}
 
-		analyzer.current_source_file.add_type_dependency (type_reference, SourceFileDependencyType.SOURCE);
-
 		value_type = analyzer.bool_type;
 
 		return !error;
diff --git a/vala/valatypeofexpression.vala b/vala/valatypeofexpression.vala
index 9331a8f..99d9145 100644
--- a/vala/valatypeofexpression.vala
+++ b/vala/valatypeofexpression.vala
@@ -1,6 +1,6 @@
 /* valatypeofexpression.vala
  *
- * Copyright (C) 2006-2008  Jürg Billeter
+ * Copyright (C) 2006-2009  Jürg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -80,8 +80,6 @@ public class Vala.TypeofExpression : Expression {
 
 		value_type = analyzer.type_type;
 
-		analyzer.current_source_file.add_type_dependency (type_reference, SourceFileDependencyType.SOURCE);
-
 		return !error;
 	}
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]