@@ -252,33 +252,81 @@ std::shared_ptr<StructValueView> KTestObjectParser::structView(const std::vector
252
252
size_t offsetInBits,
253
253
types::PointerUsage usage) {
254
254
std::vector<InitReference> tmpInitReferences;
255
- return structView (byteArray, curStruct, offsetInBits, usage, {}, " " , {}, tmpInitReferences);
255
+ return structView (byteArray, curStruct, offsetInBits, usage, {}, false , " " , {}, tmpInitReferences);
256
256
}
257
257
258
258
std::shared_ptr<StructValueView> KTestObjectParser::structView (const std::vector<char > &byteArray,
259
259
const StructInfo &curStruct,
260
260
size_t offsetInBits,
261
261
PointerUsage usage,
262
262
const std::optional<const Tests::MethodDescription> &testingMethod,
263
+ const bool anonymousField,
263
264
const std::string &name,
264
265
const MapAddressName &fromAddressToName,
265
266
std::vector<InitReference> &initReferences) {
266
267
std::vector<std::shared_ptr<AbstractValueView>> subViews;
267
268
269
+ size_t fieldIndexToInitUnion = SIZE_MAX;
270
+ size_t sizeOfFieldToInitUnion = 0 ;
271
+ size_t prevFieldEndOffset = offsetInBits;
272
+ size_t structEndOffset = offsetInBits + curStruct.size ;
273
+ size_t fieldIndex = 0 ;
274
+ bool dirtyInitializedStruct = false ;
268
275
for (const auto &field: curStruct.fields ) {
276
+ bool dirtyInitializedField = false ;
269
277
size_t fieldLen = typesHandler.typeSize (field.type );
270
- size_t fieldOffset = offsetInBits + field.offset ;
278
+ size_t fieldStartOffset = offsetInBits + field.offset ;
279
+ size_t fieldEndOffset = fieldStartOffset + fieldLen;
280
+ if (curStruct.subType == types::SubType::Union) {
281
+ prevFieldEndOffset = offsetInBits;
282
+ }
283
+
284
+ auto dirtyCheck = [&](int i) {
285
+ if (i >= byteArray.size ()) {
286
+ LOG_S (ERROR) << " Bad type size info: " << field.name << " index: " << fieldIndex;
287
+ } else if (byteArray[i] == 0 ) {
288
+ return false ;
289
+ }
290
+ // the field cannot init the union in this state
291
+ dirtyInitializedField = true ;
292
+ return true ;
293
+ };
294
+
295
+ if (prevFieldEndOffset < fieldStartOffset) {
296
+ // check an alignment gap
297
+ for (int i = prevFieldEndOffset/8 ; i < fieldStartOffset/8 ; ++i) {
298
+ if (dirtyCheck (i)) {
299
+ break ;
300
+ }
301
+ }
302
+ }
303
+ if (!dirtyInitializedField && curStruct.subType == types::SubType::Union) {
304
+ // check the rest of the union
305
+ for (int i = fieldEndOffset/8 ; i < structEndOffset/8 ; ++i) {
306
+ if (dirtyCheck (i)) {
307
+ break ;
308
+ }
309
+ }
310
+ }
271
311
272
312
switch (typesHandler.getTypeKind (field.type )) {
273
313
case TypeKind::STRUCT_LIKE:
274
- subViews.push_back (structView (byteArray, typesHandler.getStructInfo (field.type ), fieldOffset, usage, testingMethod,
275
- PrinterUtils::getFieldAccess (name, field), fromAddressToName, initReferences));
314
+ {
315
+ auto sv = structView (byteArray, typesHandler.getStructInfo (field.type ),
316
+ fieldStartOffset, usage, testingMethod, field.anonymous ,
317
+ PrinterUtils::getFieldAccess (name, field), fromAddressToName,
318
+ initReferences);
319
+ dirtyInitializedField |= sv->isDirtyInit ();
320
+ subViews.push_back (sv);
321
+ }
276
322
break ;
277
323
case TypeKind::ENUM:
278
- subViews.push_back (enumView (byteArray, typesHandler.getEnumInfo (field.type ), fieldOffset, fieldLen));
324
+ subViews.push_back (enumView (byteArray, typesHandler.getEnumInfo (field.type ),
325
+ fieldStartOffset, fieldLen));
279
326
break ;
280
327
case TypeKind::PRIMITIVE:
281
- subViews.push_back (primitiveView (byteArray, field.type .baseTypeObj (), fieldOffset,
328
+ subViews.push_back (primitiveView (byteArray, field.type .baseTypeObj (),
329
+ fieldStartOffset,
282
330
std::min (field.size , fieldLen)));
283
331
break ;
284
332
case TypeKind::ARRAY: {
@@ -296,21 +344,22 @@ std::shared_ptr<StructValueView> KTestObjectParser::structView(const std::vector
296
344
}
297
345
if (onlyArrays) {
298
346
size *= typesHandler.typeSize (field.type .baseTypeObj ());
299
- subViews.push_back (multiArrayView (byteArray, field.type , size,
300
- fieldOffset, usage));
347
+ subViews.push_back (multiArrayView (byteArray, field.type , size, fieldStartOffset, usage));
301
348
} else {
302
349
std::vector<std::shared_ptr<AbstractValueView>> nullViews (
303
350
size, std::make_shared<JustValueView>(PrinterUtils::C_NULL));
304
351
subViews.push_back (std::make_shared<ArrayValueView>(nullViews));
305
352
}
306
353
} else {
307
- auto view = arrayView (byteArray, field.type .baseTypeObj (), fieldLen, fieldOffset, usage);
354
+ auto view = arrayView (byteArray, field.type .baseTypeObj (), fieldLen,
355
+ fieldStartOffset, usage);
308
356
subViews.push_back (view);
309
357
}
310
358
}
311
359
break ;
312
360
case TypeKind::OBJECT_POINTER: {
313
- std::string res = readBytesAsValueForType (byteArray, PointerWidthType, fieldOffset,
361
+ std::string res = readBytesAsValueForType (byteArray, PointerWidthType,
362
+ fieldStartOffset,
314
363
PointerWidthSizeInBits);
315
364
subViews.push_back (getLazyPointerView (fromAddressToName, initReferences,
316
365
PrinterUtils::getFieldAccess (name, field), res, field.type ));
@@ -330,15 +379,35 @@ std::shared_ptr<StructValueView> KTestObjectParser::structView(const std::vector
330
379
LOG_S (ERROR) << message;
331
380
throw NoSuchTypeException (message);
332
381
}
382
+
383
+ if (!dirtyInitializedField && sizeOfFieldToInitUnion < fieldLen) {
384
+ fieldIndexToInitUnion = fieldIndex;
385
+ sizeOfFieldToInitUnion = fieldLen;
386
+ } else {
387
+ dirtyInitializedStruct = true ;
388
+ }
389
+ prevFieldEndOffset = fieldEndOffset;
390
+ ++fieldIndex;
333
391
}
334
392
335
393
std::optional<std::string> entryValue;
336
- if (curStruct.hasAnonymousStructOrUnion ) {
337
- auto bytesType = types::Type::createSimpleTypeFromName (" utbot_byte" );
338
- const std::shared_ptr<AbstractValueView> rawDataView = arrayView (byteArray, bytesType, curStruct.size , offsetInBits, usage);
339
- entryValue = PrinterUtils::convertBytesToUnion (curStruct.name , rawDataView->getEntryValue (nullptr ));
394
+ if (curStruct.subType == types::SubType::Union) {
395
+ if (fieldIndexToInitUnion == SIZE_MAX && !curStruct.name .empty ()) {
396
+ // init by memory copy
397
+ entryValue = PrinterUtils::convertBytesToUnion (
398
+ curStruct.name ,
399
+ arrayView (byteArray,
400
+ types::Type::createSimpleTypeFromName (" utbot_byte" ),
401
+ curStruct.size ,
402
+ offsetInBits, usage)->getEntryValue (nullptr ));
403
+ dirtyInitializedStruct = false ;
404
+ }
405
+ if (fieldIndexToInitUnion != SIZE_MAX) {
406
+ dirtyInitializedStruct = false ;
407
+ }
340
408
}
341
- return std::make_shared<StructValueView>(curStruct, subViews, entryValue);
409
+ return std::make_shared<StructValueView>(curStruct, subViews, entryValue,
410
+ anonymousField, dirtyInitializedStruct, fieldIndexToInitUnion);
342
411
}
343
412
344
413
std::string KTestObjectParser::primitiveCharView (const types::Type &type, std::string value) {
@@ -962,7 +1031,7 @@ std::shared_ptr<AbstractValueView> KTestObjectParser::testParameterView(
962
1031
switch (typesHandler.getTypeKind (paramType)) {
963
1032
case TypeKind::STRUCT_LIKE:
964
1033
return structView (rawData, typesHandler.getStructInfo (paramType), 0 ,
965
- usage, testingMethod, param.varName , fromAddressToName, initReferences);
1034
+ usage, testingMethod, false , param.varName , fromAddressToName, initReferences);
966
1035
case TypeKind::ENUM:
967
1036
return enumView (rawData, typesHandler.getEnumInfo (paramType), 0 , SizeUtils::bytesToBits (rawData.size ()));
968
1037
case TypeKind::PRIMITIVE:
0 commit comments