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

Insert Dredd declartions before first function #220

Merged
merged 8 commits into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from 6 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
17 changes: 17 additions & 0 deletions src/libdredd/include_private/include/libdredd/mutate_visitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Frontend/CompilerInstance.h"
#include "libdredd/mutation.h"
#include "libdredd/mutation_tree_node.h"

namespace dredd {
Expand Down Expand Up @@ -108,6 +109,11 @@ class MutateVisitor : public clang::RecursiveASTVisitor<MutateVisitor> {
return constant_sized_arrays_to_rewrite_;
}

[[nodiscard]] clang::SourceLocation
GetStartLocationOfFirstFunctionInSourceFile() const {
return start_location_of_first_function_in_source_file_;
}

private:
// Helper class that uses the RAII pattern to support pushing a new mutation
// tree node on to the stack of mutation tree nodes used during visitation,
Expand Down Expand Up @@ -174,9 +180,20 @@ class MutateVisitor : public clang::RecursiveASTVisitor<MutateVisitor> {
// this special case, so that it can be ignored.
bool IsConversionOfEnumToConstructor(const clang::Expr& expr) const;

// It is safe to put Dredd's prelude before the first function we encounter in
// a file as Dredd only makes source code modifications inside functions.
void UpdateStartLocationOfFirstFunctionInSourceFile();

// TODO(JLJ): Add comment
JamesLee-Jones marked this conversation as resolved.
Show resolved Hide resolved
void AddMutation(std::unique_ptr<Mutation> mutation);

const clang::CompilerInstance* compiler_instance_;
bool optimise_mutations_;

// Records the start location of the very first function definition in the
// source file, before which Dredd's prelude can be placed.
clang::SourceLocation start_location_of_first_function_in_source_file_;

// Tracks the nest of declarations currently being traversed. Any new Dredd
// functions will be put before the start of the current nest, which avoids
// e.g. putting a Dredd function inside a class or function.
Expand Down
19 changes: 9 additions & 10 deletions src/libdredd/src/mutate_ast_consumer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -137,21 +137,20 @@ void MutateAstConsumer::HandleTranslationUnit(clang::ASTContext& ast_context) {

*mutation_info_->add_info_for_files() = mutation_info_for_file;

auto& source_manager = ast_context.getSourceManager();
const clang::SourceLocation start_of_source_file =
source_manager.translateLineCol(source_manager.getMainFileID(), 1, 1);
assert(start_of_source_file.isValid() &&
"There is at least one mutation, therefore the file must have some "
"content.");
const clang::SourceLocation start_location_of_first_function_in_source_file =
visitor_->GetStartLocationOfFirstFunctionInSourceFile();
assert(start_location_of_first_function_in_source_file.isValid() &&
"There is at least one mutation, therefore there must be at least one "
"function.");

// Convert the unordered set Dredd declarations into an ordered set and add
// them to the source file before the first declaration.
std::set<std::string> sorted_dredd_declarations;
sorted_dredd_declarations.insert(dredd_declarations.begin(),
dredd_declarations.end());
for (const auto& decl : sorted_dredd_declarations) {
const bool rewriter_result =
rewriter_.InsertTextBefore(start_of_source_file, decl);
const bool rewriter_result = rewriter_.InsertTextBefore(
start_location_of_first_function_in_source_file, decl);
(void)rewriter_result; // Keep release-mode compilers happy.
assert(!rewriter_result && "Rewrite failed.\n");
}
Expand All @@ -161,8 +160,8 @@ void MutateAstConsumer::HandleTranslationUnit(clang::ASTContext& ast_context) {
? GetDreddPreludeCpp(initial_mutation_id)
: GetDreddPreludeC(initial_mutation_id);

bool rewriter_result =
rewriter_.InsertTextBefore(start_of_source_file, dredd_prelude);
bool rewriter_result = rewriter_.InsertTextBefore(
start_location_of_first_function_in_source_file, dredd_prelude);
(void)rewriter_result; // Keep release-mode compilers happy.
assert(!rewriter_result && "Rewrite failed.\n");

Expand Down
45 changes: 32 additions & 13 deletions src/libdredd/src/mutate_visitor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TypeTraits.h"
#include "clang/Frontend/CompilerInstance.h"
#include "libdredd/mutation.h"
Expand Down Expand Up @@ -63,6 +64,21 @@ bool MutateVisitor::IsTypeSupported(const clang::QualType qual_type) {
(builtin_type->isInteger() || builtin_type->isFloatingPoint());
}

void MutateVisitor::UpdateStartLocationOfFirstFunctionInSourceFile() {
if (IsInFunction()) {
const clang::BeforeThanCompare<clang::SourceLocation> comparator(
compiler_instance_->getSourceManager());
auto source_range_in_main_file = GetSourceRangeInMainFile(
compiler_instance_->getPreprocessor(), *enclosing_decls_[0]);
if (start_location_of_first_function_in_source_file_.isInvalid() ||
comparator(source_range_in_main_file.getBegin(),
start_location_of_first_function_in_source_file_)) {
start_location_of_first_function_in_source_file_ =
source_range_in_main_file.getBegin();
}
}
}

bool MutateVisitor::IsInFunction() {
// Walk up the next of enclosing declarations
for (int index = static_cast<int>(enclosing_decls_.size()) - 1; index >= 0;
Expand Down Expand Up @@ -352,10 +368,9 @@ void MutateVisitor::HandleUnaryOperator(clang::UnaryOperator* unary_operator) {
}
}

mutation_tree_path_.back()->AddMutation(
std::make_unique<MutationReplaceUnaryOperator>(
*unary_operator, compiler_instance_->getPreprocessor(),
compiler_instance_->getASTContext()));
AddMutation(std::make_unique<MutationReplaceUnaryOperator>(
*unary_operator, compiler_instance_->getPreprocessor(),
compiler_instance_->getASTContext()));
}

void MutateVisitor::HandleBinaryOperator(
Expand Down Expand Up @@ -415,10 +430,9 @@ void MutateVisitor::HandleBinaryOperator(
return;
}

mutation_tree_path_.back()->AddMutation(
std::make_unique<MutationReplaceBinaryOperator>(
*binary_operator, compiler_instance_->getPreprocessor(),
compiler_instance_->getASTContext()));
AddMutation(std::make_unique<MutationReplaceBinaryOperator>(
*binary_operator, compiler_instance_->getPreprocessor(),
compiler_instance_->getASTContext()));
}

void MutateVisitor::HandleExpr(clang::Expr* expr) {
Expand Down Expand Up @@ -508,7 +522,7 @@ void MutateVisitor::HandleExpr(clang::Expr* expr) {
}
}

mutation_tree_path_.back()->AddMutation(std::make_unique<MutationReplaceExpr>(
AddMutation(std::make_unique<MutationReplaceExpr>(
*expr, compiler_instance_->getPreprocessor(),
compiler_instance_->getASTContext()));
}
Expand Down Expand Up @@ -555,6 +569,7 @@ bool MutateVisitor::VisitExpr(clang::Expr* expr) {
return true;
}

UpdateStartLocationOfFirstFunctionInSourceFile();
JamesLee-Jones marked this conversation as resolved.
Show resolved Hide resolved
if (auto* unary_operator = llvm::dyn_cast<clang::UnaryOperator>(expr)) {
HandleUnaryOperator(unary_operator);
}
Expand Down Expand Up @@ -621,14 +636,18 @@ bool MutateVisitor::TraverseCompoundStmt(clang::CompoundStmt* compound_stmt) {
assert(!enclosing_decls_.empty() &&
"Statements can only be removed if they are nested in some "
"declaration.");
mutation_tree_path_.back()->AddMutation(
std::make_unique<MutationRemoveStmt>(
*target_stmt, compiler_instance_->getPreprocessor(),
compiler_instance_->getASTContext()));
AddMutation(std::make_unique<MutationRemoveStmt>(
*target_stmt, compiler_instance_->getPreprocessor(),
compiler_instance_->getASTContext()));
}
return true;
}

void MutateVisitor::AddMutation(std::unique_ptr<Mutation> mutation) {
UpdateStartLocationOfFirstFunctionInSourceFile();
mutation_tree_path_.back()->AddMutation(std::move(mutation));
}

bool MutateVisitor::VisitVarDecl(clang::VarDecl* var_decl) {
var_decl_source_locations_.insert(var_decl->getLocation());
return true;
Expand Down
6 changes: 3 additions & 3 deletions test/single_file/add_type_aliases.c.noopt.expected
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#include <inttypes.h>
#include <stddef.h>

#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
Expand Down Expand Up @@ -152,9 +155,6 @@ static int __dredd_replace_binary_operator_Add_arg1_int_arg2_int(int arg1, int a
return arg1 + arg2;
}

#include <inttypes.h>
#include <stddef.h>

int main() {
unsigned a;
uint32_t b;
Expand Down
6 changes: 3 additions & 3 deletions test/single_file/add_type_aliases.cc.noopt.expected
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#include <cinttypes>
#include <cstddef>

#include <cinttypes>
#include <cstddef>
#include <functional>
Expand Down Expand Up @@ -154,9 +157,6 @@ static int __dredd_replace_binary_operator_Add_arg1_int_arg2_int(int arg1, int a
return arg1 + arg2;
}

#include <cinttypes>
#include <cstddef>

int main() {
unsigned a;
uint32_t b;
Expand Down
10 changes: 5 additions & 5 deletions test/single_file/bitfield.c.expected
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
struct S {
int a : 3;
int b : 3;
};

#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
Expand Down Expand Up @@ -58,11 +63,6 @@ static int __dredd_replace_expr_int(int arg, int local_mutation_id) {
return arg;
}

struct S {
int a : 3;
int b : 3;
};

void foo() {
struct S myS;
if (!__dredd_enabled_mutation(6)) { myS.a = __dredd_replace_expr_int(myS.b, 0); }
Expand Down
10 changes: 5 additions & 5 deletions test/single_file/bitfield.c.noopt.expected
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
struct S {
int a : 3;
int b : 3;
};

#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
Expand Down Expand Up @@ -59,11 +64,6 @@ static int __dredd_replace_expr_int(int arg, int local_mutation_id) {
return arg;
}

struct S {
int a : 3;
int b : 3;
};

void foo() {
struct S myS;
if (!__dredd_enabled_mutation(12)) { __dredd_replace_expr_int(myS.a = __dredd_replace_expr_int(myS.b, 0), 6); }
Expand Down
10 changes: 5 additions & 5 deletions test/single_file/bitfield.cc.expected
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
struct S {
int a : 3;
int b : 3;
};

#include <cinttypes>
#include <cstddef>
#include <functional>
Expand Down Expand Up @@ -60,11 +65,6 @@ static int __dredd_replace_expr_int(int arg, int local_mutation_id) {
return arg;
}

struct S {
int a : 3;
int b : 3;
};

void foo() {
S myS;
if (!__dredd_enabled_mutation(6)) { myS.a = __dredd_replace_expr_int(myS.b, 0); }
Expand Down
10 changes: 5 additions & 5 deletions test/single_file/bitfield.cc.noopt.expected
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
struct S {
int a : 3;
int b : 3;
};

#include <cinttypes>
#include <cstddef>
#include <functional>
Expand Down Expand Up @@ -72,11 +77,6 @@ static int __dredd_replace_expr_int(int arg, int local_mutation_id) {
return arg;
}

struct S {
int a : 3;
int b : 3;
};

void foo() {
S myS;
if (!__dredd_enabled_mutation(6)) { myS.a = __dredd_replace_expr_int(myS.b, 0); }
Expand Down
12 changes: 6 additions & 6 deletions test/single_file/bitfield_reference_passing.cc.expected
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
template<typename T> void bloop(T& x) { }

struct foo {
int b : 2;
};

#include <cinttypes>
#include <cstddef>
#include <functional>
Expand Down Expand Up @@ -42,12 +48,6 @@ static bool __dredd_enabled_mutation(int local_mutation_id) {
return (enabled_bitset[local_mutation_id / 64] & (static_cast<uint64_t>(1) << (local_mutation_id % 64))) != 0;
}

template<typename T> void bloop(T& x) { }

struct foo {
int b : 2;
};

int main() {
const foo d = foo();
if (!__dredd_enabled_mutation(0)) { bloop(d.b); }
Expand Down
12 changes: 6 additions & 6 deletions test/single_file/bitfield_reference_passing.cc.noopt.expected
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
template<typename T> void bloop(T& x) { }

struct foo {
int b : 2;
};

#include <cinttypes>
#include <cstddef>
#include <functional>
Expand Down Expand Up @@ -42,12 +48,6 @@ static bool __dredd_enabled_mutation(int local_mutation_id) {
return (enabled_bitset[local_mutation_id / 64] & (static_cast<uint64_t>(1) << (local_mutation_id % 64))) != 0;
}

template<typename T> void bloop(T& x) { }

struct foo {
int b : 2;
};

int main() {
const foo d = foo();
if (!__dredd_enabled_mutation(0)) { bloop(d.b); }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include <stdbool.h>

#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
Expand Down Expand Up @@ -71,8 +73,6 @@ static int __dredd_replace_binary_operator_LAnd_arg1_int_arg2_int_rhs_zero_lhs_o
if (__dredd_enabled_mutation(local_mutation_id + 2)) return 1;
return arg;
}
#include <stdbool.h>

int main() {
int x = __dredd_replace_expr_int_zero(__dredd_replace_binary_operator_LAnd_arg1_int_arg2_int_rhs_zero_lhs_one_outer(__dredd_replace_binary_operator_LAnd_arg1_int_arg2_int_rhs_zero_lhs_one_lhs(__dredd_replace_expr_int_one(1, 0), 5) && __dredd_replace_binary_operator_LAnd_arg1_int_arg2_int_rhs_zero_lhs_one_rhs(__dredd_replace_expr_int_zero(0, 3), 5), 5), 8);
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include <stdbool.h>

#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
Expand Down Expand Up @@ -67,8 +69,6 @@ static int __dredd_replace_binary_operator_LAnd_arg1_int_arg2_int_lhs(int arg, i
if (__dredd_enabled_mutation(local_mutation_id + 2)) return 1;
return arg;
}
#include <stdbool.h>

int main() {
int x = __dredd_replace_expr_int(__dredd_replace_binary_operator_LAnd_arg1_int_arg2_int_outer(__dredd_replace_binary_operator_LAnd_arg1_int_arg2_int_lhs(__dredd_replace_expr_int(1, 0), 12) && __dredd_replace_binary_operator_LAnd_arg1_int_arg2_int_rhs(__dredd_replace_expr_int(0, 6), 12), 12), 15);
}
4 changes: 2 additions & 2 deletions test/single_file/comment.cc.expected
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
void g();

#include <cinttypes>
#include <cstddef>
#include <functional>
Expand Down Expand Up @@ -48,8 +50,6 @@ static bool __dredd_replace_expr_bool_true(bool arg, int local_mutation_id) {
return arg;
}

void g();

void f()
{
if (!__dredd_enabled_mutation(0)) { g() /* something */ ; }
Expand Down
Loading
Loading