From 0e7b820f28e13712ff67fb266dc8e33a748a3224 Mon Sep 17 00:00:00 2001 From: Adam Mitz Date: Tue, 12 Mar 2024 16:45:11 -0500 Subject: [PATCH 01/18] Moved RTPS SubmessageKind to its own IDL file to use the value annotation Includes limited support for IDL4 "standardized" value annotation. When opendds_idl is used to generate the language mapping for an enum, an enumerator annoatated with value() will be assigned that value. Also changes opendds_idl options used for IDL internal to the RTPS library in order to minimize footprint of generated code. --- dds/DCPS/RTPS/.gitignore | 11 ++-- dds/DCPS/RTPS/CMakeLists.txt | 25 ++++++--- dds/DCPS/RTPS/RtpsCore.idl | 61 +-------------------- dds/DCPS/RTPS/RtpsSubmessageKind.idl | 40 ++++++++++++++ dds/DCPS/RTPS/rtps.mpc | 5 ++ dds/DCPS/RTPS/rtps_optional_safety.mpb | 4 +- dds/DCPS/XTypes/TypeObjectTypeSupportImpl.h | 4 +- dds/idl/annotations.cpp | 30 ++++++++++ dds/idl/annotations.h | 15 +++++ dds/idl/be_global.cpp | 6 ++ dds/idl/be_global.h | 2 + dds/idl/langmap_generator.cpp | 8 ++- 12 files changed, 135 insertions(+), 76 deletions(-) create mode 100644 dds/DCPS/RTPS/RtpsSubmessageKind.idl diff --git a/dds/DCPS/RTPS/.gitignore b/dds/DCPS/RTPS/.gitignore index 52c4dabc9ca..ff06427a4bd 100644 --- a/dds/DCPS/RTPS/.gitignore +++ b/dds/DCPS/RTPS/.gitignore @@ -17,10 +17,6 @@ /RtpsCoreC.h /RtpsCoreC.inl /RtpsCoreS.h -/RtpsSecurityC.cpp -/RtpsSecurityC.h -/RtpsSecurityC.inl -/RtpsSecurityS.h /RtpsCoreTypeSupport.idl /RtpsCoreTypeSupportC.cpp /RtpsCoreTypeSupportC.h @@ -49,6 +45,13 @@ /RtpsRpcS.h /RtpsRpcTypeSupportImpl.cpp /RtpsRpcTypeSupportImpl.h +/RtpsSecurityC.cpp +/RtpsSecurityC.h +/RtpsSecurityC.inl +/RtpsSecurityS.h +/RtpsSubmessageKindC.h +/RtpsSubmessageKindTypeSupportImpl.cpp +/RtpsSubmessageKindTypeSupportImpl.h /TypeLookupC.cpp /TypeLookupC.h /TypeLookupC.inl diff --git a/dds/DCPS/RTPS/CMakeLists.txt b/dds/DCPS/RTPS/CMakeLists.txt index e7bebee6f70..16e7bb87305 100644 --- a/dds/DCPS/RTPS/CMakeLists.txt +++ b/dds/DCPS/RTPS/CMakeLists.txt @@ -45,26 +45,33 @@ target_sources(OpenDDS_Rtps _opendds_library(OpenDDS_Rtps) target_link_libraries(OpenDDS_Rtps PUBLIC OpenDDS::Dcps) -set(ots_args +set(common_idl_options INCLUDE_BASE "${OPENDDS_SOURCE_DIR}" USE_EXPORT "dds/DCPS/RTPS/rtps_export.h" OpenDDS_Rtps_Export ) +set(tao_idl_options -St -Scdr) +set(opendds_idl_options -St -SI -Sv -Sx) opendds_target_sources(OpenDDS_Rtps PUBLIC RtpsCore.idl - RtpsSecurity.idl RtpsRpc.idl TypeLookup.idl - ${ots_args} - SKIP_OPENDDS_IDL - TAO_IDL_OPTIONS -St -Scdr + TAO_IDL_OPTIONS ${tao_idl_options} + OPENDDS_IDL_OPTIONS ${opendds_idl_options} + ${common_idl_options} ) opendds_target_sources(OpenDDS_Rtps PUBLIC - RtpsCore.idl - RtpsRpc.idl - TypeLookup.idl - ${ots_args} + RtpsSubmessageKind.idl + OPENDDS_IDL_OPTIONS ${opendds_idl_options} -Lspcpp SKIP_TAO_IDL + ${common_idl_options} +) +opendds_target_sources(OpenDDS_Rtps + PUBLIC + RtpsSecurity.idl + TAO_IDL_OPTIONS ${tao_idl_options} + SKIP_OPENDDS_IDL + ${common_idl_options} ) opendds_install_interface_files(OpenDDS_Rtps INCLUDE_BASE "${OPENDDS_SOURCE_DIR}") diff --git a/dds/DCPS/RTPS/RtpsCore.idl b/dds/DCPS/RTPS/RtpsCore.idl index a80145dd71b..6590c2f2076 100644 --- a/dds/DCPS/RTPS/RtpsCore.idl +++ b/dds/DCPS/RTPS/RtpsCore.idl @@ -16,6 +16,8 @@ #include "dds/DdsSecurityParams.idl" #endif +#include "RtpsSubmessageKind.idl" + module OpenDDS { module RTPS { @@ -538,7 +540,7 @@ module OpenDDS { unsigned short submessageLength; /* octetsToNextHeader */ }; // Valid constants for the submessageId field are the enumerators - // of the SubmessageKind enum in MessageTypes.h. + // of the SubmessageKind enum in RtpsSubmessageKind.idl // The least-significant bit of "flags" is E, the endianness flag: // pseudoenum E { BIG_ENDIAN = 0, LITTLE_ENDIAN = 1}; @@ -773,63 +775,6 @@ module OpenDDS { DDS::OctetSeq content; }; - enum SubmessageKind { - SUBMESSAGE_NONE, - PAD, /* = 0x01, Pad */ - RESERVED_2, - RESERVED_3, - RESERVED_4, - RESERVED_5, - ACKNACK, /* = 0x06, AckNack */ - HEARTBEAT, /* = 0x07, Heartbeat */ - GAP, /* = 0x08, Gap */ - INFO_TS, /* = 0x09, InfoTimestamp */ - RESERVED_10, - RESERVED_11, - INFO_SRC, /* = 0x0c, InfoSource */ - INFO_REPLY_IP4, /* = 0x0d, InfoReplyIp4 */ - INFO_DST, /* = 0x0e, InfoDestination */ - INFO_REPLY, /* = 0x0f, InfoReply */ - RESERVED_16, - RESERVED_17, - NACK_FRAG, /* = 0x12, NackFrag */ - HEARTBEAT_FRAG, /* = 0x13, HeartbeatFrag */ - RESERVED_20, - DATA, /* = 0x15, Data */ - DATA_FRAG, /* = 0x16, DataFrag */ - RESERVED_23, - RESERVED_24, - RESERVED_25, - RESERVED_26, - RESERVED_27, - RESERVED_28, - RESERVED_29, - RESERVED_30, - RESERVED_31, - RESERVED_32, - RESERVED_33, - RESERVED_34, - RESERVED_35, - RESERVED_36, - RESERVED_37, - RESERVED_38, - RESERVED_39, - RESERVED_40, - RESERVED_41, - RESERVED_42, - RESERVED_43, - RESERVED_44, - RESERVED_45, - RESERVED_46, - RESERVED_47, - SEC_BODY, // SubmessageKinds 0x30-3f reserved for security - SEC_PREFIX, - SEC_POSTFIX, - SRTPS_PREFIX, - SRTPS_POSTFIX, - RESERVED_53_SECURITY - }; - @OpenDDS::internal::special_serialization union Submessage switch (SubmessageKind) { case PAD: diff --git a/dds/DCPS/RTPS/RtpsSubmessageKind.idl b/dds/DCPS/RTPS/RtpsSubmessageKind.idl new file mode 100644 index 00000000000..be39fdc8bd4 --- /dev/null +++ b/dds/DCPS/RTPS/RtpsSubmessageKind.idl @@ -0,0 +1,40 @@ +/* + * Distributed under the OpenDDS License. + * See: http://www.opendds.org/license.html + */ + +#ifndef OPENDDS_DCPS_RTPS_RTPSSUBMESSAGEKIND_IDL +#define OPENDDS_DCPS_RTPS_RTPSSUBMESSAGEKIND_IDL + +module OpenDDS { +module RTPS { + +enum SubmessageKind { + @value(0x00) RTPS_HE, /* HeaderExtension */ + @value(0x01) PAD, /* Pad */ + @value(0x06) ACKNACK, /* AckNack */ + @value(0x07) HEARTBEAT, /* Heartbeat */ + @value(0x08) GAP, /* Gap */ + @value(0x09) INFO_TS, /* InfoTimestamp */ + @value(0x0c) INFO_SRC, /* InfoSource */ + @value(0x0d) INFO_REPLY_IP4, /* InfoReplyIp4 */ + @value(0x0e) INFO_DST, /* InfoDestination */ + @value(0x0f) INFO_REPLY, /* InfoReply */ + @value(0x12) NACK_FRAG, /* NackFrag */ + @value(0x13) HEARTBEAT_FRAG, /* HeartbeatFrag */ + @value(0x15) DATA, /* Data */ + @value(0x16) DATA_FRAG, /* DataFrag */ + + // SubmessageKinds 0x30-3f are reserved for DDS Security + @value(0x30) SEC_BODY, + @value(0x31) SEC_PREFIX, + @value(0x32) SEC_POSTFIX, + @value(0x33) SRTPS_PREFIX, + @value(0x34) SRTPS_POSTFIX + + // SubmessageKinds 0x80 and above are vendor-specific +}; + +}; +}; +#endif diff --git a/dds/DCPS/RTPS/rtps.mpc b/dds/DCPS/RTPS/rtps.mpc index 53a2a5d6e32..4fb40165de1 100644 --- a/dds/DCPS/RTPS/rtps.mpc +++ b/dds/DCPS/RTPS/rtps.mpc @@ -12,6 +12,11 @@ project(OpenDDS_Rtps): dcpslib, install, rtps_optional_safety, opendds_testing_f ICE } + TypeSupport_Files { + dcps_ts_flags += -Lspcpp -St -Sx + RtpsSubmessageKind.idl + } + specific { install_dir = dds/DCPS/RTPS } diff --git a/dds/DCPS/RTPS/rtps_optional_safety.mpb b/dds/DCPS/RTPS/rtps_optional_safety.mpb index 47974c914fd..30494999967 100644 --- a/dds/DCPS/RTPS/rtps_optional_safety.mpb +++ b/dds/DCPS/RTPS/rtps_optional_safety.mpb @@ -1,6 +1,6 @@ feature(no_opendds_safety_profile) : dcps_ts_defaults, dds_versioning_idl_defaults { idlflags += -Wb,export_macro=OpenDDS_Rtps_Export -Wb,export_include=rtps_export.h -SS - dcps_ts_flags += -Wb,export_macro=OpenDDS_Rtps_Export -Wb,export_include=rtps_export.h -SI + dcps_ts_flags += -Wb,export_macro=OpenDDS_Rtps_Export -Wb,export_include=rtps_export.h -SI -Sx -Sv -St IDL_Files { commandflags += -St -Scdr @@ -18,7 +18,7 @@ feature(no_opendds_safety_profile) : dcps_ts_defaults, dds_versioning_idl_defaul } feature(!no_opendds_safety_profile) : dcps_ts_defaults, dds_versioning_idl_defaults { - dcps_ts_flags += -Wb,export_macro=OpenDDS_Rtps_Export -Wb,export_include=rtps_export.h -SI -Sx -Lspcpp + dcps_ts_flags += -Wb,export_macro=OpenDDS_Rtps_Export -Wb,export_include=rtps_export.h -SI -Sx -Sv -Lspcpp IDL_Files { } diff --git a/dds/DCPS/XTypes/TypeObjectTypeSupportImpl.h b/dds/DCPS/XTypes/TypeObjectTypeSupportImpl.h index a89f175ec4d..9c81896d58f 100644 --- a/dds/DCPS/XTypes/TypeObjectTypeSupportImpl.h +++ b/dds/DCPS/XTypes/TypeObjectTypeSupportImpl.h @@ -8,13 +8,15 @@ #define OPENDDS_DCPS_XTYPES_TYPEOBJECTTYPESUPPORTIMPL_H #include "TypeObject.h" -#include "dds/DCPS/ValueReader.h" OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL namespace OpenDDS { namespace DCPS { +class ValueReader; +class ValueWriter; + inline bool vread(ValueReader&, XTypes::TypeIdentifier&) { return false; diff --git a/dds/idl/annotations.cpp b/dds/idl/annotations.cpp index d2c49025ce0..46abd54faf9 100644 --- a/dds/idl/annotations.cpp +++ b/dds/idl/annotations.cpp @@ -28,6 +28,7 @@ void Annotations::register_all() register_one(); register_one(); register_one(); + register_one(); register_one(); register_one(); register_one(); @@ -132,6 +133,14 @@ ACE_UINT32 get_u32_annotation_member_value(AST_Annotation_Appl* appl, return ev->u.ulval; } +ACE_INT32 get_i32_annotation_member_value(AST_Annotation_Appl* appl, + const char* member_name) +{ + AST_Expression::AST_ExprValue* const ev = + get_annotation_member_ev(appl, member_name, AST_Expression::EV_long); + return ev->u.lval; +} + std::string get_str_annotation_member_value(AST_Annotation_Appl* appl, const char* member_name) { @@ -152,6 +161,12 @@ ACE_UINT32 AnnotationWithValue::value_from_appl(AST_Annotation_Appl* return get_u32_annotation_member_value(appl, "value"); } +template<> +int AnnotationWithValue::value_from_appl(AST_Annotation_Appl* appl) const +{ + return get_i32_annotation_member_value(appl, "value"); +} + template<> std::string AnnotationWithValue::value_from_appl(AST_Annotation_Appl* appl) const { @@ -429,6 +444,21 @@ TryConstructFailAction TryConstructAnnotation::union_value(AST_Union* node) cons return value_from_appl(appl); } +// @value ==================================================================== + +std::string ValueAnnotation::definition() const +{ + return + "@annotation value {\n" + " long value;\n" + "};\n"; +} + +std::string ValueAnnotation::name() const +{ + return "value"; +} + OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL namespace OpenDDS { diff --git a/dds/idl/annotations.h b/dds/idl/annotations.h index a0cbbb7872a..3d858044adc 100644 --- a/dds/idl/annotations.h +++ b/dds/idl/annotations.h @@ -88,6 +88,9 @@ bool get_bool_annotation_member_value(AST_Annotation_Appl* appl, ACE_UINT32 get_u32_annotation_member_value(AST_Annotation_Appl* appl, const char* member_name); +ACE_INT32 get_i32_annotation_member_value(AST_Annotation_Appl* appl, + const char* member_name); + std::string get_str_annotation_member_value(AST_Annotation_Appl* appl, const char* member_name); @@ -139,6 +142,9 @@ bool AnnotationWithValue::value_from_appl(AST_Annotation_Appl* appl) const template<> unsigned AnnotationWithValue::value_from_appl(AST_Annotation_Appl* appl) const; +template<> +int AnnotationWithValue::value_from_appl(AST_Annotation_Appl* appl) const; + template<> std::string AnnotationWithValue::value_from_appl(AST_Annotation_Appl* appl) const; @@ -335,6 +341,15 @@ class TryConstructAnnotation TryConstructFailAction union_value(AST_Union* node) const; }; +// @value ==================================================================== + +struct ValueAnnotation : AnnotationWithValue { + // @value(long) is supported for enumerators + // more general @value support as described in IDL4.2 is not yet supported + std::string definition() const; + std::string name() const; +}; + // OpenDDS Specific Annotations OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL namespace OpenDDS { diff --git a/dds/idl/be_global.cpp b/dds/idl/be_global.cpp index 5413756fb87..59f4c3f798c 100644 --- a/dds/idl/be_global.cpp +++ b/dds/idl/be_global.cpp @@ -980,6 +980,12 @@ TryConstructFailAction BE_GlobalData::union_discriminator_try_construct(AST_Unio return try_construct_annotation->union_value(node); } +bool BE_GlobalData::value(AST_Decl* node, ACE_INT32& value) const +{ + ValueAnnotation* annotation = dynamic_cast(builtin_annotations_["::@value"]); + return annotation->node_value_exists(node, value); +} + OpenDDS::DataRepresentation BE_GlobalData::data_representations( AST_Decl* node) const { diff --git a/dds/idl/be_global.h b/dds/idl/be_global.h index 6a15e6c1df6..1119e4faf75 100644 --- a/dds/idl/be_global.h +++ b/dds/idl/be_global.h @@ -236,6 +236,8 @@ class BE_GlobalData { TryConstructFailAction array_element_try_construct(AST_Array* node); TryConstructFailAction union_discriminator_try_construct(AST_Union* node); + bool value(AST_Decl* node, ACE_INT32& value) const; + OpenDDS::DataRepresentation data_representations(AST_Decl* node) const; OpenDDS::XTypes::MemberId compute_id(AST_Structure* stru, AST_Field* field, AutoidKind auto_id, diff --git a/dds/idl/langmap_generator.cpp b/dds/idl/langmap_generator.cpp index 9c2fd0afd34..38d381bfb36 100644 --- a/dds/idl/langmap_generator.cpp +++ b/dds/idl/langmap_generator.cpp @@ -1939,8 +1939,12 @@ bool langmap_generator::gen_enum(AST_Enum*, UTL_ScopedName* name, "enum " << scoped_enum << nm << enum_base << " {\n"; for (size_t i = 0; i < contents.size(); ++i) { be_global->lang_header_ << - " " << contents[i]->local_name()->get_string() - << ((i < contents.size() - 1) ? ",\n" : "\n"); + " " << contents[i]->local_name()->get_string(); + ACE_INT32 value = 0; + if (be_global->value(contents[i], value)) { + be_global->lang_header_ << " = " << value; + } + be_global->lang_header_ << ((i < contents.size() - 1) ? ",\n" : "\n"); } be_global->lang_header_ << "};\n\n"; From cd9f850d159fdaafd63964de742ba88647bbd67f Mon Sep 17 00:00:00 2001 From: Adam Mitz Date: Wed, 13 Mar 2024 12:22:15 -0500 Subject: [PATCH 02/18] Added test for value-annotated enums. Minor cleanup in dds_vistor.cpp --- dds/idl/dds_visitor.cpp | 48 ++++++------------- .../C++11/value_annotation/.gitignore | 4 ++ .../C++11/value_annotation/run_test.pl | 23 +++++++++ .../value_annotation/value_annotation.cpp | 6 +++ .../value_annotation/value_annotation.idl | 12 +++++ .../value_annotation/value_annotation.mpc | 7 +++ tests/dcps_tests.lst | 1 + 7 files changed, 67 insertions(+), 34 deletions(-) create mode 100644 tests/DCPS/Compiler/C++11/value_annotation/.gitignore create mode 100755 tests/DCPS/Compiler/C++11/value_annotation/run_test.pl create mode 100644 tests/DCPS/Compiler/C++11/value_annotation/value_annotation.cpp create mode 100644 tests/DCPS/Compiler/C++11/value_annotation/value_annotation.idl create mode 100644 tests/DCPS/Compiler/C++11/value_annotation/value_annotation.mpc diff --git a/dds/idl/dds_visitor.cpp b/dds/idl/dds_visitor.cpp index 823f37601d7..8da7a4f77a1 100644 --- a/dds/idl/dds_visitor.cpp +++ b/dds/idl/dds_visitor.cpp @@ -116,7 +116,7 @@ dds_visitor::visit_root(AST_Root* node) } gen_target_.gen_epilogue(); - return (error_) ? -1 : 0; + return error_ ? -1 : 0; } int @@ -165,8 +165,6 @@ dds_visitor::visit_module(AST_Module* node) BE_Comment_Guard g("MODULE", name); - ACE_UNUSED_ARG(g); - if (this->visit_scope(node) == -1) { ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("(%N:%l) dds_visitor::visit_module -") @@ -183,8 +181,6 @@ dds_visitor::visit_interface(AST_Interface* node) BE_Comment_Guard g("INTERFACE", name); - ACE_UNUSED_ARG(g); - vector inherits(node->n_inherits()); for (int i = 0; i < node->n_inherits(); ++i) { inherits[i] = dynamic_cast(node->inherits()[i]); @@ -223,8 +219,6 @@ dds_visitor::visit_structure(AST_Structure* node) const char* name = node->local_name()->get_string(); BE_Comment_Guard g("STRUCT", name); - ACE_UNUSED_ARG(g); - // Check That Sample Keys Are Valid TopicKeys topic_keys(node); try { @@ -338,8 +332,6 @@ dds_visitor::visit_exception(AST_Exception* node) BE_Comment_Guard g("EXCEPTION", name); - ACE_UNUSED_ARG(g); - return 0; } @@ -350,8 +342,6 @@ dds_visitor::visit_typedef(AST_Typedef* node) BE_Comment_Guard g("TYPEDEF", name); - ACE_UNUSED_ARG(g); - if (!java_ts_only_) { error_ |= !gen_target_.gen_typedef(node, node->name(), node->base_type(), node->repoID()); @@ -367,8 +357,6 @@ dds_visitor::visit_enum(AST_Enum* node) BE_Comment_Guard g("ENUM", name); - ACE_UNUSED_ARG(g); - vector contents; scope2vector(contents, node, AST_Decl::NT_enum_val); @@ -385,8 +373,6 @@ dds_visitor::visit_interface_fwd(AST_InterfaceFwd* node) { const char* name = node->local_name()->get_string(); BE_Comment_Guard g("INTERFACE-FWD", name); - ACE_UNUSED_ARG(g); - if (!java_ts_only_) { error_ |= !gen_target_.gen_interf_fwd(node->name()); } @@ -414,8 +400,6 @@ dds_visitor::visit_constant(AST_Constant* node) BE_Comment_Guard g("CONST", name); - ACE_UNUSED_ARG(g); - AST_Decl* d = ScopeAsDecl(node->defined_in()); bool nested = d && (d->node_type() == AST_Decl::NT_interface); @@ -434,8 +418,6 @@ dds_visitor::visit_native(AST_Native* node) BE_Comment_Guard g("NATIVE", name); - ACE_UNUSED_ARG(g); - if (!java_ts_only_) { error_ |= !gen_target_.gen_native(node, node->name(), node->repoID()); } @@ -449,8 +431,6 @@ dds_visitor::visit_union(AST_Union* node) const char* name = node->local_name()->get_string(); BE_Comment_Guard g("UNION", name); - ACE_UNUSED_ARG(g); - vector branches; branches.reserve(node->nfields()); const Fields fields(node); @@ -473,6 +453,19 @@ dds_visitor::visit_union(AST_Union* node) return 0; } +int +dds_visitor::visit_union_fwd(AST_UnionFwd* node) +{ + const char* name = node->local_name()->get_string(); + BE_Comment_Guard g("UNION-FWD", name); + + if (!java_ts_only_) { + error_ |= !gen_target_.gen_union_fwd(node, node->name(), node->size_type()); + } + + return 0; +} + // *** All methods below here are unimplemented (or trivially implemented) *** int @@ -574,19 +567,6 @@ dds_visitor::visit_string(AST_String*) return 0; } -int -dds_visitor::visit_union_fwd(AST_UnionFwd* node) -{ - const char* name = node->local_name()->get_string(); - BE_Comment_Guard g("UNION-FWD", name); - - if (!java_ts_only_) { - error_ |= !gen_target_.gen_union_fwd(node, node->name(), node->size_type()); - } - - return 0; -} - int dds_visitor::visit_union_branch(AST_UnionBranch*) { return 0; diff --git a/tests/DCPS/Compiler/C++11/value_annotation/.gitignore b/tests/DCPS/Compiler/C++11/value_annotation/.gitignore new file mode 100644 index 00000000000..f9891030ddf --- /dev/null +++ b/tests/DCPS/Compiler/C++11/value_annotation/.gitignore @@ -0,0 +1,4 @@ +/value_annotation +/value_annotationC.h +/value_annotationTypeSupportImpl.cpp +/value_annotationTypeSupportImpl.h diff --git a/tests/DCPS/Compiler/C++11/value_annotation/run_test.pl b/tests/DCPS/Compiler/C++11/value_annotation/run_test.pl new file mode 100755 index 00000000000..9dbf1fd3e8f --- /dev/null +++ b/tests/DCPS/Compiler/C++11/value_annotation/run_test.pl @@ -0,0 +1,23 @@ +eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' + & eval 'exec perl -S $0 $argv:q' + if 0; + +# -*- perl -*- + +use Env (DDS_ROOT); +use lib "$DDS_ROOT/bin"; +use Env (ACE_ROOT); +use lib "$ACE_ROOT/bin"; +use PerlDDS::Run_Test; +use strict; + +my $TESTDVR = PerlDDS::create_process("value_annotation"); + +my $status = $TESTDVR->SpawnWaitKill(300); + +if ($status != 0) { + print STDERR "ERROR: value_annotation returned $status\n"; + $status = 1; +} + +exit $status; diff --git a/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.cpp b/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.cpp new file mode 100644 index 00000000000..9eb02f29238 --- /dev/null +++ b/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.cpp @@ -0,0 +1,6 @@ +#include "value_annotationTypeSupportImpl.h" + +int ACE_MAIN(int argc, char* argv[]) +{ + return 0; +} diff --git a/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.idl b/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.idl new file mode 100644 index 00000000000..5bff7670162 --- /dev/null +++ b/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.idl @@ -0,0 +1,12 @@ +enum TestValueAnnotation { + ZERO, + ONE, + TWO, + @value(5) FIVE, + SIX, + @value(10) TEN +}; + +struct UsesAnnotatedEnum { + TestValueAnnotation tva; +}; diff --git a/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.mpc b/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.mpc new file mode 100644 index 00000000000..e4596cb5a84 --- /dev/null +++ b/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.mpc @@ -0,0 +1,7 @@ +project: dcpsexe, dcps_test, opendds_cxx11 { + exename = * + dcps_ts_flags += -SI + TypeSupport_Files { + value_annotation.idl + } +} \ No newline at end of file diff --git a/tests/dcps_tests.lst b/tests/dcps_tests.lst index 0d74a5e6cfb..efe998a25c7 100644 --- a/tests/dcps_tests.lst +++ b/tests/dcps_tests.lst @@ -71,6 +71,7 @@ tests/DCPS/Compiler/idl_test1_main/run_test.pl: !DCPS_MIN !OPENDDS_SAFETY_PROFIL tests/DCPS/Compiler/idl_test3_main/run_test.pl: !DCPS_MIN !OPENDDS_SAFETY_PROFILE tests/DCPS/Compiler/C++11/idl_test1_main/run_test.pl: !DCPS_MIN CXX11 !OPENDDS_SAFETY_PROFILE tests/DCPS/Compiler/C++11/idl_test3_main/run_test.pl: !DCPS_MIN CXX11 !OPENDDS_SAFETY_PROFILE +tests/DCPS/Compiler/C++11/value_annotation/run_test.pl: !DCPS_MIN CXX11 !OPENDDS_SAFETY_PROFILE tests/DCPS/Compiler/key_annotation/run_test.pl: !DCPS_MIN tests/DCPS/Compiler/is_topic_type/run_test.pl: !DCPS_MIN tests/DCPS/Compiler/vread_vwrite/run_test.pl: !DCPS_MIN RAPIDJSON CXX11 From 2c2084a3f25803cce0d439a7f94d2e3c36f8816d Mon Sep 17 00:00:00 2001 From: Adam Mitz Date: Wed, 13 Mar 2024 17:19:37 -0500 Subject: [PATCH 03/18] Continued opendds_idl support for value annotation on enumerators --- dds/DCPS/ValueCommon.cpp | 34 ++++++++++ dds/DCPS/ValueCommon.h | 9 ++- dds/idl/dds_generator.cpp | 35 ++++++++++- dds/idl/dds_generator.h | 3 + dds/idl/dds_visitor.cpp | 3 + dds/idl/langmap_generator.cpp | 2 +- dds/idl/marshal_generator.cpp | 63 +++++++++---------- dds/idl/marshal_generator.h | 3 +- dds/idl/metaclass_generator.cpp | 27 +------- dds/idl/metaclass_generator.h | 3 - dds/idl/typeobject_generator.cpp | 10 ++- dds/idl/value_reader_generator.cpp | 37 +++-------- dds/idl/value_writer_generator.cpp | 33 +++------- .../value_annotation/value_annotation.idl | 11 +++- 14 files changed, 152 insertions(+), 121 deletions(-) diff --git a/dds/DCPS/ValueCommon.cpp b/dds/DCPS/ValueCommon.cpp index 1506a26b0db..f8408a37d8e 100644 --- a/dds/DCPS/ValueCommon.cpp +++ b/dds/DCPS/ValueCommon.cpp @@ -8,11 +8,45 @@ #include "ValueCommon.h" #include "debug.h" +#include + OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL namespace OpenDDS { namespace DCPS { +ACE_CDR::Long EnumHelper::get_value(const char* name) const +{ + ACE_CDR::Long value; + return get_value(value, name) ? value : 0; +} + +const char* EnumHelper::get_name(ACE_CDR::Long value) const +{ + const char* name; + return get_name(name, value) ? name : 0; +} + +bool ListEnumHelper::valid(const char* name) const +{ + for (OPENDDS_VECTOR(Pair)::const_iterator it = pairs_.begin(); it != pairs_.end(); ++it) { + if (std::strcmp(it->name, name) == 0) { + return true; + } + } + return false; +} + +bool ListEnumHelper::valid(ACE_CDR::Long value) const +{ + for (OPENDDS_VECTOR(Pair)::const_iterator it = pairs_.begin(); it != pairs_.end(); ++it) { + if (it->value == value) { + return true; + } + } + return false; +} + bool ListEnumHelper::get_value(ACE_CDR::Long& value, const char* name) const { for (OPENDDS_VECTOR(Pair)::const_iterator it = pairs_.begin(); it != pairs_.end(); ++it) { diff --git a/dds/DCPS/ValueCommon.h b/dds/DCPS/ValueCommon.h index e716d232cd6..b5746a9834c 100644 --- a/dds/DCPS/ValueCommon.h +++ b/dds/DCPS/ValueCommon.h @@ -15,12 +15,17 @@ OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL namespace OpenDDS { namespace DCPS { -class EnumHelper { +class OpenDDS_Dcps_Export EnumHelper { public: virtual ~EnumHelper() {} + virtual bool valid(const char* name) const = 0; + virtual bool valid(ACE_CDR::Long value) const = 0; virtual bool get_value(ACE_CDR::Long& value, const char* name) const = 0; virtual bool get_name(const char*& name, ACE_CDR::Long value) const = 0; virtual XTypes::TypeKind get_equivalent_int() const = 0; + + ACE_CDR::Long get_value(const char* name) const; + const char* get_name(ACE_CDR::Long value) const; }; class OpenDDS_Dcps_Export ListEnumHelper : public EnumHelper { @@ -47,6 +52,8 @@ class OpenDDS_Dcps_Export ListEnumHelper : public EnumHelper { pairs_ = pairs; } + bool valid(const char* name) const; + bool valid(ACE_CDR::Long value) const; bool get_value(ACE_CDR::Long& value, const char* name) const; bool get_name(const char*& name, ACE_CDR::Long value) const; diff --git a/dds/idl/dds_generator.cpp b/dds/idl/dds_generator.cpp index 056fd846bc2..f7589ad4d27 100644 --- a/dds/idl/dds_generator.cpp +++ b/dds/idl/dds_generator.cpp @@ -129,6 +129,39 @@ string dds_generator::module_scope_helper(UTL_ScopedName* sn, const char* sep, E return sname; } +bool dds_generator::gen_enum_helper(AST_Enum*, UTL_ScopedName* name, + const std::vector& contents, const char*) +{ + // The EnumHelper is used across multiple generators. + NamespaceGuard ng; + const std::string underscores = scoped_helper(name, "_"), + scope = be_global->language_mapping() == BE_GlobalData::LANGMAP_CXX11 + ? scoped(name) + "::" + : module_scope(name), + helper_decl = "const EnumHelper* gen_" + underscores + "_helper", + decl_prefix = (be_global->export_macro() == "") + ? std::string("extern ") + : std::string(be_global->export_macro().c_str()) + " extern "; + + be_global->header_ << decl_prefix << helper_decl << ";\n"; + + be_global->impl_ << + "const ListEnumHelper::Pair gen_" << underscores << "_pairs[] = {\n"; + + for (size_t i = 0; i < contents.size(); ++i) { + const std::string idl_name = canonical_name(contents[i]); + be_global->impl_ << + " {\"" << idl_name << "\", static_cast(" << scope << idl_name << ")},\n"; + } + + be_global->impl_ << + " {0, 0}};\n" + "const ListEnumHelper gen_" << underscores << "_helper_impl(gen_" << underscores << "_pairs);\n" << + helper_decl << " = &gen_" << underscores << "_helper_impl;\n\n"; + return true; +} + + void composite_generator::gen_prologue() { for (vector::iterator it(components_.begin()); @@ -379,7 +412,7 @@ string type_to_default(const std::string& indent, AST_Type* type, const string& // Must be changed, if support for @default_literal is desired. AST_Enum* enu = dynamic_cast(actual_type); UTL_ScopeActiveIterator i(enu, UTL_Scope::IK_decls); - AST_EnumVal *item = dynamic_cast(i.item()); + AST_EnumVal* item = dynamic_cast(i.item()); if (use_cxx11) { def_val = scoped(type->name()) + "::" + item->local_name()->get_string(); } else { diff --git a/dds/idl/dds_generator.h b/dds/idl/dds_generator.h index b0017586b02..47fc3991631 100644 --- a/dds/idl/dds_generator.h +++ b/dds/idl/dds_generator.h @@ -114,6 +114,9 @@ class dds_generator { UTL_ScopedName* sn, const char* sep, EscapeContext cxt = EscapeContext_Normal); static std::string module_scope_helper( UTL_ScopedName* sn, const char* sep, EscapeContext cxt = EscapeContext_Normal); + + static bool gen_enum_helper(AST_Enum* node, UTL_ScopedName* name, + const std::vector& contents, const char* repoid); }; inline std::string canonical_name(UTL_ScopedName* sn) diff --git a/dds/idl/dds_visitor.cpp b/dds/idl/dds_visitor.cpp index 8da7a4f77a1..2cd4c6dde85 100644 --- a/dds/idl/dds_visitor.cpp +++ b/dds/idl/dds_visitor.cpp @@ -362,6 +362,9 @@ dds_visitor::visit_enum(AST_Enum* node) scope2vector(contents, node, AST_Decl::NT_enum_val); if (!java_ts_only_) { + if (!node->imported()) { + error_ |= !dds_generator::gen_enum_helper(node, node->name(), contents, node->repoID()); + } error_ |= !gen_target_.gen_enum(node, node->name(), contents, node->repoID()); } diff --git a/dds/idl/langmap_generator.cpp b/dds/idl/langmap_generator.cpp index 38d381bfb36..e25aedb541a 100644 --- a/dds/idl/langmap_generator.cpp +++ b/dds/idl/langmap_generator.cpp @@ -208,7 +208,7 @@ struct GeneratorBase return ""; } - switch (the_union->udisc_type ()) + switch (the_union->udisc_type()) { #if OPENDDS_HAS_EXPLICIT_INTS case AST_Expression::EV_int8: diff --git a/dds/idl/marshal_generator.cpp b/dds/idl/marshal_generator.cpp index 0095a05529f..e6c9a62c169 100644 --- a/dds/idl/marshal_generator.cpp +++ b/dds/idl/marshal_generator.cpp @@ -153,26 +153,19 @@ namespace { } /* namespace */ bool marshal_generator::gen_enum(AST_Enum*, UTL_ScopedName* name, - const std::vector& vals, const char*) + const std::vector&, const char*) { NamespaceGuard ng; be_global->add_include("dds/DCPS/Serializer.h"); - string cxx = scoped(name); // name as a C++ class + const string cxx = scoped(name), // name as a C++ class + underscores = scoped_helper(name, "_"); { Function insertion("operator<<", "bool"); insertion.addArg("strm", "Serializer&"); insertion.addArg("enumval", "const " + cxx + "&"); insertion.endArgs(); - const std::string idl_name = canonical_name(name); be_global->impl_ << - " if (CORBA::ULong(enumval) >= " << vals.size() << ") {\n" - " if (OpenDDS::DCPS::log_level >= OpenDDS::DCPS::LogLevel::Warning) {\n" - " ACE_ERROR((LM_WARNING, \"(%P|%t) WARNING: " - "%u is an invalid enumerated value for " << idl_name << "\\n\", enumval));\n" - " }\n" - " return false;\n" - " }\n" - " return strm << static_cast(enumval);\n"; + " return strm << static_cast(enumval);\n"; } { Function extraction("operator>>", "bool"); @@ -180,9 +173,9 @@ bool marshal_generator::gen_enum(AST_Enum*, UTL_ScopedName* name, extraction.addArg("enumval", cxx + "&"); extraction.endArgs(); be_global->impl_ << - " CORBA::ULong temp = 0;\n" + " ACE_CDR::Long temp = 0;\n" " if (strm >> temp) {\n" - " if (temp >= " << vals.size() << ") {\n" + " if (! ::OpenDDS::DCPS::gen_" << underscores << "_helper->valid(temp)) {\n" " strm.set_construction_status(Serializer::ElementConstructionFailure);\n" " return false;\n" " }\n" @@ -2806,17 +2799,21 @@ namespace { } // anonymous namespace -void marshal_generator::generate_dheader_code(const std::string& code, bool dheader_required, bool is_ser_func) +void marshal_generator::generate_dheader_code(const std::string& code, bool dheader_required, + bool is_ser_func, const char* indent) { + const std::string indents(indent); //DHeader appears on aggregated types that are mutable or appendable in XCDR2 //DHeader also appears on ALL sequences and arrays of non-primitives if (dheader_required) { if (is_ser_func) { - be_global->impl_ << " size_t total_size = 0;\n"; + be_global->impl_ << + indents << "size_t total_size = 0;\n"; } - be_global->impl_ << " if (encoding.xcdr_version() == Encoding::XCDR_VERSION_2) {\n" + be_global->impl_ << + indents << "if (encoding.xcdr_version() == Encoding::XCDR_VERSION_2) {\n" << code << - " }\n"; + indents << "}\n"; } } @@ -3003,9 +3000,9 @@ marshal_generator::gen_field_getValueFromSerialized(AST_Structure* node, const s " const Encoding& encoding = strm.encoding();\n" " ACE_UNUSED_ARG(encoding);\n"; marshal_generator::generate_dheader_code( - " if (!strm.read_delimiter(total_size)) {\n" - " throw std::runtime_error(\"Unable to reader delimiter in getValue\");\n" - " }\n", not_final); + " if (!strm.read_delimiter(total_size)) {\n" + " throw std::runtime_error(\"Unable to reader delimiter in getValue\");\n" + " }\n", not_final, true, " "); be_global->impl_ << " std::string base_field = field;\n" " const size_t index = base_field.find('.');\n" @@ -3059,11 +3056,11 @@ marshal_generator::gen_field_getValueFromSerialized(AST_Structure* node, const s std::string boundsCheck, transformPrefix, transformSuffix; if (fld_cls & CL_ENUM) { const std::string enumName = dds_generator::scoped_helper(field_type->name(), "_"); - boundsCheck = " if (val >= gen_" + enumName + "_names_size) {\n" - " throw std::runtime_error(\"Enum value out of bounds\");\n" + boundsCheck = " if (!gen_" + enumName + "_helper->valid(val)) {\n" + " throw std::runtime_error(\"Enum value invalid\");\n" " }\n"; - transformPrefix = "gen_" + enumName + "_names["; - transformSuffix = "]"; + transformPrefix = "gen_" + enumName + "_helper->get_name("; + transformSuffix = ")"; } cases << " if (field_id == member_id) {\n" @@ -3142,11 +3139,11 @@ marshal_generator::gen_field_getValueFromSerialized(AST_Structure* node, const s std::string boundsCheck, transformPrefix, transformSuffix; if (fld_cls & CL_ENUM) { const std::string enumName = dds_generator::scoped_helper(field_type->name(), "_"); - boundsCheck = " if (val >= gen_" + enumName + "_names_size) {\n" - " throw std::runtime_error(\"Enum value out of bounds\");\n" + boundsCheck = " if (!gen_" + enumName + "_helper->valid(val)) {\n" + " throw std::runtime_error(\"Enum value invalid\");\n" " }\n"; - transformPrefix = "gen_" + enumName + "_names["; - transformSuffix = "]"; + transformPrefix = "gen_" + enumName + "_helper->get_name("; + transformSuffix = ")"; } expr += " if (base_field == \"" + idl_name + "\") {\n" @@ -3531,8 +3528,11 @@ bool marshal_generator::gen_union(AST_Union* node, UTL_ScopedName* name, if (disc_cls & CL_ENUM) { AST_Enum* enu = dynamic_cast(disc_type); UTL_ScopeActiveIterator i(enu, UTL_Scope::IK_decls); - AST_EnumVal *item = dynamic_cast(i.item()); + AST_EnumVal* item = dynamic_cast(i.item()); default_enum_val = item->constant_value()->ev()->u.eval; + // This doesn't look at @value annotations since it's only needed to find + // a matching branch label below -- the integer value of the enumerator + // isn't used in generated code. } // Search the union branches to find the default value according to @@ -3543,7 +3543,7 @@ bool marshal_generator::gen_union(AST_Union* node, UTL_ScopedName* name, for (unsigned i = 0; i < branch->label_list_length(); ++i) { AST_UnionLabel* ul = branch->label(i); if (ul->label_kind() != AST_UnionLabel::UL_default) { - AST_Expression::AST_ExprValue* ev = branch->label(i)->label_val()->ev(); + AST_Expression::AST_ExprValue* ev = ul->label_val()->ev(); if ((ev->et == AST_Expression::EV_enum && ev->u.eval == default_enum_val) || #if OPENDDS_HAS_EXPLICIT_INTS (ev->et == AST_Expression::EV_uint8 && ev->u.uint8val == 0) || @@ -3561,8 +3561,7 @@ bool marshal_generator::gen_union(AST_Union* node, UTL_ScopedName* name, (ev->et == AST_Expression::EV_char && ev->u.cval == 0) || (ev->et == AST_Expression::EV_wchar && ev->u.wcval == 0) || (ev->et == AST_Expression::EV_octet && ev->u.oval == 0) || - (ev->et == AST_Expression::EV_bool && ev->u.bval == 0)) - { + (ev->et == AST_Expression::EV_bool && ev->u.bval == 0)) { gen_union_default(branch, varname); found = true; break; diff --git a/dds/idl/marshal_generator.h b/dds/idl/marshal_generator.h index 9fe25e71e74..47b8ced680a 100644 --- a/dds/idl/marshal_generator.h +++ b/dds/idl/marshal_generator.h @@ -26,7 +26,8 @@ class marshal_generator : public dds_generator { AST_Type* discriminator, const char* repoid); - static void generate_dheader_code(const std::string& code, bool dheader_required, bool is_ser_func = true); + static void generate_dheader_code(const std::string& code, bool dheader_required, + bool is_ser_func = true, const char* indent = " "); static void gen_field_getValueFromSerialized(AST_Structure* node, const std::string& clazz); diff --git a/dds/idl/metaclass_generator.cpp b/dds/idl/metaclass_generator.cpp index 5f21766b5a1..3827e7ebf78 100644 --- a/dds/idl/metaclass_generator.cpp +++ b/dds/idl/metaclass_generator.cpp @@ -25,29 +25,6 @@ namespace { { } }; -} - -bool -metaclass_generator::gen_enum(AST_Enum*, UTL_ScopedName* name, - const std::vector& contents, const char*) -{ - NamespaceGuard ng; - std::string array_decl = "const char* gen_" + scoped_helper(name, "_") + "_names[]"; - std::string size_decl = "const size_t gen_" + scoped_helper(name, "_") + "_names_size"; - std::string decl_prefix = ((be_global->export_macro() == "") ? std::string("extern ") : (std::string(be_global->export_macro().c_str()) + " extern ")); - be_global->header_ << decl_prefix << array_decl << ";\n"; - be_global->header_ << decl_prefix << size_decl << ";\n"; - be_global->impl_ << array_decl << " = {\n"; - for (size_t i = 0; i < contents.size(); ++i) { - be_global->impl_ << " \"" << canonical_name(contents[i]) - << ((i < contents.size() - 1) ? "\",\n" : "\"\n"); - } - be_global->impl_ << "};\n"; - be_global->impl_ << size_decl << " = " << contents.size() << ";\n"; - return true; -} - -namespace { void delegateToNested(const std::string& fieldName, AST_Field* field, @@ -76,11 +53,11 @@ namespace { AST_Type* enum_type = resolveActualType(field->field_type()); prefix = "gen_" + dds_generator::scoped_helper(enum_type->name(), "_") - + "_names["; + + "_helper->get_name("; if (use_cxx11) { prefix += "static_cast("; } - suffix = use_cxx11 ? "())]" : "]"; + suffix = use_cxx11 ? "()))" : ")"; } else if (use_cxx11) { suffix += "()"; } diff --git a/dds/idl/metaclass_generator.h b/dds/idl/metaclass_generator.h index c6b3c6d3966..c659eb3d55f 100644 --- a/dds/idl/metaclass_generator.h +++ b/dds/idl/metaclass_generator.h @@ -16,9 +16,6 @@ class metaclass_generator : public dds_generator { : first_struct_(true) {} - bool gen_enum(AST_Enum* node, UTL_ScopedName* name, - const std::vector& contents, const char* repoid); - bool gen_struct(AST_Structure* node, UTL_ScopedName* name, const std::vector& fields, AST_Type::SIZE_TYPE size, const char* repoid); diff --git a/dds/idl/typeobject_generator.cpp b/dds/idl/typeobject_generator.cpp index b8b16760047..044b1632dff 100644 --- a/dds/idl/typeobject_generator.cpp +++ b/dds/idl/typeobject_generator.cpp @@ -589,7 +589,7 @@ typeobject_generator::gen_epilogue() be_global->impl_ << "XTypes::TypeObject OPENDDS_IDL_FILE_SPECIFIC(minimal_to, " << idx << ")()\n" "{\n" - " const unsigned char to_bytes[] = { "; + " static const unsigned char to_bytes[] = { "; dump_bytes(pos->second); be_global->add_include("", BE_GlobalData::STREAM_CPP); be_global->impl_ << @@ -1177,7 +1177,7 @@ typeobject_generator::generate_union_type_identifier(AST_Type* type) for (unsigned long j = 0; j < branch->label_list_length(); ++j) { AST_UnionLabel* label = branch->label(j); if (label->label_kind() != AST_UnionLabel::UL_default) { - minimal_member.common.label_seq.append(to_long(*label->label_val()->ev())); + minimal_member.common.label_seq.append(to_long(*label->label_val()->ev())); //TODO @value } } minimal_member.common.label_seq.sort(); @@ -1244,9 +1244,13 @@ typeobject_generator::generate_enum_type_identifier(AST_Type* type) complete_to.complete.enumerated_type.header.common.bit_bound = 32; complete_to.complete.enumerated_type.header.detail.type_name = canonical_name(type->name()); + ACE_CDR::Long last_value = 0; for (size_t i = 0; i != contents.size(); ++i) { OpenDDS::XTypes::MinimalEnumeratedLiteral minimal_lit; - minimal_lit.common.value = contents[i]->constant_value()->ev()->u.eval; + if (!be_global->value(contents[i], minimal_lit.common.value)) { + minimal_lit.common.value = (i == 0) ? 0 : last_value + 1; + } + last_value = minimal_lit.common.value; minimal_lit.common.flags = (i == default_literal_idx ? OpenDDS::XTypes::IS_DEFAULT : 0); const std::string name = canonical_name(contents[i]->local_name()); OpenDDS::XTypes::hash_member_name(minimal_lit.detail.name_hash, name); diff --git a/dds/idl/value_reader_generator.cpp b/dds/idl/value_reader_generator.cpp index c12e706ae6f..1255e136a99 100644 --- a/dds/idl/value_reader_generator.cpp +++ b/dds/idl/value_reader_generator.cpp @@ -221,40 +221,21 @@ namespace { bool value_reader_generator::gen_enum(AST_Enum*, UTL_ScopedName* name, - const std::vector& contents, + const std::vector&, const char*) { - be_global->add_include("dds/DCPS/Util.h", BE_GlobalData::STREAM_H); be_global->add_include("dds/DCPS/ValueReader.h", BE_GlobalData::STREAM_H); const std::string type_name = scoped(name); - { - NamespaceGuard guard; - - Function read("vread", "bool"); - read.addArg("value_reader", "OpenDDS::DCPS::ValueReader&"); - read.addArg("value", type_name + "&"); - read.endArgs(); - - be_global->impl_ << - " static const ListEnumHelper::Pair pairs[] = {"; - - for (size_t i = 0; i != contents.size(); ++i) { - if (i) { - be_global->impl_ << ','; - } - const std::string idl_name = canonical_name(contents[i]); - be_global->impl_ << - '{' << '"' << idl_name << '"' << ',' << contents[i]->constant_value()->ev()->u.eval << '}'; - } - - be_global->impl_ << - ",{0,0}};\n" - " ListEnumHelper helper(pairs);\n" - " return value_reader.read_enum(value, helper);\n"; - } - + NamespaceGuard guard; + Function read("vread", "bool"); + read.addArg("value_reader", "OpenDDS::DCPS::ValueReader&"); + read.addArg("value", type_name + "&"); + read.endArgs(); + be_global->impl_ << + " return value_reader.read_enum(value, * ::OpenDDS::DCPS::gen_" + << scoped_helper(name, "_") << "_helper);\n"; return true; } diff --git a/dds/idl/value_writer_generator.cpp b/dds/idl/value_writer_generator.cpp index 50eb0af77a7..62e31306f8c 100644 --- a/dds/idl/value_writer_generator.cpp +++ b/dds/idl/value_writer_generator.cpp @@ -249,36 +249,21 @@ namespace { bool value_writer_generator::gen_enum(AST_Enum*, UTL_ScopedName* name, - const std::vector& contents, + const std::vector&, const char*) { be_global->add_include("dds/DCPS/ValueWriter.h", BE_GlobalData::STREAM_H); const std::string type_name = scoped(name); - { - NamespaceGuard guard; - - Function write("vwrite", "bool"); - write.addArg("value_writer", "OpenDDS::DCPS::ValueWriter&"); - write.addArg("value", "const " + type_name + "&"); - write.endArgs(); - - be_global->impl_ << - " static const ListEnumHelper::Pair pairs[] = {"; - for (size_t i = 0; i != contents.size(); ++i) { - if (i) { - be_global->impl_ << ','; - } - const std::string idl_name = canonical_name(contents[i]); - be_global->impl_ << - '{' << '"' << idl_name << '"' << ',' << contents[i]->constant_value()->ev()->u.eval << '}'; - } - be_global->impl_ << - ",{0, 0}};\n" - " ListEnumHelper helper(pairs);\n" - " return value_writer.write_enum(value, helper);\n"; - } + NamespaceGuard guard; + Function write("vwrite", "bool"); + write.addArg("value_writer", "OpenDDS::DCPS::ValueWriter&"); + write.addArg("value", "const " + type_name + "&"); + write.endArgs(); + be_global->impl_ << + " return value_writer.write_enum(value, * ::OpenDDS::DCPS::gen_" + << scoped_helper(name, "_") << "_helper);\n"; return true; } diff --git a/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.idl b/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.idl index 5bff7670162..8714c3ae450 100644 --- a/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.idl +++ b/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.idl @@ -1,6 +1,6 @@ enum TestValueAnnotation { - ZERO, - ONE, + @value(99) NON_ZERO, + @value(1) ONE, TWO, @value(5) FIVE, SIX, @@ -10,3 +10,10 @@ enum TestValueAnnotation { struct UsesAnnotatedEnum { TestValueAnnotation tva; }; + +union DiscByAnnotatedEnum switch (TestValueAnnotation) { +case ONE: + octet o; +default: + short s; +}; From 3cd5bd6094036875cbd90f4c1a01e8ef8ac92ae5 Mon Sep 17 00:00:00 2001 From: Adam Mitz Date: Thu, 14 Mar 2024 08:16:14 -0500 Subject: [PATCH 04/18] Fix generated includes and forward declarations --- dds/idl/dds_generator.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/dds/idl/dds_generator.cpp b/dds/idl/dds_generator.cpp index f7589ad4d27..b08292335f4 100644 --- a/dds/idl/dds_generator.cpp +++ b/dds/idl/dds_generator.cpp @@ -133,17 +133,21 @@ bool dds_generator::gen_enum_helper(AST_Enum*, UTL_ScopedName* name, const std::vector& contents, const char*) { // The EnumHelper is used across multiple generators. + be_global->add_include("dds/DCPS/ValueCommon.h", BE_GlobalData::STREAM_CPP); NamespaceGuard ng; const std::string underscores = scoped_helper(name, "_"), scope = be_global->language_mapping() == BE_GlobalData::LANGMAP_CXX11 ? scoped(name) + "::" : module_scope(name), + fwd_decl = be_global->value_reader_writer() ? "" : "class EnumHelper;\n", helper_decl = "const EnumHelper* gen_" + underscores + "_helper", decl_prefix = (be_global->export_macro() == "") ? std::string("extern ") : std::string(be_global->export_macro().c_str()) + " extern "; - be_global->header_ << decl_prefix << helper_decl << ";\n"; + be_global->header_ << + fwd_decl << + decl_prefix << helper_decl << ";\n"; be_global->impl_ << "const ListEnumHelper::Pair gen_" << underscores << "_pairs[] = {\n"; From 00bc94b18089c06c7777e5bba3aeb496a61028a5 Mon Sep 17 00:00:00 2001 From: Adam Mitz Date: Thu, 14 Mar 2024 08:21:31 -0500 Subject: [PATCH 05/18] fixed lint error --- tests/DCPS/Compiler/C++11/value_annotation/value_annotation.mpc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.mpc b/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.mpc index e4596cb5a84..4d344b090e7 100644 --- a/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.mpc +++ b/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.mpc @@ -4,4 +4,4 @@ project: dcpsexe, dcps_test, opendds_cxx11 { TypeSupport_Files { value_annotation.idl } -} \ No newline at end of file +} From 9be2aac56d70dc24c8e1f6137ce76fd1b2b9a765 Mon Sep 17 00:00:00 2001 From: Adam Mitz Date: Thu, 14 Mar 2024 12:23:49 -0500 Subject: [PATCH 06/18] fixed versioned namespace builds --- dds/DCPS/RTPS/rtps.mpc | 2 +- dds/idl/dds_generator.h | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/dds/DCPS/RTPS/rtps.mpc b/dds/DCPS/RTPS/rtps.mpc index 4fb40165de1..754bb4b1f4b 100644 --- a/dds/DCPS/RTPS/rtps.mpc +++ b/dds/DCPS/RTPS/rtps.mpc @@ -13,7 +13,7 @@ project(OpenDDS_Rtps): dcpslib, install, rtps_optional_safety, opendds_testing_f } TypeSupport_Files { - dcps_ts_flags += -Lspcpp -St -Sx + dcps_ts_flags += -Lspcpp RtpsSubmessageKind.idl } diff --git a/dds/idl/dds_generator.h b/dds/idl/dds_generator.h index 47fc3991631..bd6895bd925 100644 --- a/dds/idl/dds_generator.h +++ b/dds/idl/dds_generator.h @@ -245,6 +245,10 @@ struct ScopedNamespaceGuard { const char* str = name->head()->get_string(); if (str && str[0]) { ++n_; + if (!idl && !std::strcmp(str, "OpenDDS")) { + os_ << "OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL\n"; + suffix_ = "OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL\n"; + } os_ << keyword << ' ' << dds_generator::to_string(name->head(), ec) << " {\n"; } } @@ -254,10 +258,11 @@ struct ScopedNamespaceGuard { ~ScopedNamespaceGuard() { for (int i = 0; i < n_; ++i) os_ << '}' << semi_ << '\n'; + os_ << suffix_; } std::ostream& os_; - std::string semi_; + std::string semi_, suffix_; int n_; }; From b3ef2d35828f7cc459c91f290c3daf41e0eaba90 Mon Sep 17 00:00:00 2001 From: Adam Mitz Date: Thu, 14 Mar 2024 12:39:19 -0500 Subject: [PATCH 07/18] Support keywords --- dds/idl/dds_generator.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/dds/idl/dds_generator.cpp b/dds/idl/dds_generator.cpp index b08292335f4..08d5521ab9c 100644 --- a/dds/idl/dds_generator.cpp +++ b/dds/idl/dds_generator.cpp @@ -138,7 +138,7 @@ bool dds_generator::gen_enum_helper(AST_Enum*, UTL_ScopedName* name, const std::string underscores = scoped_helper(name, "_"), scope = be_global->language_mapping() == BE_GlobalData::LANGMAP_CXX11 ? scoped(name) + "::" - : module_scope(name), + : "", fwd_decl = be_global->value_reader_writer() ? "" : "class EnumHelper;\n", helper_decl = "const EnumHelper* gen_" + underscores + "_helper", decl_prefix = (be_global->export_macro() == "") @@ -153,9 +153,12 @@ bool dds_generator::gen_enum_helper(AST_Enum*, UTL_ScopedName* name, "const ListEnumHelper::Pair gen_" << underscores << "_pairs[] = {\n"; for (size_t i = 0; i < contents.size(); ++i) { - const std::string idl_name = canonical_name(contents[i]); + const std::string idl_name = canonical_name(contents[i]), + cxx_name = be_global->language_mapping() == BE_GlobalData::LANGMAP_CXX11 + ? contents[i]->local_name()->get_string() + : scoped(contents[i]->name()); be_global->impl_ << - " {\"" << idl_name << "\", static_cast(" << scope << idl_name << ")},\n"; + " {\"" << idl_name << "\", static_cast(" << scope << cxx_name << ")},\n"; } be_global->impl_ << From 93309c48c445d1f1aa33b91b6d0ea053a5bf993c Mon Sep 17 00:00:00 2001 From: Adam Mitz Date: Thu, 14 Mar 2024 14:36:45 -0500 Subject: [PATCH 08/18] fixed typo in versioned namespace support --- dds/idl/dds_generator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dds/idl/dds_generator.h b/dds/idl/dds_generator.h index bd6895bd925..7c18518f66d 100644 --- a/dds/idl/dds_generator.h +++ b/dds/idl/dds_generator.h @@ -247,7 +247,7 @@ struct ScopedNamespaceGuard { ++n_; if (!idl && !std::strcmp(str, "OpenDDS")) { os_ << "OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL\n"; - suffix_ = "OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL\n"; + suffix_ = "OPENDDS_END_VERSIONED_NAMESPACE_DECL\n"; } os_ << keyword << ' ' << dds_generator::to_string(name->head(), ec) << " {\n"; } From 4dee96e78b42c22bdeff67a9e6430d2d9ceb2c41 Mon Sep 17 00:00:00 2001 From: Adam Mitz Date: Tue, 19 Mar 2024 09:26:43 -0500 Subject: [PATCH 09/18] fixed test --- tests/DCPS/MetaStruct/MetaStructTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/DCPS/MetaStruct/MetaStructTest.cpp b/tests/DCPS/MetaStruct/MetaStructTest.cpp index 1db875a93f1..9a7adac5921 100644 --- a/tests/DCPS/MetaStruct/MetaStructTest.cpp +++ b/tests/DCPS/MetaStruct/MetaStructTest.cpp @@ -83,7 +83,7 @@ T enumToString(const T& t) { return t; } const char* enumToString(MyEnum e) { - return OpenDDS::DCPS::gen_MyEnum_names[e]; + return OpenDDS::DCPS::gen_MyEnum_helper->get_name(e); } template From d6981494482f87236ef74899553796f0136206cf Mon Sep 17 00:00:00 2001 From: Adam Mitz Date: Tue, 19 Mar 2024 09:27:26 -0500 Subject: [PATCH 10/18] Fixed versioned namespaces Consolidated some build settings related to versioned namespaces --- MPC/config/dds_versioning_idl_defaults.mpb | 6 +++- dds/DCPS/RTPS/rtps.mpc | 2 +- dds/DCPS/RTPS/rtps_optional_safety.mpb | 4 +-- dds/dcps_optional_safety.mpb | 5 +-- dds/idl/dds_generator.h | 7 +---- dds/idl/langmap_generator.cpp | 36 ++++++++++++---------- 6 files changed, 30 insertions(+), 30 deletions(-) diff --git a/MPC/config/dds_versioning_idl_defaults.mpb b/MPC/config/dds_versioning_idl_defaults.mpb index fc47b273337..136ba87448e 100644 --- a/MPC/config/dds_versioning_idl_defaults.mpb +++ b/MPC/config/dds_versioning_idl_defaults.mpb @@ -1,8 +1,12 @@ // This base project is only meant to be used by the core OpenDDS // libraries -project : taoidldefaults { +project: taoidldefaults, dcps_ts_defaults { idlflags += -Wb,versioning_begin=OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL \ -Wb,versioning_end=OPENDDS_END_VERSIONED_NAMESPACE_DECL \ -Wb,versioning_include=dds/Versioned_Namespace.h + + dcps_ts_flags += -Wb,versioning_begin=OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL \ + -Wb,versioning_end=OPENDDS_END_VERSIONED_NAMESPACE_DECL \ + -Wb,versioning_name=OPENDDS_VERSIONED_NAMESPACE_NAME } diff --git a/dds/DCPS/RTPS/rtps.mpc b/dds/DCPS/RTPS/rtps.mpc index 754bb4b1f4b..30c23e67c50 100644 --- a/dds/DCPS/RTPS/rtps.mpc +++ b/dds/DCPS/RTPS/rtps.mpc @@ -1,4 +1,4 @@ -project(OpenDDS_Rtps): dcpslib, install, rtps_optional_safety, opendds_testing_features { +project(OpenDDS_Rtps): dcpslib, install, rtps_optional_safety, opendds_testing_features, dds_versioning_idl_defaults { sharedname = OpenDDS_Rtps dynamicflags = OPENDDS_RTPS_BUILD_DLL diff --git a/dds/DCPS/RTPS/rtps_optional_safety.mpb b/dds/DCPS/RTPS/rtps_optional_safety.mpb index 30494999967..e8c08478f57 100644 --- a/dds/DCPS/RTPS/rtps_optional_safety.mpb +++ b/dds/DCPS/RTPS/rtps_optional_safety.mpb @@ -1,4 +1,4 @@ -feature(no_opendds_safety_profile) : dcps_ts_defaults, dds_versioning_idl_defaults { +feature(no_opendds_safety_profile): dds_versioning_idl_defaults { idlflags += -Wb,export_macro=OpenDDS_Rtps_Export -Wb,export_include=rtps_export.h -SS dcps_ts_flags += -Wb,export_macro=OpenDDS_Rtps_Export -Wb,export_include=rtps_export.h -SI -Sx -Sv -St @@ -17,7 +17,7 @@ feature(no_opendds_safety_profile) : dcps_ts_defaults, dds_versioning_idl_defaul } } -feature(!no_opendds_safety_profile) : dcps_ts_defaults, dds_versioning_idl_defaults { +feature(!no_opendds_safety_profile): dds_versioning_idl_defaults { dcps_ts_flags += -Wb,export_macro=OpenDDS_Rtps_Export -Wb,export_include=rtps_export.h -SI -Sx -Sv -Lspcpp IDL_Files { diff --git a/dds/dcps_optional_safety.mpb b/dds/dcps_optional_safety.mpb index a72980830c2..85326296da7 100644 --- a/dds/dcps_optional_safety.mpb +++ b/dds/dcps_optional_safety.mpb @@ -7,10 +7,7 @@ project : dds_suppress_any_support, dcps_ts_defaults, dds_versioning_idl_default dcps_ts_flags += -Wb,pch_include=DCPS/DdsDcps_pch.h \ -Wb,export_macro=OpenDDS_Dcps_Export \ - -Wb,export_include=dds/DCPS/dcps_export.h \ - -Wb,versioning_begin=OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL \ - -Wb,versioning_end=OPENDDS_END_VERSIONED_NAMESPACE_DECL \ - -Wb,versioning_name=OPENDDS_VERSIONED_NAMESPACE_NAME + -Wb,export_include=dds/DCPS/dcps_export.h } feature(no_opendds_safety_profile, built_in_topics) : dds_suppress_any_support, dcps_ts_defaults, dds_versioning_idl_defaults { diff --git a/dds/idl/dds_generator.h b/dds/idl/dds_generator.h index 7c18518f66d..47fc3991631 100644 --- a/dds/idl/dds_generator.h +++ b/dds/idl/dds_generator.h @@ -245,10 +245,6 @@ struct ScopedNamespaceGuard { const char* str = name->head()->get_string(); if (str && str[0]) { ++n_; - if (!idl && !std::strcmp(str, "OpenDDS")) { - os_ << "OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL\n"; - suffix_ = "OPENDDS_END_VERSIONED_NAMESPACE_DECL\n"; - } os_ << keyword << ' ' << dds_generator::to_string(name->head(), ec) << " {\n"; } } @@ -258,11 +254,10 @@ struct ScopedNamespaceGuard { ~ScopedNamespaceGuard() { for (int i = 0; i < n_; ++i) os_ << '}' << semi_ << '\n'; - os_ << suffix_; } std::ostream& os_; - std::string semi_, suffix_; + std::string semi_; int n_; }; diff --git a/dds/idl/langmap_generator.cpp b/dds/idl/langmap_generator.cpp index e25aedb541a..a611956851a 100644 --- a/dds/idl/langmap_generator.cpp +++ b/dds/idl/langmap_generator.cpp @@ -1931,25 +1931,29 @@ bool langmap_generator::gen_enum(AST_Enum*, UTL_ScopedName* name, const std::vector& contents, const char*) { - const ScopedNamespaceGuard namespaces(name, be_global->lang_header_); - const char* const nm = name->last_component()->get_string(); - const char* scoped_enum = generator_->scoped_enum() ? "class " : ""; - const std::string enum_base = generator_->enum_base(); - be_global->lang_header_ << - "enum " << scoped_enum << nm << enum_base << " {\n"; - for (size_t i = 0; i < contents.size(); ++i) { + be_global->lang_header_ << be_global->versioning_begin() << "\n"; + { + const ScopedNamespaceGuard namespaces(name, be_global->lang_header_); + const char* const nm = name->last_component()->get_string(); + const char* scoped_enum = generator_->scoped_enum() ? "class " : ""; + const std::string enum_base = generator_->enum_base(); be_global->lang_header_ << - " " << contents[i]->local_name()->get_string(); - ACE_INT32 value = 0; - if (be_global->value(contents[i], value)) { - be_global->lang_header_ << " = " << value; + "enum " << scoped_enum << nm << enum_base << " {\n"; + for (size_t i = 0; i < contents.size(); ++i) { + be_global->lang_header_ << + " " << contents[i]->local_name()->get_string(); + ACE_INT32 value = 0; + if (be_global->value(contents[i], value)) { + be_global->lang_header_ << " = " << value; + } + be_global->lang_header_ << ((i < contents.size() - 1) ? ",\n" : "\n"); } - be_global->lang_header_ << ((i < contents.size() - 1) ? ",\n" : "\n"); + be_global->lang_header_ << + "};\n\n"; + generator_->gen_simple_out(nm); + gen_typecode(name); } - be_global->lang_header_ << - "};\n\n"; - generator_->gen_simple_out(nm); - gen_typecode(name); + be_global->lang_header_ << be_global->versioning_end() << "\n"; return true; } From 97f6e10a8b353777c54ad7528753f6ca51716f24 Mon Sep 17 00:00:00 2001 From: Adam Mitz Date: Tue, 19 Mar 2024 12:28:45 -0500 Subject: [PATCH 11/18] fixed tests --- tests/transport/rtps_reliability/rtps_reliability.cpp | 9 +++------ tests/transport/spdp/spdp_transport.cpp | 9 +++------ 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/tests/transport/rtps_reliability/rtps_reliability.cpp b/tests/transport/rtps_reliability/rtps_reliability.cpp index 94276e58390..a2fca6a178e 100644 --- a/tests/transport/rtps_reliability/rtps_reliability.cpp +++ b/tests/transport/rtps_reliability/rtps_reliability.cpp @@ -15,6 +15,7 @@ #include "dds/DCPS/transport/framework/ReceivedDataSample.h" #include "dds/DCPS/RTPS/RtpsCoreTypeSupportImpl.h" +#include "dds/DCPS/RTPS/RtpsSubmessageKindTypeSupportImpl.h" #include "dds/DCPS/RTPS/MessageTypes.h" #include "dds/DCPS/RTPS/MessageUtils.h" #include "dds/DCPS/RTPS/GuidGenerator.h" @@ -417,17 +418,13 @@ struct TestParticipant: ACE_Event_Handler { if (!recv_nackfrag(ser, peer)) return false; break; default: -#ifdef OPENDDS_NO_CONTENT_SUBSCRIPTION_PROFILE - ACE_DEBUG((LM_INFO, "Received submessage type: %u\n", unsigned(subm))); -#else - if (static_cast(subm) < gen_OpenDDS_RTPS_SubmessageKind_names_size) { + if (gen_OpenDDS_RTPS_SubmessageKind_helper->valid(subm)) { ACE_DEBUG((LM_INFO, "Received submessage type: %C\n", - gen_OpenDDS_RTPS_SubmessageKind_names[static_cast(subm)])); + gen_OpenDDS_RTPS_SubmessageKind_helper->get_name(subm))); } else { ACE_ERROR((LM_ERROR, "ERROR: Received unknown submessage type: %u\n", unsigned(subm))); } -#endif SubmessageHeader smh; if (!(ser >> smh)) { ACE_ERROR((LM_ERROR, "ERROR: in handle_input() failed to deserialize " diff --git a/tests/transport/spdp/spdp_transport.cpp b/tests/transport/spdp/spdp_transport.cpp index 6b532f5f904..560cc198555 100644 --- a/tests/transport/spdp/spdp_transport.cpp +++ b/tests/transport/spdp/spdp_transport.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -182,17 +183,13 @@ struct TestParticipant: ACE_Event_Handler { if (smhdr.submessageId == DATA) { ok = recv_data(mp.serializer(), peer); } else { -#ifdef OPENDDS_NO_CONTENT_SUBSCRIPTION_PROFILE - ACE_DEBUG((LM_INFO, "Received submessage type: %u\n", unsigned(smhdr.submessageId))); -#else - if (static_cast(smhdr.submessageId) < gen_OpenDDS_RTPS_SubmessageKind_names_size) { + if (gen_OpenDDS_RTPS_SubmessageKind_helper->valid(smhdr.submessageId)) { ACE_DEBUG((LM_INFO, "Received submessage type: %C\n", - gen_OpenDDS_RTPS_SubmessageKind_names[static_cast(smhdr.submessageId)])); + gen_OpenDDS_RTPS_SubmessageKind_helper->get_name(smhdr.submessageId))); } else { ACE_ERROR((LM_ERROR, "ERROR: Received unknown submessage type: %u\n", unsigned(smhdr.submessageId))); } -#endif } if (!ok || !mp.hasNextSubmessage()) { From 1592dc9bb25df9deb5c96fda490da96db5e7cadb Mon Sep 17 00:00:00 2001 From: Adam Mitz Date: Tue, 19 Mar 2024 14:17:09 -0500 Subject: [PATCH 12/18] Use enum values in union typeobject generation --- dds/idl/typeobject_generator.cpp | 31 +++++++++++++++++++++++++------ dds/idl/typeobject_generator.h | 4 ++++ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/dds/idl/typeobject_generator.cpp b/dds/idl/typeobject_generator.cpp index 044b1632dff..81d3a0e4619 100644 --- a/dds/idl/typeobject_generator.cpp +++ b/dds/idl/typeobject_generator.cpp @@ -1111,7 +1111,12 @@ void typeobject_generator::generate_union_type_identifier(AST_Type* type) { AST_Union* const n = dynamic_cast(type); - AST_Type* discriminator = n->disc_type(); + + AST_Type* const discriminator = n->disc_type(); + AST_Type* const discriminatorActual = resolveActualType(discriminator); + AST_Enum* const discEnum = dynamic_cast(discriminatorActual); + const EnumValueMap::const_iterator enumValues = enum_values_.find(discEnum); + const Fields fields(n); const ExtensibilityKind exten = be_global->extensibility(n); @@ -1177,7 +1182,16 @@ typeobject_generator::generate_union_type_identifier(AST_Type* type) for (unsigned long j = 0; j < branch->label_list_length(); ++j) { AST_UnionLabel* label = branch->label(j); if (label->label_kind() != AST_UnionLabel::UL_default) { - minimal_member.common.label_seq.append(to_long(*label->label_val()->ev())); //TODO @value + if (discEnum && enumValues != enum_values_.end()) { + const std::string labelName = canonical_name(label->label_val()->n()); + const EnumValues::const_iterator iter = enumValues->second.find(labelName); + if (iter == enumValues->second.end()) { + be_util::misc_error_and_abort("Unknown union label value", branch); + } + minimal_member.common.label_seq.append(iter->second); + } else { + minimal_member.common.label_seq.append(to_long(*label->label_val()->ev())); + } } } minimal_member.common.label_seq.sort(); @@ -1244,15 +1258,20 @@ typeobject_generator::generate_enum_type_identifier(AST_Type* type) complete_to.complete.enumerated_type.header.common.bit_bound = 32; complete_to.complete.enumerated_type.header.detail.type_name = canonical_name(type->name()); - ACE_CDR::Long last_value = 0; + EnumValues& cached = enum_values_[n]; + cached.clear(); + ACE_CDR::Long last_value = -1; for (size_t i = 0; i != contents.size(); ++i) { + const std::string name = canonical_name(contents[i]->local_name()); + OpenDDS::XTypes::MinimalEnumeratedLiteral minimal_lit; if (!be_global->value(contents[i], minimal_lit.common.value)) { - minimal_lit.common.value = (i == 0) ? 0 : last_value + 1; + minimal_lit.common.value = last_value + 1; } - last_value = minimal_lit.common.value; + cached[name] = last_value = minimal_lit.common.value; + minimal_lit.common.flags = (i == default_literal_idx ? OpenDDS::XTypes::IS_DEFAULT : 0); - const std::string name = canonical_name(contents[i]->local_name()); + OpenDDS::XTypes::hash_member_name(minimal_lit.detail.name_hash, name); minimal_to.minimal.enumerated_type.literal_seq.append(minimal_lit); diff --git a/dds/idl/typeobject_generator.h b/dds/idl/typeobject_generator.h index 3251a6055a7..6cabb3e0d97 100644 --- a/dds/idl/typeobject_generator.h +++ b/dds/idl/typeobject_generator.h @@ -120,6 +120,10 @@ class typeobject_generator : public dds_generator { std::map element_; bool get_type_map_declared_; OpenDDS::DCPS::Encoding* typeid_encoding_; + + typedef std::map EnumValues; + typedef std::map EnumValueMap; + EnumValueMap enum_values_; }; #endif From c476732b86066fa4fd046b68f9b135070cbceda5 Mon Sep 17 00:00:00 2001 From: Adam Mitz Date: Tue, 19 Mar 2024 14:24:42 -0500 Subject: [PATCH 13/18] Include Definitions.h in language mapping header --- dds/idl/be_produce.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/dds/idl/be_produce.cpp b/dds/idl/be_produce.cpp index 0e1d5ecf30c..55f58da0e44 100644 --- a/dds/idl/be_produce.cpp +++ b/dds/idl/be_produce.cpp @@ -200,6 +200,7 @@ void postprocess(const char* fn, ostringstream& content, if (be_global->language_mapping() == BE_GlobalData::LANGMAP_FACE_CXX || be_global->language_mapping() == BE_GlobalData::LANGMAP_SP_CXX) { out << + "#include \n\n" "#include \n" "#include \n" "TAO_BEGIN_VERSIONED_NAMESPACE_DECL\n" From 22e1bd0b6ff99a5ee8ef850a53970f153ee312d9 Mon Sep 17 00:00:00 2001 From: Adam Mitz Date: Tue, 19 Mar 2024 17:27:58 -0500 Subject: [PATCH 14/18] updated comments in IDL --- dds/DCPS/RTPS/RtpsCore.idl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dds/DCPS/RTPS/RtpsCore.idl b/dds/DCPS/RTPS/RtpsCore.idl index 6590c2f2076..b921f8867c5 100644 --- a/dds/DCPS/RTPS/RtpsCore.idl +++ b/dds/DCPS/RTPS/RtpsCore.idl @@ -540,9 +540,9 @@ module OpenDDS { unsigned short submessageLength; /* octetsToNextHeader */ }; // Valid constants for the submessageId field are the enumerators - // of the SubmessageKind enum in RtpsSubmessageKind.idl + // of the SubmessageKind enum in RtpsSubmessageKind.idl. // The least-significant bit of "flags" is E, the endianness flag: - // pseudoenum E { BIG_ENDIAN = 0, LITTLE_ENDIAN = 1}; + // pseudoenum E { BIG_ENDIAN = 0, LITTLE_ENDIAN = 1 }; /* Type used to hold fragment numbers. */ struct FragmentNumber_t { From aa08b18573b6de598500a59a18e24049377d890e Mon Sep 17 00:00:00 2001 From: Adam Mitz Date: Tue, 19 Mar 2024 17:28:33 -0500 Subject: [PATCH 15/18] started test --- .../value_annotation/value_annotation.cpp | 54 ++++++++++++++++++- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.cpp b/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.cpp index 9eb02f29238..89083fdfdce 100644 --- a/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.cpp +++ b/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.cpp @@ -1,6 +1,56 @@ #include "value_annotationTypeSupportImpl.h" -int ACE_MAIN(int argc, char* argv[]) +#include +#include + +using namespace OpenDDS::DCPS; + +int ACE_TMAIN(int, ACE_TCHAR*[]) { - return 0; + bool failed = false; + + if (static_cast(TestValueAnnotation::NON_ZERO) != 99) { + ACE_ERROR((LM_ERROR, "ERROR: NON_ZERO wasn't 99\n")); + failed = true; + } + if (static_cast(TestValueAnnotation::SIX) != 6) { + ACE_ERROR((LM_ERROR, "ERROR: SIX wasn't 6\n")); + failed = true; + } + if (static_cast(TestValueAnnotation::TEN) != 10) { + ACE_ERROR((LM_ERROR, "ERROR: TEN wasn't 10\n")); + failed = true; + } + + const EnumHelper& helper = *gen_TestValueAnnotation_helper; + if (helper.valid("invalid")) { + ACE_ERROR((LM_ERROR, "ERROR: invalid was valid\n")); + failed = true; + } + if (helper.valid(0)) { + ACE_ERROR((LM_ERROR, "ERROR: 0 was valid\n")); + failed = true; + } + + if (helper.valid("FIVE")) { + if (helper.get_value("FIVE") != 5) { + ACE_ERROR((LM_ERROR, "ERROR: FIVE's value wasn't 5\n")); + failed = true; + } + } else { + ACE_ERROR((LM_ERROR, "ERROR: FIVE was invalid\n")); + failed = true; + } + + if (helper.valid(5)) { + if (std::strcmp(helper.get_name(5), "FIVE")) { + ACE_ERROR((LM_ERROR, "ERROR: 5's name wasn't FIVE\n")); + failed = true; + } + } else { + ACE_ERROR((LM_ERROR, "ERROR: 5 was invalid\n")); + failed = true; + } + + return failed ? EXIT_FAILURE : EXIT_SUCCESS; } From 8f3118c052c58e4a4e46a512ff3e156375b8adaa Mon Sep 17 00:00:00 2001 From: Adam Mitz Date: Wed, 20 Mar 2024 11:47:34 -0500 Subject: [PATCH 16/18] Updated test --- .../value_annotation/value_annotation.cpp | 98 +++++++++++++++++++ .../value_annotation/value_annotation.idl | 4 +- .../value_annotation/value_annotation.mpc | 3 +- tests/core_ci_tests.lst | 1 + 4 files changed, 103 insertions(+), 3 deletions(-) diff --git a/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.cpp b/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.cpp index 89083fdfdce..be44e45392f 100644 --- a/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.cpp +++ b/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.cpp @@ -4,6 +4,7 @@ #include using namespace OpenDDS::DCPS; +using namespace OpenDDS::XTypes; int ACE_TMAIN(int, ACE_TCHAR*[]) { @@ -52,5 +53,102 @@ int ACE_TMAIN(int, ACE_TCHAR*[]) failed = true; } + const UsesAnnotatedEnum stru{TestValueAnnotation::SIX}; + const Encoding enc(Encoding::KIND_XCDR2, ENDIAN_LITTLE); + const size_t size = serialized_size(enc, stru); + static const char expected[] = {6, 0, 0, 0}; + + Message_Block_Ptr mb(new ACE_Message_Block(size)); + Serializer ser(mb.get(), enc); + if (!(ser << stru)) { + ACE_ERROR((LM_ERROR, "ERROR: struct serialization failed\n")); + failed = true; + } else if (size != 4 || mb->length() != size) { + ACE_ERROR((LM_ERROR, "ERROR: struct serialization size invalid\n")); + failed = true; + } else if (0 != std::memcmp(expected, mb->rd_ptr(), size)) { + ACE_ERROR((LM_ERROR, "ERROR: struct serialization contents invalid\n")); + failed = true; + } + + mb->rd_ptr()[0] = 10; + Serializer ser2(mb.get(), enc); + UsesAnnotatedEnum stru2{TestValueAnnotation::SIX}; + if (!(ser2 >> stru2)) { + ACE_ERROR((LM_ERROR, "ERROR: struct deserialization failed\n")); + failed = true; + } else if (stru2.tva() != TestValueAnnotation::TEN) { + ACE_ERROR((LM_ERROR, "ERROR: struct deserialization result invalid\n")); + failed = true; + } + + const TypeIdentifier& enum_cti = getCompleteTypeIdentifier(); + const TypeMap& enum_ctm = getCompleteTypeMap(); + if (enum_ctm.count(enum_cti) == 0) { + ACE_ERROR((LM_ERROR, "ERROR: XTypes TypeMap (enum) invalid\n")); + failed = true; + } else { + const TypeObject& enum_cto = enum_ctm.find(enum_cti)->second; + if (enum_cto.kind != EK_COMPLETE) { + ACE_ERROR((LM_ERROR, "ERROR: XTypes TypeObject (enum) invalid\n")); + failed = true; + } else if (enum_cto.complete.kind != TK_ENUM) { + ACE_ERROR((LM_ERROR, "ERROR: XTypes CompleteTypeObject (enum) invalid\n")); + failed = true; + } else { + const CompleteEnumeratedLiteralSeq& enumerators = enum_cto.complete.enumerated_type.literal_seq; + if (enumerators.length() != 6) { + ACE_ERROR((LM_ERROR, "ERROR: XTypes invalid number of enumerators\n")); + failed = true; + } else if (enumerators[0].common.value != 1 || + enumerators[1].common.value != 2 || + enumerators[2].common.value != 5 || + enumerators[3].common.value != 6 || + enumerators[4].common.value != 10 || + enumerators[5].common.value != 99) { + ACE_ERROR((LM_ERROR, "ERROR: XTypes invalid values of enumerators\n")); + failed = true; + } else if (enumerators[0].detail.name != "ONE" || + enumerators[1].detail.name != "TWO" || + enumerators[2].detail.name != "FIVE" || + enumerators[3].detail.name != "SIX" || + enumerators[4].detail.name != "TEN" || + enumerators[5].detail.name != "NON_ZERO") { + ACE_ERROR((LM_ERROR, "ERROR: XTypes invalid names of enumerators\n")); + failed = true; + } + } + } + + const TypeIdentifier& union_cti = getCompleteTypeIdentifier(); + const TypeMap& union_ctm = getCompleteTypeMap(); + if (union_ctm.count(union_cti) == 0) { + ACE_ERROR((LM_ERROR, "ERROR: XTypes TypeMap (union) invalid\n")); + failed = true; + } else { + const TypeObject& union_cto = union_ctm.find(union_cti)->second; + if (union_cto.kind != EK_COMPLETE) { + ACE_ERROR((LM_ERROR, "ERROR: XTypes TypeObject (union) invalid\n")); + failed = true; + } else if (union_cto.complete.kind != TK_UNION) { + ACE_ERROR((LM_ERROR, "ERROR: XTypes CompleteTypeObject (union) invalid\n")); + failed = true; + } else { + const CompleteUnionMemberSeq& members = union_cto.complete.union_type.member_seq; + if (members.length() != 2) { + ACE_ERROR((LM_ERROR, "ERROR: XTypes invalid number of union members\n")); + failed = true; + } else if (members[0].common.label_seq.length() != 1 || + members[0].common.label_seq[0] != 5) { + ACE_ERROR((LM_ERROR, "ERROR: XTypes union member 0 invalid\n")); + failed = true; + } else if (members[1].common.label_seq.length() != 0 || + (members[1].common.member_flags & IS_DEFAULT) != IS_DEFAULT) { + ACE_ERROR((LM_ERROR, "ERROR: XTypes union member 1 invalid\n")); + failed = true; + } + } + } + return failed ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.idl b/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.idl index 8714c3ae450..af3a1e5ffc1 100644 --- a/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.idl +++ b/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.idl @@ -7,12 +7,14 @@ enum TestValueAnnotation { @value(10) TEN }; +@final struct UsesAnnotatedEnum { TestValueAnnotation tva; }; +@final union DiscByAnnotatedEnum switch (TestValueAnnotation) { -case ONE: +case FIVE: octet o; default: short s; diff --git a/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.mpc b/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.mpc index 4d344b090e7..9cdc5a59f24 100644 --- a/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.mpc +++ b/tests/DCPS/Compiler/C++11/value_annotation/value_annotation.mpc @@ -1,6 +1,5 @@ project: dcpsexe, dcps_test, opendds_cxx11 { - exename = * - dcps_ts_flags += -SI + dcps_ts_flags += -SI -Gxtypes-complete TypeSupport_Files { value_annotation.idl } diff --git a/tests/core_ci_tests.lst b/tests/core_ci_tests.lst index bc3d6cc66b1..c9297fa44c1 100644 --- a/tests/core_ci_tests.lst +++ b/tests/core_ci_tests.lst @@ -27,6 +27,7 @@ tests/DCPS/Compiler/idl_test1_main/run_test.pl: !DCPS_MIN !OPENDDS_SAFETY_PROFIL tests/DCPS/Compiler/idl_test3_main/run_test.pl: !DCPS_MIN !OPENDDS_SAFETY_PROFILE STATIC_COMPILER tests/DCPS/Compiler/C++11/idl_test1_main/run_test.pl: !DCPS_MIN CXX11 STATIC_COMPILER tests/DCPS/Compiler/C++11/idl_test3_main/run_test.pl: !DCPS_MIN CXX11 STATIC_COMPILER +tests/DCPS/Compiler/C++11/value_annotation/run_test.pl: !DCPS_MIN CXX11 STATIC_COMPILER tests/DCPS/Compiler/key_annotation/run_test.pl: !DCPS_MIN STATIC_COMPILER2 tests/DCPS/Compiler/is_topic_type/run_test.pl: !DCPS_MIN STATIC_COMPILER tests/DCPS/Compiler/vread_vwrite/run_test.pl: !DCPS_MIN RAPIDJSON CXX11 STATIC_COMPILER2 From d334aebbd15d7ac94b5ab04fa150a32678d342d4 Mon Sep 17 00:00:00 2001 From: Adam Mitz Date: Wed, 20 Mar 2024 13:45:30 -0500 Subject: [PATCH 17/18] Documentation for #4519 --- docs/devguide/opendds_idl.rst | 2 +- docs/devguide/xtypes.rst | 29 +++++++++++++++++++++++++++ docs/news.d/enum-value-annotation.rst | 6 ++++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 docs/news.d/enum-value-annotation.rst diff --git a/docs/devguide/opendds_idl.rst b/docs/devguide/opendds_idl.rst index 974f07417fd..6a5fede68a1 100644 --- a/docs/devguide/opendds_idl.rst +++ b/docs/devguide/opendds_idl.rst @@ -269,7 +269,7 @@ Unlike when using the classic mapping, ``Foo.idl`` is not processed by ``tao_idl * Bounded strings and sequences are supported, but bounds checks are not currently enforced. Due to this limitation, distinct types are not used for bounded instantiations. -* annotations -- see :ref:`getting_started--defining-data-types-with-idl` +* annotations -- see :ref:`getting_started--defining-data-types-with-idl` and :ref:`xtypes--idl-annotations` * ``#include``\s of IDL files that are also used with the IDL-to-C++11 mapping diff --git a/docs/devguide/xtypes.rst b/docs/devguide/xtypes.rst index 8ba042cf682..1ed9c66787b 100644 --- a/docs/devguide/xtypes.rst +++ b/docs/devguide/xtypes.rst @@ -820,6 +820,35 @@ The ``@key`` annotation marks a member used to determine the Instances of a topi See :ref:`getting_started--keys` for more details on the general concept of a Key. For XTypes specifically, two types can only be compatible if each contains the members that are keys within the other. +Customizing the values of enumerators +===================================== + +.. + Sect<16.6.7> + +.. _xtypes--value: + +@value(v) +--------- + +.. + Sect<16.6.7.1> + +Applies to: enumerators (only when :ref:`opendds_idl--using-the-idl-to-c-11-mapping`) + +Without annotations, the enumerators of each enum type take on consecutive integer values starting at 0. +The ``@value(v)`` annotation customizes the integer value of an individual enumerator. The parameter ``v`` is an integer constant (signed, 4 bytes wide). +Any enumerators that are not annotated take on the integer value one higher than the value of the previously-declared enumerator, with the first declared taking value 0. + +.. code-block:: omg-idl + + enum MyAnnotionEnabledEnum { + ZERO, + @value(3) THREE, + FOUR, + @value(2) TWO + }; + .. _xtypes--dynamic-language-binding-1: ************************ diff --git a/docs/news.d/enum-value-annotation.rst b/docs/news.d/enum-value-annotation.rst new file mode 100644 index 00000000000..575b0a4f3cf --- /dev/null +++ b/docs/news.d/enum-value-annotation.rst @@ -0,0 +1,6 @@ +.. news-prs: 4519 + +.. news-start-section: Additions +- The ``@value(x)`` annotation is now supported on IDL enumerators when using the IDL-to-C++11 mapping. + +.. news-end-section From 648ca8251e3d2d973c30ee421c996a66d2c029ef Mon Sep 17 00:00:00 2001 From: Adam Mitz Date: Thu, 21 Mar 2024 08:50:33 -0500 Subject: [PATCH 18/18] Docs updates from peer review Co-authored-by: Fred Hornsey --- docs/devguide/xtypes.rst | 2 -- docs/news.d/enum-value-annotation.rst | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/devguide/xtypes.rst b/docs/devguide/xtypes.rst index 1ed9c66787b..2476954fad2 100644 --- a/docs/devguide/xtypes.rst +++ b/docs/devguide/xtypes.rst @@ -823,8 +823,6 @@ For XTypes specifically, two types can only be compatible if each contains the m Customizing the values of enumerators ===================================== -.. - Sect<16.6.7> .. _xtypes--value: diff --git a/docs/news.d/enum-value-annotation.rst b/docs/news.d/enum-value-annotation.rst index 575b0a4f3cf..89b4cd3b489 100644 --- a/docs/news.d/enum-value-annotation.rst +++ b/docs/news.d/enum-value-annotation.rst @@ -3,4 +3,6 @@ .. news-start-section: Additions - The ``@value(x)`` annotation is now supported on IDL enumerators when using the IDL-to-C++11 mapping. + - See :ref:`xtypes--value` for details. + .. news-end-section