/******************************************************************************** * Copyright (c) 2025-2026 ZF Friedrichshafen AG * * This program and the accompanying materials are made available under the * terms of the Apache License Version 2.0 which is available at * https://www.apache.org/licenses/LICENSE-2.0 * * SPDX-License-Identifier: Apache-2.0 * * Contributors: * Erik Verhoeven - initial API and implementation ********************************************************************************/ // Several issues exist with the code generation of the unions: // - Forward declaration of unions with value based switch --> forward declarated type is union and impl. type is struct // - Unions with complex members --> constructor and destructor are deleted // Forward declaration union UStandard; /** * @brief Standard union based on a integer. */ union UStandard switch (uint32) { case 10: boolean bVal; ///< Bool value case 20: uint64 uiVal; ///< 64-bit int value case 30: string ssVal; ///< String value default: float fVal; ///< Float value }; /** * \@brief Typedef of a standard union. */ typedef UStandard UTypedefStandard; /** * @brief Enum variable for switch case */ enum ESwitch : long { ten, ///< Value 10 twenty, ///< Value 20 thirty ///< Value 30 }; /** * @brief Standard union based on an enum. */ union UStandardEnum switch (ESwitch) { case ten: boolean bVal; ///< Bool value case twenty: uint64 uiVal; ///< 64-bit int value case thirty: string ssVal; ///< String value default: float fVal; ///< Float value }; /** * @brief Standard union in struct. */ struct SStandardUnion { UStandard uStandardVar; ///< Standard union declaration. UStandardEnum uStandardEnumVar; ///< Standard union declaration based on enum. UTypedefStandard uTypedefStandardVar; ///< Typedef standard union declaration. /** * @brief Contained based union. */ union UContained switch (uint32) { case 10: boolean bVal; ///< Bool value case 20: uint64 uiVal; ///< 64-bit int value case 30: string ssVal; ///< String value default: float fVal; ///< Float value }; UContained uContainedVar; ///< Contained union declaration. /** * @brief Contained based union. */ union UContainedEnum switch (ESwitch) { case ten: boolean bVal; ///< Bool value case twenty: uint64 uiVal; ///< 64-bit int value case thirty: string ssVal; ///< String value default: float fVal; ///< Float value }; UContainedEnum uContainedEnumVar; ///< Contained union declaration based on enum. }; /** * @brief Variable based union in struct. */ struct SVariableUnion { uint32 uiSwitch; ///< Switch value /** * @brief Contained union based on variable. */ union UContained switch (uiSwitch) { case 10: boolean bVal; ///< Bool value case 20: uint64 uiVal; ///< 64-bit int value case 30: string ssVal; ///< String value default: float fVal; ///< Float value }; UContained uContainedVar; ///< Contained union declaration. }; /** * @brief Multiple variable based unions in struct. */ struct SMultiVariableUnion { uint32 uiSwitch1; ///< Switch1 value uint32 uiSwitch2; ///< Switch2 value /** * @brief Contained union based on variable #1. */ union UContained1 switch (uiSwitch1) { case 10: boolean bVal1; ///< Bool value case 20: uint64 uiVal1; ///< 64-bit int value case 30: string ssVal1; ///< String value default: float fVal1; ///< Float value }; /** * @brief Contained union based on variable #2. */ union UContained2 switch (uiSwitch2) { case 10: boolean bVal2; ///< Bool value case 20: uint64 uiVal2; ///< 64-bit int value case 30: string ssVal2; ///< String value default: float fVal2; ///< Float value }; UContained1 uContainedVar1; ///< Contained union #1 declaration. UContained2 uContainedVar2; ///< Contained union #2 declaration. }; /** * @brief Multiple variable based unions with simple data types in struct. */ struct SSimpleMultiVariableUnion { uint32 uiSwitch1; ///< Switch1 value uint32 uiSwitch2; ///< Switch2 value /** * @brief Contained union based on variable #1. */ union UContained1 switch (uiSwitch1) { case 10: boolean bVal1; ///< Bool value case 20: uint64 ui64Val1; ///< 64-bit int value case 30: uint32 ui32Val1; ///< 32-bit int value default: float fVal1; ///< Float value }; /** * @brief Contained union based on variable #2. */ union UContained2 switch (uiSwitch2) { case 10: boolean bVal2; ///< Bool value case 20: uint64 ui64Val2; ///< 64-bit int value case 30: uint32 ui32Val2; ///< 32-bit int value default: float fVal2; ///< Float value }; UContained1 uContainedVar1; ///< Contained union #1 declaration. UContained2 uContainedVar2; ///< Contained union #2 declaration. }; // This union will only work after anonymous struct/union support has been implemented: PBI #397894 /** * @brief Use transparent unions with switches from the struct holding the unions. */ struct SSimpleAnonymousUnion { int32 iVal = 10; ///< Variable for the switch of the first union. union switch (iVal) ///< Anonymous union { case 10: int32 a; ///< Var a case 20: int32 b; ///< Var b case 30: int32 c; ///< Var c }; }; /** * @brief Use transparent unions with switches from the struct holding the unions. */ struct SSimpleMultipleAnonymousUnion { int32 iVal1 = 10; ///< Variable for the switch of the first union. union switch (iVal1) ///< Anonymous union { case 10: int32 a; ///< Var a case 20: int32 b; ///< Var b case 30: int32 c; ///< Var c }; int32 iVal2 = 10; ///< Variable for the switch of the first union. union switch (iVal2) ///< Anonymous union { case 10: int32 d; ///< Var a case 20: int32 e; ///< Var b case 30: int32 f; ///< Var c }; }; /** * @brief Union with complex type as a variable. */ struct SComplexVarUnion { /// Complex type struct SComplex { u8string ss1; ///< First string u8string ss2; ///< Second string }; int32 iVal = 10; ///< Variable for the switch of the first union. union switch (iVal) ///< Anonymous union { case 10: int32 i; ///< Simple type case 20: SComplex s; ///< Complex type case 30: u8string ss; ///< String type }; }; struct STrippleIndirect { struct SDoubleIndirect { struct SIndirect { struct SSwitchValStruct { double dOtherVal; int32 iVal = 5; ///< Variable for the switch of a separate union. string ssOtherVal; } sSwitchValStruct; }; SIndirect sIndirect; union UIndirect switch (sIndirect.sSwitchValStruct.iVal) { case 5: int i; case 6: double d; default: string ss; } uIndirect; }; }; /** * @brief Union with complex type as a variable and switch case that is in a variable of a variable array within a structure * declaration of a base class two levels higher defined after the union definition. */ struct SComplexIndirectVarUnion { /// Complex type struct SComplex { u8string ss1; ///< First string u8string ss2; ///< Second string }; struct SIndirect { int32 rgiVal[3] = { 10, 20, 30 }; ///< Variable for the switch of parallel laying unions. }; SIndirect sIndirect; STrippleIndirect::SDoubleIndirect sDoubleIndirect; STrippleIndirect::SDoubleIndirect::SIndirect sOneHalfIndirect; // Child structure struct SChild { const int32 iArrayLen = 4; ///< Array length /// Transparent union union /*UUnnamed*/ switch (SComplexIndirectVarUnion::sIndirect.rgiVal[0]) { case 10: int32 i; ///< Simple type case 20: SComplex s; ///< Complex type case 30: u8string ss; ///< String type } /*Anonymous*/; /// Unnamed, but declared union union /*UUnnamed2*/ switch (sIndirect.rgiVal[1]) { case 10: int32 i; ///< Simple type case 20: SComplex s; ///< Complex type case 30: u8string ss; ///< String type } uUnnamed; /// Named and declared union union UNamed switch (/*Comment in switch case*/ sIndirect.rgiVal[2]) { case 10: int32 i; ///< Simple type case 20: SComplex s; ///< Complex type case 30: u8string ss; ///< String type } uNamed; UNamed uNamedArray[2][iArrayLen]; ///< Named array union UDoubleIndirect switch (sDoubleIndirect.sIndirect.sSwitchValStruct.iVal /*Comment in switch case*/) { case 1: int32 i; ///< Simple type case 5: SComplex s; ///< Complex type case 10: u8string ss; ///< String type } uDoubleIndirect; union UOneHalfIndirect switch (sOneHalfIndirect.sSwitchValStruct.iVal /*Comment in switch case*/) { case 1: int32 i; ///< Simple type case 5: SComplex s; ///< Complex type case 10: u8string ss; ///< String type } uOneHalfIndirect; }; SChild sChild1; ///< Child declaration SChild sChildArray[5][SChild::iArrayLen]; ///< Child array declaration }; union UEmptyCase switch (int32) { case 10: int32 i; case 20: uint32 ui; case 30: // nothing case 40: string ss; default: // nothing }; #if 0 // NOTE: The following union is not allowed, since it uses an anonymous structure in a case switch. Anonymous structures are // allowed in C, but not in C++ - therefore they are not supported by the compiler. /** * @brief Use transparent unions with switches from the struct holding the unions. */ struct STransparentUnion { int32 iVal = 10; ///< Variable for the switch of the first union. union switch (iVal) ///< Anonymous union { case 10: // NOTE: A variable based switched union cannot be used here, since it lacks the posibility for accessing the variable. // NOTE: Only one nested anonymous type based union can be used; otherwise there would be multiple switch_value-variables. union switch (int32) ///< Anonymous union { case 1: int32 a; ///< Var a case 2: int32 b; ///< Var b case 3: int32 c; ///< Var c }; case 20: struct ///< Anonymous struct { int32 d; ///< Var d int32 e; ///< Var e int32 f; ///< Var f }; case 30: int32 g; ///< Var g }; }; #endif /** * @brief Union test interface to enforce proxy/stub creation. */ interface IUnionTest { /// Test a standard union with type based integral switch. void TestStandardUnion(in UStandard uStandardVar); /// Test a standard union with type based enum switch. void TestStandardEnumUnion(in UStandardEnum uStandardEnumVar); /// Test a contained standard union with type based switch. void TestStandardContainedUnion(in SStandardUnion::UContained uStandardContainedVar); /// Test a structure containing unions void TestStandardUnionStruct(in SStandardUnion sStandardStructVar); /// Test a structure with a union with variable based switch. void TestVariableUnion(in SVariableUnion sVariableStructVar); /// Test a structure with multiple unions with variable based switch. void TestMultiVariableUnion(in SMultiVariableUnion sVariableStructVar); /// Test a structure with multiple unions with variable based switch and simple data types. void TestSimpleMultiVariableUnion(in SSimpleMultiVariableUnion sVariableStructVar); /// Test a structure with an anonymous union with variable based switch and simple data types. void TestSimpleAnonymousUnion(in SSimpleAnonymousUnion sVariableStructVar); };