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 declarations at very start of file #199

Merged
merged 2 commits into from
Nov 22, 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
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,6 @@ class MutateVisitor : public clang::RecursiveASTVisitor<MutateVisitor> {
return mutation_tree_root_;
}

[[nodiscard]] clang::SourceLocation GetStartLocationOfFirstDeclInSourceFile()
const {
return start_location_of_first_decl_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 @@ -170,10 +165,6 @@ class MutateVisitor : public clang::RecursiveASTVisitor<MutateVisitor> {
const clang::CompilerInstance* compiler_instance_;
bool optimise_mutations_;

// Records the start locat of the very first declaration in the source file,
// before which Dredd's prelude can be placed.
clang::SourceLocation start_location_of_first_decl_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
21 changes: 12 additions & 9 deletions src/libdredd/src/mutate_ast_consumer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -92,20 +92,21 @@ void MutateAstConsumer::HandleTranslationUnit(clang::ASTContext& ast_context) {

*mutation_info_->add_info_for_files() = mutation_info_for_file;

const clang::SourceLocation start_location_of_first_decl_in_source_file =
visitor_->GetStartLocationOfFirstDeclInSourceFile();
assert(start_location_of_first_decl_in_source_file.isValid() &&
"There is at least one mutation, therefore there must be at least one "
"declaration.");
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.");

// 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_location_of_first_decl_in_source_file, decl);
const bool rewriter_result =
rewriter_.InsertTextBefore(start_of_source_file, decl);
(void)rewriter_result; // Keep release-mode compilers happy.
assert(!rewriter_result && "Rewrite failed.\n");
}
Expand All @@ -115,8 +116,8 @@ void MutateAstConsumer::HandleTranslationUnit(clang::ASTContext& ast_context) {
? GetDreddPreludeCpp(initial_mutation_id)
: GetDreddPreludeC(initial_mutation_id);

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

Expand Down Expand Up @@ -270,6 +271,7 @@ std::string MutateAstConsumer::GetRegularDreddPreludeC(

std::stringstream result;
result << "#include <inttypes.h>\n";
result << "#include <stdbool.h>\n";
result << "#include <stdlib.h>\n";
result << "#include <string.h>\n";
result << "\n";
Expand Down Expand Up @@ -327,6 +329,7 @@ std::string MutateAstConsumer::GetMutantTrackingDreddPreludeC(
std::stringstream result;
result << "#include <inttypes.h>\n";
result << "#include <stdatomic.h>\n";
result << "#include <stdbool.h>\n";
result << "#include <stdio.h>\n";
result << "#include <stdlib.h>\n";
result << "\n";
Expand Down
18 changes: 0 additions & 18 deletions src/libdredd/src/mutate_visitor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Frontend/CompilerInstance.h"
#include "libdredd/mutation.h"
#include "libdredd/mutation_remove_stmt.h"
Expand Down Expand Up @@ -109,23 +108,6 @@ bool MutateVisitor::TraverseDecl(clang::Decl* decl) {
// consider it for mutation.
return true;
}
const clang::BeforeThanCompare<clang::SourceLocation> comparator(
compiler_instance_->getSourceManager());
if (start_location_of_first_decl_in_source_file_.isInvalid() ||
comparator(source_range_in_main_file.getBegin(),
start_location_of_first_decl_in_source_file_)) {
// This is the first declaration wholly contained in the main file that has
// been encountered so far: record it so that the dredd prelude can be
// inserted before it.
//
// The order in which declarations appear in the source file may not exactly
// match the order they are visited in the AST (for example, a typedef
// declaration is visited after the associated type declaration, even though
// the 'typedef' keyword occurs first in the AST), thus this location is
// updated each time a declaration that appears earlier is encountered.
start_location_of_first_decl_in_source_file_ =
source_range_in_main_file.getBegin();
}
if (llvm::dyn_cast<clang::StaticAssertDecl>(decl) != nullptr) {
// It does not make sense to mutate static assertions, as (a) this will
// very likely lead to compile-time failures due to the assertion not
Expand Down
1 change: 1 addition & 0 deletions test/single_file/add.c.expected
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

Expand Down
1 change: 1 addition & 0 deletions test/single_file/add.c.noopt.expected
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

Expand Down
1 change: 1 addition & 0 deletions test/single_file/add_float.c.expected
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

Expand Down
1 change: 1 addition & 0 deletions test/single_file/add_float.c.noopt.expected
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

Expand Down
1 change: 1 addition & 0 deletions test/single_file/add_mul.c.expected
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

Expand Down
1 change: 1 addition & 0 deletions test/single_file/add_mul.c.noopt.expected
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

Expand Down
7 changes: 4 additions & 3 deletions test/single_file/add_type_aliases.c.noopt.expected
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#include <inttypes.h>
#include <stddef.h>

#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

Expand Down Expand Up @@ -154,6 +152,9 @@ 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,6 +1,3 @@
#include <cinttypes>
#include <cstddef>

#include <cinttypes>
#include <cstddef>
#include <functional>
Expand Down Expand Up @@ -157,6 +154,9 @@ 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
1 change: 1 addition & 0 deletions test/single_file/assign.c.expected
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

Expand Down
1 change: 1 addition & 0 deletions test/single_file/assign.c.noopt.expected
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

Expand Down
1 change: 1 addition & 0 deletions test/single_file/basic.c.expected
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

Expand Down
1 change: 1 addition & 0 deletions test/single_file/basic.c.noopt.expected
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

Expand Down
1 change: 1 addition & 0 deletions test/single_file/binary_operands_both_zero.c.expected
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

Expand Down
1 change: 1 addition & 0 deletions test/single_file/bitfield.c.expected
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

Expand Down
1 change: 1 addition & 0 deletions test/single_file/bitfield.c.noopt.expected
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#include <stdbool.h>

#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

Expand Down Expand Up @@ -72,6 +71,8 @@ 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,6 +1,5 @@
#include <stdbool.h>

#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

Expand Down Expand Up @@ -68,6 +67,8 @@ 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);
}
1 change: 1 addition & 0 deletions test/single_file/comma.c.expected
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

Expand Down
1 change: 1 addition & 0 deletions test/single_file/comma.c.noopt.expected
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

Expand Down
5 changes: 5 additions & 0 deletions test/single_file/comment_at_start_of_file.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Hello

int main() {
return 42;
}
59 changes: 59 additions & 0 deletions test/single_file/comment_at_start_of_file.cc.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#include <cinttypes>
#include <cstddef>
#include <functional>
#include <string>


#ifdef _MSC_VER
#define thread_local __declspec(thread)
#elif __APPLE__
#define thread_local __thread
#endif

static thread_local bool __dredd_some_mutation_enabled = true;
static bool __dredd_enabled_mutation(int local_mutation_id) {
static thread_local bool initialized = false;
static thread_local uint64_t enabled_bitset[1];
if (!initialized) {
bool some_mutation_enabled = false;
const char* dredd_environment_variable = std::getenv("DREDD_ENABLED_MUTATION");
if (dredd_environment_variable != nullptr) {
std::string contents(dredd_environment_variable);
while (true) {
size_t pos = contents.find(",");
std::string token = (pos == std::string::npos ? contents : contents.substr(0, pos));
if (!token.empty()) {
int value = std::stoi(token);
int local_value = value - 0;
if (local_value >= 0 && local_value < 6) {
enabled_bitset[local_value / 64] |= (1 << (local_value % 64));
some_mutation_enabled = true;
}
}
if (pos == std::string::npos) {
break;
}
contents.erase(0, pos + 1);
}
}
initialized = true;
__dredd_some_mutation_enabled = some_mutation_enabled;
}
return (enabled_bitset[local_mutation_id / 64] & (1 << (local_mutation_id % 64))) != 0;
}

static int __dredd_replace_expr_int_constant(int arg, int local_mutation_id) {
if (!__dredd_some_mutation_enabled) return arg;
if (__dredd_enabled_mutation(local_mutation_id + 0)) return ~(arg);
if (__dredd_enabled_mutation(local_mutation_id + 1)) return -(arg);
if (__dredd_enabled_mutation(local_mutation_id + 2)) return 0;
if (__dredd_enabled_mutation(local_mutation_id + 3)) return 1;
if (__dredd_enabled_mutation(local_mutation_id + 4)) return -1;
return arg;
}

// Hello

int main() {
if (!__dredd_enabled_mutation(5)) { return __dredd_replace_expr_int_constant(42, 0); }
}
Loading