Bug 549799 - [C++ CodeGen] Enter in nested states from an upper region causes compilation error
Summary: [C++ CodeGen] Enter in nested states from an upper region causes compilation ...
Status: ASSIGNED
Alias: None
Product: Papyrus
Classification: Modeling
Component: Designer (show other bugs)
Version: 4.5.0   Edit
Hardware: All All
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Ansgar Radermacher CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-08-05 09:33 EDT by Yoann Farré CLA
Modified: 2021-07-12 10:12 EDT (History)
1 user (show)

See Also:


Attachments
Demo model for the bug (11.69 KB, application/x-zip-compressed)
2019-08-05 09:33 EDT, Yoann Farré CLA
no flags Details
Another demo model for a related issue (19.46 KB, application/x-zip-compressed)
2021-07-09 06:18 EDT, Yoann Farré CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Yoann Farré CLA 2019-08-05 09:33:06 EDT
Created attachment 279495 [details]
Demo model for the bug

I noticed a bug in the state machine code generation (C++) in a particular case.

A demo model is joined to illustrate the issue with a simple state machine and a simple architecture. 

To explain the issue in more details:
When entering in a region of a state machine (included in another state), a method is generated in the following way : 
void Class1::State1_Region2_Enter(char /*in*/enter_mode) { ... }

A switch is generated in this method and each case corresponds to a possible state of this region. I set :
- State A and State B in Region Alpha.
- State B-1 and B-2 in Region Beta in State B

When a transition goes from State A to State B-2, the code produced for the susmentionned method is:

void Class1::OwningState_Region_Alpha_Enter(char /*in*/enter_mode) {
	switch (enter_mode) {
	case OWNINGSTATE_REGION_ALPHA_DEFAULT:
		states[OWNINGSTATE_ID].actives[0] = STATEA_ID;

		//start activity of StateA by calling setFlag
		setFlag(STATEA_ID, statemachine::ThreadFunctions::TF_DO_ACTIVITY, true);
		//TODO: set systemState to EVENT_CONSUMED
		break;
	case STATEB_REGION_BETA_STATEB_2:
		states[OWNINGSTATE_ID].actives[0] = STATEB_ID;
		//starting the counters for time events
		StateB_Region_Beta_Enter (STATEB_REGION_BETA_STATEB_2);
		break;
	}
}

And STATEB_REGION_BETA_STATEB_2 is "not declared in this scope"

I believe that the following code should not be generated in this case :

	case STATEB_REGION_BETA_STATEB_2:
		states[OWNINGSTATE_ID].actives[0] = STATEB_ID;
		//starting the counters for time events
		StateB_Region_Beta_Enter (STATEB_REGION_BETA_STATEB_2);
		break;
	}

In more complicated model, it produced "duplicate case value" because of several state with the same int reference in the enumeration.

I can provide more complicated models to test if needed.

Yoann.
Comment 1 Yoann Farré CLA 2021-07-09 06:18:27 EDT
Created attachment 286759 [details]
Another demo model for a related issue

The joined model illustrates the issue when there is a transition between two child states. 

After generating the code : 
- Fix the compilation error by changing the integer init number for the state and region 
#define STATEC_REGION1_DEFAULT (10)
#define STATEC_REGION1_STATED (11)

With this change the code can be compiled but a non wanted behavior can be caused by the generated code : 

void Class1::processSignalEvent3(Signal2& /*in*/ sig) {
	systemState = statemachine::SystemStateEnum_t::EVENT_PROCESSING;
	if (states[STATEC_ID].actives[0] == STATED_ID) {
		//from StateD to StateE
		if (myInt == 3) {
		StateC_Region1_Exit();
		states[STATEA_ID].actives[0] = STATEB_ID;
		//starting the counters for time events
		StateB_Region1_Enter(STATEB_REGION1_STATEE);
		systemState = statemachine::SystemStateEnum_t::EVENT_CONSUMED;
		}
	}
	if (states[STATEB_ID].actives[0] == STATEE_ID) {
		//from StateE to StateD
		if (myInt == 3) {
		StateB_Region1_Exit();
		states[STATEA_ID].actives[0] = STATEC_ID;
		//starting the counters for time events
		StateC_Region1_Enter(STATEC_REGION1_STATED);
		systemState = statemachine::SystemStateEnum_t::EVENT_CONSUMED;
		}
	}
}

In this case, with the same event, we have a first transition from D to E and then from E to D which is not wanted. Only one behavior should be triggered.
Comment 2 Eclipse Genie CLA 2021-07-12 03:25:20 EDT
New Gerrit change created: https://git.eclipse.org/r/c/papyrus/org.eclipse.papyrus-designer/+/182966
Comment 4 Ansgar Radermacher CLA 2021-07-12 10:12:35 EDT
The 2nd part of bug (multiple "if" cases that could both be executed) are treated in the context of bug 549801.
As the current patch removes some code that is considered "not required", I propose not to close this bug for the moment, as I'd like to have some experience with more state-machines.