diff --git a/.github/workflows/build-utbot.yml b/.github/workflows/build-utbot.yml index 71ce6eeba..a6bf15997 100644 --- a/.github/workflows/build-utbot.yml +++ b/.github/workflows/build-utbot.yml @@ -153,7 +153,7 @@ jobs: build-portable-container: needs: build-utbot-and-generate-test - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 env: DOCKER_IMAGE_TAG: docker-image PORTABLE_CONTAINER_NAME: Portable diff --git a/.github/workflows/publish-utbot.yml b/.github/workflows/publish-utbot.yml index dc87e00ac..6752487cb 100644 --- a/.github/workflows/publish-utbot.yml +++ b/.github/workflows/publish-utbot.yml @@ -91,7 +91,7 @@ jobs: auto_installation_check: needs: publish - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 steps: - name: Checkout repository uses: actions/checkout@v3 diff --git a/server/src/Paths.cpp b/server/src/Paths.cpp index ea3d9c717..5f8eda9f2 100644 --- a/server/src/Paths.cpp +++ b/server/src/Paths.cpp @@ -51,6 +51,10 @@ namespace Paths { return m.first == base.end(); } + bool skipFile(const fs::path &file) { + return file.string().substr(file.string().size() - 4) == ".f.o"; + } + fs::path longestCommonPrefixPath(const fs::path &a, const fs::path &b) { if (a == b) { return a; diff --git a/server/src/Paths.h b/server/src/Paths.h index 19ea89697..619e6dbc1 100644 --- a/server/src/Paths.h +++ b/server/src/Paths.h @@ -101,6 +101,8 @@ namespace Paths { bool isSubPathOf(const fs::path &base, const fs::path &sub); + bool skipFile(const fs::path &file); + fs::path longestCommonPrefixPath(const fs::path &a, const fs::path &b); static inline fs::path replaceExtension(const fs::path &path, const std::string &newExt) { diff --git a/server/src/building/BuildDatabase.cpp b/server/src/building/BuildDatabase.cpp index f8b4e56cc..e06b8d0a8 100644 --- a/server/src/building/BuildDatabase.cpp +++ b/server/src/building/BuildDatabase.cpp @@ -432,6 +432,9 @@ bool BuildDatabase::ObjectFileInfo::is32bits() const { } fs::path BuildDatabase::TargetInfo::getOutput() const { + if (commands.empty()){ + throw CompilationDatabaseException("There are no targets"); + } return commands[0].getOutput(); } diff --git a/server/src/building/ProjectBuildDatabse.cpp b/server/src/building/ProjectBuildDatabse.cpp index 9d5cfbf5b..751f533de 100644 --- a/server/src/building/ProjectBuildDatabse.cpp +++ b/server/src/building/ProjectBuildDatabse.cpp @@ -6,6 +6,7 @@ #include "loguru.h" #include "utils/StringUtils.h" #include "utils/CompilationUtils.h" +#include "Paths.h" static std::string tryConvertToFullPath(const std::string &possibleFilePath, const fs::path &dirPath) { fs::path fullFilePath = Paths::getCCJsonFileFullPath(possibleFilePath, dirPath); @@ -68,6 +69,10 @@ void ProjectBuildDatabase::initObjects(const nlohmann::json &compileCommandsJson fs::path jsonFile = compileCommand.at("file").get(); fs::path sourceFile = Paths::getCCJsonFileFullPath(jsonFile, directory); + if (!Paths::isSourceFile(sourceFile)){ + continue; + } + std::vector jsonArguments; if (compileCommand.contains("command")) { std::string command = compileCommand.at("command"); @@ -125,7 +130,9 @@ void ProjectBuildDatabase::initObjects(const nlohmann::json &compileCommandsJson objectFileInfos[outputFile] = objectInfo; } const fs::path &sourcePath = objectInfo->getSourcePath(); + sourceFileInfos[sourcePath].emplace_back(objectInfo); + } for (auto &[sourceFile, objectInfos]: sourceFileInfos) { std::sort(objectInfos.begin(), objectInfos.end(), BuildDatabase::ObjectFileInfo::conflictPriorityMore); @@ -164,6 +171,9 @@ void ProjectBuildDatabase::initInfo(const nlohmann::json &linkCommandsJson) { for (nlohmann::json const &jsonFile: linkCommand.at("files")) { auto filename = jsonFile.get(); fs::path currentFile = Paths::getCCJsonFileFullPath(filename, command.getDirectory()); + if (Paths::skipFile(currentFile)){ + continue; + } targetInfo->addFile(currentFile); if (Paths::isObjectFile(currentFile)) { if (!CollectionUtils::containsKey(objectFileInfos, currentFile)) { diff --git a/server/src/clang-utils/SourceToHeaderMatchCallback.cpp b/server/src/clang-utils/SourceToHeaderMatchCallback.cpp index c1b7e7149..1205f0e21 100644 --- a/server/src/clang-utils/SourceToHeaderMatchCallback.cpp +++ b/server/src/clang-utils/SourceToHeaderMatchCallback.cpp @@ -202,6 +202,12 @@ void SourceToHeaderMatchCallback::generateInternal(const FunctionDecl *decl) con std::string curDecl = getRenamedDeclarationAsString(decl, policy, decoratedName); std::string wrapperDecl = getRenamedDeclarationAsString(decl, policy, wrapperName); + + if (IsOldStyleDefinition(curDecl)){ + curDecl = getOldStyleDeclarationAsString(decl, decoratedName); + wrapperDecl = getOldStyleDeclarationAsString(decl, wrapperName); + } + *internalStream << "extern \"C\" " << wrapperDecl << ";\n"; *internalStream << "static " << curDecl << " {\n"; printReturn(decl, wrapperName, internalStream); @@ -253,6 +259,9 @@ void SourceToHeaderMatchCallback::generateWrapper(const FunctionDecl *decl) cons std::string name = decl->getNameAsString(); std::string wrapperName = PrinterUtils::wrapperName(name, projectContext, sourceFilePath); std::string wrapperDecl = getRenamedDeclarationAsString(decl, policy, wrapperName); + if (IsOldStyleDefinition(wrapperDecl)){ + wrapperDecl = getOldStyleDeclarationAsString(decl, wrapperName); + } *wrapperStream << wrapperDecl << " {\n"; printReturn(decl, name, wrapperStream); @@ -362,3 +371,39 @@ void SourceToHeaderMatchCallback::renameDecl(const NamedDecl *decl, const std::s DeclarationName wrapperDeclarationName{ &info }; const_cast(decl)->setDeclName(wrapperDeclarationName); } + +std::string SourceToHeaderMatchCallback::getOldStyleDeclarationAsString(const FunctionDecl *decl, std::string const &name) const{ + std::string result; + llvm::raw_string_ostream resultStream{ result }; + std::string funcReturnType = decl->getFunctionType()->getReturnType().getAsString(); + std::vector parameters = CollectionUtils::transformTo>( + decl->parameters(), [](ParmVarDecl *param) { return param->getNameAsString(); }); + + std::vector param_types = CollectionUtils::transformTo>( + decl->parameters(), [](ParmVarDecl *param) { return param->getType().getAsString(); }); + resultStream << funcReturnType << ' ' << name << '('; + + for (int i = 0; i < parameters.size(); i++){ + if (i != 0){ + resultStream << ", "; + } + resultStream << param_types[i] << ' ' << parameters[i]; + } + resultStream << ")"; + resultStream.flush(); + return result; +} + +/*Example of old style definition +int sum(a, b) +int a; +int b; +{ + return a + b; +} +*/ +bool SourceToHeaderMatchCallback::IsOldStyleDefinition(std::string const &definition) const{ + std::regex normStyle ("\\([a-zA-Z0-9*&_()\\[\\]]+ [a-zA-Z0-9*&_()\\[\\]]+[,) ]"); + bool res = std::regex_search(definition, normStyle); + return !res; +} diff --git a/server/src/clang-utils/SourceToHeaderMatchCallback.h b/server/src/clang-utils/SourceToHeaderMatchCallback.h index 0b9c919db..84978b515 100644 --- a/server/src/clang-utils/SourceToHeaderMatchCallback.h +++ b/server/src/clang-utils/SourceToHeaderMatchCallback.h @@ -87,6 +87,10 @@ class SourceToHeaderMatchCallback : public clang::ast_matchers::MatchFinder::Mat void renameDecl(const clang::NamedDecl *decl, const std::string &name) const; std::string decorate(std::string_view name) const; + + std::string getOldStyleDeclarationAsString(const clang::FunctionDecl *decl, std::string const &name) const; + + bool IsOldStyleDefinition(std::string const &definition) const; }; diff --git a/server/src/fetchers/FunctionDeclsMatchCallback.cpp b/server/src/fetchers/FunctionDeclsMatchCallback.cpp index b13cce78e..14e3aa9bd 100644 --- a/server/src/fetchers/FunctionDeclsMatchCallback.cpp +++ b/server/src/fetchers/FunctionDeclsMatchCallback.cpp @@ -90,9 +90,7 @@ void FunctionDeclsMatchCallback::run(const MatchFinder::MatchResult &Result) { } const auto paramsFromDefinition = FS->parameters(); - const auto paramsFromDeclaration = FSFromHeader->parameters(); - for (size_t i = 0; i < paramsFromDeclaration.size(); ++i) { - const auto &declParam = paramsFromDeclaration[i]; + for (size_t i = 0; i < paramsFromDefinition.size(); ++i) { const auto &defParam = paramsFromDefinition[i]; std::string name = NameDecorator::decorate(defParam->getNameAsString()); std::string mangledName = PrinterUtils::getParamMangledName(name, methodName); @@ -102,9 +100,9 @@ void FunctionDeclsMatchCallback::run(const MatchFinder::MatchResult &Result) { if (name == methodDescription.name) { name = mangledName; } - auto paramType = ParamsHandler::getType(defParam->getType(), declParam->getType(), sourceManager); - addFunctionPointer(methodDescription.functionPointers, declParam->getFunctionType(), - declParam->getType(), name, sourceManager, paramType); + auto paramType = ParamsHandler::getType(defParam->getType(), defParam->getType(), sourceManager); + addFunctionPointer(methodDescription.functionPointers, defParam->getFunctionType(), + defParam->getType(), name, sourceManager, paramType); auto alignment = AlignmentFetcher::fetch(defParam); bool hasIncompleteType = ClangUtils::isIncomplete(defParam->getType()); methodDescription.params.emplace_back(paramType, name, alignment, hasIncompleteType);