@@ -1111,29 +1111,6 @@ const Type* ImplementationVisitor::Visit(ReturnStatement* stmt) {
11111111 return TypeOracle::GetNeverType ();
11121112}
11131113
1114- VisitResult ImplementationVisitor::TemporaryUninitializedStruct (
1115- const StructType* struct_type, const std::string& reason) {
1116- StackRange range = assembler ().TopRange (0 );
1117- for (const Field& f : struct_type->fields ()) {
1118- if (const StructType* struct_type =
1119- StructType::DynamicCast (f.name_and_type .type )) {
1120- range.Extend (
1121- TemporaryUninitializedStruct (struct_type, reason).stack_range ());
1122- } else {
1123- std::string descriptor = " uninitialized field '" + f.name_and_type .name +
1124- " ' declared at " + PositionAsString (f.pos ) +
1125- " (" + reason + " )" ;
1126- TypeVector lowered_types = LowerType (f.name_and_type .type );
1127- for (const Type* type : lowered_types) {
1128- assembler ().Emit (PushUninitializedInstruction{
1129- TypeOracle::GetTopType (descriptor, type)});
1130- }
1131- range.Extend (assembler ().TopRange (lowered_types.size ()));
1132- }
1133- }
1134- return VisitResult (struct_type, range);
1135- }
1136-
11371114VisitResult ImplementationVisitor::Visit (TryLabelExpression* expr) {
11381115 size_t parameter_count = expr->label_block ->parameters .names .size ();
11391116 std::vector<VisitResult> parameters;
@@ -1212,15 +1189,38 @@ VisitResult ImplementationVisitor::Visit(StatementExpression* expr) {
12121189 return VisitResult{Visit (expr->statement ), assembler ().TopRange (0 )};
12131190}
12141191
1192+ void ImplementationVisitor::CheckInitializersWellformed (
1193+ const std::string& aggregate_name,
1194+ const std::vector<Field>& aggregate_fields,
1195+ const std::vector<NameAndExpression>& initializers,
1196+ bool ignore_first_field) {
1197+ size_t fields_offset = ignore_first_field ? 1 : 0 ;
1198+ size_t fields_size = aggregate_fields.size () - fields_offset;
1199+ for (size_t i = 0 ; i < std::min (fields_size, initializers.size ()); i++) {
1200+ const std::string& field_name =
1201+ aggregate_fields[i + fields_offset].name_and_type .name ;
1202+ Identifier* found_name = initializers[i].name ;
1203+ if (field_name != found_name->value ) {
1204+ Error (" Expected field name \" " , field_name, " \" instead of \" " ,
1205+ found_name->value , " \" " )
1206+ .Position (found_name->pos )
1207+ .Throw ();
1208+ }
1209+ }
1210+ if (fields_size != initializers.size ()) {
1211+ ReportError (" expected " , fields_size, " initializers for " , aggregate_name,
1212+ " found " , initializers.size ());
1213+ }
1214+ }
1215+
12151216InitializerResults ImplementationVisitor::VisitInitializerResults (
1216- const AggregateType* current_aggregate ,
1217+ const ClassType* class_type ,
12171218 const std::vector<NameAndExpression>& initializers) {
12181219 InitializerResults result;
12191220 for (const NameAndExpression& initializer : initializers) {
12201221 result.names .push_back (initializer.name );
12211222 Expression* e = initializer.expression ;
1222- const Field& field =
1223- current_aggregate->LookupField (initializer.name ->value );
1223+ const Field& field = class_type->LookupField (initializer.name ->value );
12241224 auto field_index = field.index ;
12251225 if (SpreadExpression* s = SpreadExpression::DynamicCast (e)) {
12261226 if (!field_index) {
@@ -1239,54 +1239,30 @@ InitializerResults ImplementationVisitor::VisitInitializerResults(
12391239 return result;
12401240}
12411241
1242- size_t ImplementationVisitor::InitializeAggregateHelper (
1243- const AggregateType* aggregate_type , VisitResult allocate_result,
1242+ void ImplementationVisitor::InitializeClass (
1243+ const ClassType* class_type , VisitResult allocate_result,
12441244 const InitializerResults& initializer_results) {
1245- const ClassType* current_class = ClassType::DynamicCast (aggregate_type);
1246- size_t current = 0 ;
1247- if (current_class) {
1248- const ClassType* super = current_class->GetSuperClass ();
1249- if (super) {
1250- current = InitializeAggregateHelper (super, allocate_result,
1251- initializer_results);
1252- }
1245+ if (const ClassType* super = class_type->GetSuperClass ()) {
1246+ InitializeClass (super, allocate_result, initializer_results);
12531247 }
12541248
1255- for (Field f : aggregate_type->fields ()) {
1256- if (current == initializer_results.field_value_map .size ()) {
1257- ReportError (" insufficient number of initializers for " ,
1258- aggregate_type->name ());
1259- }
1249+ for (Field f : class_type->fields ()) {
12601250 VisitResult current_value =
12611251 initializer_results.field_value_map .at (f.name_and_type .name );
1262- Identifier* fieldname = initializer_results.names [current];
1263- if (fieldname->value != f.name_and_type .name ) {
1264- CurrentSourcePosition::Scope scope (fieldname->pos );
1265- ReportError (" Expected fieldname \" " , f.name_and_type .name ,
1266- " \" instead of \" " , fieldname->value , " \" " );
1267- }
1268- if (aggregate_type->IsClassType ()) {
1269- if (f.index ) {
1270- InitializeFieldFromSpread (allocate_result, f, initializer_results);
1271- } else {
1272- allocate_result.SetType (aggregate_type);
1273- GenerateCopy (allocate_result);
1274- assembler ().Emit (CreateFieldReferenceInstruction{
1275- ClassType::cast (aggregate_type), f.name_and_type .name });
1276- VisitResult heap_reference (
1277- TypeOracle::GetReferenceType (f.name_and_type .type ),
1278- assembler ().TopRange (2 ));
1279- GenerateAssignToLocation (
1280- LocationReference::HeapReference (heap_reference), current_value);
1281- }
1252+ if (f.index ) {
1253+ InitializeFieldFromSpread (allocate_result, f, initializer_results);
12821254 } else {
1283- LocationReference struct_field_ref = LocationReference::VariableAccess (
1284- ProjectStructField (allocate_result, f.name_and_type .name ));
1285- GenerateAssignToLocation (struct_field_ref, current_value);
1255+ allocate_result.SetType (class_type);
1256+ GenerateCopy (allocate_result);
1257+ assembler ().Emit (CreateFieldReferenceInstruction{
1258+ ClassType::cast (class_type), f.name_and_type .name });
1259+ VisitResult heap_reference (
1260+ TypeOracle::GetReferenceType (f.name_and_type .type ),
1261+ assembler ().TopRange (2 ));
1262+ GenerateAssignToLocation (LocationReference::HeapReference (heap_reference),
1263+ current_value);
12861264 }
1287- ++current;
12881265 }
1289- return current;
12901266}
12911267
12921268void ImplementationVisitor::InitializeFieldFromSpread (
@@ -1305,17 +1281,6 @@ void ImplementationVisitor::InitializeFieldFromSpread(
13051281 {field.aggregate , index.type , iterator.type ()});
13061282}
13071283
1308- void ImplementationVisitor::InitializeAggregate (
1309- const AggregateType* aggregate_type, VisitResult allocate_result,
1310- const InitializerResults& initializer_results) {
1311- size_t consumed_initializers = InitializeAggregateHelper (
1312- aggregate_type, allocate_result, initializer_results);
1313- if (consumed_initializers != initializer_results.field_value_map .size ()) {
1314- ReportError (" more initializers than fields present in " ,
1315- aggregate_type->name ());
1316- }
1317- }
1318-
13191284VisitResult ImplementationVisitor::AddVariableObjectSize (
13201285 VisitResult object_size, const ClassType* current_class,
13211286 const InitializerResults& initializer_results) {
@@ -1398,6 +1363,11 @@ VisitResult ImplementationVisitor::Visit(NewExpression* expr) {
13981363 initializer_results.field_value_map [map_field.name_and_type .name ] =
13991364 object_map;
14001365 }
1366+
1367+ CheckInitializersWellformed (class_type->name (),
1368+ class_type->ComputeAllFields (),
1369+ expr->initializers , !class_type->IsExtern ());
1370+
14011371 Arguments size_arguments;
14021372 size_arguments.parameters .push_back (object_map);
14031373 VisitResult object_size = GenerateCall (" %GetAllocationBaseSize" ,
@@ -1412,7 +1382,7 @@ VisitResult ImplementationVisitor::Visit(NewExpression* expr) {
14121382 GenerateCall (" %Allocate" , allocate_arguments, {class_type}, false );
14131383 DCHECK (allocate_result.IsOnStack ());
14141384
1415- InitializeAggregate (class_type, allocate_result, initializer_results);
1385+ InitializeClass (class_type, allocate_result, initializer_results);
14161386
14171387 return stack_scope.Yield (allocate_result);
14181388}
@@ -1802,24 +1772,36 @@ VisitResult ImplementationVisitor::GenerateCopy(const VisitResult& to_copy) {
18021772
18031773VisitResult ImplementationVisitor::Visit (StructExpression* expr) {
18041774 StackScope stack_scope (this );
1805- const Type* raw_type = TypeVisitor::ComputeType (expr->type );
1806- if (!raw_type->IsStructType ()) {
1807- ReportError (*raw_type, " is not a struct but used like one" );
1808- }
18091775
1810- const StructType* struct_type = StructType::cast (raw_type);
1776+ auto & initializers = expr->initializers ;
1777+ std::vector<VisitResult> values;
1778+ std::vector<const Type*> term_argument_types;
1779+ values.reserve (initializers.size ());
1780+ term_argument_types.reserve (initializers.size ());
18111781
1812- InitializerResults initialization_results =
1813- ImplementationVisitor::VisitInitializerResults (struct_type,
1814- expr->initializers );
1782+ // Compute values and types of all initializer arguments
1783+ for (const NameAndExpression& initializer : initializers) {
1784+ VisitResult value = Visit (initializer.expression );
1785+ values.push_back (value);
1786+ term_argument_types.push_back (value.type ());
1787+ }
18151788
1816- // Push uninitialized 'this'
1817- VisitResult result = TemporaryUninitializedStruct (
1818- struct_type, " it's not initialized in the struct " + struct_type->name ());
1789+ // Compute and check struct type from given struct name and argument types
1790+ const StructType* struct_type = TypeVisitor::ComputeTypeForStructExpression (
1791+ expr->type , term_argument_types);
1792+ CheckInitializersWellformed (struct_type->name (), struct_type->fields (),
1793+ initializers);
18191794
1820- InitializeAggregate (struct_type, result, initialization_results);
1795+ // Implicitly convert values and thereby build the struct on the stack
1796+ StackRange struct_range = assembler ().TopRange (0 );
1797+ auto & fields = struct_type->fields ();
1798+ for (size_t i = 0 ; i < values.size (); i++) {
1799+ values[i] =
1800+ GenerateImplicitConvert (fields[i].name_and_type .type , values[i]);
1801+ struct_range.Extend (values[i].stack_range ());
1802+ }
18211803
1822- return stack_scope.Yield (result );
1804+ return stack_scope.Yield (VisitResult (struct_type, struct_range) );
18231805}
18241806
18251807LocationReference ImplementationVisitor::GetLocationReference (
0 commit comments