Skip to content
Open
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
3 changes: 2 additions & 1 deletion src/libdredd/include/libdredd/mutation.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ class Mutation {
bool optimise_mutations, bool only_track_mutant_coverage,
int first_mutation_id_in_file, int& mutation_id,
clang::Rewriter& rewriter,
std::unordered_set<std::string>& dredd_declarations) const = 0;
std::unordered_set<std::string>& dredd_declarations,
std::unordered_set<std::string>& dredd_macros) const = 0;
};

} // namespace dredd
Expand Down
3 changes: 2 additions & 1 deletion src/libdredd/include/libdredd/mutation_remove_stmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ class MutationRemoveStmt : public Mutation {
bool optimise_mutations, bool only_track_mutant_coverage,
int first_mutation_id_in_file, int& mutation_id,
clang::Rewriter& rewriter,
std::unordered_set<std::string>& dredd_declarations) const override;
std::unordered_set<std::string>& dredd_declarations,
std::unordered_set<std::string>& dredd_macros) const override;

private:
// Helper method to determine whether the token immediately following the
Expand Down
25 changes: 18 additions & 7 deletions src/libdredd/include/libdredd/mutation_replace_binary_operator.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,17 @@ class MutationReplaceBinaryOperator : public Mutation {
bool optimise_mutations, bool only_track_mutant_coverage,
int first_mutation_id_in_file, int& mutation_id,
clang::Rewriter& rewriter,
std::unordered_set<std::string>& dredd_declarations) const override;
std::unordered_set<std::string>& dredd_declarations,
std::unordered_set<std::string>& dredd_macros) const override;

private:
std::string GenerateMutatorFunction(
clang::ASTContext& ast_context, const std::string& function_name,
const std::string& result_type, const std::string& lhs_type,
const std::string& rhs_type, bool optimise_mutations,
bool only_track_mutant_coverage, int& mutation_id,
clang::ASTContext& ast_context,
std::unordered_set<std::string>& dredd_macros,
const std::string& function_name, const std::string& result_type,
const std::string& lhs_type, const std::string& rhs_type,
bool optimise_mutations, bool only_track_mutant_coverage,
int& mutation_id,
protobufs::MutationReplaceBinaryOperator& protobuf_message) const;

