diff options
author | Simon Werbeck <simon.werbeck@gmail.com> | 2014-11-26 11:53:31 +0100 |
---|---|---|
committer | Rico Tzschichholz <ricotz@ubuntu.com> | 2016-12-07 10:12:31 +0100 |
commit | 73b9e4b4a2c059ceb6bce7ab173050fb70739892 (patch) | |
tree | 17051cc41398da06721d46dd93c1bc806c64ade0 /vala | |
parent | 241b058ebc4979f55daf5febce44277d50a6c909 (diff) | |
download | vala-73b9e4b4a2c059ceb6bce7ab173050fb70739892.tar.gz |
Improve constructor chain-up checks
The only valid expressions for chaining up are:
* this[.named] ()
* base[.named] ()
* Object () - for GObject style chain-ups
This patch should prevent invalid chain-ups such as:
* Foo.named (), where Foo is not a valid base class
* (new Foo ()) (), i.e. invoking expressions that return an object
In preparation to fixing bug 567269, is_chainup() was turned into a
property.
Diffstat (limited to 'vala')
-rw-r--r-- | vala/valamethodcall.vala | 98 |
1 files changed, 39 insertions, 59 deletions
diff --git a/vala/valamethodcall.vala b/vala/valamethodcall.vala index 4e9d474da..f6203160c 100644 --- a/vala/valamethodcall.vala +++ b/vala/valamethodcall.vala @@ -46,6 +46,8 @@ public class Vala.MethodCall : Expression { */ public bool is_constructv_chainup { get; private set; } + public bool is_chainup { get; private set; } + private Expression _call; private List<Expression> argument_list = new ArrayList<Expression> (); @@ -140,28 +142,6 @@ public class Vala.MethodCall : Expression { return call.is_accessible (sym); } - bool is_chainup () { - if (!(call.symbol_reference is CreationMethod)) { - return false; - } - - var expr = call; - - var ma = (MemberAccess) call; - if (ma.inner != null) { - expr = ma.inner; - } - - ma = expr as MemberAccess; - if (ma != null && ma.member_name == "this") { - return true; - } else if (expr is BaseAccess) { - return true; - } else { - return false; - } - } - public override bool check (CodeContext context) { if (checked) { return !error; @@ -231,11 +211,28 @@ public class Vala.MethodCall : Expression { } var mtype = call.value_type; + var gobject_chainup = call.symbol_reference == context.analyzer.object_type; + is_chainup = gobject_chainup; + + if (!gobject_chainup) { + var expr = call; + var ma = expr as MemberAccess; + if (ma != null && ma.symbol_reference is CreationMethod) { + expr = ma.inner; + ma = expr as MemberAccess; + } + if (ma != null && ma.member_name == "this") { + // this[.with_foo] () + is_chainup = true; + } else if (expr is BaseAccess) { + // base[.with_foo] () + is_chainup = true; + } + } CreationMethod base_cm = null; - if (mtype is ObjectType || call.symbol_reference == context.analyzer.object_type) { - // constructor chain-up + if (is_chainup) { var cm = context.analyzer.find_current_method () as CreationMethod; if (cm == null) { error = true; @@ -261,8 +258,14 @@ public class Vala.MethodCall : Expression { Report.error (source_reference, "chain up to `%s' not supported".printf (base_cm.get_full_name ())); return false; } - } else { - // GObject chain up + } else if (call.symbol_reference is CreationMethod && call.symbol_reference.parent_symbol is Class) { + 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 ())); + return false; + } + } else if (gobject_chainup) { var cl = cm.parent_symbol as Class; if (cl == null || !cl.is_subtype_of (context.analyzer.object_type)) { error = true; @@ -286,17 +289,6 @@ public class Vala.MethodCall : Expression { return false; } - if (is_chainup ()) { - var cm = context.analyzer.find_current_method () as CreationMethod; - if (cm != null) { - if (cm.chain_up) { - error = true; - Report.error (source_reference, "Multiple constructor calls in the same constructor are not permitted"); - return false; - } - cm.chain_up = true; - } - } var struct_creation_expression = new ObjectCreationExpression ((MemberAccess) call, source_reference); struct_creation_expression.struct_creation = true; foreach (Expression arg in get_argument_list ()) { @@ -307,30 +299,18 @@ public class Vala.MethodCall : Expression { parent_node.replace_expression (this, struct_creation_expression); struct_creation_expression.check (context); return true; - } else if (call is MemberAccess - && call.symbol_reference is CreationMethod) { - // constructor chain-up - var cm = context.analyzer.find_current_method () as CreationMethod; - if (cm == null) { - error = true; - Report.error (source_reference, "use `new' operator to create new objects"); - return false; - } else if (cm.chain_up) { - error = true; - Report.error (source_reference, "Multiple constructor calls in the same constructor are not permitted"); - return false; - } - cm.chain_up = true; - - 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 ())); - return false; - } + } else if (!is_chainup && call is MemberAccess && call.symbol_reference is CreationMethod) { + error = true; + Report.error (source_reference, "use `new' operator to create new objects"); + return false; } - if (mtype != null && mtype.is_invokable ()) { + if (!is_chainup && mtype is ObjectType) { + // prevent funny stuff like (new Object ()) () + error = true; + Report.error (source_reference, "invocation not supported in this context"); + return false; + } else if (mtype != null && mtype.is_invokable ()) { // call ok, expression is invokable } else if (call.symbol_reference is Class) { error = true; |