// union <union_identifier> <decl_identifier>; --> union variable declaration
EXPECT_TRUE(CParser("struct S{union U6 switch(int32){case 10: int32 i;}; union U6 u6Value;};").Parse().Root()->Find("S::u6Value"));
}
TEST_F(CParserUnionTest,IntegralSwitchType)
{
// Use any type of integral value in case
EXPECT_TRUE(CParser("union U2 switch(boolean) { case true: int32 i; case false: int64 j; };").Parse().Root()->Find("U2"));
EXPECT_TRUE(CParser("union U2 switch(int8) { case 10: int32 i; case -10: int64 j; };").Parse().Root()->Find("U2"));
EXPECT_TRUE(CParser("union U2 switch(int16) { case 10: int32 i; case -10: int64 j; };").Parse().Root()->Find("U2"));
EXPECT_TRUE(CParser("union U2 switch(int32) { case 10: int32 i; case -10: int64 j; };").Parse().Root()->Find("U2"));
EXPECT_TRUE(CParser("union U2 switch(int64) { case 10: int32 i; case -10: int64 j; };").Parse().Root()->Find("U2"));
EXPECT_TRUE(CParser("union U2 switch(uint8) { case 10: int32 i; case 20: int64 j; };").Parse().Root()->Find("U2"));
EXPECT_TRUE(CParser("union U2 switch(uint16) { case 10: int32 i; case 20: int64 j; };").Parse().Root()->Find("U2"));
EXPECT_TRUE(CParser("union U2 switch(uint32) { case 10: int32 i; case 20: int64 j; };").Parse().Root()->Find("U2"));
EXPECT_TRUE(CParser("union U2 switch(uint64) { case 10: int32 i; case 20: int64 j; };").Parse().Root()->Find("U2"));
EXPECT_TRUE(CParser("union U2 switch(char) { case 'a': int32 i; case 'b': int64 j; };").Parse().Root()->Find("U2"));
EXPECT_TRUE(CParser("union U2 switch(char16) { case u'a': int32 i; case u'b': int64 j; };").Parse().Root()->Find("U2"));
EXPECT_TRUE(CParser("union U2 switch(char32) { case U'a': int32 i; case U'A': int64 j; };").Parse().Root()->Find("U2"));
EXPECT_TRUE(CParser("union U2 switch(wchar) { case L'a': int32 i; case L'b': int64 j; };").Parse().Root()->Find("U2"));
// Use other type of value in case
EXPECT_THROW(CParser("union U2 switch(float) { case 0.0: int32 i; case 1.1: int64 j; };").Parse(),CCompileException);
}
TEST_F(CParserUnionTest,IntegralTypeMixing)
{
// Use const values in case
EXPECT_TRUE(CParser("const int32 iVal1 = 10, iVal2 = 20; union U2 switch(int32) { case iVal1: int32 i; case iVal2: int64 j; };").Parse().Root()->Find("U2"));
// Use calculated const value in case
EXPECT_TRUE(CParser("const int32 iVal1 = 10 + 10, iVal2 = 30; union U2 switch(int32) { case iVal1: int32 i; case iVal2: int64 j; };").Parse().Root()->Find("U2"));
// Use calculated value in case
EXPECT_TRUE(CParser("const int32 iVal1 = 10; union U2 switch(int32) { case iVal1: int32 i; case iVal1 + 1: int64 j; };").Parse().Root()->Find("U2"));
// Use declaration of const values following the switch case
EXPECT_TRUE(CParser("union U2 switch(int32) { case iVal1: int32 i; case iVal2: int64 j; }; const int32 iVal1 = 10, iVal2 = 20;").Parse().Root()->Find("U2"));
// Use typedef value in case
EXPECT_TRUE(CParser("typedef int32 TCaseInt; const TCaseInt iVal1 = 10, iVal2 = 20; union U2 switch(TCaseInt) { case iVal1: int32 i; case iVal2: int64 j; };").Parse().Root()->Find("U2"));
EXPECT_TRUE(CParser("typedef int32 TCaseInt; const int32 iVal1 = 10, iVal2 = 20; union U2 switch(TCaseInt) { case iVal1: int32 i; case iVal2: int64 j; };").Parse().Root()->Find("U2"));
// Use mixed const values in case
EXPECT_TRUE(CParser("const int8 iVal1 = 10; const int64 iVal2 = 20; union U2 switch(int32) { case iVal1: int32 i; case iVal2: int64 j; };").Parse().Root()->Find("U2"));
}
TEST_F(CParserUnionTest,EnumSwitchtype)
{
// Use enum values in case
EXPECT_TRUE(CParser("enum EValues {ten, twenty}; union U2 switch(EValues) { case ten: int32 i; case twenty: int64 j; };").Parse().Root()->Find("U2"));
// Use definition of enum following the switch case
EXPECT_THROW(CParser("union U2 switch(EValues) { case ten: int32 i; case twenty: int64 j; }; enum EValues {ten, twenty};").Parse(),CCompileException);
EXPECT_TRUE(CParser("enum EValues; union U2 switch(EValues) { case ten: int32 i; case twenty: int64 j; }; enum EValues {ten, twenty};").Parse().Root()->Find("U2"));
}
TEST_F(CParserUnionTest,DuplicateCaseLabel)
{
// Use values in case
EXPECT_THROW(CParser("union U2 switch(int32) { case 10: int32 i; case 10: int64 j; };").Parse(),CCompileException);
// Use const values in case
EXPECT_THROW(CParser("const int32 iVal1 = 10, iVal2 = 10; union U2 switch(int32) { case iVal1: int32 i; case iVal2: int64 j; };").Parse(),CCompileException);
// Use enum values in case
EXPECT_THROW(CParser("enum EValues {ten, twenty}; union U2 switch(EValues) { case ten: int32 i; case ten: int64 j; };").Parse(),CCompileException);
// Duplicate default
EXPECT_THROW(CParser("union U2 switch(int32) { default: double d; case 10: int32 i; case 20: int64 j; default: float f; };").Parse(),CCompileException);
}
TEST_F(CParserUnionTest,DuplicateVariables)
{
EXPECT_THROW(CParser("union U2 switch(int32) { case 10: int32 i; case 20: int64 j; case 30: int32 i; };").Parse(),CCompileException);
EXPECT_THROW(CParser("union U2 switch(int32) { case 10: int32 i; case 20: int64 j; case 30: int64 i; };").Parse(),CCompileException);
EXPECT_THROW(CParser("union U2 switch(int32) { case 10: int32 i; case 20: int64 j; default: int32 i; };").Parse(),CCompileException);
EXPECT_THROW(CParser("union U2 switch(int32) { case 10: int32 i; case 20: int64 j; default: int64 i; };").Parse(),CCompileException);
}
TEST_F(CParserUnionTest,MemberSwitchLabelType)
{
// Use const value in switch label
EXPECT_THROW(CParser("const int32 iVal = 10; union U2 switch(iVal) { case 10: int32 i; case 20: int64 j; };").Parse(),CCompileException);
// Use value in switch label
EXPECT_TRUE(CParser("struct S {int32 iVal = 10; union U2 switch(iVal) { case 10: int32 i; case 20: int64 j; } u2Var;};").Parse().Root()->Find("S::u2Var"));
// Use succeeding declared value in switch label
EXPECT_TRUE(CParser("struct S {union U2 switch(iVal) { case 10: int32 i; case 20: int64 j; }u2Var; int32 iVal = 10;};").Parse().Root()->Find("S::u2Var"));
// Use enum values in switch label
EXPECT_TRUE(CParser("struct S {enum EValues {ten, twenty}; union U2 switch(EValues) { case ten: int32 i; case twenty: int64 j; } u2Var;};").Parse().Root()->Find("S::u2Var"));
}
TEST_F(CParserUnionTest,UnnamedUnionDefinition)
{
// Declaration of unnamed union at global scope is not allowed.