vala r1390 - in trunk: . gobject vala vapi vapigen



Author: juergbi
Date: Fri May 16 19:24:58 2008
New Revision: 1390
URL: http://svn.gnome.org/viewvc/vala?rev=1390&view=rev

Log:
2008-05-16  Juerg Billeter  <j bitron ch>

	* vala/valaarraytype.vala:
	* vala/valaclass.vala:
	* vala/valaclassinstancetype.vala:
	* vala/valaclasstype.vala:
	* vala/valadatatype.vala:
	* vala/valainterfaceinstancetype.vala:
	* vala/valainterfacetype.vala:
	* vala/valainterfacewriter.vala:
	* vala/valamemorymanager.vala:
	* vala/valanullchecker.vala:
	* vala/valaparser.vala:
	* vala/valareferencetransferexpression.vala:
	* vala/valasemanticanalyzer.vala:
	* vala/valasymbolresolver.vala:
	* vala/valatypeparametertype.vala:
	* vala/valaunresolvedtype.vala:
	* vala/valavaluetype.vala:
	* gobject/valaccodeassignmentbinding.vala:
	* gobject/valaccodegenerator.vala:
	* gobject/valaccodeinvocationexpressionbinding.vala:
	* gobject/valagidlwriter.vala:
	* vapigen/valagidlparser.vala:
	* vapi/glib-2.0.vapi:

	Replace DataType.transfers_ownership and DataType.takes_ownership
	by DataType.value_owned, prepare support for owned value types


Modified:
   trunk/ChangeLog
   trunk/gobject/valaccodeassignmentbinding.vala
   trunk/gobject/valaccodegenerator.vala
   trunk/gobject/valaccodeinvocationexpressionbinding.vala
   trunk/gobject/valagidlwriter.vala
   trunk/vala/valaarraytype.vala
   trunk/vala/valaclass.vala
   trunk/vala/valaclassinstancetype.vala
   trunk/vala/valaclasstype.vala
   trunk/vala/valadatatype.vala
   trunk/vala/valainterfaceinstancetype.vala
   trunk/vala/valainterfacetype.vala
   trunk/vala/valainterfacewriter.vala
   trunk/vala/valamemorymanager.vala
   trunk/vala/valanullchecker.vala
   trunk/vala/valaparser.vala
   trunk/vala/valareferencetransferexpression.vala
   trunk/vala/valasemanticanalyzer.vala
   trunk/vala/valasymbolresolver.vala
   trunk/vala/valatypeparametertype.vala
   trunk/vala/valaunresolvedtype.vala
   trunk/vala/valavaluetype.vala
   trunk/vapi/glib-2.0.vapi
   trunk/vapigen/valagidlparser.vala

Modified: trunk/gobject/valaccodeassignmentbinding.vala
==============================================================================
--- trunk/gobject/valaccodeassignmentbinding.vala	(original)
+++ trunk/gobject/valaccodeassignmentbinding.vala	Fri May 16 19:24:58 2008
@@ -371,7 +371,7 @@
 
 		rhs = codegen.get_implicit_cast_expression (rhs, assignment.right.value_type, assignment.left.value_type);
 
-		bool unref_old = (assignment.left.value_type.takes_ownership);
+		bool unref_old = codegen.requires_destroy (assignment.left.value_type);
 		bool array = false;
 		bool instance_delegate = false;
 		if (assignment.left.value_type is ArrayType) {

Modified: trunk/gobject/valaccodegenerator.vala
==============================================================================
--- trunk/gobject/valaccodegenerator.vala	(original)
+++ trunk/gobject/valaccodegenerator.vala	Fri May 16 19:24:58 2008
@@ -616,7 +616,7 @@
 				}
 			}
 			
