From 2861f5cde4b79a190f744241ad13f8db2616e5fd Mon Sep 17 00:00:00 2001
From: Botond Baranyi <botond.baranyi@ericsson.com>
Date: Mon, 11 Apr 2016 14:07:22 +0200
Subject: [PATCH] Fixed code generation error for parameter default values
 (artf724695)

Change-Id: Ifad00e6719e4a0587314192f8e0695f5bec72048
Signed-off-by: Botond Baranyi <botond.baranyi@ericsson.com>
---
 compiler2/Value.cc                            | 58 +++++++++----------
 compiler2/Value.hh                            |  2 +-
 compiler2/ttcn3/AST_ttcn3.cc                  |  4 +-
 compiler2/ttcn3/Templatestuff.cc              | 14 ++---
 compiler2/ttcn3/Templatestuff.hh              |  4 +-
 compiler2/ttcn3/TtcnTemplate.cc               | 14 ++---
 regression_test/compileonly/Makefile          |  3 +-
 .../defaultParamUsageBeforeDecl/A.ttcn        | 35 +++++++++++
 .../defaultParamUsageBeforeDecl/B.ttcn        | 53 +++++++++++++++++
 .../defaultParamUsageBeforeDecl/Makefile      | 54 +++++++++++++++++
 10 files changed, 191 insertions(+), 50 deletions(-)
 create mode 100644 regression_test/compileonly/defaultParamUsageBeforeDecl/A.ttcn
 create mode 100644 regression_test/compileonly/defaultParamUsageBeforeDecl/B.ttcn
 create mode 100644 regression_test/compileonly/defaultParamUsageBeforeDecl/Makefile

diff --git a/compiler2/Value.cc b/compiler2/Value.cc
index 2416c269f..72e85de10 100644
--- a/compiler2/Value.cc
+++ b/compiler2/Value.cc
@@ -11144,20 +11144,18 @@ error:
     return str;
   }
 
