diff --git a/compiler2/ttcn3/AST_ttcn3.cc b/compiler2/ttcn3/AST_ttcn3.cc index b891ef2266be69327e60b6c20026ee99fe2f8f72..439e0935ff01e49b64b50d8c773e7ec5da2c924d 100644 --- a/compiler2/ttcn3/AST_ttcn3.cc +++ b/compiler2/ttcn3/AST_ttcn3.cc @@ -7490,7 +7490,6 @@ namespace Ttcn { // assemble the function body first (this also determines which parameters // are never used) char* body = create_location_object(memptystr(), "ALTSTEP", dispname_str); - body = fp_list->generate_shadow_objects(body); if (debugger_active) { body = generate_code_debugger_function_init(body, this); } @@ -7505,13 +7504,19 @@ namespace Ttcn { mputprintf(target->header.function_prototypes, "extern alt_status %s_instance(%s);\n", genname_str, formal_par_list); + // generate shadow objects for parameters if needed + // (this needs be done after the body is generated, so it to knows which + // parameters are never used) + char* shadow_objects = fp_list->generate_shadow_objects(memptystr()); + // function for altstep instance: body target->source.function_bodies = mputprintf(target->source.function_bodies, "alt_status %s_instance(%s)\n" "{\n" - "%s" - "}\n\n", genname_str, formal_par_list, body); + "%s%s" + "}\n\n", genname_str, formal_par_list, shadow_objects, body); Free(formal_par_list); + Free(shadow_objects); Free(body); char *actual_par_list = @@ -8069,6 +8074,23 @@ namespace Ttcn { if (!semantic_check_only) defval.ap->set_code_section(GovernedSimple::CS_POST_INIT); } + + if (use_runtime_2 && my_parlist->get_my_def() != NULL && + my_parlist->get_my_def()->get_asstype() == Definition::A_ALTSTEP) { + // altstep 'in' parameters are always shadowed in RT2, because if a default + // altstep deactivates itself, then its parameters are deleted; + // update the genname so that all references in the generated code + // will point to the shadow object + switch (asstype) { + case A_PAR_VAL: + case A_PAR_VAL_IN: + case A_PAR_TEMPL_IN: + set_genname(id->get_name() + "_shadow"); + break; + default: + break; + } + } } bool FormalPar::has_defval() const @@ -8834,7 +8856,9 @@ namespace Ttcn { char *FormalPar::generate_shadow_object(char *str) const { - if (used_as_lvalue && !lazy_eval) { + if ((used_as_lvalue || (use_runtime_2 && usage_found && + my_parlist->get_my_def()->get_asstype() == Definition::A_ALTSTEP)) + && !lazy_eval) { const string& t_genname = get_genname(); const char *genname_str = t_genname.c_str(); const char *name_str = id->get_name().c_str(); @@ -8848,7 +8872,7 @@ namespace Ttcn { type->get_genname_template(my_scope).c_str(), genname_str, name_str); break; default: - FATAL_ERROR("FormalPar::generate_shadow_object()"); + break; } } return str; @@ -10113,13 +10137,30 @@ namespace Ttcn { // add an extra copy constructor call to the referenced value and template // parameters if the referred definition is also passed by reference to // another parameter + bool all_in_params_shadowed = use_runtime_2 && p_fpl != NULL && + p_fpl->get_my_def()->get_asstype() == Common::Assignment::A_ALTSTEP; for (size_t i = 0; i < nof_pars; i++) { if (i > 0) expr->expr = mputstr(expr->expr, ", "); ActualPar *par = params[i]; bool copy_needed = false; // the copy constructor call is not needed if the parameter is copied // into a shadow object in the body of the called function - if (!p_fpl || !p_fpl->get_fp_byIndex(i)->get_used_as_lvalue()) { + bool shadowed = false; + if (p_fpl != NULL) { + switch (p_fpl->get_fp_byIndex(i)->get_asstype()) { + case Common::Assignment::A_PAR_VAL: + case Common::Assignment::A_PAR_VAL_IN: + case Common::Assignment::A_PAR_TEMPL_IN: + // all 'in' parameters are shadowed in altsteps in RT2, otherwise an + // 'in' parameter is shadowed if it is used as lvalue + shadowed = all_in_params_shadowed ? true : + p_fpl->get_fp_byIndex(i)->get_used_as_lvalue(); + break; + default: + break; + } + } + if (!shadowed) { switch (par->get_selection()) { case ActualPar::AP_VALUE: { Value *v = par->get_Value(); diff --git a/compiler2/ttcn3/Statement.cc b/compiler2/ttcn3/Statement.cc index 966e797a8e4aabd3d820177abe502c25cdac6f24..049d468c72ae9a8d645c89b70fa4cae67c4f1d4e 100644 --- a/compiler2/ttcn3/Statement.cc +++ b/compiler2/ttcn3/Statement.cc @@ -3409,8 +3409,18 @@ error: void Statement::chk_deactivate() { + Error_Context cntxt(this, "In deactivate statement"); + if (!use_runtime_2 && + (my_sb->get_my_def()->get_asstype() == Common::Assignment::A_ALTSTEP || + my_sb->get_my_def()->get_asstype() == Common::Assignment::A_FUNCTION)) { + // The automatic shadowing of 'in' parameters in altsteps is not done in RT1 + // for performance reasons. Issue a warning about their possible deletion. + warning("Calling `deactivate()' in a function or altstep. This %s " + "delete the `in' parameters of %s currently running altstep%s.", + deactivate != NULL ? "might" : "will", + deactivate != NULL ? "a" : "all", deactivate != NULL ? "" : "s"); + } if (deactivate) { - Error_Context cntxt(this, "In deactivate statement"); deactivate->chk_expr_default(Type::EXPECTED_DYNAMIC_VALUE); } } diff --git a/regression_test/defaultOper/Makefile b/regression_test/defaultOper/Makefile index 093f8c295502be3324bca0d00da6102a570d7086..8577bf1403430544ed93f00aa52e9faa1e4f7b58 100644 --- a/regression_test/defaultOper/Makefile +++ b/regression_test/defaultOper/Makefile @@ -23,6 +23,10 @@ TTCN3_LIB = ttcn3$(RT2_SUFFIX)-parallel$(DYNAMIC_SUFFIX) TTCN3_MODULES = TdefaultOper.ttcn +ifdef RT2 +TTCN3_MODULES += TdefaultOperRT2.ttcn +endif + GENERATED_SOURCES = $(TTCN3_MODULES:.ttcn=.cc) GENERATED_HEADERS = $(GENERATED_SOURCES:.cc=.hh) ifdef CODE_SPLIT @@ -54,7 +58,7 @@ dep: $(GENERATED_SOURCES) makedepend $(CPPFLAGS) $(GENERATED_SOURCES) run: $(TARGET) - ttcn3_start $(TARGET) config.cfg + ttcn3_start $(TARGET) config$(RT2_SUFFIX).cfg .NOTPARALLEL: diff --git a/regression_test/defaultOper/TdefaultOperRT2.ttcn b/regression_test/defaultOper/TdefaultOperRT2.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..27be1a169c5b7cd5157d762b6549d0cb2885eb86 --- /dev/null +++ b/regression_test/defaultOper/TdefaultOperRT2.ttcn @@ -0,0 +1,94 @@ +/****************************************************************************** + * Copyright (c) 2000-2016 Ericsson Telecom AB + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Baranyi, Botond + * + ******************************************************************************/ + +// This module contains tests for bug fix 500919. +// Description: If an altstep deactivates itself (more specifically deactivates the +// default variable that executed the altstep), then all of its parameters are deleted, +// and accessing them generally causes dynamic test case errors or segmentation faults. +// The bug fix is only available in Runtime 2. +module TdefaultOperRT2 { + +type port PT message { + inout integer +} +with { + extension "internal"; +} + +type component CT { + var default ct_def; + var integer ct_int; + timer ct_tmr[2]; + port PT pt; +} + +altstep as_deactivates_itself(in integer x) runs on CT { + var integer copy := x; + [] ct_tmr[x].timeout { + deactivate(ct_def); + if (x != copy) { + setverdict(fail, "Parameter has changed from ", copy, " to ", x); + } + else { + setverdict(pass); + } + } +} + +testcase tc_altstep_deactivates_itself() runs on CT { + ct_def := activate(as_deactivates_itself(1)); + connect(self:pt, self:pt); + pt.send(1); + ct_tmr[1].start(0.1); + alt { + [] pt.receive(integer:2) { + setverdict(fail, "Invalid alt branch"); + } + } +} + +altstep as_deactivates_everyone(in integer x, inout integer y) runs on CT { + var integer x_copy := x; + [] ct_tmr[x].timeout { + var integer y_copy := y; + deactivate; + if (x != x_copy) { + setverdict(fail, "Parameter 'x' has changed from ", x_copy, " to ", x); + } + else if (y != y_copy) { + setverdict(fail, "Parameter 'y' has changed from ", y_copy, " to ", y); + } + else { + setverdict(pass); + } + } +} + +testcase tc_altstep_deactivates_everyone() runs on CT { + ct_int := 6; + ct_def := activate(as_deactivates_everyone(1, ct_int)); + connect(self:pt, self:pt); + pt.send(1); + ct_tmr[1].start(0.1); + alt { + [] pt.receive(integer:2) { + setverdict(fail, "Invalid alt branch"); + } + } +} + +control { + execute(tc_altstep_deactivates_itself()); + execute(tc_altstep_deactivates_everyone()); +} + +} diff --git a/regression_test/defaultOper/config-rt2.cfg b/regression_test/defaultOper/config-rt2.cfg new file mode 100644 index 0000000000000000000000000000000000000000..74f0dabe65a75229e98aa368081bc292212181e4 --- /dev/null +++ b/regression_test/defaultOper/config-rt2.cfg @@ -0,0 +1,20 @@ +############################################################################### +# Copyright (c) 2000-2016 Ericsson Telecom AB +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Balasko, Jeno +# Baranyi, Botond +# +############################################################################### +[MODULE_PARAMETERS] +[LOGGING] +Logfile := "defaultOper.log" +FileMask := LOG_ALL +ConsoleMask := TTCN_WARNING | TTCN_ERROR | TTCN_TESTCASE | TTCN_STATISTICS +[EXECUTE] +TdefaultOper +TdefaultOperRT2