Skip to content

Commit ca3734f

Browse files
authored
Not support anonymous union in struct #317 (#391)
#317 Need support for anonymous union in struct - better tests for union printer - less divergent between struct and union - fix for Syntax_Test.Union_With_Pointer_Test - refactoring of StructView
1 parent 206f1d5 commit ca3734f

25 files changed

+370
-673
lines changed

server/src/Server.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,8 +420,9 @@ Status Server::TestsGenServiceImpl::provideLoggingCallbacks(
420420
* 1. Using gRPC async API
421421
* 2. Issuing a request from UTBot to a specific client on every log entry.
422422
*/
423+
using namespace std::chrono_literals;
423424
while (holdLockFlag[callbackName].exchange(true, std::memory_order_acquire)) {
424-
std::this_thread::yield();
425+
std::this_thread::sleep_for(100ms);
425426
}
426427
loguru::remove_callback(callbackName.c_str());
427428
if (openFiles) {

server/src/Tests.cpp

Lines changed: 54 additions & 156 deletions
Large diffs are not rendered by default.

server/src/Tests.h

Lines changed: 23 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,6 @@ namespace tests {
118118
return this->subViews;
119119
};
120120

121-
122121
protected:
123122
explicit AbstractValueView(std::vector<std::shared_ptr<AbstractValueView>> subViews) : subViews(std::move(subViews)) {}
124123

@@ -219,13 +218,11 @@ namespace tests {
219218
* Representation of struct value. It's value is stored as a string. Subviews of StructValueView are its fields.
220219
*/
221220
struct StructValueView : AbstractValueView {
222-
explicit StructValueView(bool _isCLike,
223-
std::vector<std::string> _fields,
224-
std::vector<std::shared_ptr<AbstractValueView>> subViews,
225-
std::optional<std::string> entryValue)
226-
: AbstractValueView(std::move(subViews)), entryValue(std::move(entryValue)),
227-
isCLike(_isCLike),
228-
fields(std::move(_fields)){
221+
explicit StructValueView(const types::StructInfo &_structInfo,
222+
std::vector<std::shared_ptr<AbstractValueView>> _subViews,
223+
std::optional<std::string> _entryValue)
224+
: AbstractValueView(std::move(_subViews)), entryValue(std::move(_entryValue)),
225+
structInfo(_structInfo){
229226
}
230227

231228
[[nodiscard]] const std::vector<std::shared_ptr<AbstractValueView>> &getSubViews() const override {
@@ -242,8 +239,12 @@ namespace tests {
242239
}
243240

244241
std::vector<std::string> entries;
242+
size_t i = 0;
245243
for (const auto &subView : subViews) {
246-
entries.push_back(subView->getEntryValue(nullptr));
244+
if (structInfo.subType == types::SubType::Struct || structInfo.longestFieldIndexForUnionInit == i) {
245+
entries.push_back(subView->getEntryValue(nullptr));
246+
}
247+
++i;
247248
}
248249

249250
return "{" + StringUtils::joinWith(entries, ", ") + "}";
@@ -259,8 +260,8 @@ namespace tests {
259260
}
260261

261262
[[nodiscard]] std::string getFieldPrefix(int i) const {
262-
std::string prefix = "." + fields[i] + " = ";
263-
if (isCLike) {
263+
std::string prefix = "." + structInfo.fields[i].name + " = ";
264+
if (structInfo.isCLike) {
264265
return prefix;
265266
}
266267
// it is not C Struct-initialization, but C++ List-initialization.
@@ -270,32 +271,13 @@ namespace tests {
270271
return "/*" + prefix + "*/";
271272
}
272273

273-
private:
274-
bool isCLike;
275-
std::vector<std::string> fields;
276-
std::optional<std::string> entryValue;
277-
};
278-
279-
/**
280-
* Representation of union.
281-
*/
282-
struct UnionValueView : AbstractValueView {
283-
public:
284-
explicit UnionValueView(const std::string &typeName,
285-
const std::shared_ptr<AbstractValueView> &rawDataView,
286-
std::vector<std::shared_ptr<AbstractValueView>,
287-
std::allocator<std::shared_ptr<AbstractValueView>>> subViews);
288-
289-
[[nodiscard]] std::string getEntryValue(printer::TestsPrinter *printer) const override {
290-
return entryValue;
291-
}
292-
293-
bool containsFPSpecialValue() override {
294-
return false;
274+
const types::StructInfo &getStructInfo() const {
275+
return structInfo;
295276
}
296277

297278
private:
298-
std::string entryValue;
279+
const types::StructInfo structInfo;
280+
std::optional<std::string> entryValue;
299281
};
300282

301283
struct InitReference {
@@ -674,33 +656,29 @@ namespace tests {
674656
std::shared_ptr<FunctionPointerView> functionPointerView(const std::string &structName,
675657
const std::string &fieldName);
676658

677-
std::shared_ptr<UnionValueView> unionView(const std::vector<char> &byteArray,
678-
types::UnionInfo &unionInfo,
679-
unsigned int offset,
680-
types::PointerUsage usage);
681-
682659
std::shared_ptr<StructValueView> structView(const std::vector<char> &byteArray,
683-
types::StructInfo &curStruct,
660+
const types::StructInfo &curStruct,
684661
unsigned int offset,
685662
types::PointerUsage usage);
686663

687664
std::shared_ptr<StructValueView> structView(const std::vector<char> &byteArray,
688-
types::StructInfo &curStruct,
665+
const types::StructInfo &curStruct,
689666
unsigned int offset,
690667
types::PointerUsage usage,
691668
const std::optional<const Tests::MethodDescription> &testingMethod,
692669
const std::string &name,
693670
const MapAddressName &fromAddressToName,
694671
std::vector<InitReference> &initReferences);
695672

673+
static std::shared_ptr<EnumValueView> enumView(const std::vector<char> &byteArray,
674+
const types::EnumInfo &enumInfo,
675+
size_t offset,
676+
size_t len);
677+
696678
std::shared_ptr<PrimitiveValueView> primitiveView(const std::vector<char> &byteArray,
697679
const types::Type &type,
698680
size_t offset,
699681
size_t len);
700-
static std::shared_ptr<EnumValueView> enumView(const std::vector<char> &byteArray,
701-
types::EnumInfo &enumInfo,
702-
size_t offset,
703-
size_t len);
704682

705683
std::string primitiveCharView(const types::Type &type, std::string value);
706684
static std::string primitiveBoolView(const std::string &value);
@@ -720,10 +698,6 @@ namespace tests {
720698
const Tests::MethodDescription &methodDescription,
721699
const std::unordered_map<std::string, types::Type>& methodNameToReturnTypeMap,
722700
const std::stringstream &traceStream);
723-
std::vector<std::shared_ptr<AbstractValueView>> collectUnionSubViews(const std::vector<char> &byteArray,
724-
const types::UnionInfo &info,
725-
unsigned int offset,
726-
types::PointerUsage usage);
727701
void processGlobalParamPreValue(Tests::TestCaseDescription &testCaseDescription,
728702
const Tests::MethodParam &globalParam,
729703
std::vector<RawKleeParam> &rawKleeParams);

server/src/printers/KleeConstraintsPrinter.cpp

Lines changed: 24 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,12 @@ KleeConstraintsPrinter::genConstraints(const std::string &name, const types::Typ
2424
state = { name, name, paramType, state.endString };
2525
genConstraintsForPointerOrArray(state);
2626
break;
27-
case TypeKind::STRUCT:
27+
case TypeKind::STRUCT_LIKE:
2828
genConstraintsForStruct(state);
2929
break;
3030
case TypeKind::ENUM:
3131
genConstraintsForEnum(state);
3232
break;
33-
case TypeKind::UNION:
34-
genConstraintsForUnion(state);
35-
break;
3633
default:
3734
genConstraintsForPrimitive(state);
3835
}
@@ -50,7 +47,7 @@ void KleeConstraintsPrinter::genConstraintsForPrimitive(const ConstraintsState &
5047
if (!cons.empty()) {
5148
strFunctionCall(PrinterUtils::KLEE_PREFER_CEX, { state.paramName, cons });
5249
} else {
53-
ss << TAB_N() << "// No constraints for " << state.curElement << NL;
50+
ss << LINE_INDENT() << "// No constraints for " << state.curElement << NL;
5451
}
5552
}
5653

@@ -67,38 +64,6 @@ void KleeConstraintsPrinter::genConstraintsForEnum(const ConstraintsState &state
6764
strFunctionCall(PrinterUtils::KLEE_ASSUME, { _ss.str() });
6865
}
6966

70-
void KleeConstraintsPrinter::genConstraintsForUnion(const ConstraintsState &state) {
71-
UnionInfo curUnion = typesHandler->getUnionInfo(state.curType);
72-
73-
for (const auto &field : curUnion.fields) {
74-
std::string errorMessage = "Unrecognized field of type '" + field.type.typeName() +
75-
"' in union '" + curUnion.name + "'.";
76-
auto access = PrinterUtils::getFieldAccess(state.curElement, field);
77-
ConstraintsState newState = { state.paramName, access, field.type, false, state.depth + 1 };
78-
switch (typesHandler->getTypeKind(field.type)) {
79-
case TypeKind::PRIMITIVE:
80-
return genConstraintsForPrimitive(newState);
81-
case TypeKind::STRUCT:
82-
return genConstraintsForStruct(newState);
83-
case TypeKind::ARRAY:
84-
return genConstraintsForPointerOrArray(newState);
85-
case TypeKind::ENUM:
86-
return genConstraintsForEnum(newState);
87-
case TypeKind::UNION:
88-
return genConstraintsForUnion(newState);
89-
case TypeKind::OBJECT_POINTER:
90-
return genConstraintsForPointerInUnion(newState);
91-
case TypeKind::UNKNOWN:
92-
LOG_S(ERROR) << errorMessage;
93-
throw UnImplementedException(errorMessage);
94-
default:
95-
std::string message = "Missing case for this TypeKind in switch";
96-
LOG_S(ERROR) << message;
97-
throw NoSuchTypeException(message);
98-
}
99-
}
100-
}
101-
10267
void KleeConstraintsPrinter::genConstraintsForPointerOrArray(const ConstraintsState &state) {
10368
auto sizes = state.curType.arraysSizes(types::PointerUsage::PARAMETER);
10469
genConstraintsForMultiPointerOrArray(state, sizes);
@@ -119,21 +84,19 @@ void KleeConstraintsPrinter::genConstraintsForMultiPointerOrArray(const Constrai
11984
TypesHandler::isCStringType(state.curType)) {
12085
std::vector<std::string> charSizes(indexes.begin(), indexes.end() - 1);
12186
const auto charElement = constrMultiIndex(state.curElement, charSizes);
122-
ss << TAB_N() << "if (" << indexes.back() << PrinterUtils::EQ_OPERATOR << sizes.back() - 1 << ")" << LB();
123-
ss << TAB_N() << PrinterUtils::KLEE_ASSUME << "(" << charElement << "[" << sizes.back() - 1 << "]" << PrinterUtils::EQ_OPERATOR << "'\\0'" << ")" << SCNL;
124-
ss << TAB_N() << "break" << SCNL;
87+
ss << LINE_INDENT() << "if (" << indexes.back() << PrinterUtils::EQ_OPERATOR << sizes.back() - 1 << ")" << LB();
88+
ss << LINE_INDENT() << PrinterUtils::KLEE_ASSUME << "(" << charElement << "[" << sizes.back() - 1 << "]" << PrinterUtils::EQ_OPERATOR << "'\\0'" << ")" << SCNL;
89+
ss << LINE_INDENT() << "break" << SCNL;
12590
ss << RB();
12691
}
12792

12893
ConstraintsState newState = { state.paramName, element, baseType };
12994
if (assignPointersToNull) {
13095
genConstraintsForPointerInStruct(newState);
131-
} else if (typesHandler->isStruct(baseType)) {
96+
} else if (typesHandler->isStructLike(baseType)) {
13297
genConstraintsForStruct(newState);
13398
} else if (typesHandler->isEnum(baseType)) {
13499
genConstraintsForEnum(newState);
135-
} else if (typesHandler->isUnion(baseType)) {
136-
genConstraintsForUnion(newState);
137100
} else {
138101
newState = { state.paramName, element, baseType };
139102
genConstraintsForPrimitive(newState);
@@ -148,37 +111,42 @@ void KleeConstraintsPrinter::genConstraintsForPointerInStruct(const ConstraintsS
148111

149112
void KleeConstraintsPrinter::genConstraintsForStruct(const ConstraintsState &state) {
150113
StructInfo curStruct = typesHandler->getStructInfo(state.curType);
151-
114+
bool isStruct = curStruct.subType == SubType::Struct;
152115
for (const auto &field : curStruct.fields) {
153116
std::string errorMessage = "Unrecognized field of type '" + field.type.typeName() +
154117
"' in struct '" + curStruct.name + "'.";
155118
auto access = PrinterUtils::getFieldAccess(state.curElement, field);
156-
ConstraintsState newState = { state.paramName, access, field.type, state.endString, state.depth + 1 };
119+
ConstraintsState newState = { state.paramName,
120+
access,
121+
field.type,
122+
isStruct ? state.endString : false,
123+
state.depth + 1 };
157124
TypeKind kind = typesHandler->getTypeKind(field.type);
158125
std::string stubFunctionName = PrinterUtils::getFunctionPointerAsStructFieldStubName(curStruct.name, field.name);
159126
switch (kind) {
160-
case TypeKind::PRIMITIVE:
161-
genConstraintsForPrimitive(newState);
162-
break;
163-
case TypeKind::STRUCT:
127+
case TypeKind::STRUCT_LIKE:
164128
genConstraintsForStruct(newState);
165129
break;
166-
case TypeKind::ARRAY:
167-
genConstraintsForPointerOrArray(newState);
168-
break;
169130
case TypeKind::ENUM:
170131
genConstraintsForEnum(newState);
171132
break;
172-
case TypeKind::UNION:
173-
genConstraintsForUnion(newState);
133+
134+
case TypeKind::PRIMITIVE:
135+
genConstraintsForPrimitive(newState);
136+
break;
137+
case TypeKind::ARRAY:
138+
genConstraintsForPointerOrArray(newState);
174139
break;
175140
case TypeKind::OBJECT_POINTER:
176141
if (types::TypesHandler::isArrayOfPointersToFunction(field.type)) {
177-
genStubForStructFunctionPointerArray(state.curElement, field.name, stubFunctionName);
142+
genStubForStructFunctionPointerArray(state.curElement, field,
143+
stubFunctionName);
178144
}
179145
break;
180146
case TypeKind::FUNCTION_POINTER:
181-
genStubForStructFunctionPointer(state.curElement, field.name, stubFunctionName);
147+
genStubForStructFunctionPointer(state.curElement,
148+
field,
149+
stubFunctionName);
182150
break;
183151
case TypeKind::UNKNOWN:
184152
throw UnImplementedException(errorMessage);
@@ -189,7 +157,6 @@ void KleeConstraintsPrinter::genConstraintsForStruct(const ConstraintsState &sta
189157
}
190158
}
191159
}
192-
193160
std::string KleeConstraintsPrinter::cexConstraints(const std::string &name, const types::Type &type) {
194161
std::stringstream ssCex;
195162
if (!CollectionUtils::containsKey(TypesHandler::preferredConstraints(), type.baseType())) {
@@ -205,11 +172,6 @@ std::string KleeConstraintsPrinter::cexConstraints(const std::string &name, cons
205172
return ssCex.str();
206173
}
207174

208-
void printer::KleeConstraintsPrinter::genConstraintsForPointerInUnion(
209-
const ConstraintsState &state) {
210-
strFunctionCall(PrinterUtils::KLEE_ASSUME, { state.curElement + PrinterUtils::EQ_OPERATOR + PrinterUtils::C_NULL });
211-
}
212-
213175
utbot::Language printer::KleeConstraintsPrinter::getLanguage() const {
214176
return srcLanguage;
215177
}

server/src/printers/KleeConstraintsPrinter.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,8 @@ namespace printer {
4242

4343
void genConstraintsForEnum(const ConstraintsState &state);
4444

45-
void genConstraintsForUnion(const ConstraintsState &state);
46-
4745
void genConstraintsForPointerInStruct(const ConstraintsState &state);
4846

49-
void genConstraintsForPointerInUnion(const ConstraintsState &state);
50-
5147
static std::string cexConstraints(const std::string &name, const types::Type &type);
5248
};
5349
}

server/src/printers/KleePrinter.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -456,17 +456,14 @@ void KleePrinter::genKleePathSymbolicIfNeeded(
456456
[[maybe_unused]] void KleePrinter::addHeaderIncludeIfNecessary(std::unordered_set<std::string> &headers,
457457
const types::Type &type) {
458458
const types::Type baseType = type.baseTypeObj();
459-
if (typesHandler->isStruct(baseType)) {
459+
if (typesHandler->isStructLike(baseType)) {
460460
auto filepath = typesHandler->getStructInfo(baseType).filePath;
461461
headers.insert(typesHandler->getStructInfo(baseType).filePath);
462462
}
463463
if (typesHandler->isEnum(baseType)) {
464464
auto filepath = typesHandler->getEnumInfo(baseType).filePath;
465465
headers.insert(typesHandler->getEnumInfo(baseType).filePath);
466466
}
467-
if (typesHandler->isUnion(baseType)) {
468-
headers.insert(typesHandler->getUnionInfo(baseType).filePath);
469-
}
470467
}
471468

472469
KleePrinter::Stream KleePrinter::strKleeMakeSymbolic(const std::string &varName, bool needAmpersand) {

0 commit comments

Comments
 (0)