diff --git a/compiler2/ttcn3/Statement.cc b/compiler2/ttcn3/Statement.cc index 1d670cf1326a7e3be31c769919d2e401f6560da2..45cc7680748aa330231920fb1274a19114bb9c25 100644 --- a/compiler2/ttcn3/Statement.cc +++ b/compiler2/ttcn3/Statement.cc @@ -4803,6 +4803,10 @@ error: } // checking consistency if (!ptb1 || !ptb2) return; + if (!ptb1->connect_can_receive_or_send(ptb2)) { + warning("Neither port type `%s' nor port type `%s' can send messages.", + pt1->get_typename().c_str(), pt2->get_typename().c_str()); + } if (!ptb1->is_connectable(ptb2) || (ptb1 != ptb2 && !ptb2->is_connectable(ptb1))) { error("The connection between port types `%s' and `%s' is not consistent", @@ -4908,6 +4912,10 @@ error: pt2->get_typename().c_str()); ptb1->report_mapping_errors(ptb2); } + if (!config_op.translate && !ptb1->map_can_receive_or_send(ptb2)) { + warning("Port type `%s' cannot send or receive from system port type `%s'.", + pt1->get_typename().c_str(), pt2->get_typename().c_str()); + } } else if (cref2_is_tc || cref1_is_system) { config_op.translate = !ptb2->is_legacy() && ptb2->is_translate(ptb1); if (!config_op.translate && !ptb2->is_mappable(ptb1)) { @@ -4916,6 +4924,10 @@ error: pt2->get_typename().c_str()); ptb2->report_mapping_errors(ptb1); } + if (!config_op.translate && !ptb2->map_can_receive_or_send(ptb1)) { + warning("Port type `%s' cannot send or receive from system port type `%s'.", + pt2->get_typename().c_str(), pt1->get_typename().c_str()); + } } else { // we have no idea which one is the system port config_op.translate = (!ptb1->is_legacy() && ptb1->is_translate(ptb2)) || diff --git a/compiler2/ttcn3/Ttcnstuff.cc b/compiler2/ttcn3/Ttcnstuff.cc index cac1d57c8cb2c917b060f54f4d38965ee8d9ed7a..af78f712c6c568ae731c163bf92e01f76232d9c9 100644 --- a/compiler2/ttcn3/Ttcnstuff.cc +++ b/compiler2/ttcn3/Ttcnstuff.cc @@ -1966,6 +1966,48 @@ namespace Ttcn { } return false; } + + bool PortTypeBody::map_can_receive_or_send(PortTypeBody *p_other) const { + if (operation_mode == PortTypeBody::PO_MESSAGE && + (out_msgs == NULL || out_msgs->get_nof_types() == 0) && + (p_other->in_msgs == NULL || p_other->in_msgs->get_nof_types() == 0)) { + return false; + } + if (operation_mode == PortTypeBody::PO_PROCEDURE && + (out_sigs == NULL || out_sigs->get_nof_types() == 0) && + (p_other->in_sigs == NULL || p_other->in_sigs->get_nof_types() == 0)) { + return false; + } + if (operation_mode == PortTypeBody::PO_MIXED && + (out_msgs == NULL || out_msgs->get_nof_types() == 0) && + (p_other->in_msgs == NULL || p_other->in_msgs->get_nof_types() == 0) && + (out_sigs == NULL || out_sigs->get_nof_types() == 0) && + (p_other->in_sigs == NULL || p_other->in_sigs->get_nof_types() == 0)) { + return false; + } + return true; + } + + bool PortTypeBody::connect_can_receive_or_send(PortTypeBody *p_other) const { + if (operation_mode == PortTypeBody::PO_MESSAGE && + (out_msgs == NULL || out_msgs->get_nof_types() == 0) && + (p_other->out_msgs == NULL || p_other->out_msgs->get_nof_types() == 0)) { + return false; + } + if (operation_mode == PortTypeBody::PO_PROCEDURE && + (out_sigs == NULL || out_sigs->get_nof_types() == 0) && + (p_other->out_sigs == NULL || p_other->out_sigs->get_nof_types() == 0)) { + return false; + } + if (operation_mode == PortTypeBody::PO_MIXED && + (out_msgs == NULL || out_msgs->get_nof_types() == 0) && + (p_other->out_msgs == NULL || p_other->out_msgs->get_nof_types() == 0) && + (out_sigs == NULL || out_sigs->get_nof_types() == 0) && + (p_other->out_sigs == NULL || p_other->out_sigs->get_nof_types() == 0)) { + return false; + } + return true; + } bool PortTypeBody::is_mappable(PortTypeBody *p_other) const { diff --git a/compiler2/ttcn3/Ttcnstuff.hh b/compiler2/ttcn3/Ttcnstuff.hh index 88ecdaa39fe7eb2f744333ef7406962f52e5e686..6d937e98ccf9b69e9938d1c8432d00695d1d7e89 100644 --- a/compiler2/ttcn3/Ttcnstuff.hh +++ b/compiler2/ttcn3/Ttcnstuff.hh @@ -464,6 +464,16 @@ public: void report_mapping_errors(PortTypeBody *p_other) const; /** True if the PortTypeBody has translation capability towards p_other */ bool is_translate(PortTypeBody *p_other) const; + /** Special case when mapping a port that has out procedure/message but + * the \a p_other does not have any, and \a p_other has in procedure/message but 'this' + * does not have any. In that case it is not possible to send or receive anything. + */ + bool map_can_receive_or_send(PortTypeBody *p_other) const; + /** Special case when connecting a port that has no out procedure/message + * and p_other has no out procedure/message. + * In that case it is not possible to send or receive anything. + */ + bool connect_can_receive_or_send(PortTypeBody *p_other) const; Type* get_my_type() const { return my_type; } bool is_legacy() const { return legacy; } void add_mapper_type(Type* t) { mapper_types.add(t); } diff --git a/function_test/Semantic_Analyser/Makefile.semantic b/function_test/Semantic_Analyser/Makefile.semantic index 9ddf3b0d32bc5ae11f82bdea769355d0e366cce0..99999127354ddaaeda8dfa8e18109b4f992b4e61 100644 --- a/function_test/Semantic_Analyser/Makefile.semantic +++ b/function_test/Semantic_Analyser/Makefile.semantic @@ -13,7 +13,7 @@ # ############################################################################## SADIRS := ver param template any_from pattern_ref float recof_index \ -port_translation mtc_and_system_clause +port_translation mtc_and_system_clause port_map_connect ifdef RT2 SADIRS += deprecated erroneous_attributes template_concat endif diff --git a/function_test/Semantic_Analyser/port_map_connect/Makefile b/function_test/Semantic_Analyser/port_map_connect/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..7a16554b8bbce3b10dde2cb80cc9aa0a0a19c9cb --- /dev/null +++ b/function_test/Semantic_Analyser/port_map_connect/Makefile @@ -0,0 +1,13 @@ +############################################################################## +# Copyright (c) 2000-2017 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: +# Szabo, Bence Janos +# +############################################################################## +NO3=3 +include ../common.mk diff --git a/function_test/Semantic_Analyser/port_map_connect/PortMapConnect_OK.ttcn b/function_test/Semantic_Analyser/port_map_connect/PortMapConnect_OK.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..32bdb6d294c535ffbb4800b45b4b8c6daa8457d0 --- /dev/null +++ b/function_test/Semantic_Analyser/port_map_connect/PortMapConnect_OK.ttcn @@ -0,0 +1,115 @@ +/****************************************************************************** + * Copyright (c) 2000-2017 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: + * Szabo, Bence Janos + * + ******************************************************************************/ + +module PortMapConnect_OK { //^In TTCN-3 module// + + type port P message { in integer; } + + type port P1 message { out integer; } + + signature MyRemoteProcOne (); + + type port P2 procedure { in MyRemoteProcOne; } + + type port P3 procedure { out MyRemoteProcOne; } + + type port P4 mixed { in MyRemoteProcOne; in integer; } + + type port P5 mixed { out MyRemoteProcOne; out integer; } + + type component C { + port P p; + port P1 p1; + port P2 p2; + port P3 p3; + port P4 p4; + port P5 p5; + } + + type component System { + port P p; + port P1 p1; + port P2 p2; + port P3 p3; + port P4 p4; + port P5 p5; + } + + testcase tc_map() runs on C system System { //In testcase definition// + + // message ports + /* correct */ + map(self:p, system:p); + map(self:p1, system:p1); + + /* incorrect */ + map(self:p, system:p1); //In map statement// //warning\: Port type \`\@PortMapConnect_OK\.P\' cannot send or receive from system port type \`\@PortMapConnect_OK\.P1\'\.// + map(system:p1, self:p); //In map statement// //warning\: Port type \`\@PortMapConnect_OK\.P\' cannot send or receive from system port type \`\@PortMapConnect_OK\.P1\'\.// + +/*---------------------------------------------*/ + + // procedure based ports + /* correct */ + map(self:p2, system:p2); + map(self:p3, system:p3); + + /* incorrect */ + map(self:p2, system:p3); //In map statement// //warning\: Port type \`\@PortMapConnect_OK\.P2\' cannot send or receive from system port type \`\@PortMapConnect_OK\.P3\'\.// + map(system:p3, self:p2); //In map statement// //warning\: Port type \`\@PortMapConnect_OK\.P2\' cannot send or receive from system port type \`\@PortMapConnect_OK\.P3\'\.// + +/*---------------------------------------------*/ + // mixed ports + /* correct */ + map(self:p4, system:p4); + map(self:p5, system:p5); + + /* incorrect */ + map(self:p4, system:p5); //In map statement// //warning\: Port type \`\@PortMapConnect_OK\.P4\' cannot send or receive from system port type \`\@PortMapConnect_OK\.P5\'\.// + map(system:p5, self:p4); //In map statement// //warning\: Port type \`\@PortMapConnect_OK\.P4\' cannot send or receive from system port type \`\@PortMapConnect_OK\.P5\'\.// + } + + + testcase tc_connect() runs on C system System { //In testcase definition// + var System s := System.create; + + // message ports + /* correct */ + connect(self:p, s:p1); + connect(self:p1, s:p); + + /* incorrect */ + connect(self:p, s:p); //In connect statement// //warning\: Neither port type \`\@PortMapConnect_OK\.P\' nor port type \`\@PortMapConnect_OK\.P\' can send messages\.// + + // procedure ports + /* correct */ + connect(self:p2, s:p3); + connect(self:p3, s:p2); + + /* incorrect */ + connect(self:p2, s:p2); //In connect statement// //warning\: Neither port type \`\@PortMapConnect_OK\.P2\' nor port type \`\@PortMapConnect_OK\.P2\' can send messages\.// + + // mixed ports + /* correct */ + connect(self:p4, s:p5); + connect(self:p5, s:p4); + + /* incorrect */ + connect(self:p4, s:p4); //In connect statement// //warning\: Neither port type \`\@PortMapConnect_OK\.P4\' nor port type \`\@PortMapConnect_OK\.P4\' can send messages\.// + + + } + + control { + execute(tc_map()); + execute(tc_connect()); + } +} \ No newline at end of file diff --git a/function_test/Semantic_Analyser/port_map_connect/run_test_all b/function_test/Semantic_Analyser/port_map_connect/run_test_all new file mode 100755 index 0000000000000000000000000000000000000000..f524a62f4722b00e9bbceca4f404e718915d75d8 --- /dev/null +++ b/function_test/Semantic_Analyser/port_map_connect/run_test_all @@ -0,0 +1,3 @@ +#!/bin/bash + +make run || echo "makeitfail" >float_TD.script_error && exit 42 diff --git a/function_test/Semantic_Analyser/port_map_connect/t b/function_test/Semantic_Analyser/port_map_connect/t new file mode 100755 index 0000000000000000000000000000000000000000..3a4b58ec16cf2f1390a36c7a92f8823e3b94b425 --- /dev/null +++ b/function_test/Semantic_Analyser/port_map_connect/t @@ -0,0 +1,9 @@ +#!/usr/bin/perl +# note this is called through "perl -w" +use strict; + +my $self = $0; +$self =~ s!/t!!; + +exec('make check --no-print-directory -s -C ' . $self); +