-  char *Value::rearrange_init_code(char *str)
+  char *Value::rearrange_init_code(char *str, Common::Module* usage_mod)
   {
     switch (valuetype) {
     case V_REFD: {
       Ttcn::ActualParList *parlist = u.ref.ref->get_parlist();
       if (parlist) {
-	str = parlist->rearrange_init_code(str,
-	  u.ref.ref->get_refd_assignment()->get_my_scope()->get_scope_mod_gen());
+	str = parlist->rearrange_init_code(str, usage_mod);
       }
       break; }
     case V_INVOKE: {
-      str = u.invoke.v->rearrange_init_code(str);
-      str = u.invoke.ap_list->rearrange_init_code(str,
-        u.invoke.v->get_expr_governor_last()->get_my_scope()->get_scope_mod_gen());
+      str = u.invoke.v->rearrange_init_code(str, usage_mod);
+      str = u.invoke.ap_list->rearrange_init_code(str, usage_mod);
       break; }
     case V_EXPR:
       switch (u.expr.v_optype) {
@@ -11198,16 +11196,16 @@ error:
       case OPTYPE_GET_STRINGENCODING:
       case OPTYPE_REMOVE_BOM:
       case OPTYPE_DECODE_BASE64:
-        str = u.expr.v1->rearrange_init_code(str);
+        str = u.expr.v1->rearrange_init_code(str, usage_mod);
         break;
       case OPTYPE_DECODE: {
         Ttcn::ActualParList *parlist = u.expr.r1->get_parlist();
         Common::Assignment *ass = u.expr.r1->get_refd_assignment();
-        if (parlist) str = parlist->rearrange_init_code(str, ass->get_my_scope()->get_scope_mod_gen());
+        if (parlist) str = parlist->rearrange_init_code(str, usage_mod);
 
         parlist = u.expr.r2->get_parlist();
         ass = u.expr.r2->get_refd_assignment();
-        if (parlist) str = parlist->rearrange_init_code(str, ass->get_my_scope()->get_scope_mod_gen());
+        if (parlist) str = parlist->rearrange_init_code(str, usage_mod);
         break; }
       case OPTYPE_ADD:
       case OPTYPE_SUBTRACT:
@@ -11236,35 +11234,35 @@ error:
       case OPTYPE_INT2HEX:
       case OPTYPE_INT2OCT:
       //case OPTYPE_DECODE:
-        str = u.expr.v1->rearrange_init_code(str);
-        str = u.expr.v2->rearrange_init_code(str);
+        str = u.expr.v1->rearrange_init_code(str, usage_mod);
+        str = u.expr.v2->rearrange_init_code(str, usage_mod);
         break;
       case OPTYPE_UNICHAR2OCT: // v1 [v2]
       case OPTYPE_OCT2UNICHAR:
       case OPTYPE_ENCODE_BASE64:
-        str = u.expr.v1->rearrange_init_code(str);
-        if (u.expr.v2) str = u.expr.v2->rearrange_init_code(str);
+        str = u.expr.v1->rearrange_init_code(str, usage_mod);
+        if (u.expr.v2) str = u.expr.v2->rearrange_init_code(str, usage_mod);
         break;
       case OPTYPE_SUBSTR:
-        str = u.expr.ti1->rearrange_init_code(str, my_scope->get_scope_mod_gen());
-        str = u.expr.v2->rearrange_init_code(str);
-        str = u.expr.v3->rearrange_init_code(str);
+        str = u.expr.ti1->rearrange_init_code(str, usage_mod);
+        str = u.expr.v2->rearrange_init_code(str, usage_mod);
+        str = u.expr.v3->rearrange_init_code(str, usage_mod);
         break;
       case OPTYPE_REGEXP:
-        str = u.expr.ti1->rearrange_init_code(str, my_scope->get_scope_mod_gen());
-        str = u.expr.t2->rearrange_init_code(str, my_scope->get_scope_mod_gen());
-        str = u.expr.v3->rearrange_init_code(str);
+        str = u.expr.ti1->rearrange_init_code(str, usage_mod);
+        str = u.expr.t2->rearrange_init_code(str, usage_mod);
+        str = u.expr.v3->rearrange_init_code(str, usage_mod);
         break;
       case OPTYPE_DECOMP:
-        str = u.expr.v1->rearrange_init_code(str);
-        str = u.expr.v2->rearrange_init_code(str);
-        str = u.expr.v3->rearrange_init_code(str);
+        str = u.expr.v1->rearrange_init_code(str, usage_mod);
+        str = u.expr.v2->rearrange_init_code(str, usage_mod);
+        str = u.expr.v3->rearrange_init_code(str, usage_mod);
         break;
       case OPTYPE_REPLACE:
-        str = u.expr.ti1->rearrange_init_code(str, my_scope->get_scope_mod_gen());
-        str = u.expr.v2->rearrange_init_code(str);
-        str = u.expr.v3->rearrange_init_code(str);
-        str = u.expr.ti4->rearrange_init_code(str, my_scope->get_scope_mod_gen());
+        str = u.expr.ti1->rearrange_init_code(str, usage_mod);
+        str = u.expr.v2->rearrange_init_code(str, usage_mod);
+        str = u.expr.v3->rearrange_init_code(str, usage_mod);
+        str = u.expr.ti4->rearrange_init_code(str, usage_mod);
         break;
       case OPTYPE_LENGTHOF:
       case OPTYPE_SIZEOF:
@@ -11272,14 +11270,14 @@ error:
       case OPTYPE_ENCODE:
       case OPTYPE_ISPRESENT:
       case OPTYPE_TTCN2STRING:
-        str = u.expr.ti1->rearrange_init_code(str, my_scope->get_scope_mod_gen());
+        str = u.expr.ti1->rearrange_init_code(str, usage_mod);
         break;
       case OPTYPE_ISCHOSEN_T:
-        str = u.expr.t1->rearrange_init_code(str, my_scope->get_scope_mod_gen());
+        str = u.expr.t1->rearrange_init_code(str, usage_mod);
         break;
       case OPTYPE_MATCH:
-        str = u.expr.v1->rearrange_init_code(str);
-        str = u.expr.t2->rearrange_init_code(str, my_scope->get_scope_mod_gen());
+        str = u.expr.v1->rearrange_init_code(str, usage_mod);
+        str = u.expr.t2->rearrange_init_code(str, usage_mod);
         break;
       default:
         // other kinds of expressions cannot appear within templates
diff --git a/compiler2/Value.hh b/compiler2/Value.hh
index 49ddce67b..60b0a18df 100644
--- a/compiler2/Value.hh
+++ b/compiler2/Value.hh
@@ -797,7 +797,7 @@ namespace Common {
      *  parameter list of parameterized value references
      *  (e.g. function calls) and in operands of valueof or match
      *  operations. */
-    char *rearrange_init_code(char *str);
+    char *rearrange_init_code(char *str, Common::Module* usage_mod);
     /**
      *  Generates a value for temporary use. Example:
      *
diff --git a/compiler2/ttcn3/AST_ttcn3.cc b/compiler2/ttcn3/AST_ttcn3.cc
index d1afdbcb1..b720bcb0b 100644
--- a/compiler2/ttcn3/AST_ttcn3.cc
+++ b/compiler2/ttcn3/AST_ttcn3.cc
@@ -9638,7 +9638,7 @@ namespace Ttcn {
   {
     switch (selection) {
     case AP_VALUE:
-      str = val->rearrange_init_code(str);
+      str = val->rearrange_init_code(str, usage_mod);
       break;
     case AP_TEMPLATE:
       str = temp->rearrange_init_code(str, usage_mod);
@@ -9714,7 +9714,7 @@ namespace Ttcn {
       temp->dump(level + 1);
       break;
     case AP_REF:
-      DEBUG(level, "actual parameter: referecne");
+      DEBUG(level, "actual parameter: reference");
       ref->dump(level + 1);
       break;
     case AP_DEFAULT:
diff --git a/compiler2/ttcn3/Templatestuff.cc b/compiler2/ttcn3/Templatestuff.cc
index 5cc1f6d0b..7a8241f28 100644
--- a/compiler2/ttcn3/Templatestuff.cc
+++ b/compiler2/ttcn3/Templatestuff.cc
@@ -129,10 +129,10 @@ namespace Ttcn {
     return str;
   }
 
-  char *ValueRange::rearrange_init_code(char *str)
+  char *ValueRange::rearrange_init_code(char *str, Common::Module* usage_mod)
   {
-    if (min_v) str = min_v->rearrange_init_code(str);
-    if (max_v) str = max_v->rearrange_init_code(str);
+    if (min_v) str = min_v->rearrange_init_code(str, usage_mod);
+    if (max_v) str = max_v->rearrange_init_code(str, usage_mod);
     return str;
   }
 
@@ -765,12 +765,12 @@ namespace Ttcn {
     return str;
   }
 
-  char *LengthRestriction::rearrange_init_code(char *str)
+  char *LengthRestriction::rearrange_init_code(char *str, Common::Module* usage_mod)
   {
     if (is_range) {
-      str = range.lower->rearrange_init_code(str);
-      if (range.upper) str = range.upper->rearrange_init_code(str);
-    } else str = single->rearrange_init_code(str);
+      str = range.lower->rearrange_init_code(str, usage_mod);
+      if (range.upper) str = range.upper->rearrange_init_code(str, usage_mod);
+    } else str = single->rearrange_init_code(str, usage_mod);
     return str;
   }
 
diff --git a/compiler2/ttcn3/Templatestuff.hh b/compiler2/ttcn3/Templatestuff.hh
index acf26ac71..450d9c91c 100644
--- a/compiler2/ttcn3/Templatestuff.hh
+++ b/compiler2/ttcn3/Templatestuff.hh
@@ -67,7 +67,7 @@ namespace Ttcn {
     /** Appends the initialization sequence of all (directly or indirectly)
      * referred non-parameterized templates to \a str and returns the resulting
      * string. */
-    char *rearrange_init_code(char *str);
+    char *rearrange_init_code(char *str, Common::Module* usage_mod);
     /** Appends the string representation of the value range to \a str. */
     void append_stringRepr(string& str) const;
     virtual void dump(unsigned level) const;
@@ -270,7 +270,7 @@ namespace Ttcn {
     /** Appends the initialization sequence of all (directly or indirectly)
      * referred non-parameterized templates to \a str and returns the resulting
      * string. */
-    char *rearrange_init_code(char *str);
+    char *rearrange_init_code(char *str, Common::Module* usage_mod);
     /** Appends the string representation of the length restriction to
      * \a str. */
     void append_stringRepr(string& str) const;
diff --git a/compiler2/ttcn3/TtcnTemplate.cc b/compiler2/ttcn3/TtcnTemplate.cc
index 33ea91e96..382bb944d 100644
--- a/compiler2/ttcn3/TtcnTemplate.cc
+++ b/compiler2/ttcn3/TtcnTemplate.cc
@@ -3008,7 +3008,7 @@ end:
       break;
     case SPECIFIC_VALUE:
       if (get_code_section() == CS_POST_INIT)
-        str = u.specific_value->rearrange_init_code(str);
+        str = u.specific_value->rearrange_init_code(str, my_scope->get_scope_mod_gen());
       str = u.specific_value->generate_code_init(str, name);
       break;
     case TEMPLATE_REFD:
@@ -3040,7 +3040,7 @@ end:
       break;
     case VALUE_RANGE:
       if (get_code_section() == CS_POST_INIT)
-        str = u.value_range->rearrange_init_code(str);
+        str = u.value_range->rearrange_init_code(str, my_scope->get_scope_mod_gen());
       str = u.value_range->generate_code_init(str, name);
       break;
     case SUPERSET_MATCH:
@@ -3060,7 +3060,7 @@ end:
     }
     if (length_restriction) {
       if (get_code_section() == CS_POST_INIT)
-        str = length_restriction->rearrange_init_code(str);
+        str = length_restriction->rearrange_init_code(str, my_scope->get_scope_mod_gen());
       str = length_restriction->generate_code_init(str, name);
     }
     if (is_ifpresent) str = mputprintf(str, "%s.set_ifpresent();\n", name);
@@ -3074,7 +3074,7 @@ end:
   {
     switch (templatetype) {
     case SPECIFIC_VALUE:
-      str = u.specific_value->rearrange_init_code(str);
+      str = u.specific_value->rearrange_init_code(str, usage_mod);
       break;
     case TEMPLATE_REFD:
       str = rearrange_init_code_refd(str, usage_mod);
@@ -3102,12 +3102,12 @@ end:
           ->rearrange_init_code(str, usage_mod);
       break;
     case VALUE_RANGE:
-      str = u.value_range->rearrange_init_code(str);
+      str = u.value_range->rearrange_init_code(str, usage_mod);
       break;
     default:
       break;
     }
-    if (length_restriction) str = length_restriction->rearrange_init_code(str);
+    if (length_restriction) str = length_restriction->rearrange_init_code(str, usage_mod);
     return str;
   }
 
@@ -4516,7 +4516,7 @@ compile_time:
 
   char *Template::rearrange_init_code_invoke(char *str, Common::Module* usage_mod)
   {
-    str = u.invoke.v->rearrange_init_code(str);
+    str = u.invoke.v->rearrange_init_code(str, usage_mod);
     str = u.invoke.ap_list->rearrange_init_code(str, usage_mod);
     return str;
   }
diff --git a/regression_test/compileonly/Makefile b/regression_test/compileonly/Makefile
index cbdd7517b..373f72f09 100644
--- a/regression_test/compileonly/Makefile
+++ b/regression_test/compileonly/Makefile
@@ -25,7 +25,8 @@ CODIRS := dynamicTemplate styleGuide topLevelPdu \
 	centralstorage mfgen-tpd \
 	openType optionalAssignCompare portConstructor \
 	isbound namedActualParameters assignmentNotation \
-	attribQualif HT48786 selectCase openTypeNames
+	attribQualif HT48786 selectCase openTypeNames \
+	defaultParamUsageBeforeDecl
 
 all dep clean distclean:
 	for dir in $(CODIRS); do $(MAKE) -C $$dir $@ || exit; done
diff --git a/regression_test/compileonly/defaultParamUsageBeforeDecl/A.ttcn b/regression_test/compileonly/defaultParamUsageBeforeDecl/A.ttcn
new file mode 100644
index 000000000..5c2ee0fa0
--- /dev/null
+++ b/regression_test/compileonly/defaultParamUsageBeforeDecl/A.ttcn
@@ -0,0 +1,35 @@
+/******************************************************************************
+ * 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
+ *
+ ******************************************************************************/
+
+// Test for bug fix artf724695 : Incorrect code generated for template default value
+// This module uses the template and function default values declared in module B.
+// Code for this module is generated before code for module B.
+module A
+{
+
+import from B all;
+
+type record double_wrapped_string
+{
+    wrapped_string w_string
+}
+
+template double_wrapped_string t_double_wrapped_string
+(
+    template wrapped_string pl_wrapped_string := t_wrapped_string()
+):=
+{
+    w_string := pl_wrapped_string
+}
+
+}
+
diff --git a/regression_test/compileonly/defaultParamUsageBeforeDecl/B.ttcn b/regression_test/compileonly/defaultParamUsageBeforeDecl/B.ttcn
new file mode 100644
index 000000000..e202e5f12
--- /dev/null
+++ b/regression_test/compileonly/defaultParamUsageBeforeDecl/B.ttcn
@@ -0,0 +1,53 @@
+/******************************************************************************
+ * 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
+ *
+ ******************************************************************************/
+
+// Test for bug fix artf724695 : Incorrect code generated for template default value
+// The default values of templates and functions declared in this module are used in module A.
+// Code for this module is generated after code for module A.
+module B
+{
+
+function f
+(
+    template charstring pl_stringA := omit,
+    template charstring pl_stringB := omit // code for this default value was previously generated in A.cc
+)
+return charstring
+{
+    var charstring vl_return := "";
+    if(isvalue(pl_stringA))
+    {
+        vl_return := vl_return & valueof(pl_stringA)
+    }
+    if(isvalue(pl_stringB))
+    {
+        vl_return := vl_return & valueof(pl_stringB)
+    }
+    return vl_return
+}
+
+type record wrapped_string
+{
+    charstring string
+}
+
+template wrapped_string t_wrapped_string
+(
+    template charstring pl_string := f(pl_stringA := "EMMA")
+):=
+{
+    string := pl_string
+}
+
+
+}
+
diff --git a/regression_test/compileonly/defaultParamUsageBeforeDecl/Makefile b/regression_test/compileonly/defaultParamUsageBeforeDecl/Makefile
new file mode 100644
index 000000000..024abd788
--- /dev/null
+++ b/regression_test/compileonly/defaultParamUsageBeforeDecl/Makefile
@@ -0,0 +1,54 @@
+##############################################################################
+# 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
+#   Delic, Adam
+#   Kovacs, Ferenc
+#   Raduly, Csaba
+#   Szabados, Kristof
+#   Szabo, Janos Zoltan – initial implementation
+#
+##############################################################################
+TOPDIR := ../..
+include $(TOPDIR)/Makefile.regression
+
+.PHONY: all clean dep
+
+TTCN3_LIB := ttcn3$(RT2_SUFFIX)$(DYNAMIC_SUFFIX)
+
+MODULES := A.ttcn B.ttcn
+
+GENERATED_SOURCES := $(MODULES:.ttcn=.cc)
+GENERATED_HEADERS := $(GENERATED_SOURCES:.cc=.hh)
+ifdef CODE_SPLIT
+GENERATED_SOURCES := $(foreach file, $(GENERATED_SOURCES:.cc=), $(addprefix $(file), .cc _seq.cc _set.cc  _seqof.cc _setof.cc _union.cc))
+endif
+
+OBJECTS := $(GENERATED_SOURCES:.cc=.o)
+
+TARGET := defaultParamUsageBeforeDecl$(EXESUFFIX)
+
+all: $(TARGET) ;
+
+$(TARGET): $(GENERATED_SOURCES) $(USER_SOURCES)
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ $^ -L$(TTCN3_DIR)/lib -l$(TTCN3_LIB) \
+	-L$(OPENSSL_DIR)/lib -lcrypto $($(PLATFORM)_LIBS)
+
+$(GENERATED_SOURCES) $(GENERATED_HEADERS): compile
+	@if [ ! -f $@ ]; then $(RM) compile; $(MAKE) compile; fi
+
+compile: $(MODULES)
+	$(TTCN3_COMPILER) $(COMPILER_FLAGS) $^ - $?
+	touch $@
+
+clean distclean:
+	-$(RM) $(TARGET) $(OBJECTS) $(GENERATED_HEADERS) \
+	$(GENERATED_SOURCES) compile *.log Makefile.bak
+
+dep: $(GENERATED_SOURCES)
+	makedepend $(CPPFLAGS) $(USER_SOURCES) $(GENERATED_SOURCES)
-- 
GitLab