Skip to content
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

Fix junk detection: getting the filenames right is tricky #943

Merged
merged 1 commit into from
Jan 13, 2022
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
1 change: 1 addition & 0 deletions include/mull/JunkDetection/CXX/ASTStorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class ThreadSafeASTUnit {
bool isInSystemHeader(clang::SourceLocation &location);

clang::Decl *getDecl(clang::SourceLocation &location);
bool hasAST() const;

private:
void recordDeclarations();
Expand Down
1 change: 1 addition & 0 deletions lib/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,7 @@ void mull::mutateBitcode(llvm::Module &module) {
diagnostics.info("Using configuration "s + configPath);
configuration = Configuration::loadFromDisk(diagnostics, configPath);
}
configuration.parallelization.normalize();

if (configuration.debugEnabled) {
diagnostics.enableDebugMode();
Expand Down
12 changes: 10 additions & 2 deletions lib/JunkDetection/CXX/ASTStorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ const clang::FileEntry *ThreadSafeASTUnit::findFileEntry(const std::string &file
if (!llvm::sys::path::is_absolute(currentSourceFilePath)) {
currentSourceFilePath = it->first->tryGetRealPathName();
}
if (currentSourceFilePath.equals(filePath)) {
llvm::SmallString<PATH_MAX> realFilePath;
llvm::sys::fs::real_path(filePath, realFilePath);
if (currentSourceFilePath.equals(filePath) || currentSourceFilePath.equals(realFilePath)) {
file = it->first;
break;
}
Expand Down Expand Up @@ -181,6 +183,10 @@ clang::Decl *ThreadSafeASTUnit::getDecl(clang::SourceLocation &location) {
return nullptr;
}

bool ThreadSafeASTUnit::hasAST() const {
return ast != nullptr;
}

ASTStorage::ASTStorage(Diagnostics &diagnostics, const std::string &cxxCompilationDatabasePath,
const std::string &cxxCompilationFlags,
const std::unordered_map<std::string, std::string> &bitcodeCompilationFlags)
Expand Down Expand Up @@ -214,7 +220,9 @@ ThreadSafeASTUnit *ASTStorage::findAST(const std::string &sourceFile) {
for (auto &flag : compilationFlags) {
args.push_back(flag.c_str());
}
args.push_back(sourceFile.c_str());
if (args.size() == 1) {
args.push_back(sourceFile.c_str());
}

clang::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnosticsEngine(
clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions));
Expand Down
2 changes: 1 addition & 1 deletion lib/JunkDetection/CXX/CXXJunkDetector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ bool CXXJunkDetector::isJunk(MutationPoint *point) {
}

ThreadSafeASTUnit *ast = astStorage.findAST(point->getSourceLocation());
if (!ast) {
if (!ast->hasAST()) {
return true;
}
clang::SourceLocation location = ast->getLocation(point->getSourceLocation());
Expand Down
9 changes: 0 additions & 9 deletions lib/JunkDetection/CXX/CompilationDatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,6 @@ static CompilationDatabase::Flags flagsFromCommand(const clang::tooling::Compile
CompilationDatabase::Flags flags(command.CommandLine);
flags = filterFlags(flags, true);

// The compilation database produced from running
// clang ... -MJ <comp.database.json>
// contains a file name in the "arguments" array. Since the file name
// itself is not a compilation flag we filter it out.
flags.erase(std::remove(flags.begin(), flags.end(), command.Filename), flags.end());

// append extraFlags
std::copy(std::begin(extraFlags), std::end(extraFlags), std::back_inserter(flags));

Expand Down Expand Up @@ -78,9 +72,6 @@ createBitcodeFlags(Diagnostics &diagnostics,

fileFlags = filterFlags(fileFlags, true);

/// Remove file name from the list of flags
fileFlags.erase(std::remove(fileFlags.begin(), fileFlags.end(), filename), fileFlags.end());

for (const auto &extraFlag : extraFlags) {
fileFlags.push_back(extraFlag);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ mutators:
- cxx_remove_void_call
compilerFlags:
- -DWRONG_FLAG=1
- ./sample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ mutators:
- cxx_remove_void_call
compilerFlags:
- -DFLAG=1
- ./sample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ RUN: %mull_cxx -linker=%clang_cxx -linker-flags="%sysroot" -disable-junk-detecti
WITHOUT-JUNK-DETECTION:{{^.*}}sample.cpp:5:13: warning: Survived: Removed the call to the function [cxx_remove_void_call]{{$}}
RUN: cd / && env MULL_CONFIG=%S/mull.no_flag.yml %clang_cxx %sysroot -O0 %pass_mull_ir_frontend -g -DFLAG=1 %s -o %s-ir-no-flag.exe 2>&1 | %filecheck %s --dump-input=fail --strict-whitespace --match-full-lines --check-prefix=WITH-JUNK-DETECTION-NO-FLAG-MUTATE
RUN: %mull_cxx -mutate-only -output=%s-no-flag.exe -linker=%clang_cxx -linker-flags="%sysroot" -mutators=cxx_add_to_sub -mutators=cxx_remove_void_call -reporters=IDE -ide-reporter-show-killed -compilation-flags '-DWRONG_FLAG=1' %s.exe 2>&1 | %filecheck %s --dump-input=fail --strict-whitespace --match-full-lines --check-prefix=WITH-JUNK-DETECTION-NO-FLAG-MUTATE
RUN: cd %S && env MULL_CONFIG=%S/mull.no_flag.yml %clang_cxx %sysroot -O0 %pass_mull_ir_frontend -g -DFLAG=1 %s -o %s-ir-no-flag.exe 2>&1 | %filecheck %s --dump-input=fail --strict-whitespace --match-full-lines --check-prefix=WITH-JUNK-DETECTION-NO-FLAG-MUTATE
RUN: %mull_cxx -mutate-only -output=%s-no-flag.exe -linker=%clang_cxx -linker-flags="%sysroot" -mutators=cxx_add_to_sub -mutators=cxx_remove_void_call -reporters=IDE -ide-reporter-show-killed -compilation-flags="-DWRONG_FLAG=1 %s" %s.exe 2>&1 | %filecheck %s --dump-input=fail --strict-whitespace --match-full-lines --check-prefix=WITH-JUNK-DETECTION-NO-FLAG-MUTATE
RUN: %mull_runner -ide-reporter-show-killed %s-no-flag.exe 2>&1 | %filecheck %s --dump-input=fail --strict-whitespace --match-full-lines --check-prefix=WITH-JUNK-DETECTION-NO-FLAG
RUN: %mull_runner -ide-reporter-show-killed %s-ir-no-flag.exe 2>&1 | %filecheck %s --dump-input=fail --strict-whitespace --match-full-lines --check-prefix=WITH-JUNK-DETECTION-NO-FLAG
Expand All @@ -35,8 +35,8 @@ WITH-JUNK-DETECTION-NO-FLAG-MUTATE:Make sure that the flags provided to Mull are
TODO: It is interesting why there is no junk even if we have the error above.
WITH-JUNK-DETECTION-NO-FLAG:[info] Killed mutants (1/1):
RUN: cd / && env MULL_CONFIG=%S/mull.with_flag.yml %clang_cxx %sysroot -O0 %pass_mull_ir_frontend -g -DFLAG=1 %s -o %s-ir-with-flag.exe 2>&1 | %filecheck %s --dump-input=fail --strict-whitespace --match-full-lines --check-prefix=WITH-JUNK-DETECTION-WITH-FLAG-MUTATE
RUN: %mull_cxx -mutate-only -output=%s-with-flag.exe -linker=%clang_cxx -linker-flags="%sysroot" -mutators=cxx_add_to_sub -mutators=cxx_remove_void_call -reporters=IDE -ide-reporter-show-killed -compilation-flags '-DFLAG=1' %s.exe 2>&1 | %filecheck %s --dump-input=fail --strict-whitespace --match-full-lines --check-prefix=WITH-JUNK-DETECTION-WITH-FLAG-MUTATE
RUN: cd %S && env MULL_CONFIG=%S/mull.with_flag.yml %clang_cxx %sysroot -O0 %pass_mull_ir_frontend -g -DFLAG=1 %s -o %s-ir-with-flag.exe 2>&1 | %filecheck %s --dump-input=fail --strict-whitespace --match-full-lines --check-prefix=WITH-JUNK-DETECTION-WITH-FLAG-MUTATE
RUN: %mull_cxx -mutate-only -output=%s-with-flag.exe -linker=%clang_cxx -linker-flags="%sysroot" -mutators=cxx_add_to_sub -mutators=cxx_remove_void_call -reporters=IDE -ide-reporter-show-killed -compilation-flags '-DFLAG=1 %s' %s.exe 2>&1 | %filecheck %s --dump-input=fail --strict-whitespace --match-full-lines --check-prefix=WITH-JUNK-DETECTION-WITH-FLAG-MUTATE
RUN: %mull_runner -reporters=IDE -ide-reporter-show-killed %s-with-flag.exe 2>&1 | %filecheck %s --dump-input=fail --strict-whitespace --match-full-lines --check-prefix=WITH-JUNK-DETECTION-WITH-FLAG
RUN: %mull_runner -reporters=IDE -ide-reporter-show-killed %s-ir-with-flag.exe 2>&1 | %filecheck %s --dump-input=fail --strict-whitespace --match-full-lines --check-prefix=WITH-JUNK-DETECTION-WITH-FLAG
Expand Down
3 changes: 2 additions & 1 deletion tests-lit/tests/runner/mutants-from-dylib/mull.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mutators:
- cxx_add_to_sub
compilerFlags:
- "-DSHARED_LIB"
- "-DSHARED_LIB"
- ./test.c
2 changes: 1 addition & 1 deletion tests-lit/tests/runner/mutants-from-dylib/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ RUN: %clang_cc %sysroot -DSHARED_LIB -fPIC -shared %s %pass_mull_ir_frontend -g
RUN: cd %S; %clang_cc %sysroot -DTEST_BIN ./test.c %S/shared-ir.lib -o ./test-ir.exe
RUN: %clang_cc %sysroot -DSHARED_LIB -fPIC -shared %s -fembed-bitcode -g -o %S/shared.lib
RUN: unset TERM; %mull_cxx -mutate-only --compilation-flags=-DSHARED_LIB -linker=%clang_cc -linker-flags="%sysroot -shared -fPIC" --output=%S/mutated.lib %S/shared.lib
RUN: unset TERM; %mull_cxx -mutate-only --compilation-flags="-DSHARED_LIB %s" -linker=%clang_cc -linker-flags="%sysroot -shared -fPIC" --output=%S/mutated.lib %S/shared.lib
RUN: cd %S; %clang_cc %sysroot -DTEST_BIN ./test.c ./mutated.lib -o ./test.exe
RUN: cd /; unset TERM; %mull_runner -ld-search-path=%S -ide-reporter-show-killed %S/test.exe | %filecheck %s --dump-input=fail --match-full-lines --check-prefix=CHECK
RUN: cd /; unset TERM; %mull_runner -ld-search-path=%S -ide-reporter-show-killed %S/test-ir.exe | %filecheck %s --dump-input=fail --match-full-lines --check-prefix=CHECK
Expand Down
5 changes: 3 additions & 2 deletions tests/JunkDetection/CXXJunkDetectorTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,8 +280,9 @@ TEST(CXXJunkDetector, no_compdb) {

ASSERT_EQ(points.size(), 8U);

std::string cxxCompilationFlags =
std::string("-I ") + fixtures::junk_detection_compdb_include__path();
std::string cxxCompilationFlags = std::string("-I ") +
fixtures::junk_detection_compdb_include__path() + " " +
bitcode->getModule()->getSourceFileName();

ASTStorage astStorage(diagnostics, "", cxxCompilationFlags, {});

Expand Down
27 changes: 15 additions & 12 deletions tests/JunkDetection/CompilationDatabaseTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,14 @@ TEST(CompilationDatabaseFromFile, loadsFromValidFiles) {
const CompilationDatabase database = CompilationDatabase::fromFile(diagnostics, path, "", {});

auto compilationFlags = database.compilationFlagsForFile(file);
ASSERT_EQ(compilationFlags.size(), size_t(5));
ASSERT_EQ(compilationFlags.size(), size_t(6));

ASSERT_EQ(compilationFlags.at(0), "-I"s);
ASSERT_EQ(compilationFlags.at(1), "foo"s);
ASSERT_EQ(compilationFlags.at(2), "-I"s);
ASSERT_EQ(compilationFlags.at(3), "bar"s);
ASSERT_EQ(compilationFlags.at(4), "-c"s);
ASSERT_EQ(compilationFlags.at(5), "foobar.cpp"s);
}
}
}
Expand All @@ -73,17 +74,18 @@ TEST(CompilationDatabaseFromFile, includesCompilationFlagsPassedSeparately) {

const std::string file("/foo/bar/foobar.cpp");
auto compilationFlags = database.compilationFlagsForFile(file);
ASSERT_EQ(compilationFlags.size(), size_t(9));
ASSERT_EQ(compilationFlags.size(), size_t(10));

ASSERT_EQ(compilationFlags.at(0), "-I"s);
ASSERT_EQ(compilationFlags.at(1), "foo"s);
ASSERT_EQ(compilationFlags.at(2), "-I"s);
ASSERT_EQ(compilationFlags.at(3), "bar"s);
ASSERT_EQ(compilationFlags.at(4), "-c"s);
ASSERT_EQ(compilationFlags.at(5), "-isystem"s);
ASSERT_EQ(compilationFlags.at(6), "/usr/local/include"s);
ASSERT_EQ(compilationFlags.at(7), "-isystem"s);
ASSERT_EQ(compilationFlags.at(8), "/usr/include"s);
ASSERT_EQ(compilationFlags.at(5), "foobar.cpp"s);
ASSERT_EQ(compilationFlags.at(6), "-isystem"s);
ASSERT_EQ(compilationFlags.at(7), "/usr/local/include"s);
ASSERT_EQ(compilationFlags.at(8), "-isystem"s);
ASSERT_EQ(compilationFlags.at(9), "/usr/include"s);
}

TEST(CompilationDatabaseFromFile, parsesCompilationFlagsFromClangMJCommandValid) {
Expand All @@ -95,12 +97,13 @@ TEST(CompilationDatabaseFromFile, parsesCompilationFlagsFromClangMJCommandValid)
const std::string file("/tmp/main.cpp");
auto compilationFlags = database.compilationFlagsForFile(file);

ASSERT_EQ(compilationFlags.size(), size_t(20));
ASSERT_EQ(compilationFlags.size(), size_t(21));
ASSERT_EQ(compilationFlags.at(0), "-xc++"s);
ASSERT_EQ(compilationFlags.at(1), "-fembed-bitcode=all"s);
ASSERT_EQ(compilationFlags.at(2), "-g"s);
ASSERT_EQ(compilationFlags.at(18), "-isystem"s);
ASSERT_EQ(compilationFlags.at(19), "/usr/include"s);
ASSERT_EQ(compilationFlags.at(1), "main.cpp"s);
ASSERT_EQ(compilationFlags.at(2), "-fembed-bitcode=all"s);
ASSERT_EQ(compilationFlags.at(3), "-g"s);
ASSERT_EQ(compilationFlags.at(19), "-isystem"s);
ASSERT_EQ(compilationFlags.at(20), "/usr/include"s);
}

TEST(CompilationDatabaseFromFile, parsesCompilationDatabaseWithEscapedQuotes) {
Expand All @@ -111,7 +114,7 @@ TEST(CompilationDatabaseFromFile, parsesCompilationDatabaseWithEscapedQuotes) {
const std::string file("/tmp/main.cpp");
auto compilationFlags = database.compilationFlagsForFile(file);

ASSERT_EQ(compilationFlags.size(), size_t(5));
ASSERT_EQ(compilationFlags.size(), size_t(6));
ASSERT_EQ(compilationFlags.at(0), "-DQT_CORE_LIB"s);
ASSERT_EQ(compilationFlags.at(1), "-DQT_TESTCASE_BUILDDIR=\"/src/builds/amd64-linux-mull\""s);
ASSERT_EQ(compilationFlags.at(2), "-o"s);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[
{
"directory": "@DIR@",
"command": "clang -I @INC@/include",
"command": "clang -I @INC@/include @DIR@/main.cpp",
"file": "main.cpp"
}
]
5 changes: 4 additions & 1 deletion tools/mull-cxx-ir-frontend/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@ target_include_directories(mull-cxx-ir-frontend-${LLVM_VERSION_MAJOR} SYSTEM PRI
set_target_properties(mull-cxx-ir-frontend-${LLVM_VERSION_MAJOR} PROPERTIES COMPILE_FLAGS ${MULL_CXX_FLAGS})
set_target_properties(mull-cxx-ir-frontend-${LLVM_VERSION_MAJOR} PROPERTIES LIBRARY_OUTPUT_NAME mull-ir-frontend-${LLVM_VERSION_MAJOR})
set_target_properties(mull-cxx-ir-frontend-${LLVM_VERSION_MAJOR} PROPERTIES PREFIX "")
set_target_properties(mull-cxx-ir-frontend-${LLVM_VERSION_MAJOR} PROPERTIES SUFFIX "")
set_target_properties(mull-cxx-ir-frontend-${LLVM_VERSION_MAJOR} PROPERTIES SUFFIX "")
install(TARGETS mull-cxx-ir-frontend-${LLVM_VERSION_MAJOR}
RUNTIME DESTINATION lib
)
3 changes: 2 additions & 1 deletion tools/mull-cxx-ir-frontend/mull-cxx-ir-frontend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ namespace {
class MullIRFrontend : public llvm::PassInfoMixin<MullIRFrontend> {
public:
llvm::PreservedAnalyses run(llvm::Module &module, llvm::ModuleAnalysisManager &mam) {
// module.print(llvm::errs(), nullptr);
mull::mutateBitcode(module);
module.print(llvm::errs(), nullptr);
// module.print(llvm::errs(), nullptr);
return llvm::PreservedAnalyses::none();
}
};
Expand Down