From 97c37ca3cddf1a1be0f2c80e054b0e4e0df92305 Mon Sep 17 00:00:00 2001 From: Alex Denisov Date: Thu, 5 May 2022 08:53:37 +0200 Subject: [PATCH] Logical mutations: fix 'dangling' incoming phi-node value --- include/mull/Mutators/CXX/LogicalAndToOr.h | 3 +- include/mull/Mutators/CXX/LogicalOrToAnd.h | 4 +-- lib/Mutators/CXX/LogicalAndToOr.cpp | 31 +++++++++++++++++-- lib/Mutators/CXX/LogicalOrToAnd.cpp | 11 +++++-- .../tests/mutations/logical/phi_nodes/main.c | 23 ++++++++++++++ .../mutations/logical/phi_nodes/mull.yml | 3 ++ 6 files changed, 66 insertions(+), 9 deletions(-) create mode 100644 tests-lit/tests/mutations/logical/phi_nodes/main.c create mode 100644 tests-lit/tests/mutations/logical/phi_nodes/mull.yml diff --git a/include/mull/Mutators/CXX/LogicalAndToOr.h b/include/mull/Mutators/CXX/LogicalAndToOr.h index 25fc2c978..555c978f6 100644 --- a/include/mull/Mutators/CXX/LogicalAndToOr.h +++ b/include/mull/Mutators/CXX/LogicalAndToOr.h @@ -15,6 +15,7 @@ namespace llvm { class BasicBlock; class BranchInst; class Instruction; +class PHINode; } // namespace llvm using namespace llvm; @@ -24,8 +25,8 @@ namespace mull { class Bitcode; class MutationPoint; class MutationPointAddress; -class ReachableFunction; namespace cxx { +void cleanupIncomingValues(llvm::PHINode &phi); class LogicalAndToOr : public Mutator { diff --git a/include/mull/Mutators/CXX/LogicalOrToAnd.h b/include/mull/Mutators/CXX/LogicalOrToAnd.h index 4f809b7f0..caa767e17 100644 --- a/include/mull/Mutators/CXX/LogicalOrToAnd.h +++ b/include/mull/Mutators/CXX/LogicalOrToAnd.h @@ -15,6 +15,7 @@ namespace llvm { class BasicBlock; class BranchInst; class Instruction; +class PHINode; } // namespace llvm using namespace llvm; @@ -24,10 +25,9 @@ namespace mull { class Bitcode; class MutationPoint; class MutationPointAddress; -class ReachableFunction; namespace cxx { - +void cleanupIncomingValues(llvm::PHINode &phi); class LogicalOrToAnd : public Mutator { static OR_AND_MutationType findPossibleMutation(Value &V); diff --git a/lib/Mutators/CXX/LogicalAndToOr.cpp b/lib/Mutators/CXX/LogicalAndToOr.cpp index 37c1d8da9..3474994e5 100644 --- a/lib/Mutators/CXX/LogicalAndToOr.cpp +++ b/lib/Mutators/CXX/LogicalAndToOr.cpp @@ -5,6 +5,7 @@ #include "mull/SourceLocation.h" #include +#include #include #include #include @@ -22,6 +23,24 @@ std::string LogicalAndToOr::description() { return "Replaces && with ||"; } +void mull::cxx::cleanupIncomingValues(llvm::PHINode &phi) { + std::unordered_set preds; + for (auto pred : predecessors(phi.getParent())) { + preds.insert(pred); + } + std::unordered_set toRemove; + for (auto &incoming : phi.incoming_values()) { + auto basicBlock = phi.getIncomingBlock(incoming); + if (!preds.count(basicBlock)) { + toRemove.insert(basicBlock); + } + } + + for (auto basicBlock : toRemove) { + phi.removeIncomingValue(basicBlock); + } +} + AND_OR_MutationType LogicalAndToOr::findPossibleMutation(Value &V) { auto *branchInst = dyn_cast(&V); @@ -53,15 +72,21 @@ void LogicalAndToOr::applyMutation(llvm::Function *function, const MutationPoint findPossibleMutationInBranch(branchInst, &secondBranch); if (possibleMutationType == AND_OR_MutationType_AND_to_OR_Pattern1) { - return applyMutationANDToOR_Pattern1(branchInst, secondBranch); + applyMutationANDToOR_Pattern1(branchInst, secondBranch); } if (possibleMutationType == AND_OR_MutationType_AND_to_OR_Pattern2) { - return applyMutationANDToOR_Pattern2(branchInst, secondBranch); + applyMutationANDToOR_Pattern2(branchInst, secondBranch); } if (possibleMutationType == AND_OR_MutationType_AND_to_OR_Pattern3) { - return applyMutationANDToOR_Pattern3(branchInst, secondBranch); + applyMutationANDToOR_Pattern3(branchInst, secondBranch); + } + + for (auto &instruction : llvm::instructions(function)) { + if (llvm::isa(instruction)) { + cleanupIncomingValues(llvm::cast(instruction)); + } } } diff --git a/lib/Mutators/CXX/LogicalOrToAnd.cpp b/lib/Mutators/CXX/LogicalOrToAnd.cpp index 470853ab0..680f8351c 100644 --- a/lib/Mutators/CXX/LogicalOrToAnd.cpp +++ b/lib/Mutators/CXX/LogicalOrToAnd.cpp @@ -53,15 +53,20 @@ void LogicalOrToAnd::applyMutation(llvm::Function *function, const MutationPoint findPossibleMutationInBranch(branchInst, &secondBranch); if (possibleMutationType == OR_AND_MutationType_OR_to_AND_Pattern1) { - return applyMutationORToAND_Pattern1(branchInst, secondBranch); + applyMutationORToAND_Pattern1(branchInst, secondBranch); } if (possibleMutationType == OR_AND_MutationType_OR_to_AND_Pattern2) { - return applyMutationORToAND_Pattern2(branchInst, secondBranch); + applyMutationORToAND_Pattern2(branchInst, secondBranch); } if (possibleMutationType == OR_AND_MutationType_OR_to_AND_Pattern3) { - return applyMutationORToAND_Pattern3(branchInst, secondBranch); + applyMutationORToAND_Pattern3(branchInst, secondBranch); + } + for (auto &instruction : llvm::instructions(function)) { + if (llvm::isa(instruction)) { + cleanupIncomingValues(llvm::cast(instruction)); + } } } diff --git a/tests-lit/tests/mutations/logical/phi_nodes/main.c b/tests-lit/tests/mutations/logical/phi_nodes/main.c new file mode 100644 index 000000000..ab7dacc2c --- /dev/null +++ b/tests-lit/tests/mutations/logical/phi_nodes/main.c @@ -0,0 +1,23 @@ +// clang-format off + +int main() { + int a = 1; + a = a && a && a; + int b = 2; + b = b || b || b; + return 0; +} + +// RUN: %clang_cc %sysroot -O0 %pass_mull_ir_frontend -g %s -o %s.exe +// RUN: unset TERM; %mull_runner -reporters=IDE %s.exe | %filecheck %s --dump-input=fail +// CHECK:[info] Survived mutants (3/3): +// CHECK-NEXT:{{.*}}main.c:5:9: warning: Survived: Replaced && with || [cxx_logical_and_to_or] +// CHECK-NEXT: a = a && a && a; +// CHECK-NEXT: ^ +// CHECK-NEXT:{{.*}}main.c:5:14: warning: Survived: Replaced && with || [cxx_logical_and_to_or] +// CHECK-NEXT: a = a && a && a; +// CHECK-NEXT: ^ +// CHECK-NEXT:{{.*}}main.c:7:9: warning: Survived: Replaced || with && [cxx_logical_or_to_and] +// CHECK-NEXT: b = b || b || b; +// CHECK-NEXT: ^ +// CHECK-NEXT:[info] Mutation score: 0% diff --git a/tests-lit/tests/mutations/logical/phi_nodes/mull.yml b/tests-lit/tests/mutations/logical/phi_nodes/mull.yml new file mode 100644 index 000000000..70eaf4744 --- /dev/null +++ b/tests-lit/tests/mutations/logical/phi_nodes/mull.yml @@ -0,0 +1,3 @@ +mutators: + - cxx_logical_and_to_or + - cxx_logical_or_to_and