]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Support chain up to constructv functions. ed8f32bd6696291a1bc49597b70c30335ec2917d
authorLuca Bruno <lucabru@src.gnome.org>
Sat, 21 Sep 2013 09:34:06 +0000 (11:34 +0200)
committerLuca Bruno <lucabru@src.gnome.org>
Sat, 21 Sep 2013 09:34:06 +0000 (11:34 +0200)
codegen/valaccodebasemodule.vala
codegen/valaccodemethodcallmodule.vala
codegen/valaccodemethodmodule.vala
tests/Makefile.am
tests/objects/chainup.vala [new file with mode: 0644]
vala/valaclass.vala
vala/valamethodcall.vala
vala/valasemanticanalyzer.vala

index e42c5785eef3bcd6d6c4b5ec7564fe16cd7528b8..5cdd816cd2775ccf9a327b343963f8cb9f012b5d 100644 (file)
@@ -6205,6 +6205,18 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                return get_ccode_attribute(sym).real_name;
        }
 
+       public static string get_ccode_constructv_name (CreationMethod m) {
+               const string infix = "constructv";
+
+               var parent = m.parent_symbol as Class;
+
+               if (m.name == ".new") {
+                       return "%s%s".printf (get_ccode_lower_case_prefix (parent), infix);
+               } else {
+                       return "%s%s_%s".printf (get_ccode_lower_case_prefix (parent), infix, m.name);
+               }
+       }
+
        public static string get_ccode_vfunc_name (Method m) {
                return get_ccode_attribute(m).vfunc_name;
        }
index 0bd462a134bb3e2f29cd9071623518a9db04202e..728dccdd491d4f35796e1b9862c90aae3f3bc24b 100644 (file)
@@ -48,6 +48,8 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                // Enum.VALUE.to_string()
                                var en = (Enum) ma.inner.value_type.data_type;
                                ccall.call = new CCodeIdentifier (generate_enum_tostring_function (en));
+                       } else if (expr.is_constructv_chainup) {
+                               ccall.call = new CCodeIdentifier (get_ccode_constructv_name ((CreationMethod) m));
                        }
                } else if (itype is SignalType) {
                        var sig_type = (SignalType) itype;
@@ -61,7 +63,11 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                        var cl = (Class) ((ObjectType) itype).type_symbol;
                        m = cl.default_construction_method;
                        generate_method_declaration (m, cfile);
-                       ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_real_name (m)));
+                       var real_name = get_ccode_real_name (m);
+                       if (expr.is_constructv_chainup) {
+                               real_name = get_ccode_constructv_name ((CreationMethod) m);
+                       }
+                       ccall = new CCodeFunctionCall (new CCodeIdentifier (real_name));
                } else if (itype is StructValueType) {
                        // constructor
                        var st = (Struct) ((StructValueType) itype).type_symbol;
@@ -598,7 +604,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                         * except when using printf-style arguments */
                        if (m == null) {
                                in_arg_map.set (get_param_pos (-1, true), new CCodeConstant ("NULL"));
-                       } else if (!m.printf_format && !m.scanf_format && get_ccode_sentinel (m) != "") {
+                       } else if (!m.printf_format && !m.scanf_format && get_ccode_sentinel (m) != "" && !expr.is_constructv_chainup) {
                                in_arg_map.set (get_param_pos (-1, true), new CCodeConstant (get_ccode_sentinel (m)));
                        }
                }
index f0cddaec110deb7da58b9cb3ce4ee253b5450511..c7c7818f72ec0e597c2d94d709bb4455fd1a3285 100644 (file)
@@ -204,7 +204,7 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
 
                        if (m.is_variadic ()) {
                                // _constructv function
-                               function = new CCodeFunction (get_constructv_name ((CreationMethod) m));
+                               function = new CCodeFunction (get_ccode_constructv_name ((CreationMethod) m));
 
                                cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
                                generate_cparameters (m, decl_space, cparam_map, function);
@@ -214,18 +214,6 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
                }
        }
 