-			if (f.field_type.takes_ownership && instance_dispose_fragment != null) {
+			if (requires_destroy (f.field_type) && instance_dispose_fragment != null) {
 				var ma = new MemberAccess.simple (f.name);
 				ma.symbol_reference = f;
 				instance_dispose_fragment.append (new CCodeExpressionStatement (get_unref_expression (lhs, f.field_type, ma)));
@@ -779,7 +779,6 @@
 		}
 		var cselfparam = new CCodeFormalParameter ("self", this_type.get_cname ());
 		var value_type = prop.property_type.copy ();
-		value_type.takes_ownership = value_type.transfers_ownership;
 		var cvalueparam = new CCodeFormalParameter ("value", value_type.get_cname ());
 
 		if (prop.is_abstract || prop.is_virtual) {
@@ -1071,7 +1070,7 @@
 		}
 
 		foreach (LocalVariable local in local_vars) {
-			if (local.variable_type.takes_ownership) {
+			if (requires_destroy (local.variable_type)) {
 				var ma = new MemberAccess.simple (local.name);
 				ma.symbol_reference = local;
 				cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (get_variable_cname (local.name)), local.variable_type, ma)));
@@ -1081,7 +1080,7 @@
 		if (b.parent_symbol is Method) {
 			var m = (Method) b.parent_symbol;
 			foreach (FormalParameter param in m.get_parameters ()) {
-				if (param.parameter_type.data_type != null && param.parameter_type.data_type.is_reference_type () && param.parameter_type.takes_ownership && param.direction == ParameterDirection.IN) {
+				if (requires_destroy (param.parameter_type) && param.direction == ParameterDirection.IN) {
 					var ma = new MemberAccess.simple (param.name);
 					ma.symbol_reference = param;
 					cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (get_variable_cname (param.name)), param.parameter_type, ma)));
@@ -1231,9 +1230,9 @@
 		list.ccodenode = clist;
 	}
 
-	public LocalVariable get_temp_variable (DataType type, bool takes_ownership = true, CodeNode? node_reference = null) {
+	public LocalVariable get_temp_variable (DataType type, bool value_owned = true, CodeNode? node_reference = null) {
 		var var_type = type.copy ();
-		var_type.takes_ownership = takes_ownership;
+		var_type.value_owned = value_owned;
 		var local = new LocalVariable (var_type, "_tmp%d".printf (next_temp_var_id));
 
 		if (node_reference != null) {
@@ -1263,6 +1262,8 @@
 				dup_function = type.data_type.get_ref_function ();
 			} else if (type.data_type == string_type.data_type) {
 				dup_function = type.data_type.get_dup_function ();
+			} else if (type is ValueType) {
+				dup_function = "";
 			} else {
 				// duplicating non-reference counted structs may cause side-effects (and performance issues)
 				Report.error (source_reference, "duplicating %s instance, use weak variable or explicitly invoke copy method".printf (type.data_type.name));
@@ -1288,17 +1289,17 @@
 		if (type.data_type == glist_type || type.data_type == gslist_type) {
 			// create wrapper function to free list elements if necessary
 
-			bool takes_ownership = false;
+			bool elements_require_free = false;
 			CCodeExpression element_destroy_func_expression = null;
 
 			foreach (DataType type_arg in type.get_type_arguments ()) {
-				takes_ownership = type_arg.takes_ownership;
-				if (takes_ownership) {
+				elements_require_free = requires_destroy (type_arg);
+				if (elements_require_free) {
 					element_destroy_func_expression = get_destroy_func_expression (type_arg);
 				}
 			}
 			
-			if (takes_ownership && element_destroy_func_expression is CCodeIdentifier) {
+			if (elements_require_free && element_destroy_func_expression is CCodeIdentifier) {
 				return new CCodeIdentifier (generate_glist_free_wrapper (type, (CCodeIdentifier) element_destroy_func_expression));
 			} else {
 				return new CCodeIdentifier (type.data_type.get_free_function ());
@@ -1311,8 +1312,7 @@
 				unref_function = type.data_type.get_free_function ();
 			}
 			if (unref_function == null) {
-				Report.error (type.data_type.source_reference, "The type `%s` doesn't contain a free function".printf (type.data_type.get_full_name ()));
-				return null;
+				return new CCodeConstant ("NULL");
 			}
 			return new CCodeIdentifier (unref_function);
 		} else if (type.type_parameter != null && current_type_symbol is Class) {
@@ -1891,7 +1891,7 @@
 
 				element_expr = get_implicit_cast_expression (element_expr, array_type.element_type, stmt.type_reference);
 
-				if (stmt.type_reference.takes_ownership) {
+				if (requires_copy (stmt.type_reference)) {
 					var ma = new MemberAccess.simple (stmt.variable_name);
 					ma.value_type = stmt.type_reference;
 					ma.ccodenode = element_expr;
@@ -1935,7 +1935,7 @@
 
 				element_expr = get_implicit_cast_expression (element_expr, array_type.element_type, stmt.type_reference);
 
-				if (stmt.type_reference.takes_ownership) {
+				if (requires_copy (stmt.type_reference)) {
 					var ma = new MemberAccess.simple (stmt.variable_name);
 					ma.value_type = stmt.type_reference;
 					ma.ccodenode = element_expr;
@@ -2003,7 +2003,7 @@
 
 			element_expr = convert_from_generic_pointer (element_expr, stmt.type_reference);
 
-			if (stmt.type_reference.takes_ownership) {
+			if (requires_copy (stmt.type_reference)) {
 				var ma = new MemberAccess.simple (stmt.variable_name);
 				ma.value_type = stmt.type_reference;
 				ma.ccodenode = element_expr;
@@ -2058,7 +2058,7 @@
 
 			element_expr = get_implicit_cast_expression (element_expr, it_type, stmt.type_reference);
 
-			if (stmt.type_reference.takes_ownership && !it_type.takes_ownership) {
+			if (requires_copy (stmt.type_reference) && !it_type.value_owned) {
 				var ma = new MemberAccess.simple (stmt.variable_name);
 				ma.value_type = stmt.type_reference;
 				ma.ccodenode = element_expr;
@@ -2088,7 +2088,7 @@
 		}
 
 		foreach (LocalVariable local in stmt.get_local_variables ()) {
-			if (local.variable_type.takes_ownership) {
+			if (requires_destroy (local.variable_type)) {
 				var ma = new MemberAccess.simple (local.name);
 				ma.symbol_reference = local;
 				var cunref = new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (get_variable_cname (local.name)), local.variable_type, ma));
@@ -2115,7 +2115,7 @@
 
 		var local_vars = b.get_local_variables ();
 		foreach (LocalVariable local in local_vars) {
-			if (local.active && local.variable_type.is_reference_type_or_type_parameter () && local.variable_type.takes_ownership) {
+			if (local.active && requires_destroy (local.variable_type)) {
 				var ma = new MemberAccess.simple (local.name);
 				ma.symbol_reference = local;
 				cfrag.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (get_variable_cname (local.name)), local.variable_type, ma)));
@@ -2139,7 +2139,7 @@
 
 	private void append_param_free (Method m, CCodeFragment cfrag) {
 		foreach (FormalParameter param in m.get_parameters ()) {
-			if (param.parameter_type.data_type != null && param.parameter_type.data_type.is_reference_type () && param.parameter_type.takes_ownership && param.direction == ParameterDirection.IN) {
+			if (requires_destroy (param.parameter_type) && param.direction == ParameterDirection.IN) {
 				var ma = new MemberAccess.simple (param.name);
 				ma.symbol_reference = param;
 				cfrag.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (get_variable_cname (param.name)), param.parameter_type, ma)));
@@ -2163,7 +2163,7 @@
 
 		var local_vars = b.get_local_variables ();
 		foreach (LocalVariable local in local_vars) {
-			if (local.active && local.variable_type.is_reference_type_or_type_parameter () && local.variable_type.takes_ownership) {
+			if (local.active && requires_destroy (local.variable_type)) {
 				found = true;
 				var ma = new MemberAccess.simple (local.name);
 				ma.symbol_reference = local;
@@ -2184,7 +2184,7 @@
 		bool found = false;
 
 		foreach (FormalParameter param in m.get_parameters ()) {
-			if (param.parameter_type.data_type != null && param.parameter_type.data_type.is_reference_type () && param.parameter_type.takes_ownership && param.direction == ParameterDirection.IN) {
+			if (requires_destroy (param.parameter_type) && param.direction == ParameterDirection.IN) {
 				found = true;
 				var ma = new MemberAccess.simple (param.name);
 				ma.symbol_reference = param;
@@ -2218,7 +2218,7 @@
 			if (stmt.return_expression.ref_missing &&
 			    stmt.return_expression.symbol_reference is LocalVariable) {
 				var local = (LocalVariable) stmt.return_expression.symbol_reference;
-				if (local.variable_type.takes_ownership) {
+				if (local.variable_type.value_owned) {
 					/* return expression is local variable taking ownership and
 					 * current method is transferring ownership */
 					
@@ -2243,7 +2243,7 @@
 			if (stmt.return_expression.ref_sink &&
 			    stmt.return_expression.symbol_reference is LocalVariable) {
 				var local = (LocalVariable) stmt.return_expression.symbol_reference;
-				if (local.variable_type.takes_ownership) {
+				if (local.variable_type.value_owned) {
 					/* return expression is local variable taking ownership and
 					 * current method is transferring ownership */
 					
@@ -2809,7 +2809,45 @@
 		
 		return null;
 	}
-	
+
+	public bool requires_copy (DataType type) {
+		if (!type.value_owned) {
+			return false;
+		}
+
+		if (type.is_reference_type_or_type_parameter ()) {
+			if (type.type_parameter != null) {
+				if (!(current_type_symbol is Class) || !current_class.is_subtype_of (gobject_type)) {
+					return false;
+				}
+			}
+			return true;
+		} else if (type is ValueType) {
+			// nullable structs are heap allocated
+			return type.nullable;
+		}
+		return false;
+	}
+
+	public bool requires_destroy (DataType type) {
+		if (!type.value_owned) {
+			return false;
+		}
+
+		if (type.is_reference_type_or_type_parameter ()) {
+			if (type.type_parameter != null) {
+				if (!(current_type_symbol is Class) || !current_class.is_subtype_of (gobject_type)) {
+					return false;
+				}
+			}
+			return true;
+		} else if (type is ValueType) {
+			// nullable structs are heap allocated
+			return type.nullable;
+		}
+		return false;
+	}
+
 	private CCodeExpression? get_ref_expression (Expression expr) {
 		/* (temp = expr, temp == NULL ? NULL : ref (temp))
 		 *
@@ -2878,7 +2916,8 @@
 	
 	public void visit_expression (Expression expr) {
 		if (expr.value_type != null &&
-		    expr.value_type.transfers_ownership &&
+		    expr.value_type.value_owned &&
+		    !expr.lvalue &&
 		    expr.value_type.floating_reference) {
 			/* constructor of GInitiallyUnowned subtype
 			 * returns floating reference, sink it
@@ -2889,13 +2928,20 @@
 			expr.ccodenode = csink;
 		}
 	
-		if (expr.ref_leaked) {
+		if (expr.ref_leaked && requires_destroy (expr.value_type)) {
 			var decl = get_temp_variable (expr.value_type, true, expr);
 			temp_vars.insert (0, decl);
 			temp_ref_vars.insert (0, decl);
 			expr.ccodenode = new CCodeParenthesizedExpression (new CCodeAssignment (new CCodeIdentifier (get_variable_cname (decl.name)), (CCodeExpression) expr.ccodenode));
 		} else if (expr.ref_missing) {
-			expr.ccodenode = get_ref_expression (expr);
+			// ref_missing => assignment of unowned expression to owned expression
+			// requires_copy should be called on target type but we don't have this
+			// information available here, so construct approximation of target type
+			var target_type = expr.value_type.copy ();
+			target_type.value_owned = true;
+			if (requires_copy (target_type)) {
+				expr.ccodenode = get_ref_expression (expr);
+			}
 		}
 	}
 
@@ -2954,7 +3000,7 @@
 			if (expr.type_reference.data_type is Class && expr.type_reference.data_type.is_subtype_of (gobject_type)) {
 				foreach (DataType type_arg in expr.type_reference.get_type_arguments ()) {
 					creation_call.add_argument (get_type_id_expression (type_arg));
-					if (type_arg.takes_ownership) {
+					if (requires_copy (type_arg)) {
 						var dup_func = get_dup_func_expression (type_arg, type_arg.source_reference);
 						if (dup_func == null) {
 							// type doesn't contain a copy function
@@ -3189,6 +3235,8 @@
 	}
 
 	public override void visit_reference_transfer_expression (ReferenceTransferExpression expr) {
+		expr.accept_children (this);
+
 		/* (tmp = var, var = null, tmp) */
 		var ccomma = new CCodeCommaExpression ();
 		var temp_decl = get_temp_variable (expr.value_type, true, expr);

Modified: trunk/gobject/valaccodeinvocationexpressionbinding.vala
==============================================================================
--- trunk/gobject/valaccodeinvocationexpressionbinding.vala	(original)
+++ trunk/gobject/valaccodeinvocationexpressionbinding.vala	Fri May 16 19:24:58 2008
@@ -239,7 +239,7 @@
 					}
 
 					// unref old value for non-null non-weak out arguments
-					if (param.direction == ParameterDirection.OUT && param.parameter_type.takes_ownership && !(arg.value_type is NullType)) {
+					if (param.direction == ParameterDirection.OUT && codegen.requires_destroy (param.parameter_type) && !(arg.value_type is NullType)) {
 						var unary = (UnaryExpression) arg;
 
 						// (ret_tmp = call (&tmp), free (var1), var1 = tmp, ret_tmp)

Modified: trunk/gobject/valagidlwriter.vala
==============================================================================
--- trunk/gobject/valagidlwriter.vala	(original)
+++ trunk/gobject/valagidlwriter.vala	Fri May 16 19:24:58 2008
@@ -323,18 +323,18 @@
 			if (param.direction == ParameterDirection.REF) {
 				stream.printf (" direction=\"inout\"");
 				// in/out paramter
-				if (param.parameter_type.takes_ownership) {
+				if (param.parameter_type.value_owned) {
 					stream.printf (" transfer=\"full\"");
 				}
 			} else if (param.direction == ParameterDirection.OUT) {
 				// out paramter
 				stream.printf (" direction=\"out\"");
-				if (param.parameter_type.takes_ownership) {
+				if (param.parameter_type.value_owned) {
 					stream.printf (" transfer=\"full\"");
 				}
 			} else {
 				// normal in paramter
-				if (param.parameter_type.transfers_ownership) {
+				if (param.parameter_type.value_owned) {
 					stream.printf (" transfer=\"full\"");
 				}
 			}
@@ -472,7 +472,7 @@
 	private void write_return_type (DataType type) {
 		write_indent ();
 		stream.printf ("<return-type type=\"%s\"", get_gidl_type_name (type));
-		if (type.transfers_ownership) {
+		if (type.value_owned) {
 			stream.printf (" transfer=\"full\"");
 		}
 		stream.printf ("/>\n");

Modified: trunk/vala/valaarraytype.vala
==============================================================================
--- trunk/vala/valaarraytype.vala	(original)
+++ trunk/vala/valaarraytype.vala	Fri May 16 19:24:58 2008
@@ -29,7 +29,7 @@
 	/**
 	 * The element type.
 	 */
-	public weak DataType element_type { get; construct set; }
+	public DataType element_type { get; construct set; }
 
 	/**
 	 * The rank of this array.
@@ -68,7 +68,6 @@
 				// length is an int[] containing the dimensions of the array, starting at 0
 				ValueType integer = new ValueType((Typesymbol) root_symbol.scope.lookup("int"));
 				length_field.field_type = new ArrayType (integer, 1, source_reference);
-				length_field.field_type.add_type_argument (integer);
 			} else {
 				length_field.field_type = new ValueType ((Typesymbol) root_symbol.scope.lookup ("int"));
 			}
@@ -117,15 +116,10 @@
 
 	public override DataType copy () {
 		var result = new ArrayType (element_type, rank, source_reference);
-		result.transfers_ownership = transfers_ownership;
-		result.takes_ownership = takes_ownership;
+		result.value_owned = value_owned;
 		result.nullable = nullable;
 		result.floating_reference = floating_reference;
 		
-		foreach (DataType arg in get_type_arguments ()) {
-			result.add_type_argument (arg.copy ());
-		}
-		
 		return result;
 	}
 

Modified: trunk/vala/valaclass.vala
==============================================================================
--- trunk/vala/valaclass.vala	(original)
+++ trunk/vala/valaclass.vala	Fri May 16 19:24:58 2008
@@ -287,6 +287,10 @@
 			if (empty_get && empty_set) {
 				/* automatic property accessor body generation */
 				var field_type = prop.property_type.copy ();
+				var ut = field_type as UnresolvedType;
+				if (ut != null) {
+					field_type.value_owned = !ut.is_weak;
+				}
 				var f = new Field ("_%s".printf (prop.name), field_type, prop.default_expression, prop.source_reference);
 				f.access = SymbolAccessibility.PRIVATE;
 				prop.field = f;

Modified: trunk/vala/valaclassinstancetype.vala
==============================================================================
--- trunk/vala/valaclassinstancetype.vala	(original)
+++ trunk/vala/valaclassinstancetype.vala	Fri May 16 19:24:58 2008
@@ -39,8 +39,7 @@
 	public override DataType copy () {
 		var result = new ClassInstanceType (class_symbol);
 		result.source_reference = source_reference;
-		result.transfers_ownership = transfers_ownership;
-		result.takes_ownership = takes_ownership;
+		result.value_owned = value_owned;
 		result.nullable = nullable;
 		result.is_dynamic = is_dynamic;
 		result.floating_reference = floating_reference;
@@ -53,6 +52,6 @@
 	}
 
 	public override string? get_cname () {
-		return "%s*".printf (class_symbol.get_cname (!takes_ownership && !transfers_ownership));
+		return "%s*".printf (class_symbol.get_cname (!value_owned));
 	}
 }

Modified: trunk/vala/valaclasstype.vala
==============================================================================
--- trunk/vala/valaclasstype.vala	(original)
+++ trunk/vala/valaclasstype.vala	Fri May 16 19:24:58 2008
@@ -38,8 +38,7 @@
 	public override DataType copy () {
 		var result = new ClassType (class_symbol);
 		result.source_reference = source_reference;
-		result.transfers_ownership = transfers_ownership;
-		result.takes_ownership = takes_ownership;
+		result.value_owned = value_owned;
 		result.nullable = nullable;
 		result.is_dynamic = is_dynamic;
 		result.floating_reference = floating_reference;

Modified: trunk/vala/valadatatype.vala
==============================================================================
--- trunk/vala/valadatatype.vala	(original)
+++ trunk/vala/valadatatype.vala	Fri May 16 19:24:58 2008
@@ -30,15 +30,9 @@
  */
 public abstract class Vala.DataType : CodeNode {
 	/**
-	 * Specifies that the expression transfers ownership of its value.
+	 * Specifies that the expression or variable owns the value.
 	 */
-	public bool transfers_ownership { get; set; }
-	
-	/**
-	 * Specifies that the expression assumes ownership if used as an lvalue
-	 * in an assignment.
-	 */
-	public bool takes_ownership { get; set; }
+	public bool value_owned { get; set; }
 
 	/**
 	 * Specifies that the expression may be null.
@@ -171,7 +165,7 @@
 				} else {
 					first = false;
 				}
-				if (type_arg.is_reference_type_or_type_parameter () && !type_arg.takes_ownership) {
+				if (!type_arg.value_owned) {
 					s += "weak ";
 				}
 				s += type_arg.to_string ();
@@ -201,10 +195,7 @@
 	 *              otherwise
 	 */
 	public virtual bool equals (DataType type2) {
-		if (type2.transfers_ownership != transfers_ownership) {
-			return false;
-		}
-		if (type2.takes_ownership != takes_ownership) {
+		if (type2.value_owned != value_owned) {
 			return false;
 		}
 		if (type2.nullable != nullable) {
@@ -236,10 +227,7 @@
 	 * @return      true if this type reference is stricter or equal
 	 */
 	public virtual bool stricter (DataType type2) {
-		if (type2.transfers_ownership != transfers_ownership) {
-			return false;
-		}
-		if (type2.takes_ownership != takes_ownership) {
+		if (type2.value_owned != value_owned) {
 			return false;
 		}
 		

Modified: trunk/vala/valainterfaceinstancetype.vala
==============================================================================
--- trunk/vala/valainterfaceinstancetype.vala	(original)
+++ trunk/vala/valainterfaceinstancetype.vala	Fri May 16 19:24:58 2008
@@ -39,8 +39,7 @@
 	public override DataType copy () {
 		var result = new InterfaceInstanceType (interface_symbol);
 		result.source_reference = source_reference;
-		result.transfers_ownership = transfers_ownership;
-		result.takes_ownership = takes_ownership;
+		result.value_owned = value_owned;
 		result.nullable = nullable;
 		result.is_dynamic = is_dynamic;
 		result.floating_reference = floating_reference;
@@ -53,6 +52,6 @@
 	}
 
 	public override string? get_cname () {
-		return "%s*".printf (interface_symbol.get_cname (!takes_ownership && !transfers_ownership));
+		return "%s*".printf (interface_symbol.get_cname (!value_owned));
 	}
 }

Modified: trunk/vala/valainterfacetype.vala
==============================================================================
--- trunk/vala/valainterfacetype.vala	(original)
+++ trunk/vala/valainterfacetype.vala	Fri May 16 19:24:58 2008
@@ -38,8 +38,7 @@
 	public override DataType copy () {
 		var result = new InterfaceType (interface_symbol);
 		result.source_reference = source_reference;
-		result.transfers_ownership = transfers_ownership;
-		result.takes_ownership = takes_ownership;
+		result.value_owned = value_owned;
 		result.nullable = nullable;
 		result.is_dynamic = is_dynamic;
 		result.floating_reference = floating_reference;

Modified: trunk/vala/valainterfacewriter.vala
==============================================================================
--- trunk/vala/valainterfacewriter.vala	(original)
+++ trunk/vala/valainterfacewriter.vala	Fri May 16 19:24:58 2008
@@ -465,9 +465,7 @@
 		write_indent ();
 		write_accessibility (f);
 
-		if (f.field_type.data_type != null &&
-		    f.field_type.data_type.is_reference_type () &&
-		    !f.field_type.takes_ownership) {
+		if (is_weak (f.field_type)) {
 			write_string ("weak ");
 		}
 
@@ -538,14 +536,14 @@
 				} else if (param.direction == ParameterDirection.OUT) {
 					write_string ("out ");
 				}
-				if (param.parameter_type.data_type != null && param.parameter_type.data_type.is_reference_type () && !param.parameter_type.takes_ownership) {
+				if (is_weak (param.parameter_type)) {
 					write_string ("weak ");
 				}
 			}
 
 			write_type (param.parameter_type);
 
-			if (param.parameter_type.transfers_ownership) {
+			if (param.direction == ParameterDirection.IN && param.parameter_type.value_owned) {
 				write_string ("#");
 			}
 
@@ -733,13 +731,10 @@
 		} else if (prop.is_virtual) {
 			write_string ("virtual ");
 		}
-		if (!prop.property_type.takes_ownership) {
-			write_string ("weak ");
-		}
 
 		write_type (prop.property_type);
 
-		if (prop.property_type.transfers_ownership) {
+		if (prop.property_type.value_owned) {
 			write_string ("#");
 		}
 
@@ -817,15 +812,31 @@
 	}
 
 	private void write_return_type (DataType type) {
-		if (type.is_reference_type_or_type_parameter ()) {
-			if (!type.transfers_ownership) {
-				write_string ("weak ");
-			}
+		if (is_weak (type)) {
+			write_string ("weak ");
 		}
 
 		write_type (type);
 	}
 
+	private bool is_weak (DataType type) {
+		if (type.value_owned) {
+			return false;
+		} else if (type is VoidType || type is PointerType) {
+			return false;
+		} else if (type is ValueType) {
+			if (type.nullable) {
+				// nullable structs are heap allocated
+				return false;
+			}
+
+			// TODO return true for structs with destroy
+			return false;
+		}
+
+		return true;
+	}
+
 	private void write_type (DataType type) {
 		write_string (type.to_string ());
 	}

Modified: trunk/vala/valamemorymanager.vala
==============================================================================
--- trunk/vala/valamemorymanager.vala	(original)
+++ trunk/vala/valamemorymanager.vala	Fri May 16 19:24:58 2008
@@ -42,7 +42,7 @@
 	
 	private void visit_possibly_leaked_expression (Expression expr) {
 		if (expr.value_type != null
-		    && expr.value_type.transfers_ownership) {
+		    && expr.value_type.value_owned) {
 			/* mark reference as leaked */
 			expr.ref_leaked = true;
 		}
@@ -50,7 +50,7 @@
 
 	private void visit_possibly_missing_copy_expression (Expression expr) {
 		if (expr.value_type != null
-		    && !expr.value_type.transfers_ownership
+		    && !expr.value_type.value_owned
 		    && !(expr.value_type is NullType)) {
 			/* mark reference as missing */
 			expr.ref_missing = true;
@@ -78,7 +78,7 @@
 	public override void visit_field (Field f) {
 		if (f.initializer != null) {
 			if (!(f.field_type is PointerType)) {
-				if (f.field_type.takes_ownership) {
+				if (f.field_type.value_owned) {
 					visit_possibly_missing_copy_expression (f.initializer);
 				} else {
 					visit_possibly_leaked_expression (f.initializer);
@@ -131,7 +131,7 @@
 
 		if (local.initializer != null) {
 			if (!(local.variable_type is PointerType)) {
-				if (local.variable_type.takes_ownership) {
+				if (local.variable_type.value_owned) {
 					visit_possibly_missing_copy_expression (local.initializer);
 				} else {
 					visit_possibly_leaked_expression (local.initializer);
@@ -180,7 +180,7 @@
 				var m = (Method) current_symbol;
 				
 				if (!(m.return_type is PointerType)) {
-					if (m.return_type.transfers_ownership) {
+					if (m.return_type.value_owned) {
 						visit_possibly_missing_copy_expression (stmt.return_expression);
 					} else {
 						visit_possibly_leaked_expression (stmt.return_expression);
@@ -189,7 +189,7 @@
 			} else if (current_symbol is Property) {
 				/* property get accessor */
 				var prop = (Property) current_symbol;
-				if (prop.property_type.transfers_ownership) {
+				if (prop.property_type.value_owned) {
 					visit_possibly_missing_copy_expression (stmt.return_expression);
 				} else {
 					visit_possibly_leaked_expression (stmt.return_expression);
@@ -215,11 +215,7 @@
 	public override void visit_array_creation_expression (ArrayCreationExpression e) {
 		if (e.initializer_list != null) {
 			foreach (Expression init in e.initializer_list.get_initializers ()) {
-				if (init.value_type.is_reference_type_or_type_parameter ()) {
-					visit_possibly_missing_copy_expression (init);
-				} else {
-					visit_possibly_leaked_expression (init);
-				}
+				visit_possibly_missing_copy_expression (init);
 			}
 		}
 	}
@@ -245,14 +241,14 @@
 			if (params_it.next ()) {
 				var param = params_it.get ();
 				if (!param.ellipsis
-				    && param.parameter_type.is_reference_type_or_type_parameter ()) {
-					bool is_ref = param.parameter_type.transfers_ownership;
+				    && param.direction == ParameterDirection.IN) {
+					bool is_ref = param.parameter_type.value_owned;
 					if (is_ref && param.parameter_type.type_parameter != null) {
 						if (expr.call is MemberAccess) {
 							var ma = (MemberAccess) expr.call;
 							var param_type = SemanticAnalyzer.get_actual_type (ma.inner.value_type, ma.symbol_reference, param.parameter_type, expr);
 							if (param_type != null) {
-								is_ref = param_type.takes_ownership;
+								is_ref = param_type.value_owned;
 							}
 						}
 					}
@@ -286,12 +282,12 @@
 			if (params_it.next ()) {
 				var param = params_it.get ();
 				if (!param.ellipsis
-				    && param.parameter_type.is_reference_type_or_type_parameter ()) {
-					bool is_ref = param.parameter_type.transfers_ownership;
+				    && param.direction == ParameterDirection.IN) {
+					bool is_ref = param.parameter_type.value_owned;
 					if (is_ref && param.parameter_type.type_parameter != null) {
 						var param_type = SemanticAnalyzer.get_actual_type (expr.type_reference, msym, param.parameter_type, expr);
 						if (param_type != null) {
-							is_ref = param_type.takes_ownership;
+							is_ref = param_type.value_owned;
 						}
 					}
 					
@@ -309,6 +305,10 @@
 		}
 	}
 
+	public override void visit_reference_transfer_expression (ReferenceTransferExpression expr) {
+		expr.accept_children (this);
+	}
+
 	public override void visit_binary_expression (BinaryExpression expr) {
 		visit_possibly_leaked_expression (expr.left);
 		visit_possibly_leaked_expression (expr.right);
@@ -324,7 +324,7 @@
 		if (a.left is PointerIndirection || a.left.symbol_reference is Signal) {
 		} else {
 			if (!(a.left.value_type is PointerType)) {
-				if (a.left.value_type.takes_ownership) {
+				if (a.left.value_type.value_owned) {
 					visit_possibly_missing_copy_expression (a.right);
 				} else {
 					visit_possibly_leaked_expression (a.right);

Modified: trunk/vala/valanullchecker.vala
==============================================================================
--- trunk/vala/valanullchecker.vala	(original)
+++ trunk/vala/valanullchecker.vala	Fri May 16 19:24:58 2008
@@ -229,6 +229,10 @@
 		}
 	}
 
+	public override void visit_reference_transfer_expression (ReferenceTransferExpression expr) {
+		expr.accept_children (this);
+	}
+
 	public override void visit_conditional_expression (ConditionalExpression expr) {
 		check_non_null (expr.condition);
 	}

Modified: trunk/vala/valaparser.vala
==============================================================================
--- trunk/vala/valaparser.vala	(original)
+++ trunk/vala/valaparser.vala	Fri May 16 19:24:58 2008
@@ -377,7 +377,7 @@
 			Report.warning (get_last_src (), "obsolete syntax, types are non-null by default");
 		}
 
-		bool transfers_ownership = accept (TokenType.HASH);
+		bool value_owned = accept (TokenType.HASH);
 
 		var type = new UnresolvedType.from_symbol (sym, get_src (begin));
 		if (type_arg_list != null) {
@@ -390,7 +390,7 @@
 		type.pointer_level = stars;
 		type.array_rank = array_rank;
 		type.nullable = nullable;
-		type.transfers_ownership = transfers_ownership;
+		type.value_owned = value_owned;
 		return type;
 	}
 
@@ -1314,7 +1314,7 @@
 			variable_type = parse_type ();
 			var ut = variable_type as UnresolvedType;
 			if (ut != null && !ut.is_weak) {
-				variable_type.takes_ownership = true;
+				variable_type.value_owned = true;
 			}
 		}
 		do {
@@ -1451,7 +1451,7 @@
 					variable_type = parse_type ();
 					var ut = variable_type as UnresolvedType;
 					if (ut != null && !ut.is_weak) {
-						variable_type.takes_ownership = true;
+						variable_type.value_owned = true;
 					}
 				}
 				var local = parse_local_variable (variable_type);
@@ -1495,7 +1495,7 @@
 		var type = parse_type ();
 		var unresolved_type = type as UnresolvedType;
 		if (unresolved_type != null && !unresolved_type.is_weak) {
-			unresolved_type.takes_ownership = true;
+			unresolved_type.value_owned = true;
 		}
 		string id = parse_identifier ();
 		expect (TokenType.IN);
@@ -1986,7 +1986,7 @@
 		var type = parse_type ();
 		var unresolved_type = type as UnresolvedType;
 		if (unresolved_type != null && !unresolved_type.is_weak) {
-			unresolved_type.takes_ownership = true;
+			unresolved_type.value_owned = true;
 		}
 		string id = parse_identifier ();
 		var f = new Field (id, type, null, get_src_com (begin));
@@ -2034,7 +2034,7 @@
 		var type = parse_type ();
 		var unresolved_type = type as UnresolvedType;
 		if (unresolved_type != null && !unresolved_type.is_weak) {
-			unresolved_type.transfers_ownership = true;
+			unresolved_type.value_owned = true;
 		}
 		string id = parse_identifier ();
 		parse_type_parameter_list ();
@@ -2095,10 +2095,6 @@
 		var access = parse_access_modifier ();
 		var flags = parse_member_declaration_modifiers ();
 		var type = parse_type ();
-		var ut = type as UnresolvedType;
-		if (ut != null && !ut.is_weak) {
-			type.takes_ownership = true;
-		}
 		string id = parse_identifier ();
 		var prop = new Property (id, type, null, null, get_src_com (begin));
 		prop.access = access;
@@ -2550,12 +2546,12 @@
 		var type = parse_type ();
 		var ut = type as UnresolvedType;
 		if (ut != null) {
-			if (!ut.is_weak) {
-				ut.takes_ownership = true;
-			}
-			if (direction == ParameterDirection.IN && !ut.transfers_ownership) {
-				//  take_ownership for in parameters that don't transfer ownership is not supported
-				ut.takes_ownership = false;
+			if (direction != ParameterDirection.IN && !ut.is_weak) {
+				ut.value_owned = true;
+			} else if (direction == ParameterDirection.IN && ut.is_weak) {
+				Report.error (type.source_reference, "in parameters are weak by default");
+			} else if (direction != ParameterDirection.IN && ut.value_owned) {
+				Report.error (type.source_reference, "out parameters own the value by default");
 			}
 		}
 		string id = parse_identifier ();
@@ -2610,7 +2606,7 @@
 		var type = parse_type ();
 		var unresolved_type = type as UnresolvedType;
 		if (unresolved_type != null && !unresolved_type.is_weak) {
-			unresolved_type.transfers_ownership = true;
+			unresolved_type.value_owned = true;
 		}
 		var sym = parse_symbol_name ();
 		var type_param_list = parse_type_parameter_list ();
@@ -2689,7 +2685,7 @@
 					var type = parse_type ();
 					var ut = type as UnresolvedType;
 					if (ut != null && !ut.is_weak) {
-						type.takes_ownership = true;
+						type.value_owned = true;
 					}
 					list.add (type);
 					break;

Modified: trunk/vala/valareferencetransferexpression.vala
==============================================================================
--- trunk/vala/valareferencetransferexpression.vala	(original)
+++ trunk/vala/valareferencetransferexpression.vala	Fri May 16 19:24:58 2008
@@ -1,6 +1,6 @@
 /* valareferencetransferexpression.vala
  *
- * Copyright (C) 2007  JÃrg Billeter
+ * Copyright (C) 2007-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
@@ -48,15 +48,17 @@
 	 * @return      newly created reference transfer expression
 	 */
 	public ReferenceTransferExpression (Expression inner, SourceReference? source_reference = null) {
-		this.source_reference = source_reference;
 		this.inner = inner;
+		this.source_reference = source_reference;
 	}
 	
 	public override void accept (CodeVisitor visitor) {
-		inner.accept (visitor);
-
 		visitor.visit_reference_transfer_expression (this);
 	}
+	
+	public override void accept_children (CodeVisitor visitor) {
+		inner.accept (visitor);
+	}
 
 	public override void replace_expression (Expression old_node, Expression new_node) {
 		if (inner == old_node) {

Modified: trunk/vala/valasemanticanalyzer.vala
==============================================================================
--- trunk/vala/valasemanticanalyzer.vala	(original)
+++ trunk/vala/valasemanticanalyzer.vala	Fri May 16 19:24:58 2008
@@ -670,7 +670,7 @@
 		    prop.property_type.data_type != null &&
 		    prop.property_type.data_type.is_reference_type () &&
 		    !prop.property_type.data_type.is_reference_counting () &&
-		    !prop.property_type.transfers_ownership)
+		    !prop.property_type.value_owned)
 		{
 			Report.error (prop.source_reference, "%s: abstract or virtual properties using reference types not supporting reference counting, like `%s', have to mark their return value to transfer ownership.".printf (prop.get_full_name (), prop.property_type.data_type.get_full_name ()));
 			prop.error = true;
@@ -740,7 +740,6 @@
 
 			if (acc.body != null && (acc.writable || acc.construction)) {
 				var value_type = acc.prop.property_type.copy ();
-				value_type.takes_ownership = value_type.transfers_ownership;
 				acc.value_parameter = new FormalParameter ("value", value_type, acc.source_reference);
 				acc.body.scope.add (acc.value_parameter.name, acc.value_parameter);
 			}
@@ -814,12 +813,7 @@
 			}
 
 			local.variable_type = local.initializer.value_type.copy ();
-			local.variable_type.takes_ownership = (local.variable_type.data_type == null || local.variable_type.data_type.is_reference_type ());
-			local.variable_type.transfers_ownership = false;
-
-			if (local.variable_type is PointerType) {
-				local.variable_type.takes_ownership = false;
-			}
+			local.variable_type.value_owned = true;
 		}
 
 		if (local.initializer != null) {
@@ -857,9 +851,9 @@
 				return;
 			}
 
-			if (local.initializer.value_type.transfers_ownership) {
+			if (local.initializer.value_type.value_owned) {
 				/* rhs transfers ownership of the expression */
-				if (!(local.variable_type is PointerType) && !local.variable_type.takes_ownership) {
+				if (!(local.variable_type is PointerType) && !local.variable_type.value_owned) {
 					/* lhs doesn't own the value */
 					local.error = true;
 					Report.error (local.source_reference, "Invalid assignment from owned expression to unowned variable");
@@ -1073,8 +1067,6 @@
 		}
 
 		var collection_type = stmt.collection.value_type.copy ();
-		collection_type.transfers_ownership = false;
-		collection_type.takes_ownership = stmt.collection.value_type.transfers_ownership;
 		stmt.collection_variable = new LocalVariable (collection_type, "%s_collection".printf (stmt.variable_name));
 
 		stmt.add_local_variable (stmt.collection_variable);
@@ -1094,7 +1086,7 @@
 			}
 		} else if (iterable_type != null && collection_type.compatible (iterable_type)) {
 			var foreach_iterator_type = new InterfaceInstanceType (iterator_type);
-			foreach_iterator_type.takes_ownership = true;
+			foreach_iterator_type.value_owned = true;
 			foreach_iterator_type.add_type_argument (stmt.type_reference);
 			stmt.iterator_variable = new LocalVariable (foreach_iterator_type, "%s_it".printf (stmt.variable_name));
 
@@ -1162,8 +1154,8 @@
 		}
 
 		if (stmt.return_expression != null &&
-		    stmt.return_expression.value_type.transfers_ownership &&
-		    !current_return_type.transfers_ownership) {
+		    stmt.return_expression.value_type.value_owned &&
+		    !current_return_type.value_owned) {
 			stmt.error = true;
 			Report.error (stmt.source_reference, "Return value transfers ownership but method return type hasn't been declared to transfer ownership");
 			return;
@@ -1171,8 +1163,8 @@
 
 		if (stmt.return_expression != null &&
 		    stmt.return_expression.symbol_reference is LocalVariable &&
-		    stmt.return_expression.value_type.takes_ownership &&
-		    !current_return_type.transfers_ownership) {
+		    stmt.return_expression.value_type.value_owned &&
+		    !current_return_type.value_owned) {
 			Report.warning (stmt.source_reference, "Local variable with strong reference used as return value and method return type hasn't been declared to transfer ownership");
 		}
 
@@ -1343,18 +1335,10 @@
 			return;
 		}
 
-		/* arrays of struct type elements do not take ownership since they are copied into the array */
-		if (expr.element_type.data_type is Struct) {
-			expr.element_type.takes_ownership = false;
-		} else {
-			expr.element_type.takes_ownership = true;
-		}
+		expr.element_type.value_owned = true;
 
 		expr.value_type = new ArrayType (expr.element_type, expr.rank, expr.source_reference);
-		expr.value_type.transfers_ownership = true;
-		expr.value_type.takes_ownership = true;
-
-		expr.value_type.add_type_argument (expr.element_type);
+		expr.value_type.value_owned = true;
 	}
 
 	public override void visit_boolean_literal (BooleanLiteral expr) {
@@ -1383,28 +1367,36 @@
 		expr.value_type = new NullType (expr.source_reference);
 	}
 
-	private DataType? get_value_type_for_symbol (Symbol sym) {
+	private DataType? get_value_type_for_symbol (Symbol sym, bool lvalue) {
 		if (sym is Field) {
 			var f = (Field) sym;
-			return f.field_type;
+			var type = f.field_type.copy ();
+			if (!lvalue) {
+				type.value_owned = false;
+			}
+			return type;
 		} else if (sym is Constant) {
 			var c = (Constant) sym;
 			return c.type_reference;
 		} else if (sym is Property) {
 			var prop = (Property) sym;
 			var type = prop.property_type.copy ();
-			type.takes_ownership = false;
+			type.value_owned = false;
 			return type;
 		} else if (sym is FormalParameter) {
 			var p = (FormalParameter) sym;
 			var type = p.parameter_type.copy ();
-			type.transfers_ownership = false;
+			if (!lvalue) {
+				type.value_owned = false;
+			}
 			return type;
-		} else if (sym is DataType) {
-			return (DataType) sym;
 		} else if (sym is LocalVariable) {
 			var local = (LocalVariable) sym;
-			return local.variable_type;
+			var type = local.variable_type.copy ();
+			if (!lvalue) {
+				type.value_owned = false;
+			}
+			return type;
 		} else if (sym is EnumValue) {
 			return new ValueType ((Typesymbol) sym.parent_symbol);
 		} else if (sym is Method) {
@@ -1598,7 +1590,7 @@
 					DataType ret_type;
 					if (invoc.expected_type != null) {
 						ret_type = invoc.expected_type.copy ();
-						ret_type.transfers_ownership = ret_type.is_reference_type_or_type_parameter ();
+						ret_type.value_owned = true;
 					} else {
 						ret_type = new VoidType ();
 					}
@@ -1709,12 +1701,12 @@
 				// also set static type for prototype access
 				// required when using instance methods as delegates in constants
 				// TODO replace by MethodPrototype
-				expr.value_type = get_value_type_for_symbol (expr.symbol_reference);
+				expr.value_type = get_value_type_for_symbol (expr.symbol_reference, expr.lvalue);
 			} else if (expr.symbol_reference is Field) {
 				expr.value_type = new FieldPrototype ((Field) expr.symbol_reference);
 			}
 		} else {
-			expr.value_type = get_value_type_for_symbol (expr.symbol_reference);
+			expr.value_type = get_value_type_for_symbol (expr.symbol_reference, expr.lvalue);
 
 			// resolve generic return values
 			if (expr.value_type != null && expr.value_type.type_parameter != null) {
@@ -2094,8 +2086,7 @@
 			return generic_type;
 		}
 		actual_type = actual_type.copy ();
-		actual_type.transfers_ownership = actual_type.takes_ownership && generic_type.transfers_ownership;
-		actual_type.takes_ownership = actual_type.takes_ownership && generic_type.takes_ownership;
+		actual_type.value_owned = actual_type.value_owned && generic_type.value_owned;
 		return actual_type;
 	}
 
@@ -2114,15 +2105,11 @@
 
 		/* assign a value_type when possible */
 		if (expr.container.value_type is ArrayType) {
-			var args = expr.container.value_type.get_type_arguments ();
-
-			if (args.size != 1) {
-				expr.error = true;
-				Report.error (expr.source_reference, "internal error: array reference with %d type arguments, expected 1".printf (args.size));
-				return;
+			var array_type = (ArrayType) expr.container.value_type;
+			expr.value_type = array_type.element_type.copy ();
+			if (!expr.lvalue) {
+				expr.value_type.value_owned = false;
 			}
-
-			expr.value_type = args.get (0);
 		} else if (pointer_type != null && !pointer_type.base_type.is_reference_type_or_type_parameter ()) {
 			expr.value_type = pointer_type.base_type.copy ();
 		} else if (container_type == string_type.data_type) {
@@ -2171,7 +2158,10 @@
 			}
 
 			expr.value_type = get_actual_type (expr.container.value_type, get_method, get_method.return_type, expr).copy ();
-			expr.value_type.takes_ownership = false;
+			if (expr.lvalue) {
+				// get () returns owned value, set () accepts unowned value
+				expr.value_type.value_owned = false;
+			}
 		} else {
 			expr.error = true;
 			Report.error (expr.source_reference, "The expression `%s' does not denote an Array".printf (expr.container.value_type.to_string ()));
@@ -2320,7 +2310,7 @@
 		current_source_file.add_symbol_dependency (type, SourceFileDependencyType.SOURCE);
 
 		expr.value_type = expr.type_reference.copy ();
-		expr.value_type.transfers_ownership = true;
+		expr.value_type.value_owned = true;
 
 		int given_num_type_args = expr.type_reference.get_type_arguments ().size;
 		int expected_num_type_args = 0;
@@ -2371,8 +2361,6 @@
 				Report.warning (expr.source_reference, "deprecated syntax, don't use `new' to initialize structs");
 			}
 
-			expr.value_type.transfers_ownership = false;
-
 			if (expr.symbol_reference == null) {
 				expr.symbol_reference = st.default_construction_method;
 			}
@@ -2601,7 +2589,7 @@
 		current_source_file.add_type_dependency (expr.type_reference, SourceFileDependencyType.SOURCE);
 
 		expr.value_type = expr.type_reference;
-		expr.value_type.transfers_ownership = expr.inner.value_type.transfers_ownership;
+		expr.value_type.value_owned = expr.inner.value_type.value_owned;
 	}
 
 	public override void visit_pointer_indirection (PointerIndirection expr) {
@@ -2649,6 +2637,10 @@
 	}
 
 	public override void visit_reference_transfer_expression (ReferenceTransferExpression expr) {
+		expr.inner.lvalue = true;
+
+		expr.accept_children (this);
+
 		if (expr.inner.error) {
 			/* if there was an error in the inner expression, skip type check */
 			expr.error = true;
@@ -2661,7 +2653,7 @@
 			return;
 		}
 
-		if (!expr.inner.value_type.takes_ownership
+		if (!expr.inner.value_type.value_owned
 		    && !(expr.inner.value_type is PointerType)) {
 			expr.error = true;
 			Report.error (expr.source_reference, "No reference to be transferred");
@@ -2669,8 +2661,7 @@
 		}
 
 		expr.value_type = expr.inner.value_type.copy ();
-		expr.value_type.transfers_ownership = true;
-		expr.value_type.takes_ownership = false;
+		expr.value_type.value_owned = true;
 	}
 
 	private DataType? get_arithmetic_result_type (DataType left_type, DataType right_type) {
@@ -3138,14 +3129,14 @@
 					return;
 				}
 
-				if (a.right.value_type.transfers_ownership) {
+				if (a.right.value_type.value_owned) {
 					/* rhs transfers ownership of the expression */
-					if (!(a.left.value_type is PointerType) && !a.left.value_type.takes_ownership) {
+					if (!(a.left.value_type is PointerType) && !a.left.value_type.value_owned) {
 						/* lhs doesn't own the value */
 						a.error = true;
 						Report.error (a.source_reference, "Invalid assignment from owned expression to unowned variable");
 					}
-				} else if (a.left.value_type.takes_ownership) {
+				} else if (a.left.value_type.value_owned) {
 					/* lhs wants to own the value
 					 * rhs doesn't transfer the ownership
 					 * code generator needs to add reference
@@ -3161,24 +3152,27 @@
 				return;
 			}
 
-			if (a.right.value_type.transfers_ownership) {
+			if (a.right.value_type.value_owned) {
 				/* rhs transfers ownership of the expression */
 
-				var args = ea.container.value_type.get_type_arguments ();
-				if (args.size != 1) {
-					a.error = true;
-					Report.error (ea.source_reference, "internal error: array reference with %d type arguments".printf (args.size));
-					return;
+				DataType element_type;
+
+				if (ea.container.value_type is ArrayType) {
+					var array_type = (ArrayType) ea.container.value_type;
+					element_type = array_type.element_type;
+				} else {
+					var args = ea.container.value_type.get_type_arguments ();
+					assert (args.size == 1);
+					element_type = args.get (0);
 				}
-				var element_type = args.get (0);
 
-				if (!(element_type is PointerType) && !element_type.takes_ownership) {
+				if (!(element_type is PointerType) && !element_type.value_owned) {
 					/* lhs doesn't own the value */
 					a.error = true;
 					Report.error (a.source_reference, "Invalid assignment from owned expression to unowned variable");
 					return;
 				}
-			} else if (a.left.value_type.takes_ownership) {
+			} else if (a.left.value_type.value_owned) {
 				/* lhs wants to own the value
 				 * rhs doesn't transfer the ownership
 				 * code generator needs to add reference
@@ -3192,7 +3186,7 @@
 			a.value_type = a.left.value_type.copy ();
 			if (a.parent_node is ExpressionStatement) {
 				// Gee.List.get () transfers ownership but void function Gee.List.set () doesn't
-				a.value_type.transfers_ownership = false;
+				a.value_type.value_owned = false;
 			}
 		} else {
 			a.value_type = null;

Modified: trunk/vala/valasymbolresolver.vala
==============================================================================
--- trunk/vala/valasymbolresolver.vala	(original)
+++ trunk/vala/valasymbolresolver.vala	Fri May 16 19:24:58 2008
@@ -273,8 +273,7 @@
 		}
 
 		type.source_reference = unresolved_type.source_reference;
-		type.takes_ownership = unresolved_type.takes_ownership;
-		type.transfers_ownership = unresolved_type.transfers_ownership;
+		type.value_owned = unresolved_type.value_owned;
 		type.nullable = unresolved_type.nullable;
 		type.is_dynamic = unresolved_type.is_dynamic;
 		foreach (DataType type_arg in unresolved_type.get_type_arguments ()) {
@@ -283,36 +282,23 @@
 
 		for (int pointer_level = unresolved_type.pointer_level; pointer_level > 0; pointer_level--) {
 			var base_type = type;
-			base_type.takes_ownership = false;
-			base_type.transfers_ownership = false;
+			base_type.value_owned = false;
 			base_type.nullable = false;
 			base_type.is_dynamic = false;
 
 			type = new PointerType (base_type);
 		}
 
-		if (!type.is_reference_type_or_type_parameter ()) {
-			/* reset takes_ownership and transfers_ownership of
-			 * value-types for contexts where types are ref by
-			 * default (field declarations and method return types)
-			 */
-			type.takes_ownership = false;
-			type.transfers_ownership = false;
-		}
-
 		/* check for array */
 		if (unresolved_type.array_rank > 0) {
 			var element_type = type;
 			// array contains strong references by default
-			element_type.takes_ownership = element_type.is_reference_type_or_type_parameter ();
-			element_type.transfers_ownership = false;
+			element_type.value_owned = true;
 			element_type.nullable = false;
 
 			type = new ArrayType (element_type, unresolved_type.array_rank, unresolved_type.source_reference);
-			type.add_type_argument (element_type);
 
-			type.takes_ownership = unresolved_type.takes_ownership;
-			type.transfers_ownership = unresolved_type.transfers_ownership;
+			type.value_owned = unresolved_type.value_owned;
 			type.nullable = unresolved_type.nullable;
 		}
 
@@ -396,6 +382,10 @@
 		expr.accept_children (this);
 	}
 
+	public override void visit_reference_transfer_expression (ReferenceTransferExpression expr) {
+		expr.accept_children (this);
+	}
+
 	public override void visit_lambda_expression (LambdaExpression l) {
 		l.accept_children (this);
 	}

Modified: trunk/vala/valatypeparametertype.vala
==============================================================================
--- trunk/vala/valatypeparametertype.vala	(original)
+++ trunk/vala/valatypeparametertype.vala	Fri May 16 19:24:58 2008
@@ -33,8 +33,7 @@
 	public override DataType copy () {
 		var result = new TypeParameterType (type_parameter);
 		result.source_reference = source_reference;
-		result.transfers_ownership = transfers_ownership;
-		result.takes_ownership = takes_ownership;
+		result.value_owned = value_owned;
 		result.nullable = nullable;
 		result.floating_reference = floating_reference;
 
@@ -42,7 +41,7 @@
 	}
 
 	public override string? get_cname () {
-		if (takes_ownership || transfers_ownership) {
+		if (value_owned) {
 			return "gpointer";
 		} else {
 			return "gconstpointer";

Modified: trunk/vala/valaunresolvedtype.vala
==============================================================================
--- trunk/vala/valaunresolvedtype.vala	(original)
+++ trunk/vala/valaunresolvedtype.vala	Fri May 16 19:24:58 2008
@@ -105,8 +105,7 @@
 	public override DataType copy () {
 		var result = new UnresolvedType ();
 		result.source_reference = source_reference;
-		result.transfers_ownership = transfers_ownership;
-		result.takes_ownership = takes_ownership;
+		result.value_owned = value_owned;
 		result.nullable = nullable;
 		result.is_dynamic = is_dynamic;
 		result.unresolved_symbol = unresolved_symbol.copy ();

Modified: trunk/vala/valavaluetype.vala
==============================================================================
--- trunk/vala/valavaluetype.vala	(original)
+++ trunk/vala/valavaluetype.vala	Fri May 16 19:24:58 2008
@@ -39,8 +39,7 @@
 	public override DataType copy () {
 		var result = new ValueType (type_symbol);
 		result.source_reference = source_reference;
-		result.transfers_ownership = transfers_ownership;
-		result.takes_ownership = takes_ownership;
+		result.value_owned = value_owned;
 		result.nullable = nullable;
 		result.is_dynamic = is_dynamic;
 		result.floating_reference = floating_reference;

Modified: trunk/vapi/glib-2.0.vapi
==============================================================================
--- trunk/vapi/glib-2.0.vapi	(original)
+++ trunk/vapi/glib-2.0.vapi	Fri May 16 19:24:58 2008
@@ -2212,7 +2212,7 @@
 		public void get_description ();
 		public void set_translate_func (TranslateFunc func, DestroyNotify? destroy_notify);
 		public void set_translation_domain (string domain);
-		public bool parse ([CCode (array_length_pos = 0.9)] ref string[] argv) throws OptionError;
+		public bool parse ([CCode (array_length_pos = 0.9)] ref weak string[] argv) throws OptionError;
 		public void set_help_enabled (bool help_enabled);
 		public bool get_help_enabled ();
 		public void set_ignore_unknown_options (bool ignore_unknown);
@@ -2539,7 +2539,7 @@
 		public static void minimized_result (double minimized_quantity, string format, ...);
 		[PrintfFormat]
 		public static void maximized_result (double maximized_quantity, string format, ...);
-		public static void init ([CCode (array_length_pos = 0.9)] ref string[] args, ...);
+		public static void init ([CCode (array_length_pos = 0.9)] ref weak string[] args, ...);
 		public static bool quick ();
 		public static bool slow ();
 		public static bool thorough ();

Modified: trunk/vapigen/valagidlparser.vala
==============================================================================
--- trunk/vapigen/valagidlparser.vala	(original)
+++ trunk/vapigen/valagidlparser.vala	Fri May 16 19:24:58 2008
@@ -1138,7 +1138,7 @@
 
 		return false;
 	}
-	
+
 	private DataType parse_type_string (string n) {
 		if (n == "va_list") {
 			// unsupported
@@ -1267,7 +1267,7 @@
 					}
 				} else if (nv[0] == "transfer_ownership") {
 					if (eval (nv[1]) == "1") {
-						return_type.transfers_ownership = true;
+						return_type.value_owned = true;
 					}
 				} else if (nv[0] == "sentinel") {
 					m.sentinel = eval (nv[1]);
@@ -1289,7 +1289,7 @@
 					var type_args = eval (nv[1]).split (",");
 					foreach (string type_arg in type_args) {
 						var arg_type = new UnresolvedType.from_symbol (new UnresolvedSymbol (null, type_arg));
-						arg_type.takes_ownership = true;
+						arg_type.value_owned = true;
 						return_type.add_type_argument (arg_type);
 					}
 				}
@@ -1366,11 +1366,17 @@
 						}
 					} else if (nv[0] == "transfer_ownership") {
 						if (eval (nv[1]) == "1") {
-							param_type.transfers_ownership = true;
+							param_type.value_owned = true;
 						}
 					} else if (nv[0] == "takes_ownership") {
 						if (eval (nv[1]) == "1") {
-							param_type.takes_ownership = true;
+							param_type.value_owned = true;
+						}
+					} else if (nv[0] == "value_owned") {
+						if (eval (nv[1]) == "0") {
+							param_type.value_owned = false;
+						} else if (eval (nv[1]) == "1") {
+							param_type.value_owned = true;
 						}
 					} else if (nv[0] == "hidden") {
 						if (eval (nv[1]) == "1") {
@@ -1390,7 +1396,7 @@
 						var type_args = eval (nv[1]).split (",");
 						foreach (string type_arg in type_args) {
 							var arg_type = new UnresolvedType.from_symbol (new UnresolvedSymbol (null, type_arg));
-							arg_type.takes_ownership = true;
+							arg_type.value_owned = true;
 							param_type.add_type_argument (arg_type);
 						}
 					}
@@ -1588,7 +1594,7 @@
 					}
 				} else if (nv[0] == "weak") {
 					if (eval (nv[1]) == "0") {
-						type.takes_ownership = true;
+						type.value_owned = true;
 					}
 				} else if (nv[0] == "type_name") {
 					((UnresolvedType) type).unresolved_symbol = new UnresolvedSymbol (null, eval (nv[1]));



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