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
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
35 changes: 26 additions & 9 deletions server/src/clang-utils/SourceToHeaderMatchCallback.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand Down
4 changes: 4 additions & 0 deletions server/src/clang-utils/SourceToHeaderMatchCallback.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
18 changes: 18 additions & 0 deletions server/src/utils/PrinterUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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";
}
Expand Down Expand Up @@ -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
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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";
Expand Down
38 changes: 38 additions & 0 deletions server/test/framework/Server_Tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Up @@ -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
Expand Down
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