-       private string get_constructv_name (CreationMethod m) {
-               const string infix = "constructv";
-
-               var parent = m.parent_symbol as Class;
-
-               if (m.name == ".new") {
-                       return "%s%s".printf (CCodeBaseModule.get_ccode_lower_case_prefix (parent), infix);
-               } else {
-                       return "%s%s_%s".printf (CCodeBaseModule.get_ccode_lower_case_prefix (parent), infix, m.name);
-               }
-       }
-
        void register_plugin_types (Symbol sym, Set<Symbol> registered_types) {
                var ns = sym as Namespace;
                var cl = sym as Class;
@@ -289,7 +277,7 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
        public override void visit_method (Method m) {
                string real_name = get_ccode_real_name (m);
                if (m is CreationMethod && m.is_variadic ()) {
-                       real_name = get_constructv_name ((CreationMethod) m);
+                       real_name = get_ccode_constructv_name ((CreationMethod) m);
                }
 
                push_context (new EmitContext (m));
@@ -1182,7 +1170,7 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
 
                push_function (vfunc);
 
-               string constructor = (m.is_variadic ()) ? get_constructv_name (m) : get_ccode_real_name (m);
+               string constructor = (m.is_variadic ()) ? get_ccode_constructv_name (m) : get_ccode_real_name (m);
                var vcall = new CCodeFunctionCall (new CCodeIdentifier (constructor));
 
                if (self_as_first_parameter) {
index b84ee0411a69fa1dff227d960e77ae7cdaf7b93f..b84d433ebdf24528cbb4ca1ab0daeb419cf8246b 100644 (file)
@@ -100,6 +100,7 @@ TESTS = \
        delegates/bug638415.vala \
        delegates/bug639751.vala \
        delegates/bug703804.vala \
+       objects/chainup.vala \
        objects/classes.vala \
        objects/fields.vala \
        objects/interfaces.vala \
diff --git a/tests/objects/chainup.vala b/tests/objects/chainup.vala
new file mode 100644 (file)
index 0000000..fdca08d
--- /dev/null
@@ -0,0 +1,39 @@
+class FooBase {
+       public int bar;
+
+       public FooBase (int _, ...) {
+               va_list v = va_list ();
+               bar = v.arg ();
+       }
+
+       public FooBase.baz (int _, ...) {
+               va_list v = va_list ();
+               this (_, v);
+       }
+}
+
+class Foo : FooBase {
+       public Foo (int _, ...) {
+               va_list v = va_list ();
+               base (_, v);
+       }
+
+       public Foo.baz (int _, ...) {
+               va_list v = va_list ();
+               base.baz (_, v);
+       }
+
+       public Foo.qux (int _, ...) {
+               va_list v = va_list ();
+               this.baz (_, v);
+       }
+}
+
+void main () {
+       var foo = new Foo (0, 10);
+       assert (foo.bar == 10);
+       foo = new Foo.baz (0, 20);
+       assert (foo.bar == 20);
+       foo = new Foo.qux (0, 30);
+       assert (foo.bar == 30);
+}
index 5110a7aa63854fea5f4c90331ef5f521b99cb5da..ba23a508fb6611decf042bbfcb031b1353db829b 100644 (file)
@@ -151,7 +151,7 @@ public class Vala.Class : ObjectTypeSymbol {
        /**
         * Specifies the default construction method.
         */
-       public Method default_construction_method { get; set; }
+       public CreationMethod default_construction_method { get; set; }
        
        /**
         * Specifies the instance constructor.
@@ -303,7 +303,7 @@ public class Vala.Class : ObjectTypeSymbol {
                }
                if (m is CreationMethod) {
                        if (m.name == null) {
-                               default_construction_method = m;
+                               default_construction_method = (CreationMethod) m;
                                m.name = ".new";
                        }
 
index 5b0ba8a1dec199dd74012c85c85c28ee5d57eff5..89d2ba5cc057b8cd426ea3c85a832fa6fe203095 100644 (file)
@@ -41,6 +41,11 @@ public class Vala.MethodCall : Expression {
 
        public bool is_assert { get; private set; }
 
+       /**
+        * Whether this chain up uses the constructv function with va_list.
+        */
+       public bool is_constructv_chainup { get; private set; }
+
        public Expression _call;
        
        private List<Expression> argument_list = new ArrayList<Expression> ();
@@ -213,6 +218,8 @@ public class Vala.MethodCall : Expression {
 
                var mtype = call.value_type;
 
+               CreationMethod base_cm = null;
+
                if (mtype is ObjectType || call.symbol_reference == context.analyzer.object_type) {
                        // constructor chain-up
                        var cm = context.analyzer.find_current_method () as CreationMethod;
@@ -230,7 +237,7 @@ public class Vala.MethodCall : Expression {
                        if (mtype is ObjectType) {
                                var otype = (ObjectType) mtype;
                                var cl = (Class) otype.type_symbol;
-                               var base_cm = cl.default_construction_method;
+                               base_cm = cl.default_construction_method;
                                if (base_cm == null) {
                                        error = true;
                                        Report.error (source_reference, "chain up to `%s' not supported".printf (cl.get_full_name ()));
@@ -301,7 +308,7 @@ public class Vala.MethodCall : Expression {
                        }
                        cm.chain_up = true;
 
-                       var base_cm = (CreationMethod) call.symbol_reference;
+                       base_cm = (CreationMethod) call.symbol_reference;
                        if (!base_cm.has_construct_function) {
                                error = true;
                                Report.error (source_reference, "chain up to `%s' not supported".printf (base_cm.get_full_name ()));
@@ -720,6 +727,14 @@ public class Vala.MethodCall : Expression {
                        return false;
                }
 
+               /* Check for constructv chain up */
+               if (base_cm != null && base_cm.is_variadic () && args.size == base_cm.get_parameters ().size) {
+                       var this_last_arg = args[args.size-1];
+                       if (this_last_arg.value_type is StructValueType && this_last_arg.value_type.data_type == context.analyzer.va_list_type.data_type) {
+                               is_constructv_chainup = true;
+                       }
+               }
+
                if (may_throw) {
                        if (parent_node is LocalVariable || parent_node is ExpressionStatement) {
                                // simple statements, no side effects after method call
index 90923ac2c5ddeabe095bc57465d739deab406dfa..8244896d006d4e96cdabf0ebc338a5164d837af8 100644 (file)
@@ -150,6 +150,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
        public DataType unichar_type;
        public DataType double_type;
        public DataType type_type;
+       public DataType va_list_type;
        public Class object_type;
        public StructValueType gvalue_type;
        public ObjectType gvariant_type;
@@ -196,6 +197,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                size_t_type = new IntegerType ((Struct) root_symbol.scope.lookup ("size_t"));
                ssize_t_type = new IntegerType ((Struct) root_symbol.scope.lookup ("ssize_t"));
                double_type = new FloatingType ((Struct) root_symbol.scope.lookup ("double"));
+               va_list_type = new StructValueType ((Struct) root_symbol.scope.lookup ("va_list"));
 
                var unichar_struct = (Struct) root_symbol.scope.lookup ("unichar");
                if (unichar_struct != null) {