void ReplaceOperator(const std::string& lhs_type, const std::string& rhs_type,
Expand All @@ -62,6 +65,12 @@ class MutationReplaceBinaryOperator : public Mutation {
std::string GetFunctionName(bool optimise_mutations,
clang::ASTContext& ast_context) const;

static std::string OpKindToString(clang::BinaryOperatorKind kind);

[[nodiscard]] std::string GetBinaryMacroName(
const std::string& operator_name,
const clang::ASTContext& ast_context) const;

[[nodiscard]] bool IsRedundantReplacementOperator(
clang::BinaryOperatorKind operator_kind,
const clang::ASTContext& ast_context) const;
Expand All @@ -79,15 +88,17 @@ class MutationReplaceBinaryOperator : public Mutation {
// Replaces binary expressions with either the left or right operand.
void GenerateArgumentReplacement(
const std::string& arg1_evaluated, const std::string& arg2_evaluated,
const clang::ASTContext& ast_context, bool optimise_mutations,
const clang::ASTContext& ast_context,
std::unordered_set<std::string>& dredd_macros, bool optimise_mutations,
bool only_track_mutant_coverage, int mutation_id_base,
std::stringstream& new_function, int& mutation_id_offset,
protobufs::MutationReplaceBinaryOperator& protobuf_message) const;

// Replaces binary operators with other valid binary operators.
void GenerateBinaryOperatorReplacement(
const std::string& arg1_evaluated, const std::string& arg2_evaluated,
const clang::ASTContext& ast_context, bool optimise_mutations,
const clang::ASTContext& ast_context,
std::unordered_set<std::string>& dredd_macros, bool optimise_mutations,
bool only_track_mutant_coverage, int mutation_id_base,
std::stringstream& new_function, int& mutation_id_offset,
protobufs::MutationReplaceBinaryOperator& protobuf_message) const;
Expand Down
42 changes: 27 additions & 15 deletions src/libdredd/include/libdredd/mutation_replace_expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,12 @@ class MutationReplaceExpr : public Mutation {
bool optimise_mutations, bool only_track_mutant_coverage,
int first_mutation_id_in_file, int& mutation_id,
clang::Rewriter& rewriter,
std::unordered_set<std::string>& dredd_declarations) const override;
std::unordered_set<std::string>& dredd_declarations,
std::unordered_set<std::string>& dredd_macros) const override;

[[nodiscard]] std::string GetExprMacroName(
const std::string& operator_name,
const clang::ASTContext& ast_context) const;

static void ApplyCppTypeModifiers(const clang::Expr& expr, std::string& type);

Expand Down Expand Up @@ -94,55 +99,62 @@ class MutationReplaceExpr : public Mutation {

// Replace expressions with constants.
void GenerateConstantReplacement(
clang::ASTContext& ast_context, bool optimise_mutations,
clang::ASTContext& ast_context,
std::unordered_set<std::string>& dredd_macros, bool optimise_mutations,
bool only_track_mutant_coverage, int mutation_id_base,
std::stringstream& new_function, int& mutation_id_offset,
protobufs::MutationReplaceExpr& protobuf_message) const;

void GenerateBooleanConstantReplacement(
clang::ASTContext& ast_context, bool optimise_mutations,
clang::ASTContext& ast_context,
std::unordered_set<std::string>& dredd_macros, bool optimise_mutations,
bool only_track_mutant_coverage, int mutation_id_base,
std::stringstream& new_function, int& mutation_id_offset,
protobufs::MutationReplaceExpr& protobuf_message) const;

void GenerateIntegerConstantReplacement(
const clang::ASTContext& ast_context, bool optimise_mutations,
const clang::ASTContext& ast_context,
std::unordered_set<std::string>& dredd_macros, bool optimise_mutations,
bool only_track_mutant_coverage, int mutation_id_base,
std::stringstream& new_function, int& mutation_id_offset,
protobufs::MutationReplaceExpr& protobuf_message) const;

void GenerateFloatConstantReplacement(
const clang::ASTContext& ast_context, bool optimise_mutations,
const clang::ASTContext& ast_context,
std::unordered_set<std::string>& dredd_macros, bool optimise_mutations,
bool only_track_mutant_coverage, int mutation_id_base,
std::stringstream& new_function, int& mutation_id_offset,
protobufs::MutationReplaceExpr& protobuf_message) const;

// Insert valid unary operators such as !, ~, ++ and --.
void GenerateUnaryOperatorInsertion(
const std::string& arg_evaluated, clang::ASTContext& ast_context,
bool optimise_mutations, bool only_track_mutant_coverage,
int mutation_id_base, std::stringstream& new_function,
int& mutation_id_offset,
std::unordered_set<std::string>& dredd_macros, bool optimise_mutations,
bool only_track_mutant_coverage, int mutation_id_base,
std::stringstream& new_function, int& mutation_id_offset,
protobufs::MutationReplaceExpr& protobuf_message) const;

void GenerateUnaryOperatorInsertionBeforeNonLValue(
const std::string& arg_evaluated, clang::ASTContext& ast_context,
bool optimise_mutations, bool only_track_mutant_coverage,
int mutation_id_base, std::stringstream& new_function,
int& mutation_id_offset,
std::unordered_set<std::string>& dredd_macros, bool optimise_mutations,
bool only_track_mutant_coverage, int mutation_id_base,
std::stringstream& new_function, int& mutation_id_offset,
protobufs::MutationReplaceExpr& protobuf_message) const;

void GenerateUnaryOperatorInsertionBeforeLValue(
const std::string& arg_evaluated, clang::ASTContext& ast_context,
std::unordered_set<std::string>& dredd_macros,
bool only_track_mutant_coverage, int mutation_id_base,
std::stringstream& new_function, int& mutation_id_offset,
protobufs::MutationReplaceExpr& protobuf_message) const;

std::string GenerateMutatorFunction(
clang::ASTContext& ast_context, const std::string& function_name,
const std::string& result_type, const std::string& input_type,
bool optimise_mutations, bool only_track_mutant_coverage,
int& mutation_id, protobufs::MutationReplaceExpr& protobuf_message) const;
clang::ASTContext& ast_context,
std::unordered_set<std::string>& dredd_macros,
const std::string& function_name, const std::string& result_type,
const std::string& input_type, bool optimise_mutations,
bool only_track_mutant_coverage, int& mutation_id,
protobufs::MutationReplaceExpr& protobuf_message) const;

[[nodiscard]] std::string GetFunctionName(
bool optimise_mutations, clang::ASTContext& ast_context) const;
Expand Down
24 changes: 16 additions & 8 deletions src/libdredd/include/libdredd/mutation_replace_unary_operator.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,16 @@ class MutationReplaceUnaryOperator : public Mutation {
bool optimise_mutations, bool only_track_mutant_coverage,
int first_mutation_id_in_file, int& mutation_id,
clang::Rewriter& rewriter,
std::unordered_set<std::string>& dredd_declarations) const override;
std::unordered_set<std::string>& dredd_declarations,
std::unordered_set<std::string>& dredd_macros) const override;

private:
std::string GenerateMutatorFunction(
clang::ASTContext& ast_context, const std::string& function_name,
const std::string& result_type, const std::string& input_type,
bool optimise_mutations, bool only_track_mutant_coverage,
int& mutation_id,
clang::ASTContext& ast_context,
std::unordered_set<std::string>& dredd_macros,
const std::string& function_name, const std::string& result_type,
const std::string& input_type, bool optimise_mutations,
bool only_track_mutant_coverage, int& mutation_id,
protobufs::MutationReplaceUnaryOperator& protobuf_message) const;

[[nodiscard]] static bool IsPrefix(clang::UnaryOperatorKind operator_kind);
Expand All @@ -65,12 +67,18 @@ class MutationReplaceUnaryOperator : public Mutation {
std::string GetFunctionName(bool optimise_mutations,
clang::ASTContext& ast_context) const;

static std::string OpKindToString(clang::UnaryOperatorKind kind);

[[nodiscard]] std::string GetUnaryMacroName(
const std::string& operator_name,
const clang::ASTContext& ast_context) const;

// Replaces unary operators with other valid unary operators.
void GenerateUnaryOperatorReplacement(
const std::string& arg_evaluated, const clang::ASTContext& ast_context,
bool optimise_mutations, bool only_track_mutant_coverage,
int mutation_id_base, std::stringstream& new_function,
int& mutation_id_offset,
std::unordered_set<std::string>& dredd_macros, bool optimise_mutations,
bool only_track_mutant_coverage, int mutation_id_base,
std::stringstream& new_function, int& mutation_id_offset,
protobufs::MutationReplaceUnaryOperator& protobuf_message) const;

static void AddMutationInstance(
Expand Down
6 changes: 6 additions & 0 deletions src/libdredd/include/libdredd/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,12 @@ bool EvaluateAsFloat(const clang::Expr& expr,
bool IsCxx11ConstantExpr(const clang::Expr& expr,
const clang::ASTContext& ast_context);

std::string GenerateMutationPrelude();

std::string GenerateMutationMacro(const std::string& name,
const std::string& args_evaluated);

std::string GenerateMutationReturn();
} // namespace dredd

#endif // LIBDREDD_UTIL_H
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ class MutateAstConsumer : public clang::ASTConsumer {
protobufs::MutationTreeNode ApplyMutations(
const MutationTreeNode& mutation_tree_node, int initial_mutation_id,
clang::ASTContext& context,
std::unordered_set<std::string>& dredd_declarations);
std::unordered_set<std::string>& dredd_declarations,
std::unordered_set<std::string>& dredd_macros);

const clang::CompilerInstance* compiler_instance_;

Expand Down
26 changes: 21 additions & 5 deletions src/libdredd/src/mutate_ast_consumer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "libdredd/mutation.h"
#include "libdredd/util.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"

Expand Down Expand Up @@ -74,6 +75,7 @@ void MutateAstConsumer::HandleTranslationUnit(clang::ASTContext& ast_context) {
// converted to an ordered set so that declarations can be added to the source
// file in a deterministic order.
std::unordered_set<std::string> dredd_declarations;
std::unordered_set<std::string> dredd_macros;

protobufs::MutationInfoForFile mutation_info_for_file;
mutation_info_for_file.set_filename(
Expand All @@ -83,7 +85,7 @@ void MutateAstConsumer::HandleTranslationUnit(clang::ASTContext& ast_context) {
.str());
*mutation_info_for_file.mutable_mutation_tree_root() =
ApplyMutations(visitor_->GetMutations(), initial_mutation_id, ast_context,
dredd_declarations);
dredd_declarations, dredd_macros);

if (initial_mutation_id == *mutation_id_) {
// No possibilities for mutation were found; nothing else to do.
Expand Down Expand Up @@ -111,6 +113,19 @@ void MutateAstConsumer::HandleTranslationUnit(clang::ASTContext& ast_context) {
assert(!rewriter_result && "Rewrite failed.\n");
}

rewriter_.InsertTextBefore(start_of_source_file, GenerateMutationPrelude());

std::set<std::string> sorted_dredd_macros;
sorted_dredd_macros.insert(dredd_macros.begin(), dredd_macros.end());
for (const auto& macro : sorted_dredd_macros) {
const bool rewriter_result =
rewriter_.InsertTextBefore(start_of_source_file, macro);
(void)rewriter_result; // Keep release-mode compilers happy.
assert(!rewriter_result && "Rewrite failed.\n");
}

rewriter_.InsertTextBefore(start_of_source_file, GenerateMutationReturn());

const std::string dredd_prelude =
compiler_instance_->getLangOpts().CPlusPlus
? GetDreddPreludeCpp(initial_mutation_id)
Expand Down Expand Up @@ -361,23 +376,24 @@ std::string MutateAstConsumer::GetDreddPreludeC(int initial_mutation_id) const {
protobufs::MutationTreeNode MutateAstConsumer::ApplyMutations(
const MutationTreeNode& mutation_tree_node, int initial_mutation_id,
clang::ASTContext& context,
std::unordered_set<std::string>& dredd_declarations) {
std::unordered_set<std::string>& dredd_declarations,
std::unordered_set<std::string>& dredd_macros) {
assert(!(mutation_tree_node.IsEmpty() &&
mutation_tree_node.GetChildren().size() == 1) &&
"The mutation tree should already be compressed.");
protobufs::MutationTreeNode result;
for (const auto& child : mutation_tree_node.GetChildren()) {
assert(!child->IsEmpty() &&
"The mutation tree should not have empty subtrees.");
*result.add_children() = ApplyMutations(*child, initial_mutation_id,
context, dredd_declarations);
*result.add_children() = ApplyMutations(
*child, initial_mutation_id, context, dredd_declarations, dredd_macros);
}
for (const auto& mutation : mutation_tree_node.GetMutations()) {
const int mutation_id_old = *mutation_id_;
const auto mutation_group = mutation->Apply(
context, compiler_instance_->getPreprocessor(), optimise_mutations_,
only_track_mutant_coverage_, initial_mutation_id, *mutation_id_,
rewriter_, dredd_declarations);
rewriter_, dredd_declarations, dredd_macros);
if (*mutation_id_ > mutation_id_old) {
// Only add the result of applying the mutation if it had an effect.
*result.add_mutation_groups() = mutation_group;
Expand Down
4 changes: 3 additions & 1 deletion src/libdredd/src/mutation_remove_stmt.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,10 @@ protobufs::MutationGroup MutationRemoveStmt::Apply(
clang::ASTContext& ast_context, const clang::Preprocessor& preprocessor,
bool optimise_mutations, bool only_track_mutant_coverage,
int first_mutation_id_in_file, int& mutation_id, clang::Rewriter& rewriter,
std::unordered_set<std::string>& dredd_declarations) const {
std::unordered_set<std::string>& dredd_declarations,
std::unordered_set<std::string>& dredd_macros) const {
(void)dredd_declarations; // Unused.
(void)dredd_macros; // Unused.
(void)optimise_mutations; // Unused.

// The protobuf object for the mutation, which will be wrapped in a
Expand Down
Loading