@@ -1050,38 +1050,71 @@ bool ByteCodeExprGen<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
1050
1050
if (T->isRecordType ()) {
1051
1051
const Record *R = getRecord (E->getType ());
1052
1052
1053
- if (Inits.size () == 1 && E->getType () == Inits[0 ]->getType ()) {
1053
+ if (Inits.size () == 1 && E->getType () == Inits[0 ]->getType ())
1054
1054
return this ->visitInitializer (Inits[0 ]);
1055
+
1056
+ auto initPrimitiveField = [=](const Record::Field *FieldToInit,
1057
+ const Expr *Init, PrimType T) -> bool {
1058
+ if (!this ->visit (Init))
1059
+ return false ;
1060
+
1061
+ if (FieldToInit->isBitField ()) {
1062
+ if (!this ->emitInitBitField (T, FieldToInit, E))
1063
+ return false ;
1064
+ } else {
1065
+ if (!this ->emitInitField (T, FieldToInit->Offset , E))
1066
+ return false ;
1067
+ }
1068
+ return this ->emitPopPtr (E);
1069
+ };
1070
+
1071
+ auto initCompositeField = [=](const Record::Field *FieldToInit,
1072
+ const Expr *Init) -> bool {
1073
+ // Non-primitive case. Get a pointer to the field-to-initialize
1074
+ // on the stack and recurse into visitInitializer().
1075
+ if (!this ->emitGetPtrField (FieldToInit->Offset , Init))
1076
+ return false ;
1077
+ if (!this ->visitInitializer (Init))
1078
+ return false ;
1079
+ return this ->emitPopPtr (E);
1080
+ };
1081
+
1082
+ if (R->isUnion ()) {
1083
+ assert (Inits.size () == 1 );
1084
+ const Expr *Init = Inits[0 ];
1085
+ const FieldDecl *FToInit = nullptr ;
1086
+ if (const auto *ILE = dyn_cast<InitListExpr>(E))
1087
+ FToInit = ILE->getInitializedFieldInUnion ();
1088
+ else
1089
+ FToInit = cast<CXXParenListInitExpr>(E)->getInitializedFieldInUnion ();
1090
+
1091
+ if (!this ->emitDupPtr (E))
1092
+ return false ;
1093
+
1094
+ const Record::Field *FieldToInit = R->getField (FToInit);
1095
+ if (std::optional<PrimType> T = classify (Init)) {
1096
+ if (!initPrimitiveField (FieldToInit, Init, *T))
1097
+ return false ;
1098
+ } else {
1099
+ if (!initCompositeField (FieldToInit, Init))
1100
+ return false ;
1101
+ }
1102
+ return this ->emitFinishInit (E);
1055
1103
}
1056
1104
1105
+ assert (!R->isUnion ());
1057
1106
unsigned InitIndex = 0 ;
1058
1107
for (const Expr *Init : Inits) {
1059
1108
// Skip unnamed bitfields.
1060
1109
while (InitIndex < R->getNumFields () &&
1061
1110
R->getField (InitIndex)->Decl ->isUnnamedBitField ())
1062
1111
++InitIndex;
1063
-
1064
- // Potentially skip ahead. This is especially relevant in unions.
1065
- if (const auto *D = dyn_cast<CXXDefaultInitExpr>(Init))
1066
- InitIndex = D->getField ()->getFieldIndex ();
1067
-
1068
1112
if (!this ->emitDupPtr (E))
1069
1113
return false ;
1070
1114
1071
1115
if (std::optional<PrimType> T = classify (Init)) {
1072
1116
const Record::Field *FieldToInit = R->getField (InitIndex);
1073
- if (!this ->visit (Init))
1074
- return false ;
1075
-
1076
- if (FieldToInit->isBitField ()) {
1077
- if (!this ->emitInitBitField (*T, FieldToInit, E))
1078
- return false ;
1079
- } else {
1080
- if (!this ->emitInitField (*T, FieldToInit->Offset , E))
1081
- return false ;
1082
- }
1083
-
1084
- if (!this ->emitPopPtr (E))
1117
+ if (!initPrimitiveField (FieldToInit, Init, *T))
1085
1118
return false ;
1086
1119
++InitIndex;
1087
1120
} else {
@@ -1099,21 +1132,13 @@ bool ByteCodeExprGen<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
1099
1132
// into the Record's fields.
1100
1133
} else {
1101
1134
const Record::Field *FieldToInit = R->getField (InitIndex);
1102
- // Non-primitive case. Get a pointer to the field-to-initialize
1103
- // on the stack and recurse into visitInitializer().
1104
- if (!this ->emitGetPtrField (FieldToInit->Offset , Init))
1105
- return false ;
1106
-
1107
- if (!this ->visitInitializer (Init))
1108
- return false ;
1109
-
1110
- if (!this ->emitPopPtr (E))
1135
+ if (!initCompositeField (FieldToInit, Init))
1111
1136
return false ;
1112
1137
++InitIndex;
1113
1138
}
1114
1139
}
1115
1140
}
1116
- return true ;
1141
+ return this -> emitFinishInit (E) ;
1117
1142
}
1118
1143
1119
1144
if (T->isArrayType ()) {
@@ -1137,7 +1162,7 @@ bool ByteCodeExprGen<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
1137
1162
}
1138
1163
}
1139
1164
1140
- return true ;
1165
+ return this -> emitFinishInit (E) ;
1141
1166
}
1142
1167
1143
1168
if (const auto *ComplexTy = E->getType ()->getAs <ComplexType>()) {
0 commit comments