From 9a790d4faf45fdbb2da273a9ba5fbabbe02701e0 Mon Sep 17 00:00:00 2001 From: James Lee-Jones Date: Tue, 26 Mar 2024 10:12:01 +0000 Subject: [PATCH 1/5] Add flag to build mutant tree --- src/dredd/src/main.cc | 8 +++- src/libdredd/include/libdredd/mutation.h | 15 +++++--- .../include/libdredd/mutation_remove_stmt.h | 15 +++++--- .../mutation_replace_binary_operator.h | 15 +++++--- .../include/libdredd/mutation_replace_expr.h | 15 +++++--- .../mutation_replace_unary_operator.h | 15 +++++--- .../new_mutate_frontend_action_factory.h | 8 ++-- .../include/libdredd/mutate_ast_consumer.h | 5 ++- src/libdredd/src/mutate_ast_consumer.cc | 11 ++++-- src/libdredd/src/mutation_remove_stmt.cc | 34 ++++++++++------- .../src/mutation_replace_binary_operator.cc | 28 +++++++++----- src/libdredd/src/mutation_replace_expr.cc | 34 +++++++++++------ .../src/mutation_replace_unary_operator.cc | 35 +++++++++++------- .../src/new_mutate_frontend_action_factory.cc | 37 ++++++++++++------- .../src/mutation_remove_stmt_test.cc | 2 +- .../mutation_replace_binary_operator_test.cc | 2 +- .../src/mutation_replace_expr_test.cc | 2 +- .../mutation_replace_unary_operator_test.cc | 2 +- 18 files changed, 179 insertions(+), 104 deletions(-) diff --git a/src/dredd/src/main.cc b/src/dredd/src/main.cc index 4e20ba48..838b0a9e 100644 --- a/src/dredd/src/main.cc +++ b/src/dredd/src/main.cc @@ -60,6 +60,12 @@ static llvm::cl::opt dump_asts( llvm::cl::desc("Dump each AST that is processed; useful for debugging"), llvm::cl::cat(mutate_category)); // NOLINTNEXTLINE +// TODO(James Lee-Jones): Finish +static llvm::cl::opt mutant_pass( + "mutant-pass", + llvm::cl::desc("Perform a pass to build the mutation tree. Must be passed with --mutation_info_file."), + llvm::cl::cat(mutate_category)); +// NOLINTNEXTLINE static llvm::cl::opt mutation_info_file( "mutation-info-file", llvm::cl::Required, llvm::cl::desc( @@ -98,7 +104,7 @@ int main(int argc, const char** argv) { const std::unique_ptr factory = dredd::NewMutateFrontendActionFactory(!no_mutation_opts, dump_asts, - only_track_mutant_coverage, + only_track_mutant_coverage, mutant_pass, mutation_id, mutation_info); const int return_code = Tool.run(factory.get()); diff --git a/src/libdredd/include/libdredd/mutation.h b/src/libdredd/include/libdredd/mutation.h index 56c93438..097a1b47 100644 --- a/src/libdredd/include/libdredd/mutation.h +++ b/src/libdredd/include/libdredd/mutation.h @@ -48,12 +48,15 @@ class Mutation { // The |dredd_declarations| argument provides a set of declarations that will // be added to the start of the source file being mutated. This allows // avoiding redundant repeat declarations. - virtual protobufs::MutationGroup 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& dredd_declarations) const = 0; + virtual protobufs::MutationGroup Apply(clang::ASTContext &ast_context, + const clang::Preprocessor &preprocessor, + bool optimise_mutations, + bool only_track_mutant_coverage, + bool mutation_pass, + int first_mutation_id_in_file, + int &mutation_id, + clang::Rewriter &rewriter, + std::unordered_set &dredd_declarations) const = 0; }; } // namespace dredd diff --git a/src/libdredd/include/libdredd/mutation_remove_stmt.h b/src/libdredd/include/libdredd/mutation_remove_stmt.h index b0f0f8ad..c1aa12db 100644 --- a/src/libdredd/include/libdredd/mutation_remove_stmt.h +++ b/src/libdredd/include/libdredd/mutation_remove_stmt.h @@ -35,12 +35,15 @@ class MutationRemoveStmt : public Mutation { const clang::Preprocessor& preprocessor, const clang::ASTContext& ast_context); - protobufs::MutationGroup 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& dredd_declarations) const override; + protobufs::MutationGroup Apply(clang::ASTContext &ast_context, + const clang::Preprocessor &preprocessor, + bool optimise_mutations, + bool only_track_mutant_coverage, + bool mutation_pass, + int first_mutation_id_in_file, + int &mutation_id, + clang::Rewriter &rewriter, + std::unordered_set &dredd_declarations) const override; private: // Helper method to determine whether the token immediately following the diff --git a/src/libdredd/include/libdredd/mutation_replace_binary_operator.h b/src/libdredd/include/libdredd/mutation_replace_binary_operator.h index e07b0734..02187533 100644 --- a/src/libdredd/include/libdredd/mutation_replace_binary_operator.h +++ b/src/libdredd/include/libdredd/mutation_replace_binary_operator.h @@ -37,12 +37,15 @@ class MutationReplaceBinaryOperator : public Mutation { const clang::Preprocessor& preprocessor, const clang::ASTContext& ast_context); - protobufs::MutationGroup 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& dredd_declarations) const override; + protobufs::MutationGroup Apply(clang::ASTContext &ast_context, + const clang::Preprocessor &preprocessor, + bool optimise_mutations, + bool only_track_mutant_coverage, + bool mutation_pass, + int first_mutation_id_in_file, + int &mutation_id, + clang::Rewriter &rewriter, + std::unordered_set &dredd_declarations) const override; private: std::string GenerateMutatorFunction( diff --git a/src/libdredd/include/libdredd/mutation_replace_expr.h b/src/libdredd/include/libdredd/mutation_replace_expr.h index fee39226..fb3eab67 100644 --- a/src/libdredd/include/libdredd/mutation_replace_expr.h +++ b/src/libdredd/include/libdredd/mutation_replace_expr.h @@ -36,12 +36,15 @@ class MutationReplaceExpr : public Mutation { const clang::Preprocessor& preprocessor, const clang::ASTContext& ast_context); - protobufs::MutationGroup 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& dredd_declarations) const override; + protobufs::MutationGroup Apply(clang::ASTContext &ast_context, + const clang::Preprocessor &preprocessor, + bool optimise_mutations, + bool only_track_mutant_coverage, + bool mutation_pass, + int first_mutation_id_in_file, + int &mutation_id, + clang::Rewriter &rewriter, + std::unordered_set &dredd_declarations) const override; static void ApplyCppTypeModifiers(const clang::Expr& expr, std::string& type); diff --git a/src/libdredd/include/libdredd/mutation_replace_unary_operator.h b/src/libdredd/include/libdredd/mutation_replace_unary_operator.h index 24c6f621..81c5b068 100644 --- a/src/libdredd/include/libdredd/mutation_replace_unary_operator.h +++ b/src/libdredd/include/libdredd/mutation_replace_unary_operator.h @@ -36,12 +36,15 @@ class MutationReplaceUnaryOperator : public Mutation { const clang::Preprocessor& preprocessor, const clang::ASTContext& ast_context); - protobufs::MutationGroup 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& dredd_declarations) const override; + protobufs::MutationGroup Apply(clang::ASTContext &ast_context, + const clang::Preprocessor &preprocessor, + bool optimise_mutations, + bool only_track_mutant_coverage, + bool mutation_pass, + int first_mutation_id_in_file, + int &mutation_id, + clang::Rewriter &rewriter, + std::unordered_set &dredd_declarations) const override; private: std::string GenerateMutatorFunction( diff --git a/src/libdredd/include/libdredd/new_mutate_frontend_action_factory.h b/src/libdredd/include/libdredd/new_mutate_frontend_action_factory.h index f30b452c..1ca0c4d1 100644 --- a/src/libdredd/include/libdredd/new_mutate_frontend_action_factory.h +++ b/src/libdredd/include/libdredd/new_mutate_frontend_action_factory.h @@ -23,10 +23,12 @@ namespace dredd { std::unique_ptr -NewMutateFrontendActionFactory(bool optimise_mutations, bool dump_asts, +NewMutateFrontendActionFactory(bool optimise_mutations, + bool dump_asts, bool only_track_mutant_coverage, - int& mutation_id, - protobufs::MutationInfo& mutation_info); + bool mutation_pass, + int &mutation_id, + protobufs::MutationInfo &mutation_info); } diff --git a/src/libdredd/include_private/include/libdredd/mutate_ast_consumer.h b/src/libdredd/include_private/include/libdredd/mutate_ast_consumer.h index 6cefda09..19be3412 100644 --- a/src/libdredd/include_private/include/libdredd/mutate_ast_consumer.h +++ b/src/libdredd/include_private/include/libdredd/mutate_ast_consumer.h @@ -32,11 +32,12 @@ namespace dredd { class MutateAstConsumer : public clang::ASTConsumer { public: MutateAstConsumer(const clang::CompilerInstance& compiler_instance, - bool optimise_mutations, bool dump_ast, + bool optimise_mutations, bool mutation_pass, bool dump_ast, bool only_track_mutant_coverage, int& mutation_id, protobufs::MutationInfo& mutation_info) : compiler_instance_(&compiler_instance), optimise_mutations_(optimise_mutations), + mutation_pass_(mutation_pass), dump_ast_(dump_ast), only_track_mutant_coverage_(only_track_mutant_coverage), visitor_(std::make_unique(compiler_instance, @@ -73,6 +74,8 @@ class MutateAstConsumer : public clang::ASTConsumer { // True if and only if Dredd's optimisations are enabled. bool optimise_mutations_; + bool mutation_pass_; + // True if and only if the AST being consumed should be dumped; useful for // debugging. bool dump_ast_; diff --git a/src/libdredd/src/mutate_ast_consumer.cc b/src/libdredd/src/mutate_ast_consumer.cc index 99b5dd85..99a4752d 100644 --- a/src/libdredd/src/mutate_ast_consumer.cc +++ b/src/libdredd/src/mutate_ast_consumer.cc @@ -92,6 +92,8 @@ void MutateAstConsumer::HandleTranslationUnit(clang::ASTContext& ast_context) { *mutation_info_->add_info_for_files() = mutation_info_for_file; + if (mutation_pass_) return; + auto& source_manager = ast_context.getSourceManager(); const clang::SourceLocation start_of_source_file = source_manager.translateLineCol(source_manager.getMainFileID(), 1, 1); @@ -374,10 +376,11 @@ protobufs::MutationTreeNode MutateAstConsumer::ApplyMutations( } 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); + // TODO(James Lee-Jones): Don't do this if we are only generating the mutation tree. + const auto mutation_group = mutation->Apply( + context, compiler_instance_->getPreprocessor(), optimise_mutations_, + only_track_mutant_coverage_, mutation_pass_, initial_mutation_id, *mutation_id_, + rewriter_, dredd_declarations); 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; diff --git a/src/libdredd/src/mutation_remove_stmt.cc b/src/libdredd/src/mutation_remove_stmt.cc index 344f990b..bf0d9046 100644 --- a/src/libdredd/src/mutation_remove_stmt.cc +++ b/src/libdredd/src/mutation_remove_stmt.cc @@ -38,11 +38,15 @@ MutationRemoveStmt::MutationRemoveStmt(const clang::Stmt& stmt, info_for_source_range_(GetSourceRangeInMainFile(preprocessor, stmt), ast_context) {} -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& dredd_declarations) const { +protobufs::MutationGroup MutationRemoveStmt::Apply(clang::ASTContext &ast_context, + const clang::Preprocessor &preprocessor, + bool optimise_mutations, + bool only_track_mutant_coverage, + bool mutation_pass, + int first_mutation_id_in_file, + int &mutation_id, + clang::Rewriter &rewriter, + std::unordered_set &dredd_declarations) const { (void)dredd_declarations; // Unused. (void)optimise_mutations; // Unused. @@ -57,6 +61,18 @@ protobufs::MutationGroup MutationRemoveStmt::Apply( inner_result.mutable_end()->set_column(info_for_source_range_.GetEndColumn()); *inner_result.mutable_snippet() = info_for_source_range_.GetSnippet(); + // Subtracting |first_mutation_id_in_file| turns the global mutation id, + // |mutation_id|, into a file-local mutation id. + const int local_mutation_id = mutation_id - first_mutation_id_in_file; + + mutation_id++; + + protobufs::MutationGroup result; + *result.mutable_remove_stmt() = inner_result; + + if (mutation_pass) return result; + + clang::CharSourceRange source_range = clang::CharSourceRange::getTokenRange( GetSourceRangeInMainFile(preprocessor, *stmt_)); @@ -95,10 +111,6 @@ protobufs::MutationGroup MutationRemoveStmt::Apply( source_range = source_range_extended_with_semi; } - // Subtracting |first_mutation_id_in_file| turns the global mutation id, - // |mutation_id|, into a file-local mutation id. - const int local_mutation_id = mutation_id - first_mutation_id_in_file; - if (only_track_mutant_coverage) { const bool rewriter_result = rewriter.InsertTextBefore( source_range.getBegin(), "__dredd_record_covered_mutants(" + @@ -144,10 +156,6 @@ protobufs::MutationGroup MutationRemoveStmt::Apply( (void)rewriter_result; // Keep release-mode compilers happy. } - mutation_id++; - - protobufs::MutationGroup result; - *result.mutable_remove_stmt() = inner_result; return result; } diff --git a/src/libdredd/src/mutation_replace_binary_operator.cc b/src/libdredd/src/mutation_replace_binary_operator.cc index eac4bfac..58096cd0 100644 --- a/src/libdredd/src/mutation_replace_binary_operator.cc +++ b/src/libdredd/src/mutation_replace_binary_operator.cc @@ -519,11 +519,15 @@ std::string MutationReplaceBinaryOperator::GenerateMutatorFunction( return new_function.str(); } -protobufs::MutationGroup MutationReplaceBinaryOperator::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& dredd_declarations) const { +protobufs::MutationGroup MutationReplaceBinaryOperator::Apply(clang::ASTContext &ast_context, + const clang::Preprocessor &preprocessor, + bool optimise_mutations, + bool only_track_mutant_coverage, + bool mutation_pass, + int first_mutation_id_in_file, + int &mutation_id, + clang::Rewriter &rewriter, + std::unordered_set &dredd_declarations) const { // The protobuf object for the mutation, which will be wrapped in a // MutationGroup. protobufs::MutationReplaceBinaryOperator inner_result; @@ -553,6 +557,7 @@ protobufs::MutationGroup MutationReplaceBinaryOperator::Apply( inner_result.mutable_rhs_end()->set_column(info_for_rhs_.GetEndColumn()); *inner_result.mutable_rhs_snippet() = info_for_rhs_.GetSnippet(); + const std::string new_function_name = GetFunctionName(optimise_mutations, ast_context); std::string result_type = binary_operator_->getType() @@ -604,9 +609,7 @@ protobufs::MutationGroup MutationReplaceBinaryOperator::Apply( } } - ReplaceOperator(lhs_type, rhs_type, new_function_name, ast_context, - preprocessor, first_mutation_id_in_file, mutation_id, - rewriter); + const std::string new_function = GenerateMutatorFunction( ast_context, new_function_name, result_type, lhs_type, rhs_type, @@ -614,12 +617,17 @@ protobufs::MutationGroup MutationReplaceBinaryOperator::Apply( inner_result); assert(!new_function.empty() && "Unsupported opcode."); + protobufs::MutationGroup result; + *result.mutable_replace_binary_operator() = inner_result; + if (mutation_pass) return result; + + ReplaceOperator(lhs_type, rhs_type, new_function_name, ast_context, + preprocessor, first_mutation_id_in_file, mutation_id, + rewriter); // Add the mutation function to the set of Dredd declarations - there may // already be a matching function, in which case duplication will be avoided. dredd_declarations.insert(new_function); - protobufs::MutationGroup result; - *result.mutable_replace_binary_operator() = inner_result; return result; } diff --git a/src/libdredd/src/mutation_replace_expr.cc b/src/libdredd/src/mutation_replace_expr.cc index 79f358e2..14e8b49a 100644 --- a/src/libdredd/src/mutation_replace_expr.cc +++ b/src/libdredd/src/mutation_replace_expr.cc @@ -592,11 +592,15 @@ void MutationReplaceExpr::ReplaceExprWithFunctionCall( (void)rewriter_result; // Keep release mode compilers happy. } -protobufs::MutationGroup MutationReplaceExpr::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& dredd_declarations) const { +protobufs::MutationGroup MutationReplaceExpr::Apply(clang::ASTContext &ast_context, + const clang::Preprocessor &preprocessor, + bool optimise_mutations, + bool only_track_mutant_coverage, + bool mutation_pass, + int first_mutation_id_in_file, + int &mutation_id, + clang::Rewriter &rewriter, + std::unordered_set &dredd_declarations) const { // The protobuf object for the mutation, which will be wrapped in a // MutationGroup. protobufs::MutationReplaceExpr inner_result; @@ -608,6 +612,8 @@ protobufs::MutationGroup MutationReplaceExpr::Apply( inner_result.mutable_end()->set_column(info_for_source_range_.GetEndColumn()); *inner_result.mutable_snippet() = info_for_source_range_.GetSnippet(); + + const std::string new_function_name = GetFunctionName(optimise_mutations, ast_context); const std::string result_type = expr_->getType() @@ -626,6 +632,17 @@ protobufs::MutationGroup MutationReplaceExpr::Apply( ApplyCTypeModifiers(*expr_, input_type); } + const std::string new_function = GenerateMutatorFunction( + ast_context, new_function_name, result_type, input_type, + optimise_mutations, only_track_mutant_coverage, mutation_id, + inner_result); + assert(!new_function.empty() && "Unsupported expression."); + + protobufs::MutationGroup result; + *result.mutable_replace_expr() = inner_result; + + if (mutation_pass) return result; + // Replace the expression with a function call. // Subtracting |first_mutation_id_in_file| turns the global mutation id, // |mutation_id|, into a file-local mutation id. @@ -633,16 +650,9 @@ protobufs::MutationGroup MutationReplaceExpr::Apply( mutation_id - first_mutation_id_in_file, ast_context, preprocessor, rewriter); - const std::string new_function = GenerateMutatorFunction( - ast_context, new_function_name, result_type, input_type, - optimise_mutations, only_track_mutant_coverage, mutation_id, - inner_result); - assert(!new_function.empty() && "Unsupported expression."); dredd_declarations.insert(new_function); - protobufs::MutationGroup result; - *result.mutable_replace_expr() = inner_result; return result; } diff --git a/src/libdredd/src/mutation_replace_unary_operator.cc b/src/libdredd/src/mutation_replace_unary_operator.cc index b9db1c3f..ddc1efff 100644 --- a/src/libdredd/src/mutation_replace_unary_operator.cc +++ b/src/libdredd/src/mutation_replace_unary_operator.cc @@ -335,11 +335,15 @@ void MutationReplaceUnaryOperator::GenerateUnaryOperatorReplacement( } } -protobufs::MutationGroup MutationReplaceUnaryOperator::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& dredd_declarations) const { +protobufs::MutationGroup MutationReplaceUnaryOperator::Apply(clang::ASTContext &ast_context, + const clang::Preprocessor &preprocessor, + bool optimise_mutations, + bool only_track_mutant_coverage, + bool mutation_pass, + int first_mutation_id_in_file, + int &mutation_id, + clang::Rewriter &rewriter, + std::unordered_set &dredd_declarations) const { // The protobuf object for the mutation, which will be wrapped in a // MutationGroup. protobufs::MutationReplaceUnaryOperator inner_result; @@ -366,6 +370,8 @@ protobufs::MutationGroup MutationReplaceUnaryOperator::Apply( info_for_sub_expr_.GetEndColumn()); *inner_result.mutable_operand_snippet() = info_for_sub_expr_.GetSnippet(); + + const std::string new_function_name = GetFunctionName(optimise_mutations, ast_context); std::string result_type = unary_operator_->getType() @@ -439,6 +445,17 @@ protobufs::MutationGroup MutationReplaceUnaryOperator::Apply( } suffix.append(", " + std::to_string(local_mutation_id) + ")"); + const std::string new_function = GenerateMutatorFunction( + ast_context, new_function_name, result_type, input_type, + optimise_mutations, only_track_mutant_coverage, mutation_id, + inner_result); + assert(!new_function.empty() && "Unsupported opcode."); + + protobufs::MutationGroup result; + *result.mutable_replace_unary_operator() = inner_result; + + if (mutation_pass) return result; + // The prefix and suffix are ready, so make the relevant insertions. bool rewriter_result = rewriter.InsertTextBefore( unary_operator_source_range_in_main_file.getBegin(), prefix); @@ -448,16 +465,8 @@ protobufs::MutationGroup MutationReplaceUnaryOperator::Apply( assert(!rewriter_result && "Rewrite failed.\n"); (void)rewriter_result; // Keep release-mode compilers happy. - const std::string new_function = GenerateMutatorFunction( - ast_context, new_function_name, result_type, input_type, - optimise_mutations, only_track_mutant_coverage, mutation_id, - inner_result); - assert(!new_function.empty() && "Unsupported opcode."); - dredd_declarations.insert(new_function); - protobufs::MutationGroup result; - *result.mutable_replace_unary_operator() = inner_result; return result; } diff --git a/src/libdredd/src/new_mutate_frontend_action_factory.cc b/src/libdredd/src/new_mutate_frontend_action_factory.cc index ac3b4a0e..8780d686 100644 --- a/src/libdredd/src/new_mutate_frontend_action_factory.cc +++ b/src/libdredd/src/new_mutate_frontend_action_factory.cc @@ -31,13 +31,17 @@ namespace dredd { class MutateFrontendAction : public clang::ASTFrontendAction { public: - MutateFrontendAction(bool optimise_mutations, bool dump_asts, - bool only_track_mutant_coverage, int& mutation_id, - protobufs::MutationInfo& mutation_info, - std::set& processed_files) + MutateFrontendAction(bool optimise_mutations, + bool dump_asts, + bool only_track_mutant_coverage, + bool mutation_pass, + int &mutation_id, + protobufs::MutationInfo &mutation_info, + std::set &processed_files) : optimise_mutations_(optimise_mutations), dump_asts_(dump_asts), only_track_mutant_coverage_(only_track_mutant_coverage), + mutation_pass_(mutation_pass), mutation_id_(&mutation_id), mutation_info_(&mutation_info), processed_files_(&processed_files) {} @@ -64,32 +68,38 @@ class MutateFrontendAction : public clang::ASTFrontendAction { bool optimise_mutations_; bool dump_asts_; bool only_track_mutant_coverage_; + bool mutation_pass_; int* mutation_id_; protobufs::MutationInfo* mutation_info_; std::set* processed_files_; }; std::unique_ptr -NewMutateFrontendActionFactory(bool optimise_mutations, bool dump_asts, +NewMutateFrontendActionFactory(bool optimise_mutations, + bool dump_asts, bool only_track_mutant_coverage, - int& mutation_id, - protobufs::MutationInfo& mutation_info) { + bool mutation_pass, + int &mutation_id, + protobufs::MutationInfo &mutation_info) { class MutateFrontendActionFactory : public clang::tooling::FrontendActionFactory { public: - MutateFrontendActionFactory(bool optimise_mutations, bool dump_asts, + MutateFrontendActionFactory(bool optimise_mutations, + bool dump_asts, bool only_track_mutant_coverage, - int& mutation_id, - protobufs::MutationInfo& mutation_info) + bool mutation_pass, + int &mutation_id, + protobufs::MutationInfo &mutation_info) : optimise_mutations_(optimise_mutations), dump_asts_(dump_asts), only_track_mutant_coverage_(only_track_mutant_coverage), + mutation_pass_(mutation_pass), mutation_id_(&mutation_id), mutation_info_(&mutation_info) {} std::unique_ptr create() override { return std::make_unique( - optimise_mutations_, dump_asts_, only_track_mutant_coverage_, + optimise_mutations_, dump_asts_, only_track_mutant_coverage_, mutation_pass_, *mutation_id_, *mutation_info_, processed_files_); } @@ -97,6 +107,7 @@ NewMutateFrontendActionFactory(bool optimise_mutations, bool dump_asts, bool optimise_mutations_; bool dump_asts_; bool only_track_mutant_coverage_; + bool mutation_pass_; int* mutation_id_; protobufs::MutationInfo* mutation_info_; @@ -106,7 +117,7 @@ NewMutateFrontendActionFactory(bool optimise_mutations, bool dump_asts, }; return std::make_unique( - optimise_mutations, dump_asts, only_track_mutant_coverage, mutation_id, + optimise_mutations, dump_asts, only_track_mutant_coverage, mutation_pass, mutation_id, mutation_info); } @@ -114,7 +125,7 @@ std::unique_ptr MutateFrontendAction::CreateASTConsumer( clang::CompilerInstance& compiler_instance, llvm::StringRef file) { (void)file; // Unused. return std::make_unique( - compiler_instance, optimise_mutations_, dump_asts_, + compiler_instance, optimise_mutations_, mutation_pass_, dump_asts_, only_track_mutant_coverage_, *mutation_id_, *mutation_info_); } diff --git a/src/libdreddtest/src/mutation_remove_stmt_test.cc b/src/libdreddtest/src/mutation_remove_stmt_test.cc index 315d2c9b..8c6a2a92 100644 --- a/src/libdreddtest/src/mutation_remove_stmt_test.cc +++ b/src/libdreddtest/src/mutation_remove_stmt_test.cc @@ -49,7 +49,7 @@ void TestRemoval(const std::string& original, const std::string& expected, std::unordered_set dredd_declarations; mutation_supplier(ast_unit->getPreprocessor(), ast_unit->getASTContext()) .Apply(ast_unit->getASTContext(), ast_unit->getPreprocessor(), true, - false, 0, mutation_id, rewriter, dredd_declarations); + false, false, 0, mutation_id, rewriter, dredd_declarations); ASSERT_EQ(1, mutation_id); ASSERT_EQ(0, dredd_declarations.size()); const clang::RewriteBuffer* rewrite_buffer = rewriter.getRewriteBufferFor( diff --git a/src/libdreddtest/src/mutation_replace_binary_operator_test.cc b/src/libdreddtest/src/mutation_replace_binary_operator_test.cc index 2a5bef1c..9aaa8c2b 100644 --- a/src/libdreddtest/src/mutation_replace_binary_operator_test.cc +++ b/src/libdreddtest/src/mutation_replace_binary_operator_test.cc @@ -58,7 +58,7 @@ void TestReplacement(const std::string& original, const std::string& expected, int mutation_id = 0; std::unordered_set dredd_declarations; mutation.Apply(ast_unit->getASTContext(), ast_unit->getPreprocessor(), - optimise_mutations, false, 0, mutation_id, rewriter, + optimise_mutations, false, false, 0, mutation_id, rewriter, dredd_declarations); ASSERT_EQ(num_replacements, mutation_id); ASSERT_EQ(1, dredd_declarations.size()); diff --git a/src/libdreddtest/src/mutation_replace_expr_test.cc b/src/libdreddtest/src/mutation_replace_expr_test.cc index d416e996..92692733 100644 --- a/src/libdreddtest/src/mutation_replace_expr_test.cc +++ b/src/libdreddtest/src/mutation_replace_expr_test.cc @@ -61,7 +61,7 @@ void TestReplacement(const std::string& original, const std::string& expected, int mutation_id = 0; std::unordered_set dredd_declarations; mutation.Apply(ast_unit->getASTContext(), ast_unit->getPreprocessor(), true, - false, 0, mutation_id, rewriter, dredd_declarations); + false, false, 0, mutation_id, rewriter, dredd_declarations); ASSERT_EQ(num_replacements, mutation_id); ASSERT_EQ(1, dredd_declarations.size()); ASSERT_EQ(expected_dredd_declaration, *dredd_declarations.begin()); diff --git a/src/libdreddtest/src/mutation_replace_unary_operator_test.cc b/src/libdreddtest/src/mutation_replace_unary_operator_test.cc index c31780bc..53493362 100644 --- a/src/libdreddtest/src/mutation_replace_unary_operator_test.cc +++ b/src/libdreddtest/src/mutation_replace_unary_operator_test.cc @@ -58,7 +58,7 @@ void TestReplacement(const std::string& original, const std::string& expected, int mutation_id = 0; std::unordered_set dredd_declarations; mutation.Apply(ast_unit->getASTContext(), ast_unit->getPreprocessor(), - optimise_mutations, false, 0, mutation_id, rewriter, + optimise_mutations, false, false, 0, mutation_id, rewriter, dredd_declarations); ASSERT_EQ(num_replacements, mutation_id); ASSERT_EQ(1, dredd_declarations.size()); From 7c8384269b3ad54008f0f41dfab83c690359d399 Mon Sep 17 00:00:00 2001 From: James Lee-Jones Date: Wed, 27 Mar 2024 13:55:58 +0000 Subject: [PATCH 2/5] Change protobufs object to contain enabled value --- src/dredd/src/main.cc | 1 - src/libdredd/include/libdredd/protobufs/dredd.proto | 4 ++++ src/libdredd/src/mutate_ast_consumer.cc | 1 - src/libdredd/src/mutation_remove_stmt.cc | 1 + src/libdredd/src/mutation_replace_binary_operator.cc | 1 + src/libdredd/src/mutation_replace_expr.cc | 1 + src/libdredd/src/mutation_replace_unary_operator.cc | 1 + 7 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/dredd/src/main.cc b/src/dredd/src/main.cc index 838b0a9e..96a278e3 100644 --- a/src/dredd/src/main.cc +++ b/src/dredd/src/main.cc @@ -60,7 +60,6 @@ static llvm::cl::opt dump_asts( llvm::cl::desc("Dump each AST that is processed; useful for debugging"), llvm::cl::cat(mutate_category)); // NOLINTNEXTLINE -// TODO(James Lee-Jones): Finish static llvm::cl::opt mutant_pass( "mutant-pass", llvm::cl::desc("Perform a pass to build the mutation tree. Must be passed with --mutation_info_file."), diff --git a/src/libdredd/include/libdredd/protobufs/dredd.proto b/src/libdredd/include/libdredd/protobufs/dredd.proto index b6382032..b6b96db1 100644 --- a/src/libdredd/include/libdredd/protobufs/dredd.proto +++ b/src/libdredd/include/libdredd/protobufs/dredd.proto @@ -46,6 +46,7 @@ message MutationRemoveStmt { SourceLocation start = 2; SourceLocation end = 3; string snippet = 4; + bool enabled = 5; } enum MutationReplaceExprAction { @@ -67,6 +68,7 @@ enum MutationReplaceExprAction { message MutationReplaceExprInstance { MutationReplaceExprAction action = 1; int32 mutation_id = 2; + bool enabled = 3; } message MutationReplaceExpr { @@ -113,6 +115,7 @@ enum MutationReplaceBinaryOperatorAction { message MutationReplaceBinaryOperatorInstance { MutationReplaceBinaryOperatorAction action = 1; int32 mutation_id = 2; + bool enabled = 3; } enum BinaryOperator { @@ -175,6 +178,7 @@ enum MutationReplaceUnaryOperatorAction { message MutationReplaceUnaryOperatorInstance { MutationReplaceUnaryOperatorAction action = 1; int32 mutation_id = 2; + bool enabled = 3; } enum UnaryOperator { diff --git a/src/libdredd/src/mutate_ast_consumer.cc b/src/libdredd/src/mutate_ast_consumer.cc index 99a4752d..303a046d 100644 --- a/src/libdredd/src/mutate_ast_consumer.cc +++ b/src/libdredd/src/mutate_ast_consumer.cc @@ -376,7 +376,6 @@ protobufs::MutationTreeNode MutateAstConsumer::ApplyMutations( } for (const auto& mutation : mutation_tree_node.GetMutations()) { const int mutation_id_old = *mutation_id_; - // TODO(James Lee-Jones): Don't do this if we are only generating the mutation tree. const auto mutation_group = mutation->Apply( context, compiler_instance_->getPreprocessor(), optimise_mutations_, only_track_mutant_coverage_, mutation_pass_, initial_mutation_id, *mutation_id_, diff --git a/src/libdredd/src/mutation_remove_stmt.cc b/src/libdredd/src/mutation_remove_stmt.cc index bf0d9046..f7985394 100644 --- a/src/libdredd/src/mutation_remove_stmt.cc +++ b/src/libdredd/src/mutation_remove_stmt.cc @@ -60,6 +60,7 @@ protobufs::MutationGroup MutationRemoveStmt::Apply(clang::ASTContext &ast_contex inner_result.mutable_end()->set_line(info_for_source_range_.GetEndLine()); inner_result.mutable_end()->set_column(info_for_source_range_.GetEndColumn()); *inner_result.mutable_snippet() = info_for_source_range_.GetSnippet(); + inner_result.set_enabled(true); // Subtracting |first_mutation_id_in_file| turns the global mutation id, // |mutation_id|, into a file-local mutation id. diff --git a/src/libdredd/src/mutation_replace_binary_operator.cc b/src/libdredd/src/mutation_replace_binary_operator.cc index 58096cd0..87245785 100644 --- a/src/libdredd/src/mutation_replace_binary_operator.cc +++ b/src/libdredd/src/mutation_replace_binary_operator.cc @@ -880,6 +880,7 @@ void MutationReplaceBinaryOperator::AddMutationInstance( protobufs::MutationReplaceBinaryOperatorInstance instance; instance.set_mutation_id(mutation_id_base + mutation_id_offset); instance.set_action(action); + instance.set_enabled(true); *protobuf_message.add_instances() = instance; mutation_id_offset++; } diff --git a/src/libdredd/src/mutation_replace_expr.cc b/src/libdredd/src/mutation_replace_expr.cc index 14e8b49a..67c420ae 100644 --- a/src/libdredd/src/mutation_replace_expr.cc +++ b/src/libdredd/src/mutation_replace_expr.cc @@ -682,6 +682,7 @@ void MutationReplaceExpr::AddMutationInstance( protobufs::MutationReplaceExprInstance instance; instance.set_mutation_id(mutation_id_base + mutation_id_offset); instance.set_action(action); + instance.set_enabled(true); *protobuf_message.add_instances() = instance; mutation_id_offset++; } diff --git a/src/libdredd/src/mutation_replace_unary_operator.cc b/src/libdredd/src/mutation_replace_unary_operator.cc index ddc1efff..4139604f 100644 --- a/src/libdredd/src/mutation_replace_unary_operator.cc +++ b/src/libdredd/src/mutation_replace_unary_operator.cc @@ -477,6 +477,7 @@ void MutationReplaceUnaryOperator::AddMutationInstance( protobufs::MutationReplaceUnaryOperatorInstance instance; instance.set_mutation_id(mutation_id_base + mutation_id_offset); instance.set_action(action); + instance.set_enabled(true); *protobuf_message.add_instances() = instance; mutation_id_offset++; } From 2cc3f3802e3691255ce9f540c6428ae53f602af6 Mon Sep 17 00:00:00 2001 From: James Lee-Jones Date: Wed, 27 Mar 2024 17:45:42 +0000 Subject: [PATCH 3/5] Add an option that allows a subset of mutants to be applied --- src/dredd/src/main.cc | 37 +++++++- .../new_mutate_frontend_action_factory.h | 3 +- .../include/libdredd/protobufs/dredd.proto | 4 +- .../include/libdredd/mutate_ast_consumer.h | 26 ++++-- src/libdredd/src/mutate_ast_consumer.cc | 88 +++++++++++++++---- .../src/mutation_replace_binary_operator.cc | 3 +- src/libdredd/src/mutation_replace_expr.cc | 2 +- .../src/mutation_replace_unary_operator.cc | 2 +- .../src/new_mutate_frontend_action_factory.cc | 19 ++-- 9 files changed, 145 insertions(+), 39 deletions(-) diff --git a/src/dredd/src/main.cc b/src/dredd/src/main.cc index 96a278e3..c696996d 100644 --- a/src/dredd/src/main.cc +++ b/src/dredd/src/main.cc @@ -14,6 +14,7 @@ #include #include +#include #include #include "clang/Tooling/CommonOptionsParser.h" @@ -64,6 +65,13 @@ static llvm::cl::opt mutant_pass( "mutant-pass", llvm::cl::desc("Perform a pass to build the mutation tree. Must be passed with --mutation_info_file."), llvm::cl::cat(mutate_category)); +// TODO(James Lee-Jones): Rename this to something more representative of what it does. +// NOLINTNEXTLINE +static llvm::cl::opt enabled_mutations_file( + "enabled-mutations-file", + llvm::cl::desc( + ".json file containing information on which mutations should be performed"), + llvm::cl::cat(mutate_category)); // NOLINTNEXTLINE static llvm::cl::opt mutation_info_file( "mutation-info-file", llvm::cl::Required, @@ -101,10 +109,37 @@ int main(int argc, const char** argv) { // including their hierarchical structure. dredd::protobufs::MutationInfo mutation_info; + // Contains the mutations that the user wants to apply in each source + // file, including their hierarchical structure. + std::optional enabled_mutation_info; + + // If a set of mutants to instrument has been provided, convert them to + // a protobufs representation. + if (enabled_mutations_file.empty()) { + enabled_mutation_info = std::nullopt; + } else { + // TODO(James Lee-Jones): See if there is a nicer way to do this. + // TODO(James Lee-Jones): Add extra error checks if read fails. + enabled_mutation_info = dredd::protobufs::MutationInfo(); + std::ifstream enabled_mutations_json_file; + std::stringstream enabled_mutations_json; + enabled_mutations_json_file.open(enabled_mutations_file); + enabled_mutations_json << enabled_mutations_json_file.rdbuf(); + std::string enabled_mutations_string = enabled_mutations_json.str(); + + auto json_read_status = google::protobuf::util::JsonStringToMessage(enabled_mutations_string, &*enabled_mutation_info); + if (!json_read_status.ok()) { + llvm::errs() << "Error reading JSON data from " << enabled_mutations_file + << "\n"; + llvm::errs() << json_read_status.ToString(); + return 1; + } + } + const std::unique_ptr factory = dredd::NewMutateFrontendActionFactory(!no_mutation_opts, dump_asts, only_track_mutant_coverage, mutant_pass, - mutation_id, mutation_info); + mutation_id, mutation_info, enabled_mutation_info); const int return_code = Tool.run(factory.get()); diff --git a/src/libdredd/include/libdredd/new_mutate_frontend_action_factory.h b/src/libdredd/include/libdredd/new_mutate_frontend_action_factory.h index 1ca0c4d1..ed9e6881 100644 --- a/src/libdredd/include/libdredd/new_mutate_frontend_action_factory.h +++ b/src/libdredd/include/libdredd/new_mutate_frontend_action_factory.h @@ -28,7 +28,8 @@ NewMutateFrontendActionFactory(bool optimise_mutations, bool only_track_mutant_coverage, bool mutation_pass, int &mutation_id, - protobufs::MutationInfo &mutation_info); + protobufs::MutationInfo &mutation_info, + const std::optional &enabled_mutation_info); } diff --git a/src/libdredd/include/libdredd/protobufs/dredd.proto b/src/libdredd/include/libdredd/protobufs/dredd.proto index b6b96db1..a52936d6 100644 --- a/src/libdredd/include/libdredd/protobufs/dredd.proto +++ b/src/libdredd/include/libdredd/protobufs/dredd.proto @@ -68,7 +68,6 @@ enum MutationReplaceExprAction { message MutationReplaceExprInstance { MutationReplaceExprAction action = 1; int32 mutation_id = 2; - bool enabled = 3; } message MutationReplaceExpr { @@ -76,6 +75,7 @@ message MutationReplaceExpr { SourceLocation end = 2; string snippet = 3; repeated MutationReplaceExprInstance instances = 4; + bool enabled = 5; } enum MutationReplaceBinaryOperatorAction { @@ -162,6 +162,7 @@ message MutationReplaceBinaryOperator { string rhs_snippet = 9; BinaryOperator operator = 10; repeated MutationReplaceBinaryOperatorInstance instances = 11; + bool enabled = 12; } enum MutationReplaceUnaryOperatorAction { @@ -200,4 +201,5 @@ message MutationReplaceUnaryOperator { string operand_snippet = 6; UnaryOperator operator = 7; repeated MutationReplaceUnaryOperatorInstance instances = 8; + bool enabled = 9; } diff --git a/src/libdredd/include_private/include/libdredd/mutate_ast_consumer.h b/src/libdredd/include_private/include/libdredd/mutate_ast_consumer.h index 19be3412..c30853fd 100644 --- a/src/libdredd/include_private/include/libdredd/mutate_ast_consumer.h +++ b/src/libdredd/include_private/include/libdredd/mutate_ast_consumer.h @@ -31,10 +31,14 @@ namespace dredd { class MutateAstConsumer : public clang::ASTConsumer { public: - MutateAstConsumer(const clang::CompilerInstance& compiler_instance, - bool optimise_mutations, bool mutation_pass, bool dump_ast, - bool only_track_mutant_coverage, int& mutation_id, - protobufs::MutationInfo& mutation_info) + MutateAstConsumer(const clang::CompilerInstance &compiler_instance, + bool optimise_mutations, + bool mutation_pass, + bool dump_ast, + bool only_track_mutant_coverage, + int &mutation_id, + protobufs::MutationInfo &mutation_info, + const std::optional &enabled_mutation_info) : compiler_instance_(&compiler_instance), optimise_mutations_(optimise_mutations), mutation_pass_(mutation_pass), @@ -43,7 +47,8 @@ class MutateAstConsumer : public clang::ASTConsumer { visitor_(std::make_unique(compiler_instance, optimise_mutations)), mutation_id_(&mutation_id), - mutation_info_(&mutation_info) {} + mutation_info_(&mutation_info), + enabled_mutation_info_(&enabled_mutation_info) {} void HandleTranslationUnit(clang::ASTContext& ast_context) override; @@ -64,10 +69,11 @@ class MutateAstConsumer : public clang::ASTConsumer { [[nodiscard]] std::string GetMutantTrackingDreddPreludeC( int initial_mutation_id) const; - protobufs::MutationTreeNode ApplyMutations( - const MutationTreeNode& mutation_tree_node, int initial_mutation_id, - clang::ASTContext& context, - std::unordered_set& dredd_declarations); + protobufs::MutationTreeNode ApplyMutations(const MutationTreeNode &mutation_tree_node, + std::optional &enabled_mutation_tree_node, + int initial_mutation_id, + clang::ASTContext &context, + std::unordered_set &dredd_declarations); const clang::CompilerInstance* compiler_instance_; @@ -91,6 +97,8 @@ class MutateAstConsumer : public clang::ASTConsumer { int* mutation_id_; protobufs::MutationInfo* mutation_info_; + + const std::optional* enabled_mutation_info_; }; } // namespace dredd diff --git a/src/libdredd/src/mutate_ast_consumer.cc b/src/libdredd/src/mutate_ast_consumer.cc index 303a046d..9d66e580 100644 --- a/src/libdredd/src/mutate_ast_consumer.cc +++ b/src/libdredd/src/mutate_ast_consumer.cc @@ -76,15 +76,28 @@ void MutateAstConsumer::HandleTranslationUnit(clang::ASTContext& ast_context) { std::unordered_set dredd_declarations; protobufs::MutationInfoForFile mutation_info_for_file; - mutation_info_for_file.set_filename( - ast_context.getSourceManager() - .getFileEntryForID(ast_context.getSourceManager().getMainFileID()) - ->getName() - .str()); + mutation_info_for_file.set_filename(filename); + + std::optional enabled_mutation_tree_node; + if (enabled_mutation_info_->has_value()) { + auto it = std::find_if(enabled_mutation_info_->value().info_for_files().begin(), + enabled_mutation_info_->value().info_for_files().end(), [&filename](const protobufs::MutationInfoForFile& i) { return i.filename() == filename; }); + if (it != enabled_mutation_info_->value().info_for_files().end()) { + const protobufs::MutationInfoForFile& enabled_mutation_info_for_file = *it; + enabled_mutation_tree_node = enabled_mutation_info_for_file.mutation_tree_root(); + } else { + // TODO(James Lee-Jones): Throw an error as the provided enabled mutation file does not contain this file. + } + } else { + enabled_mutation_tree_node = std::nullopt; + } + *mutation_info_for_file.mutable_mutation_tree_root() = - ApplyMutations(visitor_->GetMutations(), initial_mutation_id, ast_context, + ApplyMutations(visitor_->GetMutations(), enabled_mutation_tree_node, initial_mutation_id, ast_context, dredd_declarations); + + if (initial_mutation_id == *mutation_id_) { // No possibilities for mutation were found; nothing else to do. return; @@ -360,27 +373,66 @@ std::string MutateAstConsumer::GetDreddPreludeC(int initial_mutation_id) const { return GetRegularDreddPreludeC(initial_mutation_id); } -protobufs::MutationTreeNode MutateAstConsumer::ApplyMutations( - const MutationTreeNode& mutation_tree_node, int initial_mutation_id, - clang::ASTContext& context, - std::unordered_set& dredd_declarations) { +protobufs::MutationTreeNode MutateAstConsumer::ApplyMutations(const MutationTreeNode &mutation_tree_node, + std::optional &enabled_mutation_tree_node, + int initial_mutation_id, + clang::ASTContext &context, + std::unordered_set &dredd_declarations) { 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()) { + std::vector mutation_tree_node_children = mutation_tree_node.GetChildren(); + // TODO(James Lee-Jones): Check list size matches or throw an error. + if (enabled_mutation_tree_node.has_value()) assert(mutation_tree_node_children.size() == (unsigned long) enabled_mutation_tree_node->children_size()); + for (int i = 0; (unsigned long) i < mutation_tree_node_children.size(); i++) { + auto child = mutation_tree_node_children.at(i); assert(!child->IsEmpty() && - "The mutation tree should not have empty subtrees."); - *result.add_children() = ApplyMutations(*child, initial_mutation_id, + "The mutation tree should not have empty subtrees."); + std::optional enabled_child; + if (enabled_mutation_tree_node == std::nullopt) { + enabled_child = std::nullopt; + } else { + // TODO(James Lee-Jones): Save the call to children to avoid repeat processing. + enabled_child = enabled_mutation_tree_node.value().children().Get(i); + // TODO(James Lee-Jones): Check that this is equal to child. + } + *result.add_children() = ApplyMutations(*child, enabled_child, initial_mutation_id, context, dredd_declarations); } - for (const auto& mutation : mutation_tree_node.GetMutations()) { +// for (const auto& child : mutation_tree_node.GetChildren()) { +// assert(!child->IsEmpty() && +// "The mutation tree should not have empty subtrees."); +// // TODO(James Lee-Jones): Pass on the childs MutationTreeNode. +// *result.add_children() = ApplyMutations(*child, , initial_mutation_id, +// context, dredd_declarations); +// } + // TODO(James Lee-Jones): Check list size matches or throw an error. + const std::vector>& mutations = mutation_tree_node.GetMutations(); + for (int i = 0; (unsigned long) i < mutations.size(); i++) { const int mutation_id_old = *mutation_id_; - const auto mutation_group = mutation->Apply( - context, compiler_instance_->getPreprocessor(), optimise_mutations_, - only_track_mutant_coverage_, mutation_pass_, initial_mutation_id, *mutation_id_, - rewriter_, dredd_declarations); + // TODO(James Lee-Jones): Check if the current mutation is enabled and or with mutation_pass_. + bool enabled = true; + if (enabled_mutation_tree_node.has_value()) { + // TODO(James Lee-Jones): Save the call to children to avoid repeat processing. + const protobufs::MutationGroup& kMutationGroup = enabled_mutation_tree_node.value().mutation_groups().at(i); + if (kMutationGroup.has_remove_stmt()) { + enabled = kMutationGroup.remove_stmt().enabled(); + } else if (kMutationGroup.has_replace_binary_operator()) { + enabled = kMutationGroup.replace_binary_operator().enabled(); + } else if (kMutationGroup.has_replace_expr()) { + enabled = kMutationGroup.replace_expr().enabled(); + } else if (kMutationGroup.has_replace_unary_operator()) { + enabled = kMutationGroup.replace_unary_operator().enabled(); + } + } + + const auto mutation_group = mutations.at(i)->Apply( + context, compiler_instance_->getPreprocessor(), optimise_mutations_, + only_track_mutant_coverage_, mutation_pass_ || !enabled, initial_mutation_id, *mutation_id_, + rewriter_, dredd_declarations); if (*mutation_id_ > mutation_id_old) { + // TODO(James Lee-Jones): Only do this if the mutation is enabled. // Only add the result of applying the mutation if it had an effect. *result.add_mutation_groups() = mutation_group; } diff --git a/src/libdredd/src/mutation_replace_binary_operator.cc b/src/libdredd/src/mutation_replace_binary_operator.cc index 87245785..a4341bff 100644 --- a/src/libdredd/src/mutation_replace_binary_operator.cc +++ b/src/libdredd/src/mutation_replace_binary_operator.cc @@ -557,6 +557,8 @@ protobufs::MutationGroup MutationReplaceBinaryOperator::Apply(clang::ASTContext inner_result.mutable_rhs_end()->set_column(info_for_rhs_.GetEndColumn()); *inner_result.mutable_rhs_snippet() = info_for_rhs_.GetSnippet(); + inner_result.set_enabled(true); + const std::string new_function_name = GetFunctionName(optimise_mutations, ast_context); @@ -880,7 +882,6 @@ void MutationReplaceBinaryOperator::AddMutationInstance( protobufs::MutationReplaceBinaryOperatorInstance instance; instance.set_mutation_id(mutation_id_base + mutation_id_offset); instance.set_action(action); - instance.set_enabled(true); *protobuf_message.add_instances() = instance; mutation_id_offset++; } diff --git a/src/libdredd/src/mutation_replace_expr.cc b/src/libdredd/src/mutation_replace_expr.cc index 67c420ae..d35bed9b 100644 --- a/src/libdredd/src/mutation_replace_expr.cc +++ b/src/libdredd/src/mutation_replace_expr.cc @@ -611,6 +611,7 @@ protobufs::MutationGroup MutationReplaceExpr::Apply(clang::ASTContext &ast_conte inner_result.mutable_end()->set_line(info_for_source_range_.GetEndLine()); inner_result.mutable_end()->set_column(info_for_source_range_.GetEndColumn()); *inner_result.mutable_snippet() = info_for_source_range_.GetSnippet(); + inner_result.set_enabled(true); @@ -682,7 +683,6 @@ void MutationReplaceExpr::AddMutationInstance( protobufs::MutationReplaceExprInstance instance; instance.set_mutation_id(mutation_id_base + mutation_id_offset); instance.set_action(action); - instance.set_enabled(true); *protobuf_message.add_instances() = instance; mutation_id_offset++; } diff --git a/src/libdredd/src/mutation_replace_unary_operator.cc b/src/libdredd/src/mutation_replace_unary_operator.cc index 4139604f..eb6971d9 100644 --- a/src/libdredd/src/mutation_replace_unary_operator.cc +++ b/src/libdredd/src/mutation_replace_unary_operator.cc @@ -370,6 +370,7 @@ protobufs::MutationGroup MutationReplaceUnaryOperator::Apply(clang::ASTContext & info_for_sub_expr_.GetEndColumn()); *inner_result.mutable_operand_snippet() = info_for_sub_expr_.GetSnippet(); + inner_result.set_enabled(true); const std::string new_function_name = @@ -477,7 +478,6 @@ void MutationReplaceUnaryOperator::AddMutationInstance( protobufs::MutationReplaceUnaryOperatorInstance instance; instance.set_mutation_id(mutation_id_base + mutation_id_offset); instance.set_action(action); - instance.set_enabled(true); *protobuf_message.add_instances() = instance; mutation_id_offset++; } diff --git a/src/libdredd/src/new_mutate_frontend_action_factory.cc b/src/libdredd/src/new_mutate_frontend_action_factory.cc index 8780d686..1c3e0787 100644 --- a/src/libdredd/src/new_mutate_frontend_action_factory.cc +++ b/src/libdredd/src/new_mutate_frontend_action_factory.cc @@ -37,6 +37,7 @@ class MutateFrontendAction : public clang::ASTFrontendAction { bool mutation_pass, int &mutation_id, protobufs::MutationInfo &mutation_info, + const std::optional &enabled_mutation_info, std::set &processed_files) : optimise_mutations_(optimise_mutations), dump_asts_(dump_asts), @@ -44,6 +45,7 @@ class MutateFrontendAction : public clang::ASTFrontendAction { mutation_pass_(mutation_pass), mutation_id_(&mutation_id), mutation_info_(&mutation_info), + enabled_mutation_info_(&enabled_mutation_info), processed_files_(&processed_files) {} std::unique_ptr CreateASTConsumer( @@ -71,6 +73,7 @@ class MutateFrontendAction : public clang::ASTFrontendAction { bool mutation_pass_; int* mutation_id_; protobufs::MutationInfo* mutation_info_; + const std::optional* enabled_mutation_info_; std::set* processed_files_; }; @@ -80,7 +83,8 @@ NewMutateFrontendActionFactory(bool optimise_mutations, bool only_track_mutant_coverage, bool mutation_pass, int &mutation_id, - protobufs::MutationInfo &mutation_info) { + protobufs::MutationInfo &mutation_info, + const std::optional &enabled_mutation_info) { class MutateFrontendActionFactory : public clang::tooling::FrontendActionFactory { public: @@ -89,18 +93,20 @@ NewMutateFrontendActionFactory(bool optimise_mutations, bool only_track_mutant_coverage, bool mutation_pass, int &mutation_id, - protobufs::MutationInfo &mutation_info) + protobufs::MutationInfo &mutation_info, + const std::optional &enabled_mutation_info) : optimise_mutations_(optimise_mutations), dump_asts_(dump_asts), only_track_mutant_coverage_(only_track_mutant_coverage), mutation_pass_(mutation_pass), mutation_id_(&mutation_id), - mutation_info_(&mutation_info) {} + mutation_info_(&mutation_info), + enabled_mutation_info_(&enabled_mutation_info) {} std::unique_ptr create() override { return std::make_unique( optimise_mutations_, dump_asts_, only_track_mutant_coverage_, mutation_pass_, - *mutation_id_, *mutation_info_, processed_files_); + *mutation_id_, *mutation_info_, *enabled_mutation_info_, processed_files_); } private: @@ -110,6 +116,7 @@ NewMutateFrontendActionFactory(bool optimise_mutations, bool mutation_pass_; int* mutation_id_; protobufs::MutationInfo* mutation_info_; + const std::optional* enabled_mutation_info_; // Stores the ids of the files that have been processed so far, to avoid // processing a file multiple times. @@ -118,7 +125,7 @@ NewMutateFrontendActionFactory(bool optimise_mutations, return std::make_unique( optimise_mutations, dump_asts, only_track_mutant_coverage, mutation_pass, mutation_id, - mutation_info); + mutation_info, enabled_mutation_info); } std::unique_ptr MutateFrontendAction::CreateASTConsumer( @@ -126,7 +133,7 @@ std::unique_ptr MutateFrontendAction::CreateASTConsumer( (void)file; // Unused. return std::make_unique( compiler_instance, optimise_mutations_, mutation_pass_, dump_asts_, - only_track_mutant_coverage_, *mutation_id_, *mutation_info_); + only_track_mutant_coverage_, *mutation_id_, *mutation_info_, *enabled_mutation_info_); } } // namespace dredd From 55371c40303890c1ba724501663ef0828e05c81a Mon Sep 17 00:00:00 2001 From: James Lee-Jones Date: Wed, 27 Mar 2024 20:15:42 +0000 Subject: [PATCH 4/5] Formatting and correctness fixes --- .../dredd/protobufs/protobuf_serialization.h | 2 +- src/dredd/src/main.cc | 22 ++-- src/libdredd/include/libdredd/mutation.h | 15 +-- .../include/libdredd/mutation_remove_stmt.h | 15 +-- .../mutation_replace_binary_operator.h | 15 +-- .../include/libdredd/mutation_replace_expr.h | 15 +-- .../mutation_replace_unary_operator.h | 15 +-- .../new_mutate_frontend_action_factory.h | 13 +- .../include/libdredd/mutate_ast_consumer.h | 24 ++-- src/libdredd/src/mutate_ast_consumer.cc | 112 ++++++++++-------- src/libdredd/src/mutation_remove_stmt.cc | 16 +-- .../src/mutation_replace_binary_operator.cc | 33 +++--- src/libdredd/src/mutation_replace_expr.cc | 41 +++---- .../src/mutation_replace_unary_operator.cc | 16 +-- .../src/new_mutate_frontend_action_factory.cc | 50 ++++---- 15 files changed, 191 insertions(+), 213 deletions(-) diff --git a/src/dredd/include_private/include/dredd/protobufs/protobuf_serialization.h b/src/dredd/include_private/include/dredd/protobufs/protobuf_serialization.h index ddc57327..5e98e1f0 100644 --- a/src/dredd/include_private/include/dredd/protobufs/protobuf_serialization.h +++ b/src/dredd/include_private/include/dredd/protobufs/protobuf_serialization.h @@ -33,7 +33,7 @@ #endif // The following should be the only place in the project where protobuf files -// related to serialization are are directly included. This is so that they can +// related to serialization are directly included. This is so that they can // be compiled in a manner where warnings are ignored. #include "google/protobuf/stubs/status.h" #include "google/protobuf/util/json_util.h" diff --git a/src/dredd/src/main.cc b/src/dredd/src/main.cc index c696996d..3951bd81 100644 --- a/src/dredd/src/main.cc +++ b/src/dredd/src/main.cc @@ -15,6 +15,7 @@ #include #include #include +#include #include #include "clang/Tooling/CommonOptionsParser.h" @@ -63,14 +64,15 @@ static llvm::cl::opt dump_asts( // NOLINTNEXTLINE static llvm::cl::opt mutant_pass( "mutant-pass", - llvm::cl::desc("Perform a pass to build the mutation tree. Must be passed with --mutation_info_file."), + llvm::cl::desc("Perform a pass to build the mutation tree. Must be passed " + "with --mutation_info_file."), llvm::cl::cat(mutate_category)); -// TODO(James Lee-Jones): Rename this to something more representative of what it does. -// NOLINTNEXTLINE +// TODO(James Lee-Jones): Rename this to something more representative of what +// it does. NOLINTNEXTLINE static llvm::cl::opt enabled_mutations_file( "enabled-mutations-file", - llvm::cl::desc( - ".json file containing information on which mutations should be performed"), + llvm::cl::desc(".json file containing information on which mutations " + "should be performed"), llvm::cl::cat(mutate_category)); // NOLINTNEXTLINE static llvm::cl::opt mutation_info_file( @@ -127,19 +129,19 @@ int main(int argc, const char** argv) { enabled_mutations_json << enabled_mutations_json_file.rdbuf(); std::string enabled_mutations_string = enabled_mutations_json.str(); - auto json_read_status = google::protobuf::util::JsonStringToMessage(enabled_mutations_string, &*enabled_mutation_info); + auto json_read_status = google::protobuf::util::JsonStringToMessage( + enabled_mutations_string, &*enabled_mutation_info); if (!json_read_status.ok()) { llvm::errs() << "Error reading JSON data from " << enabled_mutations_file << "\n"; - llvm::errs() << json_read_status.ToString(); return 1; } } const std::unique_ptr factory = - dredd::NewMutateFrontendActionFactory(!no_mutation_opts, dump_asts, - only_track_mutant_coverage, mutant_pass, - mutation_id, mutation_info, enabled_mutation_info); + dredd::NewMutateFrontendActionFactory( + !no_mutation_opts, dump_asts, only_track_mutant_coverage, mutant_pass, + mutation_id, mutation_info, enabled_mutation_info); const int return_code = Tool.run(factory.get()); diff --git a/src/libdredd/include/libdredd/mutation.h b/src/libdredd/include/libdredd/mutation.h index 097a1b47..14a03744 100644 --- a/src/libdredd/include/libdredd/mutation.h +++ b/src/libdredd/include/libdredd/mutation.h @@ -48,15 +48,12 @@ class Mutation { // The |dredd_declarations| argument provides a set of declarations that will // be added to the start of the source file being mutated. This allows // avoiding redundant repeat declarations. - virtual protobufs::MutationGroup Apply(clang::ASTContext &ast_context, - const clang::Preprocessor &preprocessor, - bool optimise_mutations, - bool only_track_mutant_coverage, - bool mutation_pass, - int first_mutation_id_in_file, - int &mutation_id, - clang::Rewriter &rewriter, - std::unordered_set &dredd_declarations) const = 0; + virtual protobufs::MutationGroup Apply( + clang::ASTContext& ast_context, const clang::Preprocessor& preprocessor, + bool optimise_mutations, bool only_track_mutant_coverage, + bool mutation_pass, int first_mutation_id_in_file, int& mutation_id, + clang::Rewriter& rewriter, + std::unordered_set& dredd_declarations) const = 0; }; } // namespace dredd diff --git a/src/libdredd/include/libdredd/mutation_remove_stmt.h b/src/libdredd/include/libdredd/mutation_remove_stmt.h index c1aa12db..c388a828 100644 --- a/src/libdredd/include/libdredd/mutation_remove_stmt.h +++ b/src/libdredd/include/libdredd/mutation_remove_stmt.h @@ -35,15 +35,12 @@ class MutationRemoveStmt : public Mutation { const clang::Preprocessor& preprocessor, const clang::ASTContext& ast_context); - protobufs::MutationGroup Apply(clang::ASTContext &ast_context, - const clang::Preprocessor &preprocessor, - bool optimise_mutations, - bool only_track_mutant_coverage, - bool mutation_pass, - int first_mutation_id_in_file, - int &mutation_id, - clang::Rewriter &rewriter, - std::unordered_set &dredd_declarations) const override; + protobufs::MutationGroup Apply( + clang::ASTContext& ast_context, const clang::Preprocessor& preprocessor, + bool optimise_mutations, bool only_track_mutant_coverage, + bool mutation_pass, int first_mutation_id_in_file, int& mutation_id, + clang::Rewriter& rewriter, + std::unordered_set& dredd_declarations) const override; private: // Helper method to determine whether the token immediately following the diff --git a/src/libdredd/include/libdredd/mutation_replace_binary_operator.h b/src/libdredd/include/libdredd/mutation_replace_binary_operator.h index 02187533..dbed64c8 100644 --- a/src/libdredd/include/libdredd/mutation_replace_binary_operator.h +++ b/src/libdredd/include/libdredd/mutation_replace_binary_operator.h @@ -37,15 +37,12 @@ class MutationReplaceBinaryOperator : public Mutation { const clang::Preprocessor& preprocessor, const clang::ASTContext& ast_context); - protobufs::MutationGroup Apply(clang::ASTContext &ast_context, - const clang::Preprocessor &preprocessor, - bool optimise_mutations, - bool only_track_mutant_coverage, - bool mutation_pass, - int first_mutation_id_in_file, - int &mutation_id, - clang::Rewriter &rewriter, - std::unordered_set &dredd_declarations) const override; + protobufs::MutationGroup Apply( + clang::ASTContext& ast_context, const clang::Preprocessor& preprocessor, + bool optimise_mutations, bool only_track_mutant_coverage, + bool mutation_pass, int first_mutation_id_in_file, int& mutation_id, + clang::Rewriter& rewriter, + std::unordered_set& dredd_declarations) const override; private: std::string GenerateMutatorFunction( diff --git a/src/libdredd/include/libdredd/mutation_replace_expr.h b/src/libdredd/include/libdredd/mutation_replace_expr.h index fb3eab67..a1f4350a 100644 --- a/src/libdredd/include/libdredd/mutation_replace_expr.h +++ b/src/libdredd/include/libdredd/mutation_replace_expr.h @@ -36,15 +36,12 @@ class MutationReplaceExpr : public Mutation { const clang::Preprocessor& preprocessor, const clang::ASTContext& ast_context); - protobufs::MutationGroup Apply(clang::ASTContext &ast_context, - const clang::Preprocessor &preprocessor, - bool optimise_mutations, - bool only_track_mutant_coverage, - bool mutation_pass, - int first_mutation_id_in_file, - int &mutation_id, - clang::Rewriter &rewriter, - std::unordered_set &dredd_declarations) const override; + protobufs::MutationGroup Apply( + clang::ASTContext& ast_context, const clang::Preprocessor& preprocessor, + bool optimise_mutations, bool only_track_mutant_coverage, + bool mutation_pass, int first_mutation_id_in_file, int& mutation_id, + clang::Rewriter& rewriter, + std::unordered_set& dredd_declarations) const override; static void ApplyCppTypeModifiers(const clang::Expr& expr, std::string& type); diff --git a/src/libdredd/include/libdredd/mutation_replace_unary_operator.h b/src/libdredd/include/libdredd/mutation_replace_unary_operator.h index 81c5b068..cb202841 100644 --- a/src/libdredd/include/libdredd/mutation_replace_unary_operator.h +++ b/src/libdredd/include/libdredd/mutation_replace_unary_operator.h @@ -36,15 +36,12 @@ class MutationReplaceUnaryOperator : public Mutation { const clang::Preprocessor& preprocessor, const clang::ASTContext& ast_context); - protobufs::MutationGroup Apply(clang::ASTContext &ast_context, - const clang::Preprocessor &preprocessor, - bool optimise_mutations, - bool only_track_mutant_coverage, - bool mutation_pass, - int first_mutation_id_in_file, - int &mutation_id, - clang::Rewriter &rewriter, - std::unordered_set &dredd_declarations) const override; + protobufs::MutationGroup Apply( + clang::ASTContext& ast_context, const clang::Preprocessor& preprocessor, + bool optimise_mutations, bool only_track_mutant_coverage, + bool mutation_pass, int first_mutation_id_in_file, int& mutation_id, + clang::Rewriter& rewriter, + std::unordered_set& dredd_declarations) const override; private: std::string GenerateMutatorFunction( diff --git a/src/libdredd/include/libdredd/new_mutate_frontend_action_factory.h b/src/libdredd/include/libdredd/new_mutate_frontend_action_factory.h index ed9e6881..28d4dbc0 100644 --- a/src/libdredd/include/libdredd/new_mutate_frontend_action_factory.h +++ b/src/libdredd/include/libdredd/new_mutate_frontend_action_factory.h @@ -16,6 +16,7 @@ #define LIBDREDD_NEW_MUTATE_FRONTEND_ACTION_FACTORY_H #include +#include #include "clang/Tooling/Tooling.h" #include "libdredd/protobufs/dredd_protobufs.h" @@ -23,13 +24,11 @@ namespace dredd { std::unique_ptr -NewMutateFrontendActionFactory(bool optimise_mutations, - bool dump_asts, - bool only_track_mutant_coverage, - bool mutation_pass, - int &mutation_id, - protobufs::MutationInfo &mutation_info, - const std::optional &enabled_mutation_info); +NewMutateFrontendActionFactory( + bool optimise_mutations, bool dump_asts, bool only_track_mutant_coverage, + bool mutation_pass, int& mutation_id, + protobufs::MutationInfo& mutation_info, + const std::optional& enabled_mutation_info); } diff --git a/src/libdredd/include_private/include/libdredd/mutate_ast_consumer.h b/src/libdredd/include_private/include/libdredd/mutate_ast_consumer.h index c30853fd..9ad81467 100644 --- a/src/libdredd/include_private/include/libdredd/mutate_ast_consumer.h +++ b/src/libdredd/include_private/include/libdredd/mutate_ast_consumer.h @@ -16,6 +16,7 @@ #define LIBDREDD_MUTATE_AST_CONSUMER_H #include +#include #include #include @@ -31,14 +32,11 @@ namespace dredd { class MutateAstConsumer : public clang::ASTConsumer { public: - MutateAstConsumer(const clang::CompilerInstance &compiler_instance, - bool optimise_mutations, - bool mutation_pass, - bool dump_ast, - bool only_track_mutant_coverage, - int &mutation_id, - protobufs::MutationInfo &mutation_info, - const std::optional &enabled_mutation_info) + MutateAstConsumer( + const clang::CompilerInstance& compiler_instance, bool optimise_mutations, + bool mutation_pass, bool dump_ast, bool only_track_mutant_coverage, + int& mutation_id, protobufs::MutationInfo& mutation_info, + const std::optional& enabled_mutation_info) : compiler_instance_(&compiler_instance), optimise_mutations_(optimise_mutations), mutation_pass_(mutation_pass), @@ -69,11 +67,11 @@ class MutateAstConsumer : public clang::ASTConsumer { [[nodiscard]] std::string GetMutantTrackingDreddPreludeC( int initial_mutation_id) const; - protobufs::MutationTreeNode ApplyMutations(const MutationTreeNode &mutation_tree_node, - std::optional &enabled_mutation_tree_node, - int initial_mutation_id, - clang::ASTContext &context, - std::unordered_set &dredd_declarations); + protobufs::MutationTreeNode ApplyMutations( + const MutationTreeNode& mutation_tree_node, + std::optional& enabled_mutation_tree_node, + int initial_mutation_id, clang::ASTContext& context, + std::unordered_set& dredd_declarations); const clang::CompilerInstance* compiler_instance_; diff --git a/src/libdredd/src/mutate_ast_consumer.cc b/src/libdredd/src/mutate_ast_consumer.cc index 9d66e580..12a7e823 100644 --- a/src/libdredd/src/mutate_ast_consumer.cc +++ b/src/libdredd/src/mutate_ast_consumer.cc @@ -15,6 +15,7 @@ #include "libdredd/mutate_ast_consumer.h" #include +#include #include #include #include @@ -78,25 +79,34 @@ void MutateAstConsumer::HandleTranslationUnit(clang::ASTContext& ast_context) { protobufs::MutationInfoForFile mutation_info_for_file; mutation_info_for_file.set_filename(filename); - std::optional enabled_mutation_tree_node; + std::optional enabled_mutation_tree_node = + std::nullopt; if (enabled_mutation_info_->has_value()) { - auto it = std::find_if(enabled_mutation_info_->value().info_for_files().begin(), - enabled_mutation_info_->value().info_for_files().end(), [&filename](const protobufs::MutationInfoForFile& i) { return i.filename() == filename; }); - if (it != enabled_mutation_info_->value().info_for_files().end()) { - const protobufs::MutationInfoForFile& enabled_mutation_info_for_file = *it; - enabled_mutation_tree_node = enabled_mutation_info_for_file.mutation_tree_root(); - } else { - // TODO(James Lee-Jones): Throw an error as the provided enabled mutation file does not contain this file. + // This is used instead of find_if to avoid using protobufs internal + // pointers. + for (int i = 0; i < enabled_mutation_info_->value().info_for_files_size(); + i++) { + if (enabled_mutation_info_->value().info_for_files(i).filename() == + filename) { + enabled_mutation_tree_node = enabled_mutation_info_->value() + .info_for_files(i) + .mutation_tree_root(); + } + } + + // The enabled mutation file doesn't contain information about the current + // file, so skip it. + if (enabled_mutation_tree_node == std::nullopt) { + // TODO(James Lee-Jones): Throw an error as the provided enabled mutation + // file does not contain this file. + llvm::errs() << "Skipping due to errors\n"; + return; } - } else { - enabled_mutation_tree_node = std::nullopt; } *mutation_info_for_file.mutable_mutation_tree_root() = - ApplyMutations(visitor_->GetMutations(), enabled_mutation_tree_node, initial_mutation_id, ast_context, - dredd_declarations); - - + ApplyMutations(visitor_->GetMutations(), enabled_mutation_tree_node, + initial_mutation_id, ast_context, dredd_declarations); if (initial_mutation_id == *mutation_id_) { // No possibilities for mutation were found; nothing else to do. @@ -373,49 +383,55 @@ std::string MutateAstConsumer::GetDreddPreludeC(int initial_mutation_id) const { return GetRegularDreddPreludeC(initial_mutation_id); } -protobufs::MutationTreeNode MutateAstConsumer::ApplyMutations(const MutationTreeNode &mutation_tree_node, - std::optional &enabled_mutation_tree_node, - int initial_mutation_id, - clang::ASTContext &context, - std::unordered_set &dredd_declarations) { +protobufs::MutationTreeNode MutateAstConsumer::ApplyMutations( + const MutationTreeNode& mutation_tree_node, + std::optional& enabled_mutation_tree_node, + int initial_mutation_id, clang::ASTContext& context, + std::unordered_set& dredd_declarations) { assert(!(mutation_tree_node.IsEmpty() && mutation_tree_node.GetChildren().size() == 1) && "The mutation tree should already be compressed."); protobufs::MutationTreeNode result; - std::vector mutation_tree_node_children = mutation_tree_node.GetChildren(); + std::vector mutation_tree_node_children = + mutation_tree_node.GetChildren(); // TODO(James Lee-Jones): Check list size matches or throw an error. - if (enabled_mutation_tree_node.has_value()) assert(mutation_tree_node_children.size() == (unsigned long) enabled_mutation_tree_node->children_size()); - for (int i = 0; (unsigned long) i < mutation_tree_node_children.size(); i++) { - auto child = mutation_tree_node_children.at(i); + if (enabled_mutation_tree_node.has_value()) + assert(mutation_tree_node_children.size() == + static_cast( + enabled_mutation_tree_node->children_size())); + for (int i = 0; + static_cast(i) < mutation_tree_node_children.size(); + i++) { + auto child = mutation_tree_node_children.at(static_cast(i)); assert(!child->IsEmpty() && - "The mutation tree should not have empty subtrees."); + "The mutation tree should not have empty subtrees."); std::optional enabled_child; if (enabled_mutation_tree_node == std::nullopt) { enabled_child = std::nullopt; } else { - // TODO(James Lee-Jones): Save the call to children to avoid repeat processing. - enabled_child = enabled_mutation_tree_node.value().children().Get(i); + // TODO(James Lee-Jones): Save the call to children to avoid repeat + // processing. + enabled_child = enabled_mutation_tree_node.value().children(i); // TODO(James Lee-Jones): Check that this is equal to child. } - *result.add_children() = ApplyMutations(*child, enabled_child, initial_mutation_id, - context, dredd_declarations); + *result.add_children() = + ApplyMutations(*child, enabled_child, initial_mutation_id, context, + dredd_declarations); } -// for (const auto& child : mutation_tree_node.GetChildren()) { -// assert(!child->IsEmpty() && -// "The mutation tree should not have empty subtrees."); -// // TODO(James Lee-Jones): Pass on the childs MutationTreeNode. -// *result.add_children() = ApplyMutations(*child, , initial_mutation_id, -// context, dredd_declarations); -// } + // TODO(James Lee-Jones): Check list size matches or throw an error. - const std::vector>& mutations = mutation_tree_node.GetMutations(); - for (int i = 0; (unsigned long) i < mutations.size(); i++) { + const std::vector>& mutations = + mutation_tree_node.GetMutations(); + for (int i = 0; static_cast(i) < mutations.size(); i++) { const int mutation_id_old = *mutation_id_; - // TODO(James Lee-Jones): Check if the current mutation is enabled and or with mutation_pass_. + // TODO(James Lee-Jones): Check if the current mutation is enabled and or + // with mutation_pass_. bool enabled = true; if (enabled_mutation_tree_node.has_value()) { - // TODO(James Lee-Jones): Save the call to children to avoid repeat processing. - const protobufs::MutationGroup& kMutationGroup = enabled_mutation_tree_node.value().mutation_groups().at(i); + // TODO(James Lee-Jones): Save the call to children to avoid repeat + // processing. + const protobufs::MutationGroup& kMutationGroup = + enabled_mutation_tree_node.value().mutation_groups(i); if (kMutationGroup.has_remove_stmt()) { enabled = kMutationGroup.remove_stmt().enabled(); } else if (kMutationGroup.has_replace_binary_operator()) { @@ -427,13 +443,15 @@ protobufs::MutationTreeNode MutateAstConsumer::ApplyMutations(const MutationTree } } - const auto mutation_group = mutations.at(i)->Apply( - context, compiler_instance_->getPreprocessor(), optimise_mutations_, - only_track_mutant_coverage_, mutation_pass_ || !enabled, initial_mutation_id, *mutation_id_, - rewriter_, dredd_declarations); - if (*mutation_id_ > mutation_id_old) { - // TODO(James Lee-Jones): Only do this if the mutation is enabled. - // Only add the result of applying the mutation if it had an effect. + const auto mutation_group = + mutations.at(static_cast(i)) + ->Apply(context, compiler_instance_->getPreprocessor(), + optimise_mutations_, only_track_mutant_coverage_, + mutation_pass_ || !enabled, initial_mutation_id, + *mutation_id_, rewriter_, dredd_declarations); + if (enabled && *mutation_id_ > mutation_id_old) { + // Only add the result of applying the mutation if it is enabled and had + // an effect. *result.add_mutation_groups() = mutation_group; } } diff --git a/src/libdredd/src/mutation_remove_stmt.cc b/src/libdredd/src/mutation_remove_stmt.cc index f7985394..beba1012 100644 --- a/src/libdredd/src/mutation_remove_stmt.cc +++ b/src/libdredd/src/mutation_remove_stmt.cc @@ -38,15 +38,12 @@ MutationRemoveStmt::MutationRemoveStmt(const clang::Stmt& stmt, info_for_source_range_(GetSourceRangeInMainFile(preprocessor, stmt), ast_context) {} -protobufs::MutationGroup MutationRemoveStmt::Apply(clang::ASTContext &ast_context, - const clang::Preprocessor &preprocessor, - bool optimise_mutations, - bool only_track_mutant_coverage, - bool mutation_pass, - int first_mutation_id_in_file, - int &mutation_id, - clang::Rewriter &rewriter, - std::unordered_set &dredd_declarations) const { +protobufs::MutationGroup MutationRemoveStmt::Apply( + clang::ASTContext& ast_context, const clang::Preprocessor& preprocessor, + bool optimise_mutations, bool only_track_mutant_coverage, + bool mutation_pass, int first_mutation_id_in_file, int& mutation_id, + clang::Rewriter& rewriter, + std::unordered_set& dredd_declarations) const { (void)dredd_declarations; // Unused. (void)optimise_mutations; // Unused. @@ -73,7 +70,6 @@ protobufs::MutationGroup MutationRemoveStmt::Apply(clang::ASTContext &ast_contex if (mutation_pass) return result; - clang::CharSourceRange source_range = clang::CharSourceRange::getTokenRange( GetSourceRangeInMainFile(preprocessor, *stmt_)); diff --git a/src/libdredd/src/mutation_replace_binary_operator.cc b/src/libdredd/src/mutation_replace_binary_operator.cc index a4341bff..0ceeac81 100644 --- a/src/libdredd/src/mutation_replace_binary_operator.cc +++ b/src/libdredd/src/mutation_replace_binary_operator.cc @@ -519,15 +519,12 @@ std::string MutationReplaceBinaryOperator::GenerateMutatorFunction( return new_function.str(); } -protobufs::MutationGroup MutationReplaceBinaryOperator::Apply(clang::ASTContext &ast_context, - const clang::Preprocessor &preprocessor, - bool optimise_mutations, - bool only_track_mutant_coverage, - bool mutation_pass, - int first_mutation_id_in_file, - int &mutation_id, - clang::Rewriter &rewriter, - std::unordered_set &dredd_declarations) const { +protobufs::MutationGroup MutationReplaceBinaryOperator::Apply( + clang::ASTContext& ast_context, const clang::Preprocessor& preprocessor, + bool optimise_mutations, bool only_track_mutant_coverage, + bool mutation_pass, int first_mutation_id_in_file, int& mutation_id, + clang::Rewriter& rewriter, + std::unordered_set& dredd_declarations) const { // The protobuf object for the mutation, which will be wrapped in a // MutationGroup. protobufs::MutationReplaceBinaryOperator inner_result; @@ -559,7 +556,6 @@ protobufs::MutationGroup MutationReplaceBinaryOperator::Apply(clang::ASTContext inner_result.set_enabled(true); - const std::string new_function_name = GetFunctionName(optimise_mutations, ast_context); std::string result_type = binary_operator_->getType() @@ -611,7 +607,11 @@ protobufs::MutationGroup MutationReplaceBinaryOperator::Apply(clang::ASTContext } } - + if (!mutation_pass) { + ReplaceOperator(lhs_type, rhs_type, new_function_name, ast_context, + preprocessor, first_mutation_id_in_file, mutation_id, + rewriter); + } const std::string new_function = GenerateMutatorFunction( ast_context, new_function_name, result_type, lhs_type, rhs_type, @@ -619,17 +619,12 @@ protobufs::MutationGroup MutationReplaceBinaryOperator::Apply(clang::ASTContext inner_result); assert(!new_function.empty() && "Unsupported opcode."); - protobufs::MutationGroup result; - *result.mutable_replace_binary_operator() = inner_result; - if (mutation_pass) return result; - - ReplaceOperator(lhs_type, rhs_type, new_function_name, ast_context, - preprocessor, first_mutation_id_in_file, mutation_id, - rewriter); // Add the mutation function to the set of Dredd declarations - there may // already be a matching function, in which case duplication will be avoided. - dredd_declarations.insert(new_function); + if (!mutation_pass) dredd_declarations.insert(new_function); + protobufs::MutationGroup result; + *result.mutable_replace_binary_operator() = inner_result; return result; } diff --git a/src/libdredd/src/mutation_replace_expr.cc b/src/libdredd/src/mutation_replace_expr.cc index d35bed9b..dc22c675 100644 --- a/src/libdredd/src/mutation_replace_expr.cc +++ b/src/libdredd/src/mutation_replace_expr.cc @@ -592,15 +592,12 @@ void MutationReplaceExpr::ReplaceExprWithFunctionCall( (void)rewriter_result; // Keep release mode compilers happy. } -protobufs::MutationGroup MutationReplaceExpr::Apply(clang::ASTContext &ast_context, - const clang::Preprocessor &preprocessor, - bool optimise_mutations, - bool only_track_mutant_coverage, - bool mutation_pass, - int first_mutation_id_in_file, - int &mutation_id, - clang::Rewriter &rewriter, - std::unordered_set &dredd_declarations) const { +protobufs::MutationGroup MutationReplaceExpr::Apply( + clang::ASTContext& ast_context, const clang::Preprocessor& preprocessor, + bool optimise_mutations, bool only_track_mutant_coverage, + bool mutation_pass, int first_mutation_id_in_file, int& mutation_id, + clang::Rewriter& rewriter, + std::unordered_set& dredd_declarations) const { // The protobuf object for the mutation, which will be wrapped in a // MutationGroup. protobufs::MutationReplaceExpr inner_result; @@ -613,8 +610,6 @@ protobufs::MutationGroup MutationReplaceExpr::Apply(clang::ASTContext &ast_conte *inner_result.mutable_snippet() = info_for_source_range_.GetSnippet(); inner_result.set_enabled(true); - - const std::string new_function_name = GetFunctionName(optimise_mutations, ast_context); const std::string result_type = expr_->getType() @@ -633,27 +628,25 @@ protobufs::MutationGroup MutationReplaceExpr::Apply(clang::ASTContext &ast_conte ApplyCTypeModifiers(*expr_, input_type); } + // Replace the expression with a function call. + // Subtracting |first_mutation_id_in_file| turns the global mutation id, + // |mutation_id|, into a file-local mutation id. + if (!mutation_pass) { + ReplaceExprWithFunctionCall(new_function_name, input_type, + mutation_id - first_mutation_id_in_file, + ast_context, preprocessor, rewriter); + } + const std::string new_function = GenerateMutatorFunction( ast_context, new_function_name, result_type, input_type, optimise_mutations, only_track_mutant_coverage, mutation_id, inner_result); assert(!new_function.empty() && "Unsupported expression."); + if (!mutation_pass) dredd_declarations.insert(new_function); + protobufs::MutationGroup result; *result.mutable_replace_expr() = inner_result; - - if (mutation_pass) return result; - - // Replace the expression with a function call. - // Subtracting |first_mutation_id_in_file| turns the global mutation id, - // |mutation_id|, into a file-local mutation id. - ReplaceExprWithFunctionCall(new_function_name, input_type, - mutation_id - first_mutation_id_in_file, - ast_context, preprocessor, rewriter); - - - dredd_declarations.insert(new_function); - return result; } diff --git a/src/libdredd/src/mutation_replace_unary_operator.cc b/src/libdredd/src/mutation_replace_unary_operator.cc index eb6971d9..bf0b41f8 100644 --- a/src/libdredd/src/mutation_replace_unary_operator.cc +++ b/src/libdredd/src/mutation_replace_unary_operator.cc @@ -335,15 +335,12 @@ void MutationReplaceUnaryOperator::GenerateUnaryOperatorReplacement( } } -protobufs::MutationGroup MutationReplaceUnaryOperator::Apply(clang::ASTContext &ast_context, - const clang::Preprocessor &preprocessor, - bool optimise_mutations, - bool only_track_mutant_coverage, - bool mutation_pass, - int first_mutation_id_in_file, - int &mutation_id, - clang::Rewriter &rewriter, - std::unordered_set &dredd_declarations) const { +protobufs::MutationGroup MutationReplaceUnaryOperator::Apply( + clang::ASTContext& ast_context, const clang::Preprocessor& preprocessor, + bool optimise_mutations, bool only_track_mutant_coverage, + bool mutation_pass, int first_mutation_id_in_file, int& mutation_id, + clang::Rewriter& rewriter, + std::unordered_set& dredd_declarations) const { // The protobuf object for the mutation, which will be wrapped in a // MutationGroup. protobufs::MutationReplaceUnaryOperator inner_result; @@ -372,7 +369,6 @@ protobufs::MutationGroup MutationReplaceUnaryOperator::Apply(clang::ASTContext & inner_result.set_enabled(true); - const std::string new_function_name = GetFunctionName(optimise_mutations, ast_context); std::string result_type = unary_operator_->getType() diff --git a/src/libdredd/src/new_mutate_frontend_action_factory.cc b/src/libdredd/src/new_mutate_frontend_action_factory.cc index 1c3e0787..24f2d256 100644 --- a/src/libdredd/src/new_mutate_frontend_action_factory.cc +++ b/src/libdredd/src/new_mutate_frontend_action_factory.cc @@ -31,14 +31,12 @@ namespace dredd { class MutateFrontendAction : public clang::ASTFrontendAction { public: - MutateFrontendAction(bool optimise_mutations, - bool dump_asts, - bool only_track_mutant_coverage, - bool mutation_pass, - int &mutation_id, - protobufs::MutationInfo &mutation_info, - const std::optional &enabled_mutation_info, - std::set &processed_files) + MutateFrontendAction( + bool optimise_mutations, bool dump_asts, bool only_track_mutant_coverage, + bool mutation_pass, int& mutation_id, + protobufs::MutationInfo& mutation_info, + const std::optional& enabled_mutation_info, + std::set& processed_files) : optimise_mutations_(optimise_mutations), dump_asts_(dump_asts), only_track_mutant_coverage_(only_track_mutant_coverage), @@ -78,23 +76,19 @@ class MutateFrontendAction : public clang::ASTFrontendAction { }; std::unique_ptr -NewMutateFrontendActionFactory(bool optimise_mutations, - bool dump_asts, - bool only_track_mutant_coverage, - bool mutation_pass, - int &mutation_id, - protobufs::MutationInfo &mutation_info, - const std::optional &enabled_mutation_info) { +NewMutateFrontendActionFactory( + bool optimise_mutations, bool dump_asts, bool only_track_mutant_coverage, + bool mutation_pass, int& mutation_id, + protobufs::MutationInfo& mutation_info, + const std::optional& enabled_mutation_info) { class MutateFrontendActionFactory : public clang::tooling::FrontendActionFactory { public: - MutateFrontendActionFactory(bool optimise_mutations, - bool dump_asts, - bool only_track_mutant_coverage, - bool mutation_pass, - int &mutation_id, - protobufs::MutationInfo &mutation_info, - const std::optional &enabled_mutation_info) + MutateFrontendActionFactory( + bool optimise_mutations, bool dump_asts, + bool only_track_mutant_coverage, bool mutation_pass, int& mutation_id, + protobufs::MutationInfo& mutation_info, + const std::optional& enabled_mutation_info) : optimise_mutations_(optimise_mutations), dump_asts_(dump_asts), only_track_mutant_coverage_(only_track_mutant_coverage), @@ -105,8 +99,9 @@ NewMutateFrontendActionFactory(bool optimise_mutations, std::unique_ptr create() override { return std::make_unique( - optimise_mutations_, dump_asts_, only_track_mutant_coverage_, mutation_pass_, - *mutation_id_, *mutation_info_, *enabled_mutation_info_, processed_files_); + optimise_mutations_, dump_asts_, only_track_mutant_coverage_, + mutation_pass_, *mutation_id_, *mutation_info_, + *enabled_mutation_info_, processed_files_); } private: @@ -124,8 +119,8 @@ NewMutateFrontendActionFactory(bool optimise_mutations, }; return std::make_unique( - optimise_mutations, dump_asts, only_track_mutant_coverage, mutation_pass, mutation_id, - mutation_info, enabled_mutation_info); + optimise_mutations, dump_asts, only_track_mutant_coverage, mutation_pass, + mutation_id, mutation_info, enabled_mutation_info); } std::unique_ptr MutateFrontendAction::CreateASTConsumer( @@ -133,7 +128,8 @@ std::unique_ptr MutateFrontendAction::CreateASTConsumer( (void)file; // Unused. return std::make_unique( compiler_instance, optimise_mutations_, mutation_pass_, dump_asts_, - only_track_mutant_coverage_, *mutation_id_, *mutation_info_, *enabled_mutation_info_); + only_track_mutant_coverage_, *mutation_id_, *mutation_info_, + *enabled_mutation_info_); } } // namespace dredd From 8d484e63fae0c77475b96eba99a88b31ff354413 Mon Sep 17 00:00:00 2001 From: James Lee-Jones Date: Wed, 27 Mar 2024 20:55:19 +0000 Subject: [PATCH 5/5] Clang-tidy fixes --- src/dredd/src/main.cc | 2 +- src/libdredd/include/libdredd/mutation.h | 2 ++ src/libdredd/src/mutate_ast_consumer.cc | 16 +++++++--------- src/libdredd/src/mutation_remove_stmt.cc | 4 +++- .../src/mutation_replace_binary_operator.cc | 4 +++- src/libdredd/src/mutation_replace_expr.cc | 4 +++- .../src/mutation_replace_unary_operator.cc | 4 +++- 7 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/dredd/src/main.cc b/src/dredd/src/main.cc index 3951bd81..64959a27 100644 --- a/src/dredd/src/main.cc +++ b/src/dredd/src/main.cc @@ -127,7 +127,7 @@ int main(int argc, const char** argv) { std::stringstream enabled_mutations_json; enabled_mutations_json_file.open(enabled_mutations_file); enabled_mutations_json << enabled_mutations_json_file.rdbuf(); - std::string enabled_mutations_string = enabled_mutations_json.str(); + const std::string enabled_mutations_string = enabled_mutations_json.str(); auto json_read_status = google::protobuf::util::JsonStringToMessage( enabled_mutations_string, &*enabled_mutation_info); diff --git a/src/libdredd/include/libdredd/mutation.h b/src/libdredd/include/libdredd/mutation.h index 14a03744..7b4c8aaf 100644 --- a/src/libdredd/include/libdredd/mutation.h +++ b/src/libdredd/include/libdredd/mutation.h @@ -48,6 +48,8 @@ class Mutation { // The |dredd_declarations| argument provides a set of declarations that will // be added to the start of the source file being mutated. This allows // avoiding redundant repeat declarations. + // TODO(James Lee-Jones): Change 'mutation_pass' to something like + // 'apply_mutations'. virtual protobufs::MutationGroup Apply( clang::ASTContext& ast_context, const clang::Preprocessor& preprocessor, bool optimise_mutations, bool only_track_mutant_coverage, diff --git a/src/libdredd/src/mutate_ast_consumer.cc b/src/libdredd/src/mutate_ast_consumer.cc index 12a7e823..86c112b8 100644 --- a/src/libdredd/src/mutate_ast_consumer.cc +++ b/src/libdredd/src/mutate_ast_consumer.cc @@ -115,7 +115,9 @@ void MutateAstConsumer::HandleTranslationUnit(clang::ASTContext& ast_context) { *mutation_info_->add_info_for_files() = mutation_info_for_file; - if (mutation_pass_) return; + if (mutation_pass_) { + return; + } auto& source_manager = ast_context.getSourceManager(); const clang::SourceLocation start_of_source_file = @@ -395,22 +397,22 @@ protobufs::MutationTreeNode MutateAstConsumer::ApplyMutations( std::vector mutation_tree_node_children = mutation_tree_node.GetChildren(); // TODO(James Lee-Jones): Check list size matches or throw an error. - if (enabled_mutation_tree_node.has_value()) + if (enabled_mutation_tree_node.has_value()) { assert(mutation_tree_node_children.size() == static_cast( enabled_mutation_tree_node->children_size())); + } for (int i = 0; static_cast(i) < mutation_tree_node_children.size(); i++) { - auto child = mutation_tree_node_children.at(static_cast(i)); + const auto* child = + mutation_tree_node_children.at(static_cast(i)); assert(!child->IsEmpty() && "The mutation tree should not have empty subtrees."); std::optional enabled_child; if (enabled_mutation_tree_node == std::nullopt) { enabled_child = std::nullopt; } else { - // TODO(James Lee-Jones): Save the call to children to avoid repeat - // processing. enabled_child = enabled_mutation_tree_node.value().children(i); // TODO(James Lee-Jones): Check that this is equal to child. } @@ -424,12 +426,8 @@ protobufs::MutationTreeNode MutateAstConsumer::ApplyMutations( mutation_tree_node.GetMutations(); for (int i = 0; static_cast(i) < mutations.size(); i++) { const int mutation_id_old = *mutation_id_; - // TODO(James Lee-Jones): Check if the current mutation is enabled and or - // with mutation_pass_. bool enabled = true; if (enabled_mutation_tree_node.has_value()) { - // TODO(James Lee-Jones): Save the call to children to avoid repeat - // processing. const protobufs::MutationGroup& kMutationGroup = enabled_mutation_tree_node.value().mutation_groups(i); if (kMutationGroup.has_remove_stmt()) { diff --git a/src/libdredd/src/mutation_remove_stmt.cc b/src/libdredd/src/mutation_remove_stmt.cc index beba1012..e6a2c20e 100644 --- a/src/libdredd/src/mutation_remove_stmt.cc +++ b/src/libdredd/src/mutation_remove_stmt.cc @@ -68,7 +68,9 @@ protobufs::MutationGroup MutationRemoveStmt::Apply( protobufs::MutationGroup result; *result.mutable_remove_stmt() = inner_result; - if (mutation_pass) return result; + if (mutation_pass) { + return result; + } clang::CharSourceRange source_range = clang::CharSourceRange::getTokenRange( GetSourceRangeInMainFile(preprocessor, *stmt_)); diff --git a/src/libdredd/src/mutation_replace_binary_operator.cc b/src/libdredd/src/mutation_replace_binary_operator.cc index 0ceeac81..9763cac5 100644 --- a/src/libdredd/src/mutation_replace_binary_operator.cc +++ b/src/libdredd/src/mutation_replace_binary_operator.cc @@ -621,7 +621,9 @@ protobufs::MutationGroup MutationReplaceBinaryOperator::Apply( // Add the mutation function to the set of Dredd declarations - there may // already be a matching function, in which case duplication will be avoided. - if (!mutation_pass) dredd_declarations.insert(new_function); + if (!mutation_pass) { + dredd_declarations.insert(new_function); + } protobufs::MutationGroup result; *result.mutable_replace_binary_operator() = inner_result; diff --git a/src/libdredd/src/mutation_replace_expr.cc b/src/libdredd/src/mutation_replace_expr.cc index dc22c675..d0937d15 100644 --- a/src/libdredd/src/mutation_replace_expr.cc +++ b/src/libdredd/src/mutation_replace_expr.cc @@ -643,7 +643,9 @@ protobufs::MutationGroup MutationReplaceExpr::Apply( inner_result); assert(!new_function.empty() && "Unsupported expression."); - if (!mutation_pass) dredd_declarations.insert(new_function); + if (!mutation_pass) { + dredd_declarations.insert(new_function); + } protobufs::MutationGroup result; *result.mutable_replace_expr() = inner_result; diff --git a/src/libdredd/src/mutation_replace_unary_operator.cc b/src/libdredd/src/mutation_replace_unary_operator.cc index bf0b41f8..2cb24f14 100644 --- a/src/libdredd/src/mutation_replace_unary_operator.cc +++ b/src/libdredd/src/mutation_replace_unary_operator.cc @@ -451,7 +451,9 @@ protobufs::MutationGroup MutationReplaceUnaryOperator::Apply( protobufs::MutationGroup result; *result.mutable_replace_unary_operator() = inner_result; - if (mutation_pass) return result; + if (mutation_pass) { + return result; + } // The prefix and suffix are ready, so make the relevant insertions. bool rewriter_result = rewriter.InsertTextBefore(