Skip to content

Commit

Permalink
Merge pull request #512 from mull-project/junk_detection_replace_call
Browse files Browse the repository at this point in the history
Junk detection for ReplaceCall mutator
  • Loading branch information
AlexDenisov committed May 12, 2019
2 parents 64f5e33 + e2364c4 commit c3d321d
Show file tree
Hide file tree
Showing 9 changed files with 128 additions and 1 deletion.
26 changes: 26 additions & 0 deletions include/mull/JunkDetection/CXX/Visitors/ReplaceCallVisitor.h
@@ -0,0 +1,26 @@
#pragma once

#include "InstructionRangeVisitor.h"
#include "VisitorParameters.h"

#include <clang/AST/RecursiveASTVisitor.h>

namespace mull {

class ReplaceCallVisitor
: public clang::RecursiveASTVisitor<ReplaceCallVisitor> {
public:
ReplaceCallVisitor(const VisitorParameters &parameters);

bool VisitCallExpr(clang::CallExpr *callExpression);
bool VisitCXXMemberCallExpr(clang::CXXMemberCallExpr *callExpression);
bool VisitCXXOperatorCallExpr(clang::CXXOperatorCallExpr *callExpression);
void handleCallExpr(clang::CallExpr *callExpression);
bool foundMutant();

private:
InstructionRangeVisitor visitor;
const clang::ASTContext &astContext;
};

} // namespace mull
1 change: 1 addition & 0 deletions include/mull/Mutators/Mutator.h
Expand Up @@ -27,6 +27,7 @@ enum class MutatorKind {
MathMulMutator,
NegateMutator,
RemoveVoidFunctionMutator,
ReplaceCallMutator,
AndOrReplacementMutator,
};

