Bug 413587 - Using an <in> parameter as an argument to an <out>/<inout> parameter shouldn't be allowed
Summary: Using an <in> parameter as an argument to an <out>/<inout> parameter shouldn'...
Status: NEW
Alias: None
Product: QVTo
Classification: Modeling
Component: Engine (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows 7
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Project Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-07-23 21:10 EDT by Alex Paperno CLA
Modified: 2013-08-02 21:53 EDT (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Alex Paperno CLA 2013-07-23 21:10:51 EDT
The following code compiles and change the <in> parameters ATM.

--------------------
modeltype Ecore uses ecore('http://www.eclipse.org/emf/2002/Ecore');

transformation bug_n;

main() {
	var t1 := List{}->map m();
	var t2 := List{}->map m();
	log(t1.name);
	log(t2.name);
	t1.map m(t2);
	log(t1.name);
	log(t2.name);
}


mapping inout List(Real) :: m() : EClass {
	name := "old";
}

mapping EClass :: m(in ss:EClass) : EClass {
	map m2(self);
	map m2(ss);
}

mapping m2(inout ss:EClass) : EClass {
	ss.name := 'new';
}
--------------------

This bug is related to bug 404647.
Comment 1 Sergey Boyko CLA 2013-07-28 15:10:18 EDT
It's endeed an inaccuracy in the implementation. However it's difficult to ensure such constraints in common case. For example, consider the following:

main() {
	var t1 := object EClass {name := 'old'};
	log(t1.name);
	t1.map m();
	log(t1.name);
}
mapping EClass :: m() : EClass {
	var r := self;
	r.name := 'new';
}
Comment 2 Ed Willink CLA 2013-07-29 00:59:49 EDT
(In reply to comment #1)
In your example you 'just' need to traverse the expression to identify the conteher(s). If any of these is in for an assigbnment there can be a warning/error.

In your example, the container of r.name is r, and the container of r is self which is 'in'.
Comment 3 Sergey Boyko CLA 2013-07-29 10:24:15 EDT
(In reply to comment #2)
> (In reply to comment #1)
> In your example you 'just' need to traverse the expression to identify the
> conteher(s). If any of these is in for an assigbnment there can be a
> warning/error.
> 
> In your example, the container of r.name is r, and the container of r is
> self which is 'in'.

I gave an example of trivial reference replacement. More sophisticated code will be to use 'if' statement:

mapping EClass :: m(inout ss:EClass) : EClass {
	var r := if true then self else ss endif;
	r.name := 'new';
}

In case when flow analyzer is able to detect 'dead' code (condition always evaluates to true) it should mark assignment 'r.name := 'new'' with error. Otherwise it can/should mark it with a warning.

Another case is when blackbox calls are used:

mapping EClass :: m(inout ss:EClass) : EClass {
	var r := blackboxSelect(self, ss);
	r.name := 'new';
}

Or when using blackbox calls with a memory effect:

mapping EClass :: m(inout ss:EClass) : EClass {
	blackboxPush(self);
	blackboxPush(ss);
	var r := blackboxPop();
	r.name := 'new';
}

Corresponding Bug 255098.

Of course advanced code flow analyzer which can audit read-only access violations, using of uninitialized variables etc. will be helpful.
Comment 4 Alex Paperno CLA 2013-08-02 21:53:28 EDT
Re: control flow analyzer see also bug 414347 (comment #1).