Commit 8f52fd59 authored by Jürg Billeter's avatar Jürg Billeter Committed by Jürg Billeter
Browse files

fix implicit casts to support non-GObject classes, enable run-time checks

2007-09-01  Juerg Billeter  <j@bitron.ch>

	* vala/valalockable.vala, gobject/valacodegenerator.vala,
	  gobject/valacodegeneratorassignment.vala,
	  gobject/valacodegeneratorclass.vala,
	  gobject/valacodegeneratorinvocationexpression.vala,
	  gobject/valacodegeneratormemberaccess.vala,
	  gobject/valacodegeneratormethod.vala, compiler/valacompiler.vala:
	  fix implicit casts to support non-GObject classes, enable run-time
	  checks by default, fixes bug 472446

svn path=/trunk/; revision=567
parent 46044c7e
2007-09-01 Jürg Billeter <j@bitron.ch>
* vala/valalockable.vala, gobject/valacodegenerator.vala,
gobject/valacodegeneratorassignment.vala,
gobject/valacodegeneratorclass.vala,
gobject/valacodegeneratorinvocationexpression.vala,
gobject/valacodegeneratormemberaccess.vala,
gobject/valacodegeneratormethod.vala, compiler/valacompiler.vala:
fix implicit casts to support non-GObject classes, enable run-time
checks by default, fixes bug 472446
2007-09-01 Mathias Hasselmann <mathias.hasselmann@gmx.de>
* vapi/packages/pango/pango.metadata: mark
......
......@@ -41,7 +41,7 @@ class Vala.Compiler : Object {
static bool thread;
static int optlevel;
static bool disable_assert;
static bool enable_checking;
static bool disable_checking;
static string cc_command;
[NoArrayLength]
static string[] cc_options;
......@@ -63,7 +63,7 @@ class Vala.Compiler : Object {
{ "thread", 0, 0, OptionArg.NONE, ref thread, "Enable multithreading support", null },
{ "optimize", 'O', 0, OptionArg.INT, ref optlevel, "Optimization level", "OPTLEVEL" },
{ "disable-assert", 0, 0, OptionArg.NONE, ref disable_assert, "Disable assertions", null },
{ "enable-checking", 0, 0, OptionArg.NONE, ref enable_checking, "Enable run-time checks", null },
{ "disable-checking", 0, 0, OptionArg.NONE, ref disable_checking, "Disable run-time checks", null },
{ "cc", 0, 0, OptionArg.STRING, out cc_command, "Use COMMAND as C compiler command", "COMMAND" },
{ "Xcc", 'X', 0, OptionArg.STRING_ARRAY, out cc_options, "Pass OPTION to the C compiler", "OPTION..." },
{ "save-temps", 0, 0, OptionArg.NONE, out save_temps, "Keep temporary files", null },
......@@ -159,7 +159,7 @@ class Vala.Compiler : Object {
context.library = library;
context.memory_management = !disable_memory_management;
context.assert = !disable_assert;
context.checking = enable_checking;
context.checking = !disable_checking;
context.ccode_only = ccode_only;
context.compile_only = compile_only;
......
......@@ -97,6 +97,7 @@ public class Vala.CodeGenerator : CodeVisitor {
TypeReference string_type;
TypeReference float_type;
TypeReference double_type;
DataType gtypeinstance_type;
DataType gobject_type;
DataType gerror_type;
DataType glist_type;
......@@ -248,6 +249,7 @@ public class Vala.CodeGenerator : CodeVisitor {
var glib_ns = root_symbol.scope.lookup ("GLib");
gtypeinstance_type = (DataType) glib_ns.scope.lookup ("TypeInstance");
gobject_type = (DataType) glib_ns.scope.lookup ("Object");
gerror_type = (DataType) glib_ns.scope.lookup ("Error");
glist_type = (DataType) glib_ns.scope.lookup ("List");
......@@ -469,13 +471,7 @@ public class Vala.CodeGenerator : CodeVisitor {
if (f.initializer != null) {
var rhs = (CCodeExpression) f.initializer.ccodenode;
if (f.type_reference.data_type != null
&& f.initializer.static_type.data_type != null
&& f.type_reference.data_type.is_reference_type ()
&& f.initializer.static_type.data_type != f.type_reference.data_type) {
// FIXME: use C cast if debugging disabled
rhs = new InstanceCast (rhs, f.type_reference.data_type);
}
rhs = get_implicit_cast_expression (rhs, f.initializer.static_type, f.type_reference);
instance_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (lhs, rhs)));
......@@ -713,9 +709,8 @@ public class Vala.CodeGenerator : CodeVisitor {
cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("obj"), ccall)));
ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_upper_case_cname (null)));
ccall.add_argument (new CCodeIdentifier ("obj"));
ccall = new InstanceCast (new CCodeIdentifier ("obj"), cl);
cdecl = new CCodeDeclaration ("%s *".printf (cl.get_cname ()));
cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("self", ccall));
......@@ -869,14 +864,7 @@ public class Vala.CodeGenerator : CodeVisitor {
CCodeExpression rhs = null;
if (decl.initializer != null) {
rhs = (CCodeExpression) decl.initializer.ccodenode;
if (decl.type_reference.data_type != null
&& decl.initializer.static_type.data_type != null
&& decl.type_reference.data_type.is_reference_type ()
&& decl.initializer.static_type.data_type != decl.type_reference.data_type) {
// FIXME: use C cast if debugging disabled
rhs = new InstanceCast (rhs, decl.type_reference.data_type);
}
rhs = get_implicit_cast_expression (rhs, decl.initializer.static_type, decl.type_reference);
if (decl.type_reference.data_type is Array) {
var arr = (Array) decl.type_reference.data_type;
......@@ -1780,14 +1768,7 @@ public class Vala.CodeGenerator : CodeVisitor {
create_local_free_expr (stmt.return_expression);
if (stmt.return_expression.static_type != null &&
stmt.return_expression.static_type.data_type != current_return_type.data_type) {
/* cast required */
if ((current_return_type.data_type is Class && ((Class) current_return_type.data_type).is_subtype_of (gobject_type)) ||
current_return_type.data_type is Interface) {
stmt.return_expression.ccodenode = new InstanceCast ((CCodeExpression) stmt.return_expression.ccodenode, current_return_type.data_type);
}
}
stmt.return_expression.ccodenode = get_implicit_cast_expression ((CCodeExpression) stmt.return_expression.ccodenode, stmt.return_expression.static_type, current_return_type);
stmt.ccodenode = new CCodeReturnStatement ((CCodeExpression) stmt.return_expression.ccodenode);
......@@ -1901,10 +1882,9 @@ public class Vala.CodeGenerator : CodeVisitor {
if (inner_node == null) {
l = new CCodeIdentifier ("self");
} else if (stmt.resource.symbol_reference.parent_symbol != current_type_symbol) {
l = new CCodeFunctionCall (new CCodeIdentifier (((DataType) stmt.resource.symbol_reference.parent_symbol).get_upper_case_cname ()));
((CCodeFunctionCall) l).add_argument ((CCodeExpression)inner_node.ccodenode);
l = new InstanceCast ((CCodeExpression) inner_node.ccodenode, (DataType) stmt.resource.symbol_reference.parent_symbol);
} else {
l = (CCodeExpression)inner_node.ccodenode;
l = (CCodeExpression) inner_node.ccodenode;
}
l = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (l, "priv"), get_symbol_lock_name (stmt.resource.symbol_reference));
......@@ -2088,14 +2068,12 @@ public class Vala.CodeGenerator : CodeVisitor {
}
if (field.instance) {
CCodeExpression typed_inst;
if (field.parent_symbol != base_type) {
// FIXME: use C cast if debugging disabled
typed_inst = new CCodeFunctionCall (new CCodeIdentifier (((DataType) field.parent_symbol).get_upper_case_cname (null)));
((CCodeFunctionCall) typed_inst).add_argument (pub_inst);
} else {
typed_inst = pub_inst;
}
var instance_expression_type = new TypeReference ();
instance_expression_type.data_type = base_type;
var instance_target_type = new TypeReference ();
instance_target_type.data_type = (DataType) field.parent_symbol;
CCodeExpression typed_inst = get_implicit_cast_expression (pub_inst, instance_expression_type, instance_target_type);
CCodeExpression inst;
if (field.access == SymbolAccessibility.PRIVATE) {
inst = new CCodeMemberAccess.pointer (typed_inst, "priv");
......@@ -2390,15 +2368,8 @@ public class Vala.CodeGenerator : CodeVisitor {
if (params_it.next ()) {
var param = params_it.get ();
ellipsis = param.ellipsis;
if (!param.ellipsis
&& param.type_reference.data_type != null
&& param.type_reference.data_type.is_reference_type ()
&& arg.static_type.data_type != null
&& param.type_reference.data_type != arg.static_type.data_type) {
// FIXME: use C cast if debugging disabled
var ccall = new CCodeFunctionCall (new CCodeIdentifier (param.type_reference.data_type.get_upper_case_cname (null)));
ccall.add_argument (cexpr);
cexpr = ccall;
if (!param.ellipsis) {
cexpr = get_implicit_cast_expression (cexpr, arg.static_type, param.type_reference);
}
}
......@@ -2496,7 +2467,7 @@ public class Vala.CodeGenerator : CodeVisitor {
}
public override void visit_cast_expression (CastExpression! expr) {
if ((expr.type_reference.data_type is Class && ((Class) expr.type_reference.data_type).is_subtype_of (gobject_type)) || expr.type_reference.data_type is Interface) {
if (expr.type_reference.data_type != null && expr.type_reference.data_type.is_subtype_of (gtypeinstance_type)) {
// GObject cast
if (expr.is_silent_cast) {
var ccomma = new CCodeCommaExpression ();
......@@ -2518,6 +2489,11 @@ public class Vala.CodeGenerator : CodeVisitor {
expr.ccodenode = new InstanceCast ((CCodeExpression) expr.inner.ccodenode, expr.type_reference.data_type);
}
} else {
if (expr.is_silent_cast) {
expr.error = true;
Report.error (expr.source_reference, "Operation not supported for this type");
return;
}
expr.ccodenode = new CCodeCastExpression ((CCodeExpression) expr.inner.ccodenode, expr.type_reference.get_cname ());
}
......@@ -2664,4 +2640,30 @@ public class Vala.CodeGenerator : CodeVisitor {
}
return result;
}
private CCodeExpression! get_implicit_cast_expression (CCodeExpression! cexpr, TypeReference! expression_type, TypeReference! target_type) {
if (expression_type.data_type == target_type.data_type) {
// same type, no cast required
return cexpr;
}
if (expression_type.type_parameter != null) {
return convert_from_generic_pointer (cexpr, target_type);
} else if (target_type.type_parameter != null) {
return convert_to_generic_pointer (cexpr, expression_type);
}
if (expression_type.data_type == null && expression_type.type_parameter == null) {
// null literal, no cast required when not converting to generic type pointer
return cexpr;
}
if (context.checking && target_type.data_type.is_subtype_of (gtypeinstance_type)) {
return new InstanceCast (cexpr, target_type.data_type);
} else if (target_type.data_type.is_reference_type () && expression_type.get_cname () != target_type.get_cname ()) {
return new CCodeCastExpression (cexpr, target_type.get_cname ());
} else {
return cexpr;
}
}
}
......@@ -65,18 +65,11 @@ public class Vala.CodeGenerator {
a.ccodenode = ccomma;
} else {
CCodeExpression cexpr = (CCodeExpression) a.right.ccodenode;
if (!prop.no_accessor_method
&& prop.type_reference.data_type != null
&& prop.type_reference.data_type.is_reference_type ()
&& a.right.static_type.data_type != null
&& prop.type_reference.data_type != a.right.static_type.data_type) {
/* cast is necessary */
var ccast = new CCodeFunctionCall (new CCodeIdentifier (prop.type_reference.data_type.get_upper_case_cname (null)));
ccast.add_argument (cexpr);
cexpr = ccast;
if (!prop.no_accessor_method) {
cexpr = get_implicit_cast_expression (cexpr, a.right.static_type, prop.type_reference);
}
if (a.operator != AssignmentOperator.SIMPLE) {
CCodeBinaryOperator cop;
if (a.operator == AssignmentOperator.BITWISE_OR) {
......@@ -264,16 +257,9 @@ public class Vala.CodeGenerator {
} else if (a.left is ElementAccess && !(((ElementAccess) a.left).container.static_type.data_type is Array)) {
// custom element access
CCodeExpression rhs = (CCodeExpression) a.right.ccodenode;
if (a.left.static_type.data_type != null
&& a.right.static_type.data_type != null
&& a.left.static_type.data_type.is_reference_type ()
&& a.right.static_type.data_type != a.left.static_type.data_type) {
var ccast = new CCodeFunctionCall (new CCodeIdentifier (a.left.static_type.data_type.get_upper_case_cname (null)));
ccast.add_argument (rhs);
rhs = ccast;
}
rhs = get_implicit_cast_expression (rhs, a.right.static_type, a.left.static_type);
var expr = (ElementAccess) a.left;
var container_type = expr.container.static_type.data_type;
Collection<Expression> indices = expr.get_indices ();
......@@ -308,16 +294,9 @@ public class Vala.CodeGenerator {
}
} else {
CCodeExpression rhs = (CCodeExpression) a.right.ccodenode;
if (a.left.static_type.data_type != null
&& a.right.static_type.data_type != null
&& a.left.static_type.data_type.is_reference_type ()
&& a.right.static_type.data_type != a.left.static_type.data_type) {
var ccast = new CCodeFunctionCall (new CCodeIdentifier (a.left.static_type.data_type.get_upper_case_cname (null)));
ccast.add_argument (rhs);
rhs = ccast;
}
rhs = get_implicit_cast_expression (rhs, a.right.static_type, a.left.static_type);
bool unref_old = (memory_management && a.left.static_type.takes_ownership);
bool array = false;
if (a.left.static_type.data_type is Array) {
......@@ -413,25 +392,21 @@ public class Vala.CodeGenerator {
/* target instance is first argument */
CCodeExpression instance;
var req_cast = false;
TypeReference instance_expression_type;
if (ma.inner == null) {
instance = new CCodeIdentifier ("self");
/* require casts for inherited properties */
req_cast = (base_property.parent_symbol != current_type_symbol);
instance_expression_type = new TypeReference ();
instance_expression_type.data_type = current_type_symbol;
} else {
instance = (CCodeExpression) ma.inner.ccodenode;
/* require casts if the type of the used instance is
* different than the type which declared the property */
req_cast = base_property.parent_symbol != ma.inner.static_type.data_type;
}
if (req_cast && ((DataType) prop.parent_symbol).is_reference_type ()) {
var ccast = new CCodeFunctionCall (new CCodeIdentifier (((DataType) base_property.parent_symbol).get_upper_case_cname (null)));
ccast.add_argument (instance);
instance = ccast;
instance_expression_type = ma.inner.static_type;
}
var instance_target_type = new TypeReference ();
instance_target_type.data_type = (DataType) base_property.parent_symbol;
instance = get_implicit_cast_expression (instance, instance_expression_type, instance_target_type);
ccall.add_argument (instance);
if (prop.no_accessor_method) {
......
......@@ -410,9 +410,8 @@ public class Vala.CodeGenerator {
var cblock = new CCodeBlock ();
var ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_upper_case_cname (null)));
ccall.add_argument (new CCodeIdentifier ("obj"));
CCodeFunctionCall ccall = new InstanceCast (new CCodeIdentifier ("obj"), cl);
var cdecl = new CCodeDeclaration ("%s *".printf (cl.get_cname ()));
cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("self", ccall));
......@@ -492,8 +491,7 @@ public class Vala.CodeGenerator {
var block = new CCodeBlock ();
var ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_upper_case_cname (null)));
ccall.add_argument (new CCodeIdentifier ("object"));
var ccall = new InstanceCast (new CCodeIdentifier ("object"), cl);
var cdecl = new CCodeDeclaration ("%s *".printf (cl.get_cname ()));
cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("self", ccall));
block.add_statement (cdecl);
......@@ -543,8 +541,7 @@ public class Vala.CodeGenerator {
var block = new CCodeBlock ();
var ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_upper_case_cname (null)));
ccall.add_argument (new CCodeIdentifier ("object"));
var ccall = new InstanceCast (new CCodeIdentifier ("object"), cl);
var cdecl = new CCodeDeclaration ("%s *".printf (cl.get_cname ()));
cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("self", ccall));
block.add_statement (cdecl);
......
......@@ -69,29 +69,24 @@ public class Vala.CodeGenerator {
base_method = m.base_method;
}
var req_cast = false;
TypeReference instance_expression_type;
if (ma.inner == null) {
instance = new CCodeIdentifier ("self");
/* require casts for overriden and inherited methods */
req_cast = m.overrides || m.base_interface_method != null || (m.parent_symbol != null && m.parent_symbol != current_type_symbol);
instance_expression_type = new TypeReference ();
instance_expression_type.data_type = current_type_symbol;
} else {
instance = (CCodeExpression) ma.inner.ccodenode;
/* reqiure casts if the type of the used instance is
* different than the type which declared the method */
req_cast = base_method.parent_symbol != null && base_method.parent_symbol != ma.inner.static_type.data_type;
instance_expression_type = ma.inner.static_type;
}
if (m.instance_by_reference && (ma.inner != null || m.parent_symbol != current_type_symbol)) {
instance = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, instance);
}
if (req_cast && ((DataType) m.parent_symbol).is_reference_type ()) {
// FIXME: use C cast if debugging disabled
var ccall = new CCodeFunctionCall (new CCodeIdentifier (((DataType) base_method.parent_symbol).get_upper_case_cname (null)));
ccall.add_argument (instance);
instance = ccall;
}
var instance_target_type = new TypeReference ();
instance_target_type.data_type = (DataType) base_method.parent_symbol;
instance = get_implicit_cast_expression (instance, instance_expression_type, instance_target_type);
if (!m.instance_last) {
ccall.add_argument (instance);
}
......@@ -226,25 +221,16 @@ public class Vala.CodeGenerator {
var param = params_it.get ();
ellipsis = param.ellipsis;
if (!ellipsis) {
if (param.type_reference.data_type != null
&& param.type_reference.data_type.is_reference_type ()) {
if (param.type_reference.data_type is Callback) {
cexpr = new CCodeCastExpression (cexpr, param.type_reference.data_type.get_cname ());
} else {
if (!param.no_array_length && param.type_reference.data_type is Array) {
var arr = (Array) param.type_reference.data_type;
for (int dim = 1; dim <= arr.rank; dim++) {
ccall.add_argument (get_array_length_cexpression (arg, dim));
}
}
if (arg.static_type.data_type != null && param.type_reference.data_type != arg.static_type.data_type) {
// FIXME: use C cast if debugging disabled
var ccall = new CCodeFunctionCall (new CCodeIdentifier (param.type_reference.data_type.get_upper_case_cname (null)));
ccall.add_argument (cexpr);
cexpr = ccall;
}
} else if (param.type_reference.data_type is Callback) {
cexpr = new CCodeCastExpression (cexpr, param.type_reference.data_type.get_cname ());
} else if (param.type_reference.data_type == null
&& arg.static_type.data_type is Struct) {
cexpr = convert_to_generic_pointer (cexpr, arg.static_type);
cexpr = get_implicit_cast_expression (cexpr, arg.static_type, param.type_reference);
}
}
}
......
......@@ -57,17 +57,12 @@ public class Vala.CodeGenerator {
} else if (expr.symbol_reference is Field) {
var f = (Field) expr.symbol_reference;
if (f.instance) {
CCodeExpression typed_inst;
if (f.parent_symbol != base_type) {
if (context.debug) {
typed_inst = new CCodeFunctionCall (new CCodeIdentifier (((DataType) f.parent_symbol).get_upper_case_cname (null)));
((CCodeFunctionCall) typed_inst).add_argument (pub_inst);
} else {
typed_inst = new CCodeCastExpression (pub_inst, ((DataType) f.parent_symbol).get_cname () + "*");
}
} else {
typed_inst = pub_inst;
}
var instance_expression_type = new TypeReference ();
instance_expression_type.data_type = base_type;
var instance_target_type = new TypeReference ();
instance_target_type.data_type = (DataType) f.parent_symbol;
CCodeExpression typed_inst = get_implicit_cast_expression (pub_inst, instance_expression_type, instance_target_type);
CCodeExpression inst;
if (f.access == SymbolAccessibility.PRIVATE) {
inst = new CCodeMemberAccess.pointer (typed_inst, "priv");
......@@ -97,19 +92,12 @@ public class Vala.CodeGenerator {
}
var base_property_type = (DataType) base_property.parent_symbol;
var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_get_%s".printf (base_property_type.get_lower_case_cname (null), base_property.name)));
CCodeExpression typed_pub_inst = pub_inst;
/* cast if necessary */
if (base_property_type != base_type) {
if (context.debug) {
var ccast = new CCodeFunctionCall (new CCodeIdentifier (base_property_type.get_upper_case_cname (null)));
ccast.add_argument (pub_inst);
typed_pub_inst = ccast;
} else {
typed_pub_inst = new CCodeCastExpression (pub_inst, base_property_type.get_cname () + "*");
}
}
var instance_expression_type = new TypeReference ();
instance_expression_type.data_type = base_type;
var instance_target_type = new TypeReference ();
instance_target_type.data_type = base_property_type;
CCodeExpression typed_pub_inst = get_implicit_cast_expression (pub_inst, instance_expression_type, instance_target_type);
ccall.add_argument (typed_pub_inst);
expr.ccodenode = ccall;
......@@ -162,19 +150,11 @@ public class Vala.CodeGenerator {
if (sig.has_emitter) {
var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_%s".printf (cl.get_lower_case_cname (null), sig.name)));
/* explicitly use strong reference as ccast
* gets unrefed at the end of the inner block
*/
CCodeExpression typed_pub_inst = pub_inst;
/* cast if necessary */
if (cl != base_type) {
// FIXME: use C cast if debugging disabled
var ccast = new CCodeFunctionCall (new CCodeIdentifier (cl.get_upper_case_cname (null)));
ccast.add_argument (pub_inst);
typed_pub_inst = ccast;
}
var instance_expression_type = new TypeReference ();
instance_expression_type.data_type = base_type;
var instance_target_type = new TypeReference ();
instance_target_type.data_type = cl;
CCodeExpression typed_pub_inst = get_implicit_cast_expression (pub_inst, instance_expression_type, instance_target_type);
ccall.add_argument (typed_pub_inst);
expr.ccodenode = ccall;
......
......@@ -215,15 +215,18 @@ public class Vala.CodeGenerator {
if (m.parent_symbol is Class) {
var cl = (Class) m.parent_symbol;
if (m.overrides || m.base_interface_method != null) {
CCodeExpression cself;
if (context.debug) {
var ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_upper_case_cname (null)));
ccall.add_argument (new CCodeIdentifier ("base"));
cself = ccall;
Method base_method;
if (m.overrides) {
base_method = m.base_method;
} else {
cself = new CCodeCastExpression (new CCodeIdentifier ("base"), cl.get_cname () + "*");
base_method = m.base_interface_method;
}
var base_expression_type = new TypeReference ();
base_expression_type.data_type = base_method.parent_symbol;
var self_target_type = new TypeReference ();
self_target_type.data_type = cl;
CCodeExpression cself = get_implicit_cast_expression (new CCodeIdentifier ("base"), base_expression_type, self_target_type);
var cdecl = new CCodeDeclaration ("%s *".printf (cl.get_cname ()));
cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("self", cself));
......
/* valalockable.vala
*
* Copyright (C) 2006 Raffaele Sandrini
* Copyright (C) 2006-2007 Raffaele Sandrini, 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
......@@ -18,12 +18,15 @@
*
* Author:
* Raffaele Sandrini <rasa@gmx.ch>
* Jürg Billeter <j@bitron.ch>
*/
using GLib;
/**
* Represents a lockable object.
*/
public interface Vala.Lockable {
public interface Vala.Lockable : Object {
/**
* Indicates a specific lockable object beeing actually locked somewhere.
*/
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment