]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Ensure constructors are chained up
authorJürg Billeter <j@bitron.ch>
Sun, 16 Aug 2009 17:19:38 +0000 (19:19 +0200)
committerJürg Billeter <j@bitron.ch>
Sun, 16 Aug 2009 18:47:26 +0000 (20:47 +0200)
Fixes bug 571453.

codegen/valaccodemethodmodule.vala
vala/valacreationmethod.vala
vala/valamethod.vala
vala/valaunresolvedsymbol.vala

index f4bbc5e2c7c8bf9e3a424bc2e234be126f64b525..0ba3bc9fd5127ebd8b7d8900726d275a23b422bd 100644 (file)
@@ -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);
index 7f78ae4cee9b6c5cf5c3c7c94e9a1443b363cbe5..1279b9601296dffd1613d6e544a82232b2044e16 100644 (file)
@@ -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;
index 51ea569ef06eb8936b5fcabc100eb5e219a0849f..3036f2a96f94d16d4f00e5d583cc53eb2b24317e 100644 (file)
@@ -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
index fcfaa3c3742c7e788a935e279a96f6cec1d47c00..0c6c099ec9be0590033fe2f5b039fa1b5744e3ae 100644 (file)
@@ -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 () {