From aa4cd2a7ebb6ee645210820504cee2ae7f27a0e1 Mon Sep 17 00:00:00 2001
From: Botond Baranyi <botond.baranyi@ericsson.com>
Date: Thu, 13 Jul 2017 17:25:07 +0200
Subject: [PATCH] Fixed C++ warning in JSON coders generated for unions with no
 fields (bug 519642)

Change-Id: I21b1d3684a9dc754cee100b0af4370247a8dadc2
Signed-off-by: Botond Baranyi <botond.baranyi@ericsson.com>
---
 compiler2/union.c | 565 ++++++++++++++++++++++++----------------------
 1 file changed, 298 insertions(+), 267 deletions(-)

diff --git a/compiler2/union.c b/compiler2/union.c
index 05e835e15..ce599013f 100644
--- a/compiler2/union.c
+++ b/compiler2/union.c
@@ -589,10 +589,13 @@ void defUnionClass(struct_def const *sdef, output_struct *output)
         "  BER_chk_descr(p_td);\n"
         "  ASN_BER_TLV_t *new_tlv = NULL;\n"
         "  TTCN_EncDec_ErrorContext ec_0(\"Alternative '\");\n"
-        "  TTCN_EncDec_ErrorContext ec_1;\n"
-        "  const Erroneous_values_t* err_vals = NULL;\n"
-        "  const Erroneous_descriptor_t* emb_descr = NULL;\n"
-        "  switch (union_selection) {\n", name);
+        "  TTCN_EncDec_ErrorContext ec_1;\n", name);
+      if (sdef->nElements > 0) {
+        src = mputstr(src,
+          "  const Erroneous_values_t* err_vals = NULL;\n"
+          "  const Erroneous_descriptor_t* emb_descr = NULL;\n");
+      }
+      src = mputstr(src, "  switch (union_selection) {\n");
       for (i = 0; i < sdef->nElements; i++) {
         src = mputprintf(src, "  case %s_%s:\n"
           "    err_vals = p_err_descr->get_field_err_values(%d);\n"
@@ -2017,62 +2020,11 @@ void defUnionClass(struct_def const *sdef, output_struct *output)
     // JSON encode
     src = mputprintf(src,
       "int %s::JSON_encode(const TTCN_Typedescriptor_t&%s, JSON_Tokenizer& p_tok) const\n"
-      "{\n", name, (use_runtime_2 || !sdef->jsonAsValue) ? " p_td" : "");
-    if (use_runtime_2) {
-      src = mputstr(src, "  if (err_descr) return JSON_encode_negtest(err_descr, p_td, p_tok);\n");
-    }
-    if (!sdef->jsonAsValue) {
-      // 'as value' is not set for the base type, but it might still be set in
-      // the type descriptor
-      src = mputstr(src, 
-        "  boolean as_value = NULL != p_td.json && p_td.json->as_value;\n"
-        "  int enc_len = as_value ? 0 : "
-        "p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);\n");
-    } else {
-      src = mputstr(src, "  int enc_len = 0;\n");
-    }
-    src = mputstr(src, "  switch(union_selection) {\n");
-      
-    for (i = 0; i < sdef->nElements; ++i) {
-      src = mputprintf(src, "  case %s_%s:\n", selection_prefix, sdef->elements[i].name);
-      if (!sdef->jsonAsValue) {
-        src = mputprintf(src,
-          "    if (!as_value) {\n"
-          "      enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"%s\");\n"
-          "    }\n"
-          , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname);
+      "{\n", name, (sdef->nElements > 0) && (use_runtime_2 || !sdef->jsonAsValue) ? " p_td" : "");
+    if (sdef->nElements > 0) {
+      if (use_runtime_2) {
+        src = mputstr(src, "  if (err_descr) return JSON_encode_negtest(err_descr, p_td, p_tok);\n");
       }
-      src = mputprintf(src, 
-	      "    enc_len += field_%s->JSON_encode(%s_descr_, p_tok);\n"
-	      "    break;\n"
-        , sdef->elements[i].name, sdef->elements[i].typedescrname);
-    }
-    src = mputprintf(src, 
-      "  default:\n"
-      "    TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, \n"
-	    "      \"Encoding an unbound value of type %s.\");\n"
-      "    return -1;\n"
-      "  }\n\n"
-      , dispname);
-    if (!sdef->jsonAsValue) {
-      src = mputstr(src,
-        "  if (!as_value) {\n"
-        "    enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);\n"
-        "  }\n");
-    }
-    src = mputstr(src,
-      "  return enc_len;\n"
-      "}\n\n");
-    
-    if (use_runtime_2) {
-      // JSON encode for negative testing
-      def = mputstr(def,
-        "int JSON_encode_negtest(const Erroneous_descriptor_t*, "
-        "const TTCN_Typedescriptor_t&, JSON_Tokenizer&) const;\n");
-      src = mputprintf(src,
-        "int %s::JSON_encode_negtest(const Erroneous_descriptor_t* p_err_descr, "
-        "const TTCN_Typedescriptor_t&%s, JSON_Tokenizer& p_tok) const\n"
-        "{\n", name, !sdef->jsonAsValue ? " p_td" : "");
       if (!sdef->jsonAsValue) {
         // 'as value' is not set for the base type, but it might still be set in
         // the type descriptor
@@ -2081,55 +2033,22 @@ void defUnionClass(struct_def const *sdef, output_struct *output)
           "  int enc_len = as_value ? 0 : "
           "p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);\n");
       } else {
-        src = mputstr(src, "  int enc_len = 0;\n\n");
+        src = mputstr(src, "  int enc_len = 0;\n");
       }
-      src = mputstr(src,
-        "  const Erroneous_values_t* err_vals = NULL;\n"
-        "  const Erroneous_descriptor_t* emb_descr = NULL;\n"
-        "  switch(union_selection) {\n");
-        
+      src = mputstr(src, "  switch(union_selection) {\n");
+
       for (i = 0; i < sdef->nElements; ++i) {
-        src = mputprintf(src, 
-          "  case %s_%s:\n"
-          "    err_vals = p_err_descr->get_field_err_values(%d);\n"
-          "    emb_descr = p_err_descr->get_field_emb_descr(%d);\n"
-          "    if (NULL != err_vals && NULL != err_vals->value) {\n"
-          "      if (NULL != err_vals->value->errval) {\n"
-          "        if(err_vals->value->raw){\n"
-          "          enc_len += err_vals->value->errval->JSON_encode_negtest_raw(p_tok);\n"
-          "        } else {\n"
-          "          if (NULL == err_vals->value->type_descr) {\n"
-          "            TTCN_error(\"internal error: erroneous value typedescriptor missing\");\n"
-          "          }\n"
-          , selection_prefix, sdef->elements[i].name, (int)i, (int)i);
+        src = mputprintf(src, "  case %s_%s:\n", selection_prefix, sdef->elements[i].name);
         if (!sdef->jsonAsValue) {
           src = mputprintf(src,
-            "          if (!as_value) {\n"
-            "            enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"%s\");\n"
-            "          }\n"
-            , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname);
-        }
-        src = mputstr(src,
-          "          enc_len += err_vals->value->errval->JSON_encode(*err_vals->value->type_descr, p_tok);\n"
-          "        }\n"
-          "      }\n"
-          "    } else {\n");
-        if (!sdef->jsonAsValue) {
-          src = mputprintf(src,
-            "      if (!as_value) {\n"
-            "        enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"%s\");\n"
-            "      }\n"
+            "    if (!as_value) {\n"
+            "      enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"%s\");\n"
+            "    }\n"
             , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname);
         }
-        src = mputprintf(src,
-          "      if (NULL != emb_descr) {\n"
-          "        enc_len += field_%s->JSON_encode_negtest(emb_descr, %s_descr_, p_tok);\n"
-          "      } else {\n"
-          "        enc_len += field_%s->JSON_encode(%s_descr_, p_tok);\n"
-          "      }\n"
-          "    }\n"
+        src = mputprintf(src, 
+          "    enc_len += field_%s->JSON_encode(%s_descr_, p_tok);\n"
           "    break;\n"
-          , sdef->elements[i].name, sdef->elements[i].typedescrname
           , sdef->elements[i].name, sdef->elements[i].typedescrname);
       }
       src = mputprintf(src, 
@@ -2143,195 +2062,307 @@ void defUnionClass(struct_def const *sdef, output_struct *output)
         src = mputstr(src,
           "  if (!as_value) {\n"
           "    enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);\n"
-          "}\n");
+          "  }\n");
       }
       src = mputstr(src,
         "  return enc_len;\n"
         "}\n\n");
     }
+    else {
+      src = mputprintf(src,
+        "  TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, \n"
+        "    \"Cannot encode union of type %s, because it has zero alternatives.\");\n"
+        "  return -1;\n"
+        "}\n\n", dispname);   
+    }
+    
+    if (use_runtime_2) {
+      // JSON encode for negative testing
+      def = mputstr(def,
+        "int JSON_encode_negtest(const Erroneous_descriptor_t*, "
+        "const TTCN_Typedescriptor_t&, JSON_Tokenizer&) const;\n");
+      src = mputprintf(src,
+        "int %s::JSON_encode_negtest(const Erroneous_descriptor_t*%s, "
+        "const TTCN_Typedescriptor_t&%s, JSON_Tokenizer& p_tok) const\n"
+        "{\n", name, sdef->nElements > 0 ? " p_err_descr" : "",
+        (sdef->nElements > 0 && !sdef->jsonAsValue) ? " p_td" : "");
+      if (sdef->nElements > 0) {
+        if (!sdef->jsonAsValue) {
+          // 'as value' is not set for the base type, but it might still be set in
+          // the type descriptor
+          src = mputstr(src, 
+            "  boolean as_value = NULL != p_td.json && p_td.json->as_value;\n"
+            "  int enc_len = as_value ? 0 : "
+            "p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);\n");
+        } else {
+          src = mputstr(src, "  int enc_len = 0;\n\n");
+        }
+        src = mputstr(src,
+          "  const Erroneous_values_t* err_vals = NULL;\n"
+          "  const Erroneous_descriptor_t* emb_descr = NULL;\n"
+          "  switch(union_selection) {\n");
+
+        for (i = 0; i < sdef->nElements; ++i) {
+          src = mputprintf(src, 
+            "  case %s_%s:\n"
+            "    err_vals = p_err_descr->get_field_err_values(%d);\n"
+            "    emb_descr = p_err_descr->get_field_emb_descr(%d);\n"
+            "    if (NULL != err_vals && NULL != err_vals->value) {\n"
+            "      if (NULL != err_vals->value->errval) {\n"
+            "        if(err_vals->value->raw){\n"
+            "          enc_len += err_vals->value->errval->JSON_encode_negtest_raw(p_tok);\n"
+            "        } else {\n"
+            "          if (NULL == err_vals->value->type_descr) {\n"
+            "            TTCN_error(\"internal error: erroneous value typedescriptor missing\");\n"
+            "          }\n"
+            , selection_prefix, sdef->elements[i].name, (int)i, (int)i);
+          if (!sdef->jsonAsValue) {
+            src = mputprintf(src,
+              "          if (!as_value) {\n"
+              "            enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"%s\");\n"
+              "          }\n"
+              , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname);
+          }
+          src = mputstr(src,
+            "          enc_len += err_vals->value->errval->JSON_encode(*err_vals->value->type_descr, p_tok);\n"
+            "        }\n"
+            "      }\n"
+            "    } else {\n");
+          if (!sdef->jsonAsValue) {
+            src = mputprintf(src,
+              "      if (!as_value) {\n"
+              "        enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"%s\");\n"
+              "      }\n"
+              , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname);
+          }
+          src = mputprintf(src,
+            "      if (NULL != emb_descr) {\n"
+            "        enc_len += field_%s->JSON_encode_negtest(emb_descr, %s_descr_, p_tok);\n"
+            "      } else {\n"
+            "        enc_len += field_%s->JSON_encode(%s_descr_, p_tok);\n"
+            "      }\n"
+            "    }\n"
+            "    break;\n"
+            , sdef->elements[i].name, sdef->elements[i].typedescrname
+            , sdef->elements[i].name, sdef->elements[i].typedescrname);
+        }
+        src = mputprintf(src, 
+          "  default:\n"
+          "    TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, \n"
+          "      \"Encoding an unbound value of type %s.\");\n"
+          "    return -1;\n"
+          "  }\n\n"
+          , dispname);
+        if (!sdef->jsonAsValue) {
+          src = mputstr(src,
+            "  if (!as_value) {\n"
+            "    enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);\n"
+            "}\n");
+        }
+        src = mputstr(src,
+          "  return enc_len;\n"
+          "}\n\n");
+      }
+      else {
+        src = mputprintf(src,
+          "  TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, \n"
+          "    \"Cannot encode union of type %s, because it has zero alternatives.\");\n"
+          "  return -1;\n"
+          "}\n\n", dispname);
+      }
+    }
     
     // JSON decode
     src = mputprintf(src,
       "int %s::JSON_decode(const TTCN_Typedescriptor_t&%s, JSON_Tokenizer& p_tok, boolean p_silent)\n"
       "{\n"
-      "  json_token_t j_token = JSON_TOKEN_NONE;\n"
-      , name, !sdef->jsonAsValue ? " p_td" : "");
-    if (!sdef->jsonAsValue) {
-      src = mputstr(src,
-        " if (NULL != p_td.json && p_td.json->as_value) {\n");
-    }
-    src = mputstr(src,
-      "  size_t buf_pos = p_tok.get_buf_pos();\n"
-      "  p_tok.get_next_token(&j_token, NULL, NULL);\n"
-      "  int ret_val = 0;\n"
-      "  switch(j_token) {\n"
-      "  case JSON_TOKEN_NUMBER: {\n");
-    for (i = 0; i < sdef->nElements; ++i) {
-      if (JSON_NUMBER & sdef->elements[i].jsonValueType) {
-        src = mputprintf(src,
-          "    p_tok.set_buf_pos(buf_pos);\n"
-          "    ret_val = %s%s().JSON_decode(%s_descr_, p_tok, TRUE);\n"
-          "    if (0 <= ret_val) {\n"
-          "      return ret_val;\n"
-          "    }\n"
-          , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
-      }
-    }
-    src = mputstr(src,
-      "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, \"number\");\n"
-      "    clean_up();\n"
-      "    return JSON_ERROR_FATAL;\n"
-      "  }\n"
-      "  case JSON_TOKEN_STRING: {\n");
-    for (i = 0; i < sdef->nElements; ++i) {
-      if (JSON_STRING & sdef->elements[i].jsonValueType) {
-        src = mputprintf(src,
-          "    p_tok.set_buf_pos(buf_pos);\n"
-          "    ret_val = %s%s().JSON_decode(%s_descr_, p_tok, TRUE);\n"
-          "    if (0 <= ret_val) {\n"
-          "      return ret_val;\n"
-          "    }\n"
-          , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
+      , name, sdef->nElements > 0 && !sdef->jsonAsValue ? " p_td" : "");
+    if (sdef->nElements > 0) {
+      src = mputstr(src, "  json_token_t j_token = JSON_TOKEN_NONE;\n");
+      if (!sdef->jsonAsValue) {
+        src = mputstr(src,
+          " if (NULL != p_td.json && p_td.json->as_value) {\n");
       }
-    }
-    src = mputstr(src,
-      "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, \"string\");\n"
-      "    clean_up();\n"
-      "    return JSON_ERROR_FATAL;\n"
-      "  }\n"
-      "  case JSON_TOKEN_LITERAL_TRUE:\n"
-      "  case JSON_TOKEN_LITERAL_FALSE: {\n");
-    for (i = 0; i < sdef->nElements; ++i) {
-      if (JSON_BOOLEAN & sdef->elements[i].jsonValueType) {
-        src = mputprintf(src,
-          "    p_tok.set_buf_pos(buf_pos);\n"
-          "    ret_val = %s%s().JSON_decode(%s_descr_, p_tok, TRUE);\n"
-          "    if (0 <= ret_val) {\n"
-          "      return ret_val;\n"
-          "    }\n"
-          , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
+      src = mputstr(src,
+        "  size_t buf_pos = p_tok.get_buf_pos();\n"
+        "  p_tok.get_next_token(&j_token, NULL, NULL);\n"
+        "  int ret_val = 0;\n"
+        "  switch(j_token) {\n"
+        "  case JSON_TOKEN_NUMBER: {\n");
+      for (i = 0; i < sdef->nElements; ++i) {
+        if (JSON_NUMBER & sdef->elements[i].jsonValueType) {
+          src = mputprintf(src,
+            "    p_tok.set_buf_pos(buf_pos);\n"
+            "    ret_val = %s%s().JSON_decode(%s_descr_, p_tok, TRUE);\n"
+            "    if (0 <= ret_val) {\n"
+            "      return ret_val;\n"
+            "    }\n"
+            , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
+        }
       }
-    }
-    src = mputstr(src,
-      "    char* literal_str = mprintf(\"literal (%s)\",\n"
-      "      (JSON_TOKEN_LITERAL_TRUE == j_token) ? \"true\" : \"false\");\n"
-      "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, literal_str);\n"
-      "    Free(literal_str);\n"
-      "    clean_up();\n"
-      "    return JSON_ERROR_FATAL;\n"
-      "  }\n"
-      "  case JSON_TOKEN_ARRAY_START: {\n");
-    for (i = 0; i < sdef->nElements; ++i) {
-      if (JSON_ARRAY & sdef->elements[i].jsonValueType) {
-        src = mputprintf(src,
-          "    p_tok.set_buf_pos(buf_pos);\n"
-          "    ret_val = %s%s().JSON_decode(%s_descr_, p_tok, TRUE);\n"
-          "    if (0 <= ret_val) {\n"
-          "      return ret_val;\n"
-          "    }\n"
-          , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
+      src = mputstr(src,
+        "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, \"number\");\n"
+        "    clean_up();\n"
+        "    return JSON_ERROR_FATAL;\n"
+        "  }\n"
+        "  case JSON_TOKEN_STRING: {\n");
+      for (i = 0; i < sdef->nElements; ++i) {
+        if (JSON_STRING & sdef->elements[i].jsonValueType) {
+          src = mputprintf(src,
+            "    p_tok.set_buf_pos(buf_pos);\n"
+            "    ret_val = %s%s().JSON_decode(%s_descr_, p_tok, TRUE);\n"
+            "    if (0 <= ret_val) {\n"
+            "      return ret_val;\n"
+            "    }\n"
+            , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
+        }
       }
-    }
-    src = mputstr(src,
-      "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, \"array\");\n"
-      "    clean_up();\n"
-      "    return JSON_ERROR_FATAL;\n"
-      "  }\n"
-      "  case JSON_TOKEN_OBJECT_START: {\n");
-    for (i = 0; i < sdef->nElements; ++i) {
-      if (JSON_OBJECT & sdef->elements[i].jsonValueType) {
-        src = mputprintf(src,
-          "    p_tok.set_buf_pos(buf_pos);\n"
-          "    ret_val = %s%s().JSON_decode(%s_descr_, p_tok, TRUE);\n"
-          "    if (0 <= ret_val) {\n"
-          "      return ret_val;\n"
-          "    }\n"
-          , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
+      src = mputstr(src,
+        "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, \"string\");\n"
+        "    clean_up();\n"
+        "    return JSON_ERROR_FATAL;\n"
+        "  }\n"
+        "  case JSON_TOKEN_LITERAL_TRUE:\n"
+        "  case JSON_TOKEN_LITERAL_FALSE: {\n");
+      for (i = 0; i < sdef->nElements; ++i) {
+        if (JSON_BOOLEAN & sdef->elements[i].jsonValueType) {
+          src = mputprintf(src,
+            "    p_tok.set_buf_pos(buf_pos);\n"
+            "    ret_val = %s%s().JSON_decode(%s_descr_, p_tok, TRUE);\n"
+            "    if (0 <= ret_val) {\n"
+            "      return ret_val;\n"
+            "    }\n"
+            , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
+        }
       }
-    }
-    src = mputstr(src,
-      "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, \"object\");\n"
-      "    clean_up();\n"
-      "    return JSON_ERROR_FATAL;\n"
-      "  }\n"
-      "  case JSON_TOKEN_LITERAL_NULL: {\n");
-    for (i = 0; i < sdef->nElements; ++i) {
-      if (JSON_NULL & sdef->elements[i].jsonValueType) {
-        src = mputprintf(src,
-          "    p_tok.set_buf_pos(buf_pos);\n"
-          "    ret_val = %s%s().JSON_decode(%s_descr_, p_tok, TRUE);\n"
-          "    if (0 <= ret_val) {\n"
-          "      return ret_val;\n"
-          "    }\n"
-          , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
+      src = mputstr(src,
+        "    char* literal_str = mprintf(\"literal (%s)\",\n"
+        "      (JSON_TOKEN_LITERAL_TRUE == j_token) ? \"true\" : \"false\");\n"
+        "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, literal_str);\n"
+        "    Free(literal_str);\n"
+        "    clean_up();\n"
+        "    return JSON_ERROR_FATAL;\n"
+        "  }\n"
+        "  case JSON_TOKEN_ARRAY_START: {\n");
+      for (i = 0; i < sdef->nElements; ++i) {
+        if (JSON_ARRAY & sdef->elements[i].jsonValueType) {
+          src = mputprintf(src,
+            "    p_tok.set_buf_pos(buf_pos);\n"
+            "    ret_val = %s%s().JSON_decode(%s_descr_, p_tok, TRUE);\n"
+            "    if (0 <= ret_val) {\n"
+            "      return ret_val;\n"
+            "    }\n"
+            , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
+        }
       }
-    }
-    src = mputstr(src,
-      "    clean_up();\n"
-      // the caller might be able to decode the null value if it's an optional field
-      // only return an invalid token error, not a fatal error
-      "    return JSON_ERROR_INVALID_TOKEN;\n"
-      "  }\n"
-      "  case JSON_TOKEN_ERROR:\n"
-      "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n"
-      "    return JSON_ERROR_FATAL;\n"
-      "  default:\n"
-      "    return JSON_ERROR_INVALID_TOKEN;\n"
-      "  }\n"
-      "  return ret_val;\n");
-    if (!sdef->jsonAsValue) {
-      src = mputprintf(src,
-        " }\n"
-        " else {\n" // if there is no 'as value' set in the type descriptor
-        "  size_t dec_len = p_tok.get_next_token(&j_token, NULL, NULL);\n"
-        "  if (JSON_TOKEN_ERROR == j_token) {\n"
-        "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n"
+      src = mputstr(src,
+        "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, \"array\");\n"
+        "    clean_up();\n"
         "    return JSON_ERROR_FATAL;\n"
         "  }\n"
-        "  else if (JSON_TOKEN_OBJECT_START != j_token) {\n"
-        "    return JSON_ERROR_INVALID_TOKEN;\n"
-        "  }\n\n"
-        "  char* fld_name = 0;\n"
-        "  size_t name_len = 0;\n"
-        "  dec_len += p_tok.get_next_token(&j_token, &fld_name, &name_len);\n"
-        "  if (JSON_TOKEN_NAME != j_token) {\n"
-        "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_NAME_TOKEN_ERROR);\n"
+        "  case JSON_TOKEN_OBJECT_START: {\n");
+      for (i = 0; i < sdef->nElements; ++i) {
+        if (JSON_OBJECT & sdef->elements[i].jsonValueType) {
+          src = mputprintf(src,
+            "    p_tok.set_buf_pos(buf_pos);\n"
+            "    ret_val = %s%s().JSON_decode(%s_descr_, p_tok, TRUE);\n"
+            "    if (0 <= ret_val) {\n"
+            "      return ret_val;\n"
+            "    }\n"
+            , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
+        }
+      }
+      src = mputstr(src,
+        "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, \"object\");\n"
+        "    clean_up();\n"
         "    return JSON_ERROR_FATAL;\n"
-        "  } else {\n"
-        "    union_selection = %s;\n    "
-        , unbound_value);
+        "  }\n"
+        "  case JSON_TOKEN_LITERAL_NULL: {\n");
       for (i = 0; i < sdef->nElements; ++i) {
-        src = mputprintf(src,
-          "if (0 == strncmp(fld_name, \"%s\", name_len)) {\n"
-          "      int ret_val = %s%s().JSON_decode(%s_descr_, p_tok, p_silent);\n"
-          "      if (0 > ret_val) {\n"
-          "        if (JSON_ERROR_INVALID_TOKEN) {\n"
-          "          JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FIELD_TOKEN_ERROR, %lu, \"%s\");\n"
-          "        }\n"
-          "        return JSON_ERROR_FATAL;\n"
-          "      } else {\n"
-          "        dec_len += (size_t)ret_val;\n"
-          "      }\n"
-          "    } else "
-          , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname
-          , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname
-          , (unsigned long) strlen(sdef->elements[i].dispname), sdef->elements[i].dispname);
+        if (JSON_NULL & sdef->elements[i].jsonValueType) {
+          src = mputprintf(src,
+            "    p_tok.set_buf_pos(buf_pos);\n"
+            "    ret_val = %s%s().JSON_decode(%s_descr_, p_tok, TRUE);\n"
+            "    if (0 <= ret_val) {\n"
+            "      return ret_val;\n"
+            "    }\n"
+            , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
+        }
       }
       src = mputstr(src,
-        "{\n"
-        "      JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_INVALID_NAME_ERROR, (int)name_len, fld_name);\n"
-        "      return JSON_ERROR_FATAL;\n"
-        "    }\n"
-        "  }\n\n"
-        "  dec_len += p_tok.get_next_token(&j_token, NULL, NULL);\n"
-        "  if (JSON_TOKEN_OBJECT_END != j_token) {\n"
-        "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_STATIC_OBJECT_END_TOKEN_ERROR, \"\");\n"
+        "    clean_up();\n"
+        // the caller might be able to decode the null value if it's an optional field
+        // only return an invalid token error, not a fatal error
+        "    return JSON_ERROR_INVALID_TOKEN;\n"
+        "  }\n"
+        "  case JSON_TOKEN_ERROR:\n"
+        "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n"
         "    return JSON_ERROR_FATAL;\n"
-        "  }\n\n"
-        "  return (int)dec_len;\n"
-        " }\n");
+        "  default:\n"
+        "    return JSON_ERROR_INVALID_TOKEN;\n"
+        "  }\n"
+        "  return ret_val;\n");
+      if (!sdef->jsonAsValue) {
+        src = mputprintf(src,
+          " }\n"
+          " else {\n" // if there is no 'as value' set in the type descriptor
+          "  size_t dec_len = p_tok.get_next_token(&j_token, NULL, NULL);\n"
+          "  if (JSON_TOKEN_ERROR == j_token) {\n"
+          "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n"
+          "    return JSON_ERROR_FATAL;\n"
+          "  }\n"
+          "  else if (JSON_TOKEN_OBJECT_START != j_token) {\n"
+          "    return JSON_ERROR_INVALID_TOKEN;\n"
+          "  }\n\n"
+          "  char* fld_name = 0;\n"
+          "  size_t name_len = 0;\n"
+          "  dec_len += p_tok.get_next_token(&j_token, &fld_name, &name_len);\n"
+          "  if (JSON_TOKEN_NAME != j_token) {\n"
+          "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_NAME_TOKEN_ERROR);\n"
+          "    return JSON_ERROR_FATAL;\n"
+          "  } else {\n"
+          "    union_selection = %s;\n    "
+          , unbound_value);
+        for (i = 0; i < sdef->nElements; ++i) {
+          src = mputprintf(src,
+            "if (0 == strncmp(fld_name, \"%s\", name_len)) {\n"
+            "      int ret_val = %s%s().JSON_decode(%s_descr_, p_tok, p_silent);\n"
+            "      if (0 > ret_val) {\n"
+            "        if (JSON_ERROR_INVALID_TOKEN) {\n"
+            "          JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FIELD_TOKEN_ERROR, %lu, \"%s\");\n"
+            "        }\n"
+            "        return JSON_ERROR_FATAL;\n"
+            "      } else {\n"
+            "        dec_len += (size_t)ret_val;\n"
+            "      }\n"
+            "    } else "
+            , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname
+            , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname
+            , (unsigned long) strlen(sdef->elements[i].dispname), sdef->elements[i].dispname);
+        }
+        src = mputstr(src,
+          "{\n"
+          "      JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_INVALID_NAME_ERROR, (int)name_len, fld_name);\n"
+          "      return JSON_ERROR_FATAL;\n"
+          "    }\n"
+          "  }\n\n"
+          "  dec_len += p_tok.get_next_token(&j_token, NULL, NULL);\n"
+          "  if (JSON_TOKEN_OBJECT_END != j_token) {\n"
+          "    JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_STATIC_OBJECT_END_TOKEN_ERROR, \"\");\n"
+          "    return JSON_ERROR_FATAL;\n"
+          "  }\n\n"
+          "  return (int)dec_len;\n"
+          " }\n");
+      }
+      src = mputstr(src, "}\n\n");
+    }
+    else { // no fields
+      src = mputprintf(src,
+        "  JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, \n"
+        "    \"Cannot decode union of type %s, because it has zero alternatives.\");\n"
+        "  return JSON_ERROR_FATAL;\n"
+        "}\n\n", dispname);
     }
-    src = mputstr(src, "}\n\n");
   }
 
   /* end of class definition */
-- 
GitLab