diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index 9102e70..c9f9613 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -4364,14 +4364,21 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
 			} else if (st != null && get_ccode_name (st) == "va_list") {
 				creation_call.add_argument (instance);
 				if (get_ccode_name (m) == "va_start") {
-					Parameter last_param = null;
-					foreach (var param in current_method.get_parameters ()) {
-						if (param.ellipsis) {
-							break;
-						}
-						last_param = param;
-					}
-					creation_call.add_argument (new CCodeIdentifier (get_variable_cname (last_param.name)));
+                    if (current_method is CreationMethod) {
+                        creation_call = new CCodeFunctionCall (new CCodeIdentifier ("va_copy"));
+				        creation_call.add_argument (instance);
+                        creation_call.add_argument (new CCodeIdentifier ("__va_list"));
+                    } else {
+                        Parameter last_param = null;
+                        // FIXME: this doesn't take into account exception handling parameters
+                        foreach (var param in current_method.get_parameters ()) {
+                            if (param.ellipsis) {
+                                break;
+                            }
+                            last_param = param;
+                        }
+                        creation_call.add_argument (new CCodeIdentifier (get_variable_cname (last_param.name)));
+                    }
 				}
 			}
 
diff --git a/codegen/valaccodemethodmodule.vala b/codegen/valaccodemethodmodule.vala
index 5559898..1b69712 100644
--- a/codegen/valaccodemethodmodule.vala
+++ b/codegen/valaccodemethodmodule.vala
@@ -27,6 +27,9 @@ using GLib;
  * The link between a method and generated code.
  */
 public abstract class Vala.CCodeMethodModule : CCodeStructModule {
+
+	private bool ellipses_to_valist = false;
+
 	public override bool method_has_wrapper (Method method) {
 		return (method.get_attribute ("NoWrapper") == null);
 	}
@@ -175,7 +178,10 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
 
 		// do not generate _new functions for creation methods of abstract classes
 		if (!(m is CreationMethod && cl != null && cl.is_abstract)) {
+			bool etv_tmp = ellipses_to_valist;
+			ellipses_to_valist = false;
 			generate_cparameters (m, decl_space, cparam_map, function, null, carg_map, new CCodeFunctionCall (new CCodeIdentifier ("fake")));
+			ellipses_to_valist = etv_tmp;
 
 			decl_space.add_function_declaration (function);
 		}
@@ -189,9 +195,37 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
 			}
 
 			cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
+			bool etv_tmp = ellipses_to_valist;
+			ellipses_to_valist = false;
 			generate_cparameters (m, decl_space, cparam_map, function);
+			ellipses_to_valist = etv_tmp;
 
 			decl_space.add_function_declaration (function);
+
+			if (m.is_variadic ()) {
+				// _constructv function
+				function = new CCodeFunction (get_constructv_name ((CreationMethod) m));
+				function.modifiers |= CCodeModifiers.STATIC;
+
+				cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
+				generate_cparameters (m, decl_space, cparam_map, function);
+
+				decl_space.add_function_declaration (function);
+			}
+		}
+	}
+
+	private string get_constructv_name (CreationMethod m) {
+		const string infix = "constructv";
+
+		// FIXME: DOVA?
+
+		var parent = m.parent_symbol as Class;
+
+		if (m.name == ".new") {
+			return "%s%s".printf (CCodeBaseModule.get_ccode_lower_case_prefix (parent), infix);
+		} else {
+			return "%s%s_%s".printf (CCodeBaseModule.get_ccode_lower_case_prefix (parent), infix, m.name);
 		}
 	}
 
@@ -249,7 +283,18 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
 		ccode.add_expression (register_call);
 	}
 
+	/**
+	 * This function generates the code the given method. If the method is
+	 * a constructor, _construct is generated, unless it's variadic, in which
+	 * case _constructv is generated (and _construct is generated together
+	 * with _new in visit_creation_method).
+	 */
 	public override void visit_method (Method m) {
+		string real_name = get_ccode_real_name (m);
+		if (m is CreationMethod && m.is_variadic ()) {
+			real_name = get_constructv_name ((CreationMethod) m);
+		}
+
 		push_context (new EmitContext (m));
 		push_line (m.source_reference);
 
@@ -303,7 +348,7 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
 		}
 
 		if (profile) {
-			string prefix = "_vala_prof_%s".printf (get_ccode_real_name (m));
+			string prefix = "_vala_prof_%s".printf (real_name);
 
 			cfile.add_include ("stdio.h");
 
@@ -364,7 +409,7 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
 		}
 
 		CCodeFunction function;
-		function = new CCodeFunction (get_ccode_real_name (m));
+		function = new CCodeFunction (real_name);
 
 		if (m.is_inline) {
 			function.modifiers |= CCodeModifiers.INLINE;
@@ -387,7 +432,7 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
 				}
 			} else {
 				if (m.body != null) {
-					function = new CCodeFunction (get_ccode_real_name (m) + "_co", "gboolean");
+					function = new CCodeFunction (real_name + "_co", "gboolean");
 
 					// data struct to hold parameters, local variables, and the return value
 					function.add_parameter (new CCodeParameter ("_data_", Symbol.lower_case_to_camel_case (get_ccode_const_name (m)) + "Data*"));
@@ -628,7 +673,7 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
 		}
 
 		if (profile) {
-			string prefix = "_vala_prof_%s".printf (get_ccode_real_name (m));
+			string prefix = "_vala_prof_%s".printf (real_name);
 
 			var level = new CCodeIdentifier (prefix + "_level");
 			ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, level)));
@@ -645,11 +690,12 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
 		}
 
 		if (m.body != null) {
+			// FIXME: replace va_list calls with the tmp parameter
 			m.body.emit (this);
 		}
 
 		if (profile) {
-			string prefix = "_vala_prof_%s".printf (get_ccode_real_name (m));
+			string prefix = "_vala_prof_%s".printf (real_name);
 
 			var level = new CCodeIdentifier (prefix + "_level");
 			ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeUnaryExpression (CCodeUnaryOperator.PREFIX_DECREMENT, level)));
@@ -843,6 +889,8 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
 			}
 
 			cparam = new CCodeParameter (get_variable_cname (param.name), ctypename);
+		} else if (ellipses_to_valist) {
+			cparam = new CCodeParameter ("__va_list", "va_list");
 		} else {
 			cparam = new CCodeParameter.with_ellipsis ();
 		}
@@ -1107,7 +1155,9 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
 
 		bool visible = !m.is_private_symbol ();
 
+		ellipses_to_valist = true;
 		visit_method (m);
+		ellipses_to_valist = false;
 
 		if (m.source_type == SourceFileType.FAST) {
 			return;
@@ -1115,26 +1165,69 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
 
 		// do not generate _new functions for creation methods of abstract classes
 		if (current_type_symbol is Class && !current_class.is_compact && !current_class.is_abstract) {
-			var vfunc = new CCodeFunction (get_ccode_name (m));
+			string constructor = (m.is_variadic ()) ? get_constructv_name (m) : get_ccode_real_name (m);
 
-			var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
-			var carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
+			string[] extra_functions = {};
+
+			// _new function
+			extra_functions += get_ccode_name (m);
 
-			push_function (vfunc);
+			// _construct function (if visit_method generated _constructv)
+			if (m.is_variadic ()) {
+				extra_functions += get_ccode_real_name (m);
+			}
 
-			var vcall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_real_name (m)));
-			vcall.add_argument (new CCodeIdentifier (get_ccode_type_id (current_class)));
+			bool first = true;
+			foreach (var func_name in extra_functions) {
+				var vfunc = new CCodeFunction (func_name);
+				if (!visible) {
+					vfunc.modifiers |= CCodeModifiers.STATIC;
+				}
 
-			generate_cparameters (m, cfile, cparam_map, vfunc, null, carg_map, vcall);
-			ccode.add_return (vcall);
+				var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
+				var carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
 
-			if (!visible) {
-				vfunc.modifiers |= CCodeModifiers.STATIC;
-			}
+				push_function (vfunc);
 
-			pop_function ();
+				var vcall = new CCodeFunctionCall (new CCodeIdentifier (constructor));
+				vcall.add_argument (new CCodeIdentifier (get_ccode_type_id (current_class)));
+
+				if (!first) {
+					cparam_map.set (get_param_pos (get_ccode_instance_pos (m)), new CCodeParameter ("object_type", "GType"));
+				} else {
+					first = false;
+				}
+
+				generate_cparameters (m, cfile, cparam_map, vfunc, null, carg_map, vcall);
+
+				if (m.is_variadic ()) {
+					int last_pos = -1;
+					int second_last_pos = -1;
+					foreach (int pos in cparam_map.get_keys ()) {
+						if (pos > last_pos) {
+							second_last_pos = last_pos;
+							last_pos = pos;
+						} else if (pos > second_last_pos) {
+							second_last_pos = pos;
+						}
+					}
+
+					var va_start = new CCodeFunctionCall (new CCodeIdentifier ("va_start"));
+					va_start.add_argument (new CCodeIdentifier ("__va_list_obj"));
+					va_start.add_argument (carg_map.get (second_last_pos));
 
-			cfile.add_function (vfunc);
+					ccode.add_declaration ("va_list", new CCodeVariableDeclarator ("__va_list_obj"));
+					ccode.add_expression (va_start);
+
+					vcall.add_argument (new CCodeIdentifier("__va_list_obj"));
+				}
+
+				ccode.add_return (vcall);
+
+				pop_function ();
+
+				cfile.add_function (vfunc);
+			}
 		}
 
 		pop_line ();
diff --git a/vala/valamethod.vala b/vala/valamethod.vala
index 9f397c4..e5fefdd 100644
--- a/vala/valamethod.vala
+++ b/vala/valamethod.vala
@@ -231,6 +231,13 @@ public class Vala.Method : Subroutine {
 		parameters.clear ();
 	}
 
+	public bool is_variadic () {
+		foreach (Parameter param in parameters) {
+			if (param.ellipsis) return true;
+		}
+		return false;
+	}
+
 	public override void accept (CodeVisitor visitor) {
 		visitor.visit_method (this);
 	}
