Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion integration-tests/c-example/lib/structures/simple_unions.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ union SuperFloat {

union Vector2D {
int m[2];
struct Point /*make me anonymous*/{
struct {
int x, y;
};
};
Expand Down
3 changes: 0 additions & 3 deletions server/src/Server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -541,9 +541,6 @@ Status Server::TestsGenServiceImpl::PrintModulesContent(ServerContext *context,

MEASURE_FUNCTION_EXECUTION_TIME

fs::path compileCommandsJsonPath =
CompilationUtils::substituteRemotePathToCompileCommandsJsonPath(
request->projectpath(), request->builddirrelativepath());
fs::path serverBuildDir = Paths::getTmpDir(request->projectname());
utbot::ProjectContext projectContext{ *request };
shared_ptr<BuildDatabase> buildDatabase = BuildDatabase::create(projectContext);
Expand Down
9 changes: 8 additions & 1 deletion server/src/Tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,14 @@ shared_ptr<StructValueView> KTestObjectParser::structView(const vector<char> &by
throw NoSuchTypeException(message);
}
}
return std::make_shared<StructValueView>(subViews);

std::optional<std::string> entryValue;
if(curStruct.hasUnnamedFields) {
auto bytesType = types::Type::createSimpleTypeFromName("utbot_byte");
const shared_ptr<AbstractValueView> rawDataView = arrayView(byteArray, bytesType, curStruct.size, offset, usage);
entryValue = PrinterUtils::convertBytesToUnion(curStruct.name, rawDataView->getEntryValue());
}
return std::make_shared<StructValueView>(subViews, entryValue);
}

string KTestObjectParser::primitiveCharView(const types::Type &type, string value) {
Expand Down
14 changes: 11 additions & 3 deletions server/src/Tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,14 +204,18 @@ namespace tests {
* In order to get fields and subfields values (leaves in terms of trees) method fieldEntryValues().
*/
struct StructValueView : AbstractValueView {
explicit StructValueView(vector<shared_ptr<AbstractValueView>> subViews)
: AbstractValueView(std::move(subViews)) {}
explicit StructValueView(vector<shared_ptr<AbstractValueView>> subViews, std::optional<std::string> entryValue)
: AbstractValueView(std::move(subViews)), entryValue(entryValue) {}

[[nodiscard]] const vector<shared_ptr<AbstractValueView>> &getSubViews() const override {
return this->subViews;
}

[[nodiscard]] string getEntryValue() const override {
if (entryValue.has_value()) {
return entryValue.value();
}

vector<string> entries;
for (const auto &subView : subViews) {
entries.push_back(subView->getEntryValue());
Expand Down Expand Up @@ -241,6 +245,8 @@ namespace tests {
}
return false;
}
private:
std::optional<std::string> entryValue;
};

/**
Expand Down Expand Up @@ -304,7 +310,9 @@ namespace tests {
}

bool isChangeable() const {
if((type.isObjectPointer() || type.isLValueReference()) && !type.isConstQualifiedValue()) {
if((type.isObjectPointer() || type.isLValueReference()) &&
!type.isTypeContainsFunctionPointer() &&
!type.isConstQualifiedValue()) {
return true;
}
return false;
Expand Down
4 changes: 4 additions & 0 deletions server/src/environment/EnvironmentPaths.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,8 @@ namespace Paths {
fs::path getLdGold() {
return getUTBotDebsInstallDir() / "usr" / "bin" / "ld.gold";
}

fs::path getLd() {
return getUTBotDebsInstallDir() / "usr" / "bin" / "ld";
}
}
4 changes: 3 additions & 1 deletion server/src/environment/EnvironmentPaths.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ namespace Paths {

fs::path getLdGold();

// Gcc is used only in tests
fs::path getLd();

// Gcc is used only in tests
fs::path getGcc();
fs::path getGpp();
}
Expand Down
89 changes: 55 additions & 34 deletions server/src/printers/NativeMakefilePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
* Copyright (c) Huawei Technologies Co., Ltd. 2012-2021. All rights reserved.
*/

#include <Paths.h>
#include <FeaturesFilter.h>
#include <algorithm>
#include "NativeMakefilePrinter.h"
#include "Synchronizer.h"

Expand All @@ -28,6 +31,7 @@ namespace printer {
};
static const std::string STATIC_FLAG = "-static";
static const std::string SHARED_FLAG = "-shared";
static const std::string RELOCATE_FLAG = "-r";
static const std::string OPTIMIZATION_FLAG = "-O0";

static const std::string FORCE = ".FORCE";
Expand Down Expand Up @@ -267,7 +271,7 @@ namespace printer {

std::vector<std::string> filesToLink{ "$(GTEST_MAIN)", "$(GTEST_ALL)", testObjectPath,
sharedOutput.value() };
if (rootLinkUnitInfo->commands[0].isArchiveCommand()) {
if (rootLinkUnitInfo->commands.front().isArchiveCommand()) {
std::vector<std::string> dynamicLinkCommandLine{ cxxLinker, "$(LDFLAGS)",
pthreadFlag, coverageLinkFlags,
sanitizerLinkFlags, "-o",
Expand All @@ -279,7 +283,7 @@ namespace printer {
declareTarget(testExecutablePath, filesToLink,
{ dynamicLinkCommand.toStringWithChangingDirectory() });
} else {
utbot::LinkCommand dynamicLinkCommand = rootLinkUnitInfo->commands[0];
utbot::LinkCommand dynamicLinkCommand = rootLinkUnitInfo->commands.front();
dynamicLinkCommand.setLinker(cxxLinker);
dynamicLinkCommand.setOutput(testExecutablePath);
dynamicLinkCommand.erase_if([&](std::string const &argument) {
Expand All @@ -295,6 +299,13 @@ namespace printer {
dynamicLinkCommand.setOptimizationLevel(OPTIMIZATION_FLAG);
dynamicLinkCommand.addFlagsToBegin(
{ pthreadFlag, coverageLinkFlags, sanitizerLinkFlags });
std::copy_if(rootLinkUnitInfo->files.begin(), rootLinkUnitInfo->files.end(), std::back_inserter(filesToLink),
[](const fs::path& path) {return Paths::isLibraryFile(path);});
for(std::string& file : filesToLink) {
if (CollectionUtils::contains(buildResults, fs::path(file))) {
file = buildResults.at(fs::path(file)).output.string();
}
}
dynamicLinkCommand.addFlagsToBegin(filesToLink);
dynamicLinkCommand.addFlagToBegin(
getLibraryDirectoryFlag(sharedOutput.value().parent_path()));
Expand Down Expand Up @@ -328,7 +339,9 @@ namespace printer {
sanitizerLinkFlags(baseMakefilePrinter.sanitizerLinkFlags),
buildDirectory(baseMakefilePrinter.buildDirectory),
dependencyDirectory(baseMakefilePrinter.dependencyDirectory),
artifacts(baseMakefilePrinter.artifacts), sharedOutput(baseMakefilePrinter.sharedOutput) {
artifacts(baseMakefilePrinter.artifacts),
buildResults(baseMakefilePrinter.buildResults),
sharedOutput(baseMakefilePrinter.sharedOutput) {
resetStream();

ss << baseMakefilePrinter.ss.str();
Expand Down Expand Up @@ -386,15 +399,19 @@ namespace printer {
unitBuildResults, [](BuildResult const &buildResult) { return buildResult.output; });

bool isExecutable = !Paths::isLibraryFile(unitFile);

fs::path recompiledFile =
Paths::getRecompiledFile(projectContext, linkUnitInfo->getOutput());
if (isExecutable) {
recompiledFile = Paths::isObjectFile(Paths::addExtension(recompiledFile, ".o")) ?
recompiledFile : Paths::addExtension(recompiledFile, ".o");
} else if (Paths::isSharedLibraryFile(unitFile)) {
recompiledFile = getSharedLibrary(linkUnitInfo->getOutput());
}
recompiledFile = LinkerUtils::applySuffix(recompiledFile, unitType, suffixForParentOfStubs);

if (isExecutable || Paths::isSharedLibraryFile(unitFile)) {
sharedOutput =
getSharedLibrary(*linkUnitInfo, unitType, suffixForParentOfStubs);
recompiledFile = sharedOutput.value();
} else {
recompiledFile =
LinkerUtils::applySuffix(recompiledFile, unitType, suffixForParentOfStubs);
sharedOutput = recompiledFile;
}

auto commandActions =
Expand All @@ -407,39 +424,48 @@ namespace printer {
}
}
if (!linkCommand.isArchiveCommand()) {
linkCommand.setLinker(CompilationUtils::getBundledCompilerPath(
CompilationUtils::getCompilerName(linkCommand.getLinker())));
std::vector<std::string> libraryDirectoriesFlags;
if (isExecutable) {
linkCommand.setLinker(Paths::getLd());
} else {
linkCommand.setLinker(CompilationUtils::getBundledCompilerPath(
CompilationUtils::getCompilerName(linkCommand.getLinker())));
}
std::vector <std::string> libraryDirectoriesFlags;
for (std::string &argument : linkCommand.getCommandLine()) {
removeScriptFlag(argument);
removeSonameFlag(argument);
auto optionalLibraryAbsolutePath =
getLibraryAbsolutePath(argument, linkCommand.getDirectory());
getLibraryAbsolutePath(argument, linkCommand.getDirectory());
if (optionalLibraryAbsolutePath.has_value()) {
const fs::path &absolutePath = optionalLibraryAbsolutePath.value();
if (Paths::isSubPathOf(projectContext.buildDir, absolutePath)) {
fs::path recompiledDir =
Paths::getRecompiledFile(projectContext, absolutePath);
Paths::getRecompiledFile(projectContext, absolutePath);
string directoryFlag = getLibraryDirectoryFlag(recompiledDir);
libraryDirectoriesFlags.push_back(directoryFlag);
}
}
}
linkCommand.addFlagsToBegin(libraryDirectoriesFlags);
linkCommand.addFlagsToBegin({ "-Wl,--allow-multiple-definition",
coverageLinkFlags, sanitizerLinkFlags, "-Wl,--whole-archive" });
if (linkCommand.isSharedLibraryCommand()) {
linkCommand.addFlagToEnd(STUB_OBJECT_FILES);
dependencies.emplace(STUB_OBJECT_FILES);
if (!isExecutable) {
linkCommand.addFlagsToBegin({"-Wl,--allow-multiple-definition",
coverageLinkFlags, sanitizerLinkFlags, "-Wl,--whole-archive"});
if (linkCommand.isSharedLibraryCommand()) {
linkCommand.addFlagToEnd(STUB_OBJECT_FILES);
dependencies.emplace(STUB_OBJECT_FILES);
}
linkCommand.addFlagToEnd("-Wl,--no-whole-archive");
linkCommand.setOptimizationLevel(OPTIMIZATION_FLAG);
}
linkCommand.addFlagToEnd("-Wl,--no-whole-archive");
linkCommand.setOptimizationLevel(OPTIMIZATION_FLAG);
linkCommand.addFlagToBegin("$(LDFLAGS)");
if (isExecutable) {
linkCommand.addFlagToBegin(RELOCATE_FLAG);
}
}
if (isExecutable) {
linkCommand.addFlagToBegin(SHARED_FLAG);
}
return linkCommand.toStringWithChangingDirectory();
return isExecutable ? stringFormat("%s && objcopy --redefine-sym main=old_main %s",
linkCommand.toStringWithChangingDirectory(),
linkCommand.getOutput().string()) :
linkCommand.toStringWithChangingDirectory();
});
std::string removeAction = stringFormat("rm -f %s", recompiledFile);
std::vector<std::string> actions{ removeAction };
Expand All @@ -450,8 +476,7 @@ namespace printer {
artifacts.push_back(recompiledFile);

if (!hasParent && Paths::isStaticLibraryFile(unitFile)) {
sharedOutput =
getSharedLibrary(*linkUnitInfo, unitType, suffixForParentOfStubs);
sharedOutput = LinkerUtils::applySuffix(getSharedLibrary(linkUnitInfo->getOutput()), unitType, suffixForParentOfStubs);
std::vector<std::string> sharedLinkCommandLine{
primaryCompiler, "$(LDFLAGS)", SHARED_FLAG, coverageLinkFlags,
sanitizerLinkFlags, "-o", sharedOutput.value(),
Expand All @@ -469,16 +494,12 @@ namespace printer {
}


fs::path
NativeMakefilePrinter::getSharedLibrary(const BuildDatabase::TargetInfo &linkUnitInfo,
BuildResult::Type unitType,
std::string const &suffixForParentOfStubs) {
fs::path output = Paths::getRecompiledFile(projectContext, linkUnitInfo.getOutput());
output = CompilationUtils::removeSharedLibraryVersion(output);
fs::path NativeMakefilePrinter::getSharedLibrary(const fs::path &filePath) {
fs::path output = CompilationUtils::removeSharedLibraryVersion(filePath);
fs::path sharedLibrary = Paths::isSharedLibraryFile(output)
? output
: Paths::addPrefix(Paths::addExtension(output, ".so"), "lib");
return LinkerUtils::applySuffix(sharedLibrary, unitType, suffixForParentOfStubs);
return sharedLibrary;
}

void NativeMakefilePrinter::addStubs(const CollectionUtils::FileSet &stubsSet) {
Expand Down
4 changes: 1 addition & 3 deletions server/src/printers/NativeMakefilePrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,7 @@ namespace printer {
void gtestMainTargets(const utbot::CompileCommand &defaultCompileCommand,
const fs::path &gtestBuildDir);

fs::path getSharedLibrary(const BuildDatabase::TargetInfo &linkUnitInfo,
BuildResult::Type unitType,
std::string const &suffixForParentOfStubs);
fs::path getSharedLibrary(const fs::path &filePath);

void addTestTarget(const fs::path &sourcePath);

Expand Down
10 changes: 10 additions & 0 deletions server/src/printers/Printer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,16 @@ namespace printer {
} else {
if (paramTypes[i].isPointerToArray()) {
auto decomposedType = StringUtils::split(paramTypes[i].usedType(), '*');
/*
* code example
* typedef int int_array[1];
* int_array* int_array_pointer;
* usedType == int_array*
* mTypeName == int_array*[1]
*/
if (decomposedType.size() != 2) {
decomposedType = StringUtils::split(paramTypes[i].mTypeName(), '*');
}
LOG_IF_S(ERROR, decomposedType.size() != 2) << "Type::isPointerToArray malfunction";
ss << decomposedType[0] << "*" << paramValues[i] << decomposedType[1];
named = true;
Expand Down
9 changes: 4 additions & 5 deletions server/src/printers/TestsPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -372,11 +372,10 @@ void TestsPrinter::changeableParamsAsserts(const Tests::MethodDescription &metho
auto assertsVisitor = visitor::VerboseAssertsParamVisitor(typesHandler, this);
auto usage = types::PointerUsage::PARAMETER;
size_t param_i = 0;
for (const auto& i : methodDescription.params) {
if (i.isChangeable()) {
auto const &param = i;
for (const auto& param : methodDescription.params) {
if (param.isChangeable()) {
auto const &value = testCase.paramPostValues[param_i];
string expectedName = "expected_" + param.name;
string expectedName = PrinterUtils::getExpectedVarName(param.name);
const types::Type expectedType = param.type.arrayCloneMultiDim(usage);
parameterVisitor.visit(expectedType, expectedName, value.view.get(), std::nullopt);
assertsVisitor.visit(param, param.name);
Expand All @@ -393,7 +392,7 @@ void TestsPrinter::globalParamsAsserts(const Tests::MethodDescription &methodDes
for (size_t i = 0; i < methodDescription.globalParams.size(); i++) {
auto const &param = methodDescription.globalParams[i];
auto const &value = testCase.globalPostValues[i];
string expectedName = "expected_" + param.name;
string expectedName = PrinterUtils::getExpectedVarName(param.name);
auto expectedType = typesHandler->getReturnTypeToCheck(param.type);
Tests::MethodParam expectedParam{expectedType, expectedName, param.alignment};
parameterVisitor.visit(expectedParam.type, expectedParam.name, value.view.get(), std::nullopt);
Expand Down
17 changes: 15 additions & 2 deletions server/src/types/Types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ types::Type types::Type::baseTypeObj() const {
return baseTypeObj(getDimension());
}

std::string types::Type::mTypeName() const {
return this->mType;
}

size_t types::Type::getDimension() const {
// usage doesn't matter here
return arraysSizes(PointerUsage::PARAMETER).size();
Expand Down Expand Up @@ -297,6 +301,15 @@ bool types::Type::isTypeContainsPointer() const {
return false;
}

bool types::Type::isTypeContainsFunctionPointer() const {
for (const auto &kind : mKinds) {
if (kind->getKind() == AbstractType::FUNCTION_POINTER) {
return true;
}
}
return false;
}

int types::Type::indexOfFirstPointerInTypeKinds() const {
int index = 0;
for (const auto &kind : pointerArrayKinds()) {
Expand Down Expand Up @@ -863,7 +876,7 @@ types::TypesHandler::isSupportedType(const Type &type, TypeUsage usage, int dept
}
if (isStruct(type)) {
auto structInfo = getStructInfo(type);
return unsupportedFields(structInfo.fields);
return !structInfo.hasUnnamedFields && unsupportedFields(structInfo.fields);
}
return false;
} },
Expand Down Expand Up @@ -919,7 +932,7 @@ types::TypesHandler::isSupportedType(const Type &type, TypeUsage usage, int dept
};
if (isStruct(type)) {
auto structInfo = getStructInfo(type);
return unsupportedFields(structInfo.fields);
return !structInfo.hasUnnamedFields && unsupportedFields(structInfo.fields);
}

if (isUnion(type)) {
Expand Down
Loading