diff options
author | user1 <user1@ubuntu> | 2017-06-09 23:48:03 +0000 |
---|---|---|
committer | user1 <user1@ubuntu> | 2017-06-09 23:48:03 +0000 |
commit | f226eacb392047c7f8336b879e2e73dff7c64211 (patch) | |
tree | 7724245e98395ff09fdcbb162a0587ce63466eca /safercpp | |
parent | fixed a (just introduced) bug in MCSSSParameterPassing in which only the (diff) | |
download | mutator-f226eacb392047c7f8336b879e2e73dff7c64211.tar.gz mutator-f226eacb392047c7f8336b879e2e73dff7c64211.zip |
added insertion of "#include" directives
Diffstat (limited to '')
-rw-r--r-- | safercpp/safercpp-arr.cpp | 465 |
1 files changed, 281 insertions, 184 deletions
diff --git a/safercpp/safercpp-arr.cpp b/safercpp/safercpp-arr.cpp index 6b2c4ff..f7644a1 100644 --- a/safercpp/safercpp-arr.cpp +++ b/safercpp/safercpp-arr.cpp @@ -44,6 +44,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.* #include "clang/Tooling/CommonOptionsParser.h" #include "clang/Tooling/Tooling.h" #include "clang/Rewrite/Core/Rewriter.h" +#include "clang/Lex/Preprocessor.h" /*LLVM Headers*/ #include "llvm/Support/raw_ostream.h" #include "llvm/IR/Function.h" @@ -80,16 +81,16 @@ SourceRange nice_source_range(const SourceRange& sr, Rewriter &Rewrite) { } } -bool filtered_out_by_location(const ast_matchers::MatchFinder::MatchResult &MR, SourceLocation SL) { +bool filtered_out_by_location(const SourceManager &SM, SourceLocation SL) { bool retval = false; - if (Devi::IsTheMatchInSysHeader(CheckSystemHeader, MR, SL)) { + if (Devi::IsTheMatchInSysHeader(CheckSystemHeader, SM, SL)) { retval = true; - } else if (!Devi::IsTheMatchInMainFile(MainFileOnly, MR, SL)) { + } else if (!Devi::IsTheMatchInMainFile(MainFileOnly, SM, SL)) { retval = true; } else { bool filename_is_invalid = false; - std::string full_path_name = MR.SourceManager->getBufferName(SL, &filename_is_invalid); + std::string full_path_name = SM.getBufferName(SL, &filename_is_invalid); std::string filename = full_path_name; auto last_slash_pos = full_path_name.find_last_of('/'); if (std::string::npos != last_slash_pos) { @@ -102,11 +103,19 @@ bool filtered_out_by_location(const ast_matchers::MatchFinder::MatchResult &MR, static const std::string mse_str = "mse"; if (0 == filename.compare(0, mse_str.size(), mse_str)) { retval = true; + } else if ("<built-in>" == filename) { + retval = true; } } return retval; } +bool filtered_out_by_location(const ast_matchers::MatchFinder::MatchResult &MR, SourceLocation SL) { + ASTContext *const ASTC = MR.Context; + const SourceManager &SM = ASTC->getSourceManager(); + return filtered_out_by_location(SM, SL); +} + static std::string with_whitespace_removed(const std::string& str) { std::string retval = str; retval.erase(std::remove_if(retval.begin(), retval.end(), isspace), retval.end()); @@ -1791,6 +1800,14 @@ static void update_declaration(const DeclaratorDecl& ddecl, Rewriter &Rewrite, C } auto res = generate_declaration_replacement_code(&ddecl, Rewrite, state1.m_ddecl_conversion_state_map, options_str); + static const std::string const_space_str = "const "; + if (string_begins_with(res.m_replacement_code, const_space_str)) { + /* FunctionDecl::getReturnTypeSourceRange() seems to not include prefix qualifiers, like + * "const". Since the source range to be replaced doesn't include the "const " qualifier, + * if present, here we make sure it's not included in the replacement code either. */ + res.m_replacement_code = res.m_replacement_code.substr(const_space_str.length()); + } + if (ConvertToSCPP && return_type_source_range.isValid() && (1 <= res.m_replacement_code.size())) { auto res2 = Rewrite.ReplaceText(return_type_source_range, res.m_replacement_code); } else { @@ -3104,6 +3121,7 @@ private: struct CAllocFunctionInfo { bool m_seems_to_be_some_kind_of_malloc_or_realloc = false; + bool m_seems_to_be_some_kind_of_realloc = false; clang::CallExpr::const_arg_iterator m_num_bytes_arg_iter; std::string m_num_bytes_arg_source_text; }; @@ -3186,6 +3204,9 @@ CAllocFunctionInfo analyze_malloc_resemblance(const clang::CallExpr& call_expr, retval.m_num_bytes_arg_iter = arg_iter; retval.m_seems_to_be_some_kind_of_malloc_or_realloc = true; retval.m_num_bytes_arg_source_text = arg_source_text; + if (ends_with_realloc) { + retval.m_seems_to_be_some_kind_of_realloc = true; + } } } } @@ -3318,18 +3339,30 @@ public: } } if ("" != lhs_element_type_str) { - num_elements_text = "("; - num_elements_text += alloc_function_info1.m_num_bytes_arg_source_text; - num_elements_text += ") / sizeof("; - num_elements_text += lhs_element_type_str; - num_elements_text += ")"; - auto lhs_source_range = nice_source_range(LHS->getSourceRange(), Rewrite); auto lhs_source_text = Rewrite.getRewrittenText(lhs_source_range); - bo_replacement_code += "(" + lhs_source_text + ")"; - bo_replacement_code += ".resize("; - bo_replacement_code += num_elements_text; - bo_replacement_code += ")"; + + if (false) { + num_elements_text = "("; + num_elements_text += alloc_function_info1.m_num_bytes_arg_source_text; + num_elements_text += ") / sizeof("; + num_elements_text += lhs_element_type_str; + num_elements_text += ")"; + + bo_replacement_code += "(" + lhs_source_text + ")"; + bo_replacement_code += ".resize("; + bo_replacement_code += num_elements_text; + bo_replacement_code += ")"; + } else { + if (alloc_function_info1.m_seems_to_be_some_kind_of_realloc) { + bo_replacement_code = "MSE_LH_REALLOC("; + } else { + bo_replacement_code = "MSE_LH_ALLOC("; + } + bo_replacement_code += lhs_element_type_str + ", "; + bo_replacement_code += lhs_source_text + ", "; + bo_replacement_code += alloc_function_info1.m_num_bytes_arg_source_text + ")"; + } auto decl_source_location_str = decl_source_range.getBegin().printToString(*MR.SourceManager); std::string decl_source_text; @@ -3403,189 +3436,115 @@ public: int q = 5; } - auto function_decl = CE->getDirectCallee(); - auto num_args = CE->getNumArgs(); - if (function_decl && ((1 == num_args) || (2 == num_args))) { - std::string function_name = function_decl->getNameAsString(); - static const std::string alloc_str = "alloc"; - static const std::string realloc_str = "realloc"; - auto lc_function_name = tolowerstr(function_name); - bool ends_with_alloc = ((lc_function_name.size() >= alloc_str.size()) - && (0 == lc_function_name.compare(lc_function_name.size() - alloc_str.size(), alloc_str.size(), alloc_str))); - bool ends_with_realloc = (ends_with_alloc && (lc_function_name.size() >= realloc_str.size()) - && (0 == lc_function_name.compare(lc_function_name.size() - realloc_str.size(), realloc_str.size(), realloc_str))); - bool still_potentially_valid1 = (ends_with_alloc && (1 == num_args)) || (ends_with_realloc && (2 == num_args)); - if (still_potentially_valid1) { - auto iter = CE->arg_begin(); - if (ends_with_realloc) { - iter++; - } - { - auto arg_source_range = nice_source_range((*iter)->getSourceRange(), Rewrite); - std::string arg_source_text; - if (arg_source_range.isValid()) { - arg_source_text = Rewrite.getRewrittenText(arg_source_range); - //auto arg_source_text_sans_ws = with_whitespace_removed(arg_source_text); - - bool asterisk_found = false; - auto sizeof_start_index = arg_source_text.find("sizeof("); - if (std::string::npos != sizeof_start_index) { - auto sizeof_end_index = arg_source_text.find(")", sizeof_start_index); - if (std::string::npos != sizeof_end_index) { - assert(sizeof_end_index > sizeof_start_index); - std::string before_str = arg_source_text.substr(0, sizeof_start_index); - std::string after_str; - if (sizeof_end_index + 1 < arg_source_text.size()) { - after_str = arg_source_text.substr(sizeof_end_index + 1); - } - - auto index = before_str.size() - 1; - while (0 <= index) { - if ('*' == before_str[index]) { - asterisk_found = true; - } - if (!std::isspace(before_str[index])) { - break; - } - - index -= 1; - } - if (asterisk_found) { - before_str = before_str.substr(0, index); - } else { - size_t index2 = 0; - while (after_str.size() > index2) { - if ('*' == after_str[index2]) { - asterisk_found = true; - } - if (!std::isspace(after_str[index2])) { - break; - } - - index2 += 1; - } - if (asterisk_found) { - after_str = after_str.substr(index2 + 1); - } - } - } - } - if (true || asterisk_found) { - /* The argument is in the form "something * sizeof(something_else)" or - * "sizeof(something) * something_else". So we're just going to assume that - * this is an instance of an array being allocated. */ - std::string num_elements_text/* = before_str + after_str*/; - - if (nullptr != DD) { - auto decl_source_range = nice_source_range(DD->getSourceRange(), Rewrite); - auto decl_source_location_str = decl_source_range.getBegin().printToString(*MR.SourceManager); - std::string decl_source_text; - if (decl_source_range.isValid()) { - decl_source_text = Rewrite.getRewrittenText(decl_source_range); - } else { - return; - } - QualType QT = DD->getType(); - auto variable_name = DD->getNameAsString(); + auto alloc_function_info1 = analyze_malloc_resemblance(*CE, Rewrite); + if (alloc_function_info1.m_seems_to_be_some_kind_of_malloc_or_realloc) { + /* The argument is in the form "something * sizeof(something_else)" or + * "sizeof(something) * something_else". So we're just going to assume that + * this is an instance of an array being allocated. */ + std::string num_elements_text/* = before_str + after_str*/; - auto qualified_name = DD->getQualifiedNameAsString(); - static const std::string mse_namespace_str1 = "mse::"; - static const std::string mse_namespace_str2 = "::mse::"; - if ((0 == qualified_name.compare(0, mse_namespace_str1.size(), mse_namespace_str1)) - || (0 == qualified_name.compare(0, mse_namespace_str2.size(), mse_namespace_str2))) { - return; - } + if (nullptr != DD) { + auto decl_source_range = nice_source_range(DD->getSourceRange(), Rewrite); + auto decl_source_location_str = decl_source_range.getBegin().printToString(*MR.SourceManager); + std::string decl_source_text; + if (decl_source_range.isValid()) { + decl_source_text = Rewrite.getRewrittenText(decl_source_range); + } else { + return; + } + QualType QT = DD->getType(); + auto variable_name = DD->getNameAsString(); - if (!is_an_indirect_type(DD->getType())) { - return; - } + auto qualified_name = DD->getQualifiedNameAsString(); + static const std::string mse_namespace_str1 = "mse::"; + static const std::string mse_namespace_str2 = "::mse::"; + if ((0 == qualified_name.compare(0, mse_namespace_str1.size(), mse_namespace_str1)) + || (0 == qualified_name.compare(0, mse_namespace_str2.size(), mse_namespace_str2))) { + return; + } - auto res1 = (*this).m_state1.m_ddecl_conversion_state_map.insert(*DD); - auto ddcs_map_iter = res1.first; - auto& ddcs_ref = (*ddcs_map_iter).second; - bool update_declaration_flag = res1.second; + if (!is_an_indirect_type(DD->getType())) { + return; + } - bool lhs_has_been_determined_to_be_an_array = false; - if ("native pointer" == ddcs_ref.m_indirection_state_stack.at(0).current()) { - ddcs_ref.set_indirection_current(0, "malloc target"); - } else if ("inferred array" == ddcs_ref.m_indirection_state_stack.at(0).current()) { - ddcs_ref.set_indirection_current(0, "dynamic array"); - lhs_has_been_determined_to_be_an_array = true; - //update_declaration_flag = true; - m_state1.m_dynamic_array2_contingent_replacement_map.do_and_dispose_matching_replacements(m_state1, CDDeclIndirection(*DD, 0)); - } else if ("dynamic array" == ddcs_ref.m_indirection_state_stack.at(0).current()) { - lhs_has_been_determined_to_be_an_array = true; - } else { - assert("native array" != ddcs_ref.m_indirection_state_stack.at(0).current()); - } + auto res1 = (*this).m_state1.m_ddecl_conversion_state_map.insert(*DD); + auto ddcs_map_iter = res1.first; + auto& ddcs_ref = (*ddcs_map_iter).second; + bool update_declaration_flag = res1.second; - const clang::Type* TP = QT.getTypePtr(); - auto lhs_type_str = QT.getAsString(); + bool lhs_has_been_determined_to_be_an_array = false; + if ("native pointer" == ddcs_ref.m_indirection_state_stack.at(0).current()) { + ddcs_ref.set_indirection_current(0, "malloc target"); + } else if ("inferred array" == ddcs_ref.m_indirection_state_stack.at(0).current()) { + ddcs_ref.set_indirection_current(0, "dynamic array"); + lhs_has_been_determined_to_be_an_array = true; + //update_declaration_flag = true; + m_state1.m_dynamic_array2_contingent_replacement_map.do_and_dispose_matching_replacements(m_state1, CDDeclIndirection(*DD, 0)); + } else if ("dynamic array" == ddcs_ref.m_indirection_state_stack.at(0).current()) { + lhs_has_been_determined_to_be_an_array = true; + } else { + assert("native array" != ddcs_ref.m_indirection_state_stack.at(0).current()); + } - std::string element_type_str; - if (TP->isArrayType()) { - auto ATP = llvm::cast<const clang::ArrayType>(TP); - assert(nullptr != ATP); - auto element_type = ATP->getElementType(); - auto type_str = element_type.getAsString(); - if (("char" != type_str) && ("const char" != type_str)) { - element_type_str = type_str; - } - } else if (TP->isPointerType()) { - auto TPP = llvm::cast<const clang::PointerType>(TP); - assert(nullptr != TPP); - auto target_type = TPP->getPointeeType(); - auto type_str = target_type.getAsString(); - if (("char" != type_str) && ("const char" != type_str)) { - element_type_str = type_str; - } - } - if ("" != element_type_str) { - num_elements_text = "("; - num_elements_text += arg_source_text; - if (true || (("void" != element_type_str) && ("const void" != element_type_str))) { - num_elements_text += ") / sizeof("; - num_elements_text += element_type_str; - } else { - /* todo: something */ - } - num_elements_text += ")"; + const clang::Type* TP = QT.getTypePtr(); + auto lhs_type_str = QT.getAsString(); - std::string initializer_info_str = "(" + num_elements_text + ")"; + std::string element_type_str; + if (TP->isArrayType()) { + auto ATP = llvm::cast<const clang::ArrayType>(TP); + assert(nullptr != ATP); + auto element_type = ATP->getElementType(); + auto type_str = element_type.getAsString(); + if (("char" != type_str) && ("const char" != type_str)) { + element_type_str = type_str; + } + } else if (TP->isPointerType()) { + auto TPP = llvm::cast<const clang::PointerType>(TP); + assert(nullptr != TPP); + auto target_type = TPP->getPointeeType(); + auto type_str = target_type.getAsString(); + if (("char" != type_str) && ("const char" != type_str)) { + element_type_str = type_str; + } + } + if ("" != element_type_str) { + num_elements_text = "("; + num_elements_text += alloc_function_info1.m_num_bytes_arg_source_text; + if (true || (("void" != element_type_str) && ("const void" != element_type_str))) { + num_elements_text += ") / sizeof("; + num_elements_text += element_type_str; + } else { + /* todo: something */ + } + num_elements_text += ")"; - auto decl_source_location_str = decl_source_range.getBegin().printToString(*MR.SourceManager); - std::string decl_source_text; - if (decl_source_range.isValid()) { - decl_source_text = Rewrite.getRewrittenText(decl_source_range); - } else { - return; - } + std::string initializer_info_str = "(" + num_elements_text + ")"; - auto DSSR = clang::SourceRange(DSSL, DSSLE); - if (ConvertToSCPP && decl_source_range.isValid() && (DSSR.isValid())) { - auto cr_shptr = std::make_shared<CInitializerArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*DD, 0/*indirection_level*/), DS, initializer_info_str); + auto decl_source_location_str = decl_source_range.getBegin().printToString(*MR.SourceManager); + std::string decl_source_text; + if (decl_source_range.isValid()) { + decl_source_text = Rewrite.getRewrittenText(decl_source_range); + } else { + return; + } - if (lhs_has_been_determined_to_be_an_array) { - (*cr_shptr).do_replacement(m_state1); - } else { - m_state1.m_dynamic_array2_contingent_replacement_map.insert(cr_shptr); - } + auto DSSR = clang::SourceRange(DSSL, DSSLE); + if (ConvertToSCPP && decl_source_range.isValid() && (DSSR.isValid())) { + auto cr_shptr = std::make_shared<CInitializerArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*DD, 0/*indirection_level*/), DS, initializer_info_str); - int q = 3; - } else { - int q = 7; - } - } - } - int q = 5; + if (lhs_has_been_determined_to_be_an_array) { + (*cr_shptr).do_replacement(m_state1); + } else { + m_state1.m_dynamic_array2_contingent_replacement_map.insert(cr_shptr); } + + int q = 3; } else { - int q = 5; + int q = 7; } - int q = 5; } } - + int q = 5; } } } @@ -3635,7 +3594,7 @@ public: } Expr::NullPointerConstantKind kind = RHS->IgnoreParenCasts()->isNullPointerConstant(*ASTC, Expr::NullPointerConstantValueDependence()); - if (clang::Expr::NPCK_NotNull != kind) { + if (false && clang::Expr::NPCK_NotNull != kind) { if (true) { { if (true) { @@ -3825,8 +3784,8 @@ public: if ("" != arg_element_type_str) { if (ConvertToSCPP && (arg_res2.ddecl_conversion_state_ptr) && arg_is_an_indirect_type) { auto arg_source_text = Rewrite.getRewrittenText(arg_source_range); - std::string ce_replacement_code = "(" + arg_source_text + ")"; - ce_replacement_code += ".resize(0)"; + //std::string ce_replacement_code = "(" + arg_source_text + ").resize(0)"; + std::string ce_replacement_code = "MSE_LH_FREE(" + arg_source_text + ")"; auto cr_shptr = std::make_shared<CFreeDynamicArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*(arg_res2.ddecl_cptr), arg_res2.indirection_level), CE, ce_replacement_code); @@ -6114,6 +6073,100 @@ private: }; /**********************************************************************************************************************/ + +struct CFirstIncludeInfo { + CFirstIncludeInfo(const SourceLocation &beginning_of_file_loc) : m_beginning_of_file_loc(beginning_of_file_loc), + m_beginning_of_file_loc_is_valid(true) {} + + bool m_legacyhelpers_include_directive_found = false; + + bool m_first_include_directive_loc_is_valid = false; + SourceLocation m_first_include_directive_loc; + + bool m_first_macro_directive_ptr_is_valid = false; + const MacroDirective* m_first_macro_directive_ptr = nullptr; + + SourceLocation m_beginning_of_file_loc; + bool m_beginning_of_file_loc_is_valid = false; +}; + +class MyPPCallbacks : public PPCallbacks +{ +public: + MyPPCallbacks(Rewriter& Rewriter_ref) : m_Rewriter_ref(Rewriter_ref) {} + + void InclusionDirective( + SourceLocation hash_loc, + const Token &include_token, + StringRef file_name, + bool is_angled, + CharSourceRange filename_range, + const FileEntry *file, + StringRef search_path, + StringRef relative_path, + const clang::Module *imported) override { + + if (current_fii_shptr()) { + if (!(current_fii_shptr()->m_first_include_directive_loc_is_valid)) { + current_fii_shptr()->m_first_include_directive_loc = hash_loc; + current_fii_shptr()->m_first_include_directive_loc_is_valid = true; + } + + std::string file_name_str = file_name; + if ("mselegacyhelpers.h" == file_name_str) { + current_fii_shptr()->m_legacyhelpers_include_directive_found = true; + } + int q = 5; + } + } + + void MacroDefined(const Token &MacroNameTok, const MacroDirective *MD) override { + if (current_fii_shptr()) { + if (!(current_fii_shptr()->m_first_macro_directive_ptr_is_valid)) { + if (MD) { + current_fii_shptr()->m_first_macro_directive_ptr = MD; + current_fii_shptr()->m_first_macro_directive_ptr_is_valid = true; + } else { assert(false); } + } + } + } + + void FileChanged(SourceLocation Loc, FileChangeReason Reason, + SrcMgr::CharacteristicKind FileType, + FileID PrevFID = FileID()) override { + + bool filename_is_invalid = false; + std::string full_path_name = m_Rewriter_ref.getSourceMgr().getBufferName(Loc, &filename_is_invalid); + + if (PPCallbacks::FileChangeReason::EnterFile == Reason) { + auto fii_iter = m_first_include_info_map.find(Loc); + if (m_first_include_info_map.end() == fii_iter) { + std::map<SourceLocation, std::shared_ptr<CFirstIncludeInfo>>::value_type item(Loc, std::make_shared<CFirstIncludeInfo>(Loc)); + fii_iter = (m_first_include_info_map.insert(item)).first; + } + m_current_fii_shptr_stack.push_back((*fii_iter).second); + } else if (PPCallbacks::FileChangeReason::ExitFile == Reason) { + if (1 <= m_current_fii_shptr_stack.size()) { + m_current_fii_shptr_stack.pop_back(); + } else { + assert(false); + } + } + } + + std::shared_ptr<CFirstIncludeInfo> current_fii_shptr() { + std::shared_ptr<CFirstIncludeInfo> retval = nullptr; + if (1 <= m_current_fii_shptr_stack.size()) { + retval = m_current_fii_shptr_stack.back(); + } + return retval; + } + + std::map<SourceLocation, std::shared_ptr<CFirstIncludeInfo>> m_first_include_info_map; + std::vector<std::shared_ptr<CFirstIncludeInfo>> m_current_fii_shptr_stack; + Rewriter& m_Rewriter_ref; +}; + class MyFrontendAction : public ASTFrontendAction { public: @@ -6125,8 +6178,52 @@ public: } } + bool BeginSourceFileAction(CompilerInstance &ci, StringRef) override { + std::unique_ptr<MyPPCallbacks> my_pp_callbacks_ptr(new MyPPCallbacks(TheRewriter)); + + clang::Preprocessor &pp = ci.getPreprocessor(); + pp.addPPCallbacks(std::move(my_pp_callbacks_ptr)); + + return true; + } + void EndSourceFileAction() override { TheRewriter.getEditBuffer(TheRewriter.getSourceMgr().getMainFileID()).write(llvm::outs()); + + { + clang::CompilerInstance &ci = getCompilerInstance(); + clang::Preprocessor &pp = ci.getPreprocessor(); + MyPPCallbacks *my_pp_callbacks_ptr = static_cast<MyPPCallbacks *>(pp.getPPCallbacks()); + + assert(my_pp_callbacks_ptr); + if (my_pp_callbacks_ptr) { + // do whatever you want with the callback now + + for (auto& item_ref : my_pp_callbacks_ptr->m_first_include_info_map) { + auto& fii_ref = *(item_ref.second); + assert(fii_ref.m_beginning_of_file_loc_is_valid); + + bool filename_is_invalid = false; + std::string full_path_name = TheRewriter.getSourceMgr().getBufferName(fii_ref.m_beginning_of_file_loc, &filename_is_invalid); + + if (filtered_out_by_location(TheRewriter.getSourceMgr(), fii_ref.m_beginning_of_file_loc)) { + continue; + } + + if (!(fii_ref.m_legacyhelpers_include_directive_found)) { + assert(fii_ref.m_first_include_directive_loc_is_valid); + TheRewriter.InsertTextBefore(fii_ref.m_first_include_directive_loc, + "#include \"mselegacyhelpers.h\"\n"); + } else if (fii_ref.m_first_macro_directive_ptr_is_valid) { + TheRewriter.InsertTextAfterToken(fii_ref.m_first_macro_directive_ptr->getLocation(), + "#include \"mselegacyhelpers.h\"\n"); + } else if (fii_ref.m_beginning_of_file_loc_is_valid) { + TheRewriter.InsertTextBefore(fii_ref.m_beginning_of_file_loc, + "#include \"mselegacyhelpers.h\"\n"); + } + } + } else { assert(false); } + } } std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef file) override { |