From: Jürg Billeter Date: Sun, 16 Aug 2009 17:19:38 +0000 (+0200) Subject: Ensure constructors are chained up X-Git-Tag: 0.7.6~192 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8aee994df85acd913547f932c1e5e7be7b90a690;p=thirdparty%2Fvala.git Ensure constructors are chained up Fixes bug 571453. --- diff --git a/codegen/valaccodemethodmodule.vala b/codegen/valaccodemethodmodule.vala index f4bbc5e2c..0ba3bc9fd 100644 --- a/codegen/valaccodemethodmodule.vala +++ b/codegen/valaccodemethodmodule.vala @@ -945,42 +945,21 @@ internal class Vala.CCodeMethodModule : CCodeStructModule { private void add_object_creation (CCodeBlock b, bool has_params) { var cl = (Class) current_type_symbol; - bool chain_up = false; - CreationMethod cm = null; - if (cl.base_class != null) { - cm = cl.base_class.default_construction_method as CreationMethod; - if (cm != null && cm.get_parameters ().size == 0 - && cm.has_construct_function) { - if (!has_params) { - chain_up = true; - } - } - } - - if (!has_params && !chain_up - && cl.base_class != gobject_type) { + if (!has_params && cl.base_class != gobject_type) { // possibly report warning or error about missing base call } var cdecl = new CCodeVariableDeclarator ("self"); - if (chain_up) { - generate_method_declaration (cm, source_declarations); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier (cm.get_real_cname ())); - ccall.add_argument (new CCodeIdentifier ("object_type")); - cdecl.initializer = new CCodeCastExpression (ccall, "%s*".printf (cl.get_cname ())); + var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_newv")); + ccall.add_argument (new CCodeIdentifier ("object_type")); + if (has_params) { + ccall.add_argument (new CCodeConstant ("__params_it - __params")); + ccall.add_argument (new CCodeConstant ("__params")); } else { - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_newv")); - ccall.add_argument (new CCodeIdentifier ("object_type")); - if (has_params) { - ccall.add_argument (new CCodeConstant ("__params_it - __params")); - ccall.add_argument (new CCodeConstant ("__params")); - } else { - ccall.add_argument (new CCodeConstant ("0")); - ccall.add_argument (new CCodeConstant ("NULL")); - } - cdecl.initializer = ccall; + ccall.add_argument (new CCodeConstant ("0")); + ccall.add_argument (new CCodeConstant ("NULL")); } + cdecl.initializer = ccall; var cdeclaration = new CCodeDeclaration ("%s *".printf (cl.get_cname ())); cdeclaration.add_declarator (cdecl); diff --git a/vala/valacreationmethod.vala b/vala/valacreationmethod.vala index 7f78ae4ce..1279b9601 100644 --- a/vala/valacreationmethod.vala +++ b/vala/valacreationmethod.vala @@ -150,6 +150,37 @@ public class Vala.CreationMethod : Method { if (body != null) { body.check (analyzer); + + // ensure we chain up to base constructor + var cl = parent_symbol as Class; + if (!chain_up && cl != null && cl.base_class != null) { + if (cl.base_class.default_construction_method != null + && !cl.base_class.default_construction_method.has_construct_function) { + // chain up impossible + } else if (analyzer.context.profile == Profile.GOBJECT && cl.base_class == analyzer.object_type) { + // no chain up necessary for direct GObject subclasses + } else if (analyzer.context.profile == Profile.GOBJECT + && cl.is_subtype_of (analyzer.object_type) + && n_construction_params > 0) { + // no chain up when using GObject construct properties + } else if (cl.base_class.default_construction_method == null + || cl.base_class.default_construction_method.access == SymbolAccessibility.PRIVATE) { + Report.warning (source_reference, "unable to chain up to private base constructor"); + } else if (cl.base_class.default_construction_method.get_required_arguments () > 0) { + Report.warning (source_reference, "unable to chain up to base constructor requiring arguments"); + } else { + var old_insert_block = analyzer.insert_block; + analyzer.current_symbol = body; + analyzer.insert_block = body; + + var stmt = new ExpressionStatement (new MethodCall (new BaseAccess (source_reference), source_reference), source_reference); + body.insert_statement (0, stmt); + stmt.check (analyzer); + + analyzer.current_symbol = this; + analyzer.insert_block = old_insert_block; + } + } } analyzer.current_source_file = old_source_file; diff --git a/vala/valamethod.vala b/vala/valamethod.vala index 51ea569ef..3036f2a96 100644 --- a/vala/valamethod.vala +++ b/vala/valamethod.vala @@ -899,6 +899,18 @@ public class Vala.Method : Member { return true; } + + public int get_required_arguments () { + int n = 0; + foreach (var param in parameters) { + if (param.default_expression != null) { + // optional argument + break; + } + n++; + } + return n; + } } // vim:sw=8 noet diff --git a/vala/valaunresolvedsymbol.vala b/vala/valaunresolvedsymbol.vala index fcfaa3c37..0c6c099ec 100644 --- a/vala/valaunresolvedsymbol.vala +++ b/vala/valaunresolvedsymbol.vala @@ -1,6 +1,6 @@ /* valaunresolvedsymbol.vala * - * Copyright (C) 2008 Jürg Billeter + * Copyright (C) 2008-2009 Jürg Billeter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -35,9 +35,8 @@ public class Vala.UnresolvedSymbol : Symbol { public bool qualified { get; set; } public UnresolvedSymbol (UnresolvedSymbol? inner, string name, SourceReference? source_reference = null) { + base (name, source_reference); this.inner = inner; - this.name = name; - this.source_reference = source_reference; } public override string to_string () {