- 
                Notifications
    You must be signed in to change notification settings 
- Fork 30
Not support anonymous union in struct #317 #391
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
a87c6a7
              a161fe2
              a48a989
              e7092ce
              04fcb52
              6fedba2
              b1b09b1
              File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
|  | @@ -118,7 +118,6 @@ namespace tests { | |
| return this->subViews; | ||
| }; | ||
|  | ||
|  | ||
| protected: | ||
| explicit AbstractValueView(std::vector<std::shared_ptr<AbstractValueView>> subViews) : subViews(std::move(subViews)) {} | ||
|  | ||
|  | @@ -221,9 +220,11 @@ namespace tests { | |
| struct StructValueView : AbstractValueView { | ||
| explicit StructValueView(bool _isCLike, | ||
| std::vector<std::string> _fields, | ||
| std::vector<std::shared_ptr<AbstractValueView>> subViews, | ||
| std::optional<std::string> entryValue) | ||
| : AbstractValueView(std::move(subViews)), entryValue(std::move(entryValue)), | ||
| int _longestFieldIndexForUnionInit, | ||
| std::vector<std::shared_ptr<AbstractValueView>> _subViews, | ||
| std::optional<std::string> _entryValue) | ||
| : AbstractValueView(std::move(_subViews)), entryValue(std::move(_entryValue)), | ||
| longestFieldIndexForUnionInit(_longestFieldIndexForUnionInit), | ||
| isCLike(_isCLike), | ||
| fields(std::move(_fields)){ | ||
| } | ||
|  | @@ -242,8 +243,12 @@ namespace tests { | |
| } | ||
|  | ||
| std::vector<std::string> entries; | ||
| int i = 0; | ||
| for (const auto &subView : subViews) { | ||
| entries.push_back(subView->getEntryValue(nullptr)); | ||
| if (longestFieldIndexForUnionInit < 0 || longestFieldIndexForUnionInit == i) { | ||
| entries.push_back(subView->getEntryValue(nullptr)); | ||
| } | ||
| ++i; | ||
| } | ||
|  | ||
| return "{" + StringUtils::joinWith(entries, ", ") + "}"; | ||
|  | @@ -270,34 +275,17 @@ namespace tests { | |
| return "/*" + prefix + "*/"; | ||
| } | ||
|  | ||
| int getLongestFieldIndexForUnionInit() const { | ||
| return longestFieldIndexForUnionInit; | ||
| } | ||
|  | ||
| private: | ||
| bool isCLike; | ||
| int longestFieldIndexForUnionInit; | ||
| std::vector<std::string> fields; | ||
| std::optional<std::string> entryValue; | ||
| }; | ||
|  | ||
| /** | ||
| * Representation of union. | ||
| */ | ||
| struct UnionValueView : AbstractValueView { | ||
| public: | ||
| explicit UnionValueView(const std::string &typeName, | ||
| const std::shared_ptr<AbstractValueView> &rawDataView, | ||
| std::vector<std::shared_ptr<AbstractValueView>, | ||
| std::allocator<std::shared_ptr<AbstractValueView>>> subViews); | ||
|  | ||
| [[nodiscard]] std::string getEntryValue(printer::TestsPrinter *printer) const override { | ||
| return entryValue; | ||
| } | ||
|  | ||
| bool containsFPSpecialValue() override { | ||
| return false; | ||
| } | ||
|  | ||
| private: | ||
| std::string entryValue; | ||
| }; | ||
|  | ||
| struct InitReference { | ||
| std::string varName; | ||
| std::string refName; | ||
|  | @@ -674,33 +662,29 @@ namespace tests { | |
| std::shared_ptr<FunctionPointerView> functionPointerView(const std::string &structName, | ||
| const std::string &fieldName); | ||
|  | ||
| std::shared_ptr<UnionValueView> unionView(const std::vector<char> &byteArray, | ||
| types::UnionInfo &unionInfo, | ||
| unsigned int offset, | ||
| types::PointerUsage usage); | ||
|  | ||
| std::shared_ptr<StructValueView> structView(const std::vector<char> &byteArray, | ||
| types::StructInfo &curStruct, | ||
| const types::StructInfo &curStruct, | ||
| unsigned int offset, | ||
| types::PointerUsage usage); | ||
|  | ||
| std::shared_ptr<StructValueView> structView(const std::vector<char> &byteArray, | ||
| types::StructInfo &curStruct, | ||
| const types::StructInfo &curStruct, | ||
| unsigned int offset, | ||
| types::PointerUsage usage, | ||
| const std::optional<const Tests::MethodDescription> &testingMethod, | ||
| const std::string &name, | ||
| const MapAddressName &fromAddressToName, | ||
| std::vector<InitReference> &initReferences); | ||
|  | ||
| static std::shared_ptr<EnumValueView> enumView(const std::vector<char> &byteArray, | ||
| const types::EnumInfo &enumInfo, | ||
| size_t offset, | ||
| size_t len); | ||
|  | ||
| std::shared_ptr<PrimitiveValueView> primitiveView(const std::vector<char> &byteArray, | ||
| const types::Type &type, | ||
| size_t offset, | ||
| size_t len); | ||
| static std::shared_ptr<EnumValueView> enumView(const std::vector<char> &byteArray, | ||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Group enum and struct-like. Seems they need to be joined in the future. | ||
| types::EnumInfo &enumInfo, | ||
| size_t offset, | ||
| size_t len); | ||
|  | ||
| std::string primitiveCharView(const types::Type &type, std::string value); | ||
| static std::string primitiveBoolView(const std::string &value); | ||
|  | @@ -720,10 +704,6 @@ namespace tests { | |
| const Tests::MethodDescription &methodDescription, | ||
| const std::unordered_map<std::string, types::Type>& methodNameToReturnTypeMap, | ||
| const std::stringstream &traceStream); | ||
| std::vector<std::shared_ptr<AbstractValueView>> collectUnionSubViews(const std::vector<char> &byteArray, | ||
| const types::UnionInfo &info, | ||
| unsigned int offset, | ||
| types::PointerUsage usage); | ||
| void processGlobalParamPreValue(Tests::TestCaseDescription &testCaseDescription, | ||
| const Tests::MethodParam &globalParam, | ||
| std::vector<RawKleeParam> &rawKleeParams); | ||
|  | ||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
|  | @@ -24,15 +24,12 @@ KleeConstraintsPrinter::genConstraints(const std::string &name, const types::Typ | |
| state = { name, name, paramType, state.endString }; | ||
| genConstraintsForPointerOrArray(state); | ||
| break; | ||
| case TypeKind::STRUCT: | ||
| case TypeKind::STRUCT_LIKE: | ||
| genConstraintsForStruct(state); | ||
| break; | ||
| case TypeKind::ENUM: | ||
| genConstraintsForEnum(state); | ||
| break; | ||
| case TypeKind::UNION: | ||
| genConstraintsForUnion(state); | ||
| break; | ||
| default: | ||
| genConstraintsForPrimitive(state); | ||
| } | ||
|  | @@ -50,7 +47,7 @@ void KleeConstraintsPrinter::genConstraintsForPrimitive(const ConstraintsState & | |
| if (!cons.empty()) { | ||
| strFunctionCall(PrinterUtils::KLEE_PREFER_CEX, { state.paramName, cons }); | ||
| } else { | ||
| ss << TAB_N() << "// No constraints for " << state.curElement << NL; | ||
| ss << LINE_INDENT() << "// No constraints for " << state.curElement << NL; | ||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indent can include the inline comment, so rename it to indent. | ||
| } | ||
| } | ||
|  | ||
|  | @@ -67,38 +64,6 @@ void KleeConstraintsPrinter::genConstraintsForEnum(const ConstraintsState &state | |
| strFunctionCall(PrinterUtils::KLEE_ASSUME, { _ss.str() }); | ||
| } | ||
|  | ||
| void KleeConstraintsPrinter::genConstraintsForUnion(const ConstraintsState &state) { | ||
| UnionInfo curUnion = typesHandler->getUnionInfo(state.curType); | ||
|  | ||
| for (const auto &field : curUnion.fields) { | ||
| std::string errorMessage = "Unrecognized field of type '" + field.type.typeName() + | ||
| "' in union '" + curUnion.name + "'."; | ||
| auto access = PrinterUtils::getFieldAccess(state.curElement, field); | ||
| ConstraintsState newState = { state.paramName, access, field.type, false, state.depth + 1 }; | ||
| switch (typesHandler->getTypeKind(field.type)) { | ||
| case TypeKind::PRIMITIVE: | ||
| return genConstraintsForPrimitive(newState); | ||
| case TypeKind::STRUCT: | ||
| return genConstraintsForStruct(newState); | ||
| case TypeKind::ARRAY: | ||
| return genConstraintsForPointerOrArray(newState); | ||
| case TypeKind::ENUM: | ||
| return genConstraintsForEnum(newState); | ||
| case TypeKind::UNION: | ||
| return genConstraintsForUnion(newState); | ||
| case TypeKind::OBJECT_POINTER: | ||
| return genConstraintsForPointerInUnion(newState); | ||
| case TypeKind::UNKNOWN: | ||
| LOG_S(ERROR) << errorMessage; | ||
| throw UnImplementedException(errorMessage); | ||
| default: | ||
| std::string message = "Missing case for this TypeKind in switch"; | ||
| LOG_S(ERROR) << message; | ||
| throw NoSuchTypeException(message); | ||
| } | ||
| } | ||
| } | ||
|  | ||
| void KleeConstraintsPrinter::genConstraintsForPointerOrArray(const ConstraintsState &state) { | ||
| auto sizes = state.curType.arraysSizes(types::PointerUsage::PARAMETER); | ||
| genConstraintsForMultiPointerOrArray(state, sizes); | ||
|  | @@ -119,9 +84,9 @@ void KleeConstraintsPrinter::genConstraintsForMultiPointerOrArray(const Constrai | |
| TypesHandler::isCStringType(state.curType)) { | ||
| std::vector<std::string> charSizes(indexes.begin(), indexes.end() - 1); | ||
| const auto charElement = constrMultiIndex(state.curElement, charSizes); | ||
| ss << TAB_N() << "if (" << indexes.back() << PrinterUtils::EQ_OPERATOR << sizes.back() - 1 << ")" << LB(); | ||
| ss << TAB_N() << PrinterUtils::KLEE_ASSUME << "(" << charElement << "[" << sizes.back() - 1 << "]" << PrinterUtils::EQ_OPERATOR << "'\\0'" << ")" << SCNL; | ||
| ss << TAB_N() << "break" << SCNL; | ||
| ss << LINE_INDENT() << "if (" << indexes.back() << PrinterUtils::EQ_OPERATOR << sizes.back() - 1 << ")" << LB(); | ||
| ss << LINE_INDENT() << PrinterUtils::KLEE_ASSUME << "(" << charElement << "[" << sizes.back() - 1 << "]" << PrinterUtils::EQ_OPERATOR << "'\\0'" << ")" << SCNL; | ||
| ss << LINE_INDENT() << "break" << SCNL; | ||
| ss << RB(); | ||
| } | ||
|  | ||
|  | @@ -132,8 +97,6 @@ void KleeConstraintsPrinter::genConstraintsForMultiPointerOrArray(const Constrai | |
| genConstraintsForStruct(newState); | ||
| } else if (typesHandler->isEnum(baseType)) { | ||
| genConstraintsForEnum(newState); | ||
| } else if (typesHandler->isUnion(baseType)) { | ||
| genConstraintsForUnion(newState); | ||
| } else { | ||
| newState = { state.paramName, element, baseType }; | ||
| genConstraintsForPrimitive(newState); | ||
|  | @@ -148,37 +111,42 @@ void KleeConstraintsPrinter::genConstraintsForPointerInStruct(const ConstraintsS | |
|  | ||
| void KleeConstraintsPrinter::genConstraintsForStruct(const ConstraintsState &state) { | ||
| StructInfo curStruct = typesHandler->getStructInfo(state.curType); | ||
|  | ||
| bool isStruct = curStruct.subType == SubType::Struct; | ||
| for (const auto &field : curStruct.fields) { | ||
| std::string errorMessage = "Unrecognized field of type '" + field.type.typeName() + | ||
| "' in struct '" + curStruct.name + "'."; | ||
| auto access = PrinterUtils::getFieldAccess(state.curElement, field); | ||
| ConstraintsState newState = { state.paramName, access, field.type, state.endString, state.depth + 1 }; | ||
| ConstraintsState newState = { state.paramName, | ||
| access, | ||
| field.type, | ||
| isStruct ? state.endString : false, | ||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is still essential difference between struct and union. Need to be investigated (in progress). | ||
| state.depth + 1 }; | ||
| TypeKind kind = typesHandler->getTypeKind(field.type); | ||
| std::string stubFunctionName = PrinterUtils::getFunctionPointerAsStructFieldStubName(curStruct.name, field.name); | ||
| switch (kind) { | ||
| case TypeKind::PRIMITIVE: | ||
| genConstraintsForPrimitive(newState); | ||
| break; | ||
| case TypeKind::STRUCT: | ||
| case TypeKind::STRUCT_LIKE: | ||
| genConstraintsForStruct(newState); | ||
| break; | ||
| case TypeKind::ARRAY: | ||
| genConstraintsForPointerOrArray(newState); | ||
| break; | ||
| case TypeKind::ENUM: | ||
| genConstraintsForEnum(newState); | ||
| break; | ||
| case TypeKind::UNION: | ||
| genConstraintsForUnion(newState); | ||
|  | ||
| case TypeKind::PRIMITIVE: | ||
| genConstraintsForPrimitive(newState); | ||
| break; | ||
| case TypeKind::ARRAY: | ||
| genConstraintsForPointerOrArray(newState); | ||
| break; | ||
| case TypeKind::OBJECT_POINTER: | ||
| if (types::TypesHandler::isArrayOfPointersToFunction(field.type)) { | ||
| genStubForStructFunctionPointerArray(state.curElement, field.name, stubFunctionName); | ||
| genStubForStructFunctionPointerArray(state.curElement, field, | ||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no more  | ||
| stubFunctionName); | ||
| } | ||
| break; | ||
| case TypeKind::FUNCTION_POINTER: | ||
| genStubForStructFunctionPointer(state.curElement, field.name, stubFunctionName); | ||
| genStubForStructFunctionPointer(state.curElement, | ||
| field, | ||
| stubFunctionName); | ||
| break; | ||
| case TypeKind::UNKNOWN: | ||
| throw UnImplementedException(errorMessage); | ||
|  | @@ -189,7 +157,6 @@ void KleeConstraintsPrinter::genConstraintsForStruct(const ConstraintsState &sta | |
| } | ||
| } | ||
| } | ||
|  | ||
| std::string KleeConstraintsPrinter::cexConstraints(const std::string &name, const types::Type &type) { | ||
| std::stringstream ssCex; | ||
| if (!CollectionUtils::containsKey(TypesHandler::preferredConstraints(), type.baseType())) { | ||
|  | @@ -205,11 +172,6 @@ std::string KleeConstraintsPrinter::cexConstraints(const std::string &name, cons | |
| return ssCex.str(); | ||
| } | ||
|  | ||
| void printer::KleeConstraintsPrinter::genConstraintsForPointerInUnion( | ||
| const ConstraintsState &state) { | ||
| strFunctionCall(PrinterUtils::KLEE_ASSUME, { state.curElement + PrinterUtils::EQ_OPERATOR + PrinterUtils::C_NULL }); | ||
| } | ||
|  | ||
| utbot::Language printer::KleeConstraintsPrinter::getLanguage() const { | ||
| return srcLanguage; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[PERF] UTBot consumes CPU in spinlocks #382