Skip to content

Alter variable wrappers generation and usage #617

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

Merged
merged 2 commits into from
Aug 9, 2023
Merged
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
35 changes: 26 additions & 9 deletions server/src/clang-utils/SourceToHeaderMatchCallback.cpp
Original file line number Diff line number Diff line change
@@ -236,8 +236,8 @@ void SourceToHeaderMatchCallback::generateInternal(const VarDecl *decl) const {
policy.SuppressInitializers = 1;

/*
* extern "C" (*var_wrapper);
* &DECL = *var_wrapper;
* extern "C" (*get_var_wrapper);
* &DECL = *get_var_wrapper();
*/

std::string name = decl->getNameAsString();
@@ -252,9 +252,13 @@ void SourceToHeaderMatchCallback::generateInternal(const VarDecl *decl) const {
std::string wrapperPointerDecl =
getRenamedDeclarationAsString(decl, policy, wrapperPointerName);
std::string refDecl = getRenamedDeclarationAsString(decl, policy, refName);
PrinterUtils::removeThreadLocalQualifiers(refDecl);

*internalStream << "extern \"C\" " << wrapperPointerDecl << ";\n";
*internalStream << refDecl << " = " << wrapperPointerName << ";\n";
std::string returnTypeName = PrinterUtils::getPointerMangledName(name);
std::string getterName = PrinterUtils::getterName(wrapperName);
*internalStream << generateTypedefForGetterReturnType(decl, policy, returnTypeName);
*internalStream << "extern \"C\" " << PrinterUtils::getterDecl(returnTypeName, wrapperName) << ";\n";
*internalStream << stringFormat("%s = *%s();\n", refDecl, getterName);
}

void SourceToHeaderMatchCallback::generateWrapper(const FunctionDecl *decl) const {
@@ -295,15 +299,18 @@ void SourceToHeaderMatchCallback::generateWrapper(const VarDecl *decl) const {
policy.SuppressInitializers = 1;

/*
* (*var_wrapper) = &var;
* get_var_wrapper {
* return &var;
* }
*/

std::string name = decl->getNameAsString();
std::string wrapperName = PrinterUtils::wrapperName(name, projectContext, sourceFilePath);
std::string wrapperPointerName = stringFormat("(*%s)", wrapperName);
std::string wrapperPointerDecl =
getRenamedDeclarationAsString(decl, policy, wrapperPointerName);
*wrapperStream << wrapperPointerDecl << " = &" << name << ";\n";
std::string returnTypeName = PrinterUtils::getPointerMangledName(name);
*wrapperStream << generateTypedefForGetterReturnType(decl, policy, returnTypeName);
*wrapperStream << PrinterUtils::getterDecl(returnTypeName, wrapperName) << " {\n";
*wrapperStream << stringFormat("return &%s;\n", name);
*wrapperStream << "}\n";
}

void SourceToHeaderMatchCallback::generateUnnamedTypeDecls(const clang::RecordDecl *decl) const {
@@ -411,6 +418,16 @@ SourceToHeaderMatchCallback::getDefaultPrintingPolicy(const Decl *decl,
return policy;
}

std::string
SourceToHeaderMatchCallback::generateTypedefForGetterReturnType(const clang::VarDecl *decl,
const clang::PrintingPolicy &policy,
const std::string &returnTypeName) const {
std::string wrapperPointerName = stringFormat("(*%s)", returnTypeName);
std::string wrapperPointerDecl = getRenamedDeclarationAsString(decl, policy, wrapperPointerName);
PrinterUtils::removeThreadLocalQualifiers(wrapperPointerDecl);
return "typedef " + wrapperPointerDecl + ";\n";
}

std::string
SourceToHeaderMatchCallback::getRenamedDeclarationAsString(const clang::NamedDecl *decl,
clang::PrintingPolicy const &policy,
4 changes: 4 additions & 0 deletions server/src/clang-utils/SourceToHeaderMatchCallback.h
Original file line number Diff line number Diff line change
@@ -93,6 +93,10 @@ class SourceToHeaderMatchCallback : public clang::ast_matchers::MatchFinder::Mat

void generateUnnamedTypeDecls(const clang::RecordDecl *decl) const;

std::string generateTypedefForGetterReturnType(const clang::VarDecl *decl,
const clang::PrintingPolicy &policy,
const std::string &returnTypeName) const;

std::string getRenamedDeclarationAsString(const clang::NamedDecl *decl,
clang::PrintingPolicy const &policy,
std::string const &name) const;
18 changes: 18 additions & 0 deletions server/src/utils/PrinterUtils.cpp
Original file line number Diff line number Diff line change
@@ -22,6 +22,16 @@ namespace PrinterUtils {
return StringUtils::stringFormat("%s_%s", declName, mangledPath);
}

std::string getterName(const std::string &wrapperName) {
return "get_" + wrapperName;
}

std::string getterDecl(const std::string &returnTypeName,
const std::string &wrapperName) {
std::string gName = getterName(wrapperName);
return StringUtils::stringFormat("%s %s()", returnTypeName, gName);
}

std::string getFieldAccess(const std::string &objectName, const types::Field &field) {
if (field.name.empty()) {
return objectName;
@@ -89,6 +99,10 @@ namespace PrinterUtils {
}
}

std::string getPointerMangledName(const std::string &name) {
return name + "_pointer";
}

std::string getParamMangledName(const std::string& paramName, const std::string& methodName) {
return methodName + "_" + paramName + "_arg";
}
@@ -128,4 +142,8 @@ namespace PrinterUtils {
std::string getFileWriteBytesParamKTestJSON(char fileName) {
return StringUtils::stringFormat("%c-data-write", fileName);
}

void removeThreadLocalQualifiers(std::string &decl) {
StringUtils::replaceAll(decl, "__thread ", "");
}
}
8 changes: 8 additions & 0 deletions server/src/utils/PrinterUtils.h
Original file line number Diff line number Diff line change
@@ -68,6 +68,11 @@ namespace PrinterUtils {
utbot::ProjectContext const &projectContext,
const fs::path &sourceFilePath);

std::string getterName(const std::string &wrapperName);

std::string getterDecl(const std::string &returnTypeName,
const std::string &wrapperName);

std::string getFieldAccess(const std::string &objectName, const types::Field &field);

std::string fillVarName(std::string const &temp, std::string const &varName);
@@ -76,6 +81,7 @@ namespace PrinterUtils {

std::string wrapUserValue(const testsgen::ValidationType &type, const std::string &value);

std::string getPointerMangledName(const std::string &name);
std::string getParamMangledName(const std::string &paramName, const std::string &methodName);
std::string getReturnMangledName(const std::string &methodName);
std::string getReturnMangledTypeName(const std::string& methodName);
@@ -99,6 +105,8 @@ namespace PrinterUtils {
std::string getFileReadBytesParamKTestJSON(char fileName);
std::string getFileWriteBytesParamKTestJSON(char fileName);

void removeThreadLocalQualifiers(std::string &decl);

const std::string LAZYRENAME = "utbotInnerVar";
const std::string UTBOT_ARGC = "utbot_argc";
const std::string UTBOT_ARGV = "utbot_argv";
38 changes: 38 additions & 0 deletions server/test/framework/Server_Tests.cpp
Original file line number Diff line number Diff line change
@@ -2179,4 +2179,42 @@ namespace {
StatusCountMap expectedStatusCountMap{ { testsgen::TEST_PASSED, 3 } };
testUtils::checkStatuses(resultsMap, tests);
}

TEST_F(Server_Test, Run_Tests_For_Thread_Local) {
fs::path thread_local_c = getTestFilePath("thread_local.c");
auto request = testUtils::createFileRequest(projectName, suitePath, buildDirRelativePath,
srcPaths, thread_local_c,
GrpcUtils::UTBOT_AUTO_TARGET_PATH, true, false);
auto testGen = FileTestGen(*request, writer.get(), TESTMODE);
Status status = Server::TestsGenServiceImpl::ProcessBaseTestRequest(testGen, writer.get());
ASSERT_TRUE(status.ok()) << status.error_message();
EXPECT_GE(testUtils::getNumberOfTests(testGen.tests), 3);

fs::path testsDirPath = getTestFilePath("tests");

fs::path thread_local_test_cpp = Paths::sourcePathToTestPath(
utbot::ProjectContext(projectName, suitePath, testsDirPath, buildDirRelativePath, clientProjectPath),
thread_local_c);
auto testFilter = GrpcUtils::createTestFilterForFile(thread_local_test_cpp);
auto runRequest = testUtils::createCoverageAndResultsRequest(
projectName, suitePath, testsDirPath, buildDirRelativePath, std::move(testFilter));

static auto coverageAndResultsWriter =
std::make_unique<ServerCoverageAndResultsWriter>(nullptr);
CoverageAndResultsGenerator coverageGenerator{ runRequest.get(),
coverageAndResultsWriter.get() };
utbot::SettingsContext settingsContext{
true, false, 45, 0, false, false, ErrorMode::FAILING, false
};
coverageGenerator.generate(false, settingsContext);

EXPECT_FALSE(coverageGenerator.hasExceptions());
ASSERT_TRUE(coverageGenerator.getCoverageMap().empty());

auto resultsMap = coverageGenerator.getTestResultMap();
auto tests = coverageGenerator.getTestsToLaunch();

StatusCountMap expectedStatusCountMap{ { testsgen::TEST_PASSED, 3 } };
testUtils::checkStatuses(resultsMap, tests);
}
}
1 change: 1 addition & 0 deletions server/test/suites/server/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -26,6 +26,7 @@ add_executable(server
simple_unions.c
struct_with_union.c
structs_with_pointers.c
thread_local.c
complex_structs.c
typedefs.c
types.c
19 changes: 19 additions & 0 deletions server/test/suites/server/thread_local.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include "thread_local.h"

__thread int thread_local_id;

void set_id(int id) {
thread_local_id = id + 5;
}

__thread char thread_local_bytes[8];
void set_bytes(char bytes[8]) {
for (int i = 0; i < 8; ++i) {
thread_local_bytes[i] = bytes[7 - i];
}
}

__thread struct ThreadLocalStorage thread_local_storage;
void set_storage(struct ThreadLocalStorage storage) {
thread_local_storage.fld = - storage.fld - 10;
}
12 changes: 12 additions & 0 deletions server/test/suites/server/thread_local.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#ifndef UNITTESTBOT_THREAD_LOCAL_H
#define UNITTESTBOT_THREAD_LOCAL_H

struct ThreadLocalStorage {
int fld;
};

void set_id(int id);

void set_bytes(char bytes[8]);

#endif // UNITTESTBOT_THREAD_LOCAL_H