#include "includes.h" #include "parser_test.h" #include "../../../sdv_executables/sdv_idl_compiler/parser.h" #include "../../../sdv_executables/sdv_idl_compiler/entities/definition_entity.cpp" #include "../../../sdv_executables/sdv_idl_compiler/entities/struct_entity.cpp" #include "../../../sdv_executables/sdv_idl_compiler/entities/variable_entity.h" #include "../../../sdv_executables/sdv_idl_compiler/entities/declaration_entity.h" #include "../../../sdv_executables/sdv_idl_compiler/entities/entity_value.h" using CParserStructTest = CParserTest; TEST_F(CParserStructTest, ForwardDeclaration) { // struct ; --> forward declaration EXPECT_TRUE(CParser("struct S1; struct S1 {};").Parse().Root()->Find("S1")); EXPECT_TRUE(CParser("struct S1 {}; struct S1;").Parse().Root()->Find("S1")); EXPECT_TRUE(CParser("struct S1; struct S1; struct S1; struct S1;").Parse().Root()->Find("S1")); EXPECT_TRUE(CParser("struct S1 {}; struct S1; struct S1; ").Parse().Root()->Find("S1")); EXPECT_THROW(CParser("struct S1 {}; struct S1; struct S1 {}; ").Parse(), CCompileException); } TEST_F(CParserStructTest, Definition) { // struct {...}; --> struct definition EXPECT_TRUE(CParser("struct S2 {};").Parse().Root()->Find("S2")); EXPECT_TRUE(CParser("struct S2 { int32 i; };").Parse().Root()->Find("S2")); EXPECT_TRUE(CParser("struct S2 { int32 i; };").Parse().Root()->Find("S2::i")); } TEST_F(CParserStructTest, DefinitionWithInheritance) { // struct : {...}; --> struct definition with inheritance EXPECT_TRUE(CParser("struct S3base {int32 i;}; struct S3 : S3base {int32 j;};").Parse().Root()->Find("S3")); EXPECT_TRUE(CParser("struct S3base_1 {int32 i;}; struct S3base_2 {int32 i;}; struct S3_12 : S3base_1, S3base_2 {int32 j;};").Parse().Root()->Find("S3_12")); EXPECT_TRUE(CParser("struct S3base_1 {}; struct S3base_2 : S3base_1 {}; struct S3_12 : S3base_2 {};").Parse().Root()->Find("S3_12")); EXPECT_TRUE(CParser("struct S3base_1 {}; struct S3base_2 : S3base_1 {}; struct S3_12 : S3base_1, S3base_2 {};").Parse().Root()->Find("S3_12")); // S3base is not defined EXPECT_THROW(CParser("struct S3 : S3base {};").Parse(), CCompileException); EXPECT_THROW(CParser("struct S3base; struct S3 : S3base {};").Parse(), CCompileException); // Invalid base struct EXPECT_THROW(CParser("const uint32_t S1 = 10; struct S2 : S1 {};").Parse(), CCompileException); } TEST_F(CParserStructTest, DuplicateNameThroughInheritance) { EXPECT_THROW(CParser("struct S1 {const char c = 'C';}; struct S2 : S1 {const int32 c = 10;};").Parse(), CCompileException); EXPECT_THROW(CParser("struct S1; struct S1 {const char c = 'C';}; struct S2 : S1 {const int32 c = 10;};").Parse(), CCompileException); EXPECT_THROW(CParser("struct S1 {const char c = 'C';}; struct S2 : S1 {}; struct S3 : S2 {const int32 c = 10;};").Parse(), CCompileException); } TEST_F(CParserStructTest, DeclarationsAndTypedefs) { const char szCode[] = R"code( struct S { struct S1 { int32 a; int32 b; int32 c; }; typedef S1 TS1; struct S2 : TS1 { int32 d; int32 e; int32 f; }; typedef S2 TS2; struct S3 { TS1 ts1Value; TS2 ts2Value; }; typedef S3 TS3; TS3 ts3Value; typedef TS3 TS4; TS4 ts4Value; }; )code"; CParser parser(szCode); parser.Parse(); EXPECT_TRUE(parser.Root()->Find("S::S1")); EXPECT_TRUE(parser.Root()->Find("S::S1::a")); EXPECT_TRUE(parser.Root()->Find("S::S1::b")); EXPECT_TRUE(parser.Root()->Find("S::S1::c")); EXPECT_TRUE(parser.Root()->Find("S::TS1")); EXPECT_TRUE(parser.Root()->Find("S::TS1::a")); EXPECT_TRUE(parser.Root()->Find("S::TS1::b")); EXPECT_TRUE(parser.Root()->Find("S::TS1::c")); EXPECT_TRUE(parser.Root()->Find("S::S2")); EXPECT_TRUE(parser.Root()->Find("S::S2::a")); EXPECT_TRUE(parser.Root()->Find("S::S2::b")); EXPECT_TRUE(parser.Root()->Find("S::S2::c")); EXPECT_TRUE(parser.Root()->Find("S::S2::d")); EXPECT_TRUE(parser.Root()->Find("S::S2::e")); EXPECT_TRUE(parser.Root()->Find("S::S2::f")); EXPECT_TRUE(parser.Root()->Find("S::TS2")); EXPECT_TRUE(parser.Root()->Find("S::TS2::a")); EXPECT_TRUE(parser.Root()->Find("S::TS2::b")); EXPECT_TRUE(parser.Root()->Find("S::TS2::c")); EXPECT_TRUE(parser.Root()->Find("S::TS2::d")); EXPECT_TRUE(parser.Root()->Find("S::TS2::e")); EXPECT_TRUE(parser.Root()->Find("S::TS2::f")); EXPECT_TRUE(parser.Root()->Find("S::S3")); EXPECT_TRUE(parser.Root()->Find("S::TS3")); EXPECT_TRUE(parser.Root()->Find("S::ts3Value.ts1Value")); EXPECT_TRUE(parser.Root()->Find("S::ts3Value.ts2Value")); EXPECT_TRUE(parser.Root()->Find("S::ts3Value.ts1Value.a")); EXPECT_TRUE(parser.Root()->Find("S::ts3Value.ts1Value.b")); EXPECT_TRUE(parser.Root()->Find("S::ts3Value.ts1Value.c")); EXPECT_TRUE(parser.Root()->Find("S::ts3Value.ts2Value.a")); EXPECT_TRUE(parser.Root()->Find("S::ts3Value.ts2Value.b")); EXPECT_TRUE(parser.Root()->Find("S::ts3Value.ts2Value.c")); EXPECT_TRUE(parser.Root()->Find("S::ts3Value.ts2Value.d")); EXPECT_TRUE(parser.Root()->Find("S::ts3Value.ts2Value.e")); EXPECT_TRUE(parser.Root()->Find("S::ts3Value.ts2Value.f")); EXPECT_TRUE(parser.Root()->Find("S::TS4")); EXPECT_TRUE(parser.Root()->Find("S::ts4Value.ts1Value")); EXPECT_TRUE(parser.Root()->Find("S::ts4Value.ts2Value")); EXPECT_TRUE(parser.Root()->Find("S::ts4Value.ts1Value.a")); EXPECT_TRUE(parser.Root()->Find("S::ts4Value.ts1Value.b")); EXPECT_TRUE(parser.Root()->Find("S::ts4Value.ts1Value.c")); EXPECT_TRUE(parser.Root()->Find("S::ts4Value.ts2Value.a")); EXPECT_TRUE(parser.Root()->Find("S::ts4Value.ts2Value.b")); EXPECT_TRUE(parser.Root()->Find("S::ts4Value.ts2Value.c")); EXPECT_TRUE(parser.Root()->Find("S::ts4Value.ts2Value.d")); EXPECT_TRUE(parser.Root()->Find("S::ts4Value.ts2Value.e")); EXPECT_TRUE(parser.Root()->Find("S::ts4Value.ts2Value.f")); } TEST_F(CParserStructTest, VariableDeclaration) { // ; --> struct variable declaration EXPECT_TRUE(CParser("struct S{struct S4 {int32 i;}; S4 s4Value;};").Parse().Root()->Find("S::s4Value")); EXPECT_TRUE(CParser("struct S{struct S4 {int32 i;}; S4 s4Value;};").Parse().Root()->Find("S::s4Value.i")); EXPECT_TRUE(CParser("struct S{struct S4 {int32 i;}; typedef S4 S5; S5 s5Value;};").Parse().Root()->Find("S::s5Value.i")); EXPECT_TRUE(CParser("struct S{struct S4 {struct S5{int32 i;} s5Value;}; typedef S4 S6; S6 s6Value;};").Parse().Root()->Find("S::s6Value.s5Value.i")); EXPECT_TRUE(CParser("struct S{struct S4 {struct S5{int32 i;} s5Value;}; typedef S4 S6; S6 s6Value;}; const S sValue = {{{10}}};").Parse().Root()->Find("sValue.s6Value.s5Value.i")); // struct ; --> struct variable declaration EXPECT_TRUE(CParser("struct S{struct S6 {int32 i;}; struct S6 s6Value;};").Parse().Root()->Find("S::s6Value")); } TEST_F(CParserStructTest, VarDeclarationAndAssignment) { // = {...}; --> struct variable declaration and assignment EXPECT_TRUE(CParser("struct S{struct S5 {int32 i;}; S5 s5Value = {10};};").Parse().Root()->Find("S::s5Value")); EXPECT_TRUE(CParser("struct S{struct S5b {int32 i = 11;}; S5b s5bValue = {10};};").Parse().Root()->Find("S::s5bValue")); // struct = {...}; --> struct variable declaration and assignment EXPECT_TRUE(CParser("struct S{struct S7 {int32 i;}; struct S7 s7Value = {10};};").Parse().Root()->Find("S::s7Value")); } TEST_F(CParserStructTest, VarDeclarationAndAssignmentOfStructDecl) { EXPECT_EQ(CParser("struct S1{int32 i;}; struct S2{ S1 sValue1 = {10}; S1 sValue2 = sValue1; };").Parse().Root()->FindValueVariant("S2::sValue2.i").Get(), 10); EXPECT_EQ(CParser("struct S1{int32 i[2];}; struct S2{ S1 sValue1 = {{10, 20}}; S1 sValue2 = sValue1; };").Parse().Root()->FindValueVariant("S2::sValue2.i[1]").Get(), 20); EXPECT_EQ(CParser("struct S1{int32 i[2][2];}; struct S2{ S1 sValue1 = {{{10, 20}, {30, 40}}}; S1 sValue2 = sValue1; };").Parse().Root()->FindValueVariant("S2::sValue2.i[1][1]").Get(), 40); EXPECT_EQ(CParser("struct S1{typedef int32 ti[2]; ti i[2];}; struct S2{ S1 sValue1 = {{{10, 20}, {30, 40}}}; S1 sValue2 = sValue1; };").Parse().Root()->FindValueVariant("S2::sValue2.i[1][1]").Get(), 40); EXPECT_EQ(CParser("typedef struct tagS1 {int32 i;} S1; struct S2{ S1 sValue1 = {10}; S1 sValue2 = sValue1; };").Parse().Root()->FindValueVariant("S2::sValue2.i").Get(), 10); EXPECT_EQ(CParser("typedef struct tagS1 {int32 i;} S1; struct S2{ S1 sValue1[2] = {{10}, {20}}; S1 sValue2 = sValue1[1]; };").Parse().Root()->FindValueVariant("S2::sValue2.i").Get(), 20); EXPECT_EQ(CParser("typedef struct tagS1 {int32 i;} S1; const int32 index = 2; struct S2{ S1 sValue1[index] = {{10}, {20}}; S1 sValue2 = sValue1[1]; };").Parse().Root()->FindValueVariant("S2::sValue2.i").Get(), 20); EXPECT_EQ(CParser("typedef struct tagS1 {int32 i;} S1; struct S2{ S1 sValue1[2] = {{10}, {20}};}; struct S3{S1 sValue2 = S2.sValue1[1]; };").Parse().Root()->FindValueVariant("S3::sValue2.i").Get(), 20); } TEST_F(CParserStructTest, DefinitionAndVariableDeclaration) { // struct {...} ; --> struct definition and variable declaration EXPECT_TRUE(CParser("struct S{struct S8 {int32 i;} s8Value;};").Parse().Root()->Find("S::s8Value")); } TEST_F(CParserStructTest, DefinitionWithInheritanceAndVariableDeclaration) { // struct : {...} ; --> struct definition with inheritance and variable declaration EXPECT_TRUE(CParser("struct S{struct S9base {int32 i;}; struct S9 : S9base {int32 j;} s9Value;};").Parse().Root()->Find("S::s9Value")); } TEST_F(CParserStructTest, DefinitionAndVariableDeclarationAndAssignment) { // struct {...} = {...}; --> struct definition, variable declaration and assignment EXPECT_TRUE(CParser("struct S{struct S10 {int32 i;} s10Value = {10};};").Parse().Root()->Find("S::s10Value")); } TEST_F(CParserStructTest, DefinitionWithInheritanceAndVariableDeclarationAndAssignment) { // struct : {...} = {...}; --> struct definition with inheritance, variable declaration and assignment EXPECT_TRUE(CParser("struct S{struct S11base {int32 i;}; struct S11 : S11base {int32 j;} s11Value = {{10}, 10};};").Parse().Root()->Find("S::s11Value")); EXPECT_TRUE(CParser("struct S{struct S11base {int32 i;}; struct S11 : S11base {} s11Value = {{10}};};").Parse().Root()->Find("S::s11Value")); } TEST_F(CParserStructTest, UnnamedDefinitionAndVariableDeclaration) { // struct {...} ; --> unnamed struct definition and variable declaration // NOTE 11.04.2025: Not allowed due to incompatibility in C++ standard EXPECT_THROW(CParser("struct S{struct {int32 i;} s12Value;};").Parse(), CCompileException); } TEST_F(CParserStructTest, UnnamedDefinitionWithInheritanceAndVariableDeclaration) { // struct : {...} ; --> unnamed struct definition with inheritance and variable declaration // NOTE 11.04.2025: Not allowed due to incompatibility in C++ standard EXPECT_THROW(CParser("struct S{struct S13base {int32 i;}; struct : S13base {int32 j;} s13Value;};").Parse(), CCompileException); } TEST_F(CParserStructTest, UnnamedDefinitionAndVariableDeclarationAndAssignment) { // struct {...} = {...}; --> unnamed struct definition, variable declaration and assignment // NOTE 11.04.2025: Not allowed due to incompatibility in C++ standard EXPECT_THROW(CParser("struct S{struct {int32 i;} s14Value = {10};};").Parse(), CCompileException); } TEST_F(CParserStructTest, UnnamedDefinitionWithInheritanceAndVariableDeclarationAndAssignment) { // struct : {...} = {...}; --> unnamed struct definition with inheritance, variable declaration and assignment // NOTE 11.04.2025: Not allowed due to incompatibility in C++ standard EXPECT_THROW(CParser("struct S{struct S15base {int32 i;}; struct : S15base {int32 j;} s15Value = {{10}, 10};};").Parse(), CCompileException); } TEST_F(CParserStructTest, ComplexCombinationWithStructTypedefMultiDimmensionalArrayDeclarations) { const char szCode[] = R"code( struct S { const int32 a = 2; typedef int32 intarray[a]; typedef intarray initintarray[3][1]; initintarray rgarray[4] = {{{{1,2}}, {{3,4}}, {{5,6}}}, {{{7,8}},{{9,10}}, {{a,b}}}, {{{13,14}}, {{15,16}}, {{17,18}}}, {{{19,20}},{{21,22}}, {{23,24}}} }; const int32 b = 4; }; )code"; CParser parser(szCode); EXPECT_NO_THROW(parser.Parse()); CEntityPtr ptrVar = parser.Root()->Find("S::rgarray"); ASSERT_TRUE(ptrVar); CDeclarationEntity* pVar = ptrVar->Get(); ASSERT_NE(pVar, nullptr); CValueNodePtr ptrVal = ptrVar->ValueRef(); ASSERT_TRUE(ptrVal); CArrayValueNode* pInitIntArrayVal = ptrVal->Get(); ASSERT_NE(pInitIntArrayVal, nullptr); EXPECT_EQ(pInitIntArrayVal->GetSize(), 4); CValueNodePtr ptrIntArrayVal = (*pInitIntArrayVal)[3]; ASSERT_TRUE(ptrIntArrayVal); CArrayValueNode* pIntArrayVal = ptrIntArrayVal->Get(); ASSERT_NE(pIntArrayVal, nullptr); EXPECT_EQ(pIntArrayVal->GetSize(), 3); CValueNodePtr ptrIntArrayVal_2 = (*pIntArrayVal)[2]; ASSERT_TRUE(ptrIntArrayVal_2); CArrayValueNode* pIntArrayVal_2 = ptrIntArrayVal_2->Get(); ASSERT_NE(pIntArrayVal_2, nullptr); EXPECT_EQ(pIntArrayVal_2->GetSize(), 1); CValueNodePtr ptrIntArrayVal_3 = (*pIntArrayVal_2)[0]; ASSERT_TRUE(ptrIntArrayVal_3); CArrayValueNode* pIntArrayVal_3 = ptrIntArrayVal_3->Get(); ASSERT_NE(pIntArrayVal_3, nullptr); EXPECT_EQ(pIntArrayVal_3->GetSize(), 2); CValueNodePtr ptrIntVal = (*pIntArrayVal_3)[1]; ASSERT_TRUE(ptrIntVal); CSimpleTypeValueNode* pIntVal = ptrIntVal->Get(); ASSERT_NE(pIntVal, nullptr); EXPECT_EQ(pIntVal->Variant().Get(), 24); } TEST_F(CParserStructTest, StringAssignmentInStruct) { // Tests bug fix: #380904 const char szCode[] = R"code( struct SStringTest { string ssVal = "hello"; u8string ss8Val = u8"hello"; }; )code"; CParser parser(szCode); EXPECT_NO_THROW(parser.Parse()); }