From 1ac61b5150218c6cb80003cb17c880bcb3e1e920 Mon Sep 17 00:00:00 2001
From: BenceJanosSzabo <bence.janos.szabo@ericsson.com>
Date: Tue, 15 Aug 2017 14:42:50 +0200
Subject: [PATCH] report impossible connect and map statements (Bug 515533)

Change-Id: I1b40b2ca3663d6f3734ece7683868a4dd01aaf52
Signed-off-by: BenceJanosSzabo <bence.janos.szabo@ericsson.com>
---
 compiler2/ttcn3/Statement.cc                  |  12 ++
 compiler2/ttcn3/Ttcnstuff.cc                  |  42 +++++++
 compiler2/ttcn3/Ttcnstuff.hh                  |  10 ++
 .../Semantic_Analyser/Makefile.semantic       |   2 +-
 .../port_map_connect/Makefile                 |  13 ++
 .../port_map_connect/PortMapConnect_OK.ttcn   | 115 ++++++++++++++++++
 .../port_map_connect/run_test_all             |   3 +
 .../Semantic_Analyser/port_map_connect/t      |   9 ++
 8 files changed, 205 insertions(+), 1 deletion(-)
 create mode 100644 function_test/Semantic_Analyser/port_map_connect/Makefile
 create mode 100644 function_test/Semantic_Analyser/port_map_connect/PortMapConnect_OK.ttcn
 create mode 100755 function_test/Semantic_Analyser/port_map_connect/run_test_all
 create mode 100755 function_test/Semantic_Analyser/port_map_connect/t

diff --git a/compiler2/ttcn3/Statement.cc b/compiler2/ttcn3/Statement.cc
index 1d670cf13..45cc76807 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 cac1d57c8..af78f712c 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 88ecdaa39..6d937e98c 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 9ddf3b0d3..999991273 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 000000000..7a16554b8
--- /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 000000000..32bdb6d29
--- /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 000000000..f524a62f4
--- /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 000000000..3a4b58ec1
--- /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);
+
-- 
GitLab