diff --git a/compiler2/Type.cc b/compiler2/Type.cc index 0f0221295106f10e5d01a265c1206df2e9ad1542..4602ccca5d28aefa2bdb5fe2c7f4b80fdf579189 100644 --- a/compiler2/Type.cc +++ b/compiler2/Type.cc @@ -3458,12 +3458,17 @@ namespace Common { default: // no need to generate coder functions for basic types, but this function // is also used to determine codec-specific descriptor generation - return can_have_coding(coding); + return can_have_coding(coding) == TTRUE; } } void Type::set_gen_coder_functions(MessageEncodingType_t coding) { + if (is_asn1() && !checked) { + // probably a recursive ASN.1 type + // this function will be called again after the type is checked + return; + } // TODO: this should also influence type descriptor generation switch (coding) { case CT_BER: @@ -3528,19 +3533,27 @@ namespace Common { } if (built_in_coding != CT_CUSTOM && built_in_coding != CT_PER) { - if (get_type_refd_last()->can_have_coding(built_in_coding)) { + switch (get_type_refd_last()->can_have_coding(built_in_coding)) { + case TTRUE: { coding_t* new_coding = new coding_t; new_coding->built_in = TRUE; new_coding->modifier = modifier; new_coding->built_in_coding = built_in_coding; coding_table.add(new_coding); get_type_refd_last()->set_gen_coder_functions(built_in_coding); - } - else if (!silent) { - // TODO: if an ASN.1 type cannot have a specific encoding, - // it shouldn't be given that encoding in 'Type::chk_encodings' - warning("Type `%s' cannot have %s encoding. Encode attribute ignored.", - get_typename().c_str(), get_encoding_name(built_in_coding)); + break; } + case TFALSE: + if (!silent) { + // TODO: if an ASN.1 type cannot have a specific encoding, + // it shouldn't be given that encoding in 'Type::chk_encodings' + warning("Type `%s' cannot have %s encoding. Encode attribute ignored.", + get_typename().c_str(), get_encoding_name(built_in_coding)); + } + break; + case TUNKNOWN: + // do nothing, parts of the type are unchecked + // this function will be called later after the type has been checked + break; } } else { @@ -3689,11 +3702,15 @@ namespace Common { return t_parent; } - bool Type::can_have_coding(MessageEncodingType_t coding) + tribool Type::can_have_coding(MessageEncodingType_t coding) { + if (is_asn1() && !checked) { + // the type isn't fully checked yet + return TUNKNOWN; + } // this helps avoid infinite recursions in self-referencing types if (RecursionTracker::is_happening(this)) { - return true; + return TTRUE; } RecursionTracker tracker(this); @@ -3705,24 +3722,24 @@ namespace Common { (coding == CT_XER && !enable_xer()) || (coding == CT_JSON && !enable_json()) || (coding == CT_OER && !enable_oer())) { - return false; + return TFALSE; } // BER encoding is handled by 'has_encoding' if (coding == CT_BER) { - return has_encoding(CT_BER); + return has_encoding(CT_BER) ? TTRUE: TFALSE; } // XER encoding for ASN.1 types can only be enabled by a compiler option if (coding == CT_XER && !asn1_xer && is_asn1()) { - return false; + return TFALSE; } // optimization: if it already has the encoding set, then the answer is true for (size_t i = 0; i < coding_table.size(); ++i) { if (coding_table[i]->built_in && coding_table[i]->built_in_coding == coding) { - return true; + return TTRUE; } } @@ -3738,15 +3755,16 @@ namespace Common { // all field types must be able to have the specified encoding for (size_t i = 0; i < get_nof_comps(); ++i) { Type* field_type = get_comp_byIndex(i)->get_type()->get_type_refd_last(); - if (!field_type->can_have_coding(coding)) { - return false; + tribool tb = field_type->can_have_coding(coding); + if (tb != TTRUE) { + return tb; } } - return true; + return TTRUE; case T_ARRAY: if (coding != CT_JSON) { - return false; // arrays can only have JSON encoding + return TFALSE; // arrays can only have JSON encoding } // else fall through case T_SEQOF: @@ -3769,9 +3787,9 @@ namespace Common { case T_CSTR: case T_USTR: case T_ENUM_T: - return true; + return TTRUE; default: - return false; + return TFALSE; } case CT_TEXT: @@ -3783,9 +3801,9 @@ namespace Common { case T_CSTR: case T_USTR: case T_ENUM_T: - return true; + return TTRUE; default: - return false; + return TFALSE; } case CT_XER: @@ -3802,9 +3820,9 @@ namespace Common { case T_CSTR: case T_USTR: case T_ENUM_T: - return true; // TODO: what about T_ERROR? + return TTRUE; // TODO: what about T_ERROR? default: - return false; + return TFALSE; } case CT_JSON: @@ -3837,9 +3855,9 @@ namespace Common { case T_ANY: case T_ENUM_T: case T_ENUM_A: - return true; // TODO: what about T_ERROR? + return TTRUE; // TODO: what about T_ERROR? default: - return false; + return TFALSE; } case CT_OER: @@ -3869,9 +3887,9 @@ namespace Common { case T_SEQOF: case T_EXTERNAL: case T_OBJECTDESCRIPTOR: - return true; + return TTRUE; default: - return false; + return TFALSE; } default: FATAL_ERROR("Type::can_have_coding"); @@ -6585,7 +6603,7 @@ namespace Common { // types need an 'encode' attribute for user-defined codecs return false; } - return last->can_have_coding(encoding_type); + return last->can_have_coding(encoding_type) == TTRUE; } // legacy codec handling, plus BER and PER encoding in both cases static memoizer memory; diff --git a/compiler2/Type.hh b/compiler2/Type.hh index d3ebf42447db8540b004ef19bcf0c93ee67bc22c..b8f524c79210a0a731793ac29ef4bd1ab4fd8764 100644 --- a/compiler2/Type.hh +++ b/compiler2/Type.hh @@ -699,8 +699,10 @@ namespace Common { const vector<coding_t>& get_coding_table() const { return coding_table; } /** Returns whether this type can have the specified encoding. + * (Returns 'unknown' if the type is part of an ASN.1 structure that + * hasn't been fully checked yet.) * Only used with new codec handling. */ - bool can_have_coding(MessageEncodingType_t coding); + tribool can_have_coding(MessageEncodingType_t coding); /** Checks whether the type itself or one of its fields/elements is a * component or default type. Recursive. */ diff --git a/regression_test/compileonly/Bug550526/.gitignore b/regression_test/compileonly/Bug550526/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..3515fd525eccff20f14a6c0ecdf52c84348ebed2 --- /dev/null +++ b/regression_test/compileonly/Bug550526/.gitignore @@ -0,0 +1,4 @@ +Bug550526 +Bug550526.exe +Bug550526*.cc +Bug550526*.hh diff --git a/regression_test/compileonly/Bug550526/Bug550526.asn b/regression_test/compileonly/Bug550526/Bug550526.asn new file mode 100644 index 0000000000000000000000000000000000000000..307ca892f688c69e846260ba938b7cf0687223df --- /dev/null +++ b/regression_test/compileonly/Bug550526/Bug550526.asn @@ -0,0 +1,30 @@ +--///////////////////////////////////////////////////////////////////////////// +-- Copyright (c) 2000-2019 Ericsson Telecom AB +-- All rights reserved. This program and the accompanying materials +-- are made available under the terms of the Eclipse Public License v2.0 +-- which accompanies this distribution, and is available at +-- https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html +-- +-- Contributors: +-- Baranyi, Botond +-- +--///////////////////////////////////////////////////////////////////////////// +Bug550526 +DEFINITIONS AUTOMATIC TAGS ::= +BEGIN + +Main ::= SEQUENCE +{ + field1 CHOICE + { + alt1 INTEGER, + alt2 SEQUENCE SIZE (2..255) OF Main + }, + field2 CHOICE + { + alt3 INTEGER, + alt4 NULL + } +} + +END diff --git a/regression_test/compileonly/Bug550526/Makefile b/regression_test/compileonly/Bug550526/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..849124775d81b9559f553365141f594b5bce2019 --- /dev/null +++ b/regression_test/compileonly/Bug550526/Makefile @@ -0,0 +1,50 @@ +############################################################################## +# Copyright (c) 2000-2019 Ericsson Telecom AB +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v2.0 +# which accompanies this distribution, and is available at +# https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html +# +# Contributors: +# Botond, Baranyi +# +############################################################################## +TOPDIR := ../.. +include $(TOPDIR)/Makefile.regression + +.PHONY: all clean dep + +TTCN3_LIB = ttcn3$(RT2_SUFFIX)$(DYNAMIC_SUFFIX) + +ASN1_MODULES = Bug550526.asn + +GENERATED_SOURCES = $(ASN1_MODULES:.asn=.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)) +else ifdef SPLIT_TO_SLICES +POSTFIXES := $(foreach file, $(SPLIT_TO_SLICES), $(addsuffix $(file), _part_)) +POSTFIXES := $(foreach file, $(POSTFIXES), $(addprefix $(file), .cc)) +GENERATED_SOURCES2 := $(foreach file, $(GENERATED_SOURCES:.cc=), $(addprefix $(file), $(POSTFIXES))) +GENERATED_SOURCES += $(GENERATED_SOURCES2) +endif + +OBJECTS = $(GENERATED_SOURCES:.cc=.o) + +TARGET = Bug550526$(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): $(ASN1_MODULES) + $(TTCN3_COMPILER) $(COMPILER_FLAGS) $^ + +clean distclean: + $(RM) $(TARGET) $(OBJECTS) $(GENERATED_HEADERS) \ + $(GENERATED_SOURCES) compile *.log + +dep: $(GENERATED_SOURCES) + makedepend $(CPPFLAGS) $(GENERATED_SOURCES) diff --git a/regression_test/compileonly/Makefile b/regression_test/compileonly/Makefile index ba24b8a53ed48f0a783fb0f56f25b4e01a93440f..6be5170b4ff7c888e12dc3c51a333ac57119eff1 100644 --- a/regression_test/compileonly/Makefile +++ b/regression_test/compileonly/Makefile @@ -30,7 +30,7 @@ CODIRS := dynamicTemplate styleGuide topLevelPdu \ defaultParamUsageBeforeDecl deterministic readFromFile \ asn1_hyphen nameClash portTranslation UntaggedOnTopLevelUnionSwitch \ typeDescrGenWIthNoXER languageSpec asn1_opentype openTypeXER \ - asnStringSubtypes componentParameter realtimeKeywords + asnStringSubtypes componentParameter realtimeKeywords Bug550526 ifdef DYN CODIRS += mfgen-xsd