Expand Down
1 change: 1 addition & 0 deletions include/mull/Mutators/ReplaceCallMutator.h
Expand Up @@ -23,6 +23,7 @@ class ReplaceCallMutator : public Mutator {
std::string getUniqueIdentifier() override { return ID; }
std::string getUniqueIdentifier() const override { return ID; }
std::string getDescription() const override { return description; }
MutatorKind mutatorKind() override { return MutatorKind::ReplaceCallMutator; }

bool canBeApplied(llvm::Value &V) override;
llvm::Value *applyMutation(llvm::Function *function,
Expand Down
2 changes: 1 addition & 1 deletion lib/CMakeLists.txt
Expand Up @@ -84,7 +84,7 @@ set(mull_sources
JunkDetection/CXX/Visitors/NegateConditionVisitor.cpp
JunkDetection/CXX/ASTStorage.cpp
JunkDetection/CXX/CompilationDatabase.cpp
Reporters/IDEReporter.cpp TestFrameworks/NativeTestRunner.cpp JunkDetection/CXX/Visitors/AndOrReplacementVisitor.cpp JunkDetection/CXX/Visitors/MathMulVisitor.cpp JunkDetection/CXX/Visitors/MathDivVisitor.cpp)
Reporters/IDEReporter.cpp TestFrameworks/NativeTestRunner.cpp JunkDetection/CXX/Visitors/AndOrReplacementVisitor.cpp JunkDetection/CXX/Visitors/MathMulVisitor.cpp JunkDetection/CXX/Visitors/MathDivVisitor.cpp JunkDetection/CXX/Visitors/ReplaceCallVisitor.cpp)

set (MULL_INCLUDE_DIR ${MULL_SOURCE_DIR}/include/mull)

Expand Down
3 changes: 3 additions & 0 deletions lib/JunkDetection/CXX/CXXJunkDetector.cpp
Expand Up @@ -12,6 +12,7 @@
#include "mull/JunkDetection/CXX/Visitors/MathSubVisitor.h"
#include "mull/JunkDetection/CXX/Visitors/NegateConditionVisitor.h"
#include "mull/JunkDetection/CXX/Visitors/RemoveVoidFunctionVisitor.h"
#include "mull/JunkDetection/CXX/Visitors/ReplaceCallVisitor.h"

using namespace mull;

Expand Down Expand Up @@ -55,6 +56,8 @@ bool CXXJunkDetector::isJunk(MutationPoint *point) {
return isJunkMutation<MathDivVisitor>(astStorage, point);
case MutatorKind::RemoveVoidFunctionMutator:
return isJunkMutation<RemoveVoidFunctionVisitor>(astStorage, point);
case MutatorKind::ReplaceCallMutator:
return isJunkMutation<ReplaceCallVisitor>(astStorage, point);
case MutatorKind::NegateMutator:
return isJunkMutation<NegateConditionVisitor>(astStorage, point);
case MutatorKind::AndOrReplacementMutator:
Expand Down
33 changes: 33 additions & 0 deletions lib/JunkDetection/CXX/Visitors/ReplaceCallVisitor.cpp
@@ -0,0 +1,33 @@
#include "mull/JunkDetection/CXX/Visitors/ReplaceCallVisitor.h"

using namespace mull;

ReplaceCallVisitor::ReplaceCallVisitor(const VisitorParameters &parameters)
: visitor(parameters), astContext(parameters.astContext) {}

bool ReplaceCallVisitor::VisitCallExpr(clang::CallExpr *callExpression) {
handleCallExpr(callExpression);
return true;
}

bool ReplaceCallVisitor::VisitCXXMemberCallExpr(
clang::CXXMemberCallExpr *callExpression) {
handleCallExpr(callExpression);
return true;
}

bool ReplaceCallVisitor::VisitCXXOperatorCallExpr(
clang::CXXOperatorCallExpr *callExpression) {
handleCallExpr(callExpression);
return true;
}

void ReplaceCallVisitor::handleCallExpr(clang::CallExpr *callExpression) {
auto *type = callExpression->getType().getTypePtrOrNull();
/// Real Type = float, double, long double, integer
if (type && type->isRealType()) {
visitor.visitRangeWithLocation(callExpression->getSourceRange());
}
}

bool ReplaceCallVisitor::foundMutant() { return visitor.foundRange(); }
4 changes: 4 additions & 0 deletions tests/JunkDetection/CXXJunkDetectorTests.cpp
Expand Up @@ -13,6 +13,7 @@
#include "mull/Mutators/MathSubMutator.h"
#include "mull/Mutators/NegateConditionMutator.h"
#include "mull/Mutators/RemoveVoidFunctionMutator.h"
#include "mull/Mutators/ReplaceCallMutator.h"
#include "mull/Program/Program.h"
#include "mull/Testee.h"
#include "mull/Toolchain/Compiler.h"
Expand Down Expand Up @@ -124,6 +125,9 @@ static const CXXJunkDetectorTestParameter parameters[] = {
CXXJunkDetectorTestParameter(
fixtures::mutators_remove_void_function_junk_bc_path(),
new RemoveVoidFunctionMutator, 9, 6),
CXXJunkDetectorTestParameter(fixtures::mutators_replace_call_junk_bc_path(),
new ReplaceCallMutator, 12, 11),

CXXJunkDetectorTestParameter(
fixtures::mutators_negate_condition_junk_bc_path(),
new NegateConditionMutator, 42, 30),
Expand Down
5 changes: 5 additions & 0 deletions tests/fixtures/mutators/replace_call/CMakeLists.txt
Expand Up @@ -4,3 +4,8 @@ compile_fixture(
FLAGS -g -c -emit-llvm
)

compile_fixture(
INPUT ${CMAKE_CURRENT_LIST_DIR}/junk.cpp
OUTPUT_EXTENSION bc
FLAGS -g -c -emit-llvm
)
54 changes: 54 additions & 0 deletions tests/fixtures/mutators/replace_call/junk.cpp
@@ -0,0 +1,54 @@
#define call_wrap(x) x()

extern "C" int external_function(int a, int b, int c);
extern "C" float external_function_f(float a, float b, float c);

int sum(int x, int b) {
return x + b;
}

int bar();

int foo() {
int r = sum(5, 8);
int s = bar();
int q = call_wrap(bar);
int a = external_function(r, s, q);
int b = external_function_f(r, s, q);

return r + s + q + a + b;
}

class FooBar {
public:
FooBar(int x) : i(x) {}

int getValue() { return i; }
int increment() { return i++; }
int decrement() { return i--; }
private:
int i;
};

struct Buzz {
int x;
int y;
int z;
int w;
};

int bar() {
FooBar fbr(42);
external_function(fbr.increment(), fbr.increment(), fbr.increment());

external_function(fbr.getValue(), 0, 0);

return fbr.decrement();
}

void buzz() {
Buzz b;
Buzz a = b;
Buzz c;
c = a;
}

0 comments on commit c3d321d

Please sign in to comment.