[vala/wip/bug567269: 1/7] Improve constructor chain-up checks
- From: Rico Tzschichholz <ricotz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/wip/bug567269: 1/7] Improve constructor chain-up checks
- Date: Fri, 2 Dec 2016 12:42:48 +0000 (UTC)
commit 1a61c014656992ef9f1af98f926ff0011a91b614
Author: Simon Werbeck <simon werbeck gmail com>
Date: Wed Nov 26 11:53:31 2014 +0100
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.
vala/valamethodcall.vala | 98 ++++++++++++++++++---------------------------
1 files changed, 39 insertions(+), 59 deletions(-)
---
diff --git a/vala/valamethodcall.vala b/vala/valamethodcall.vala
index 4e9d474..f620316 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;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]