static void dorewrite(terra_State * T, const char * code, const char ** argbegin, const char ** argend, std::string * output, Obj * result) { llvm::MemoryBuffer * membuffer = llvm::MemoryBuffer::getMemBufferCopy(code, "<buffer>"); CompilerInstance TheCompInst; initializeclang(T, membuffer, argbegin, argend, &TheCompInst); // Create an AST consumer instance which is going to get called by // ParseAST. // A Rewriter helps us manage the code rewriting task. SourceManager & SourceMgr = TheCompInst.getSourceManager(); Rewriter TheRewriter; TheRewriter.setSourceMgr(SourceMgr, TheCompInst.getLangOpts()); std::stringstream dummy; IncludeCConsumer TheConsumer(TheRewriter,dummy,result); // Parse the file to AST, registering our consumer as the AST consumer. ParseAST(TheCompInst.getPreprocessor(), &TheConsumer, TheCompInst.getASTContext()); // At this point the rewriter's buffer should be full with the rewritten // file contents. const RewriteBuffer *RewriteBuf = TheRewriter.getRewriteBufferFor(SourceMgr.getMainFileID()); std::ostringstream out; out << std::string(membuffer->getBufferStart(),membuffer->getBufferEnd()) << "\n" << "void __makeeverythinginclanglive_" << T->C->next_unused_id++ << "() {\n" << dummy.str() << "\n}\n"; *output = out.str(); //printf("output is %s\n",(*output).c_str()); }
int main(int argc, char *argv[]) { if (argc != 2) { llvm::errs() << "Usage: rewritersample <filename>\n"; return 1; } // CompilerInstance will hold the instance of the Clang compiler for us, // managing the various objects needed to run the compiler. CompilerInstance TheCompInst; TheCompInst.createDiagnostics(); LangOptions &lo = TheCompInst.getLangOpts(); lo.CPlusPlus = 1; // Initialize target info with the default triple for our platform. auto TO = std::make_shared<TargetOptions>(); TO->Triple = llvm::sys::getDefaultTargetTriple(); TargetInfo *TI = TargetInfo::CreateTargetInfo(TheCompInst.getDiagnostics(), TO); TheCompInst.setTarget(TI); TheCompInst.createFileManager(); FileManager &FileMgr = TheCompInst.getFileManager(); TheCompInst.createSourceManager(FileMgr); SourceManager &SourceMgr = TheCompInst.getSourceManager(); TheCompInst.createPreprocessor(TU_Module); TheCompInst.createASTContext(); // A Rewriter helps us manage the code rewriting task. Rewriter TheRewriter; TheRewriter.setSourceMgr(SourceMgr, TheCompInst.getLangOpts()); // Set the main file handled by the source manager to the input file. const FileEntry *FileIn = FileMgr.getFile(argv[1]); SourceMgr.setMainFileID( SourceMgr.createFileID(FileIn, SourceLocation(), SrcMgr::C_User)); TheCompInst.getDiagnosticClient().BeginSourceFile( TheCompInst.getLangOpts(), &TheCompInst.getPreprocessor()); // Create an AST consumer instance which is going to get called by // ParseAST. MyASTConsumer TheConsumer(TheRewriter); // Parse the file to AST, registering our consumer as the AST consumer. ParseAST(TheCompInst.getPreprocessor(), &TheConsumer, TheCompInst.getASTContext()); // At this point the rewriter's buffer should be full with the rewritten // file contents. const RewriteBuffer *RewriteBuf = TheRewriter.getRewriteBufferFor(SourceMgr.getMainFileID()); llvm::outs() << std::string(RewriteBuf->begin(), RewriteBuf->end()); return 0; }
int main(int argc, char *argv[]) { if (argc != 2) { llvm::errs() << "Usage: rewritersample <filename>\n"; return 1; } // CompilerInstance will hold the instance of the Clang compiler for us, // managing the various objects needed to run the compiler. CompilerInstance ci; ci.createDiagnostics(0, 0); // Initialize target info with the default triple for our platform. TargetOptions TO; TO.Triple = llvm::sys::getDefaultTargetTriple(); TargetInfo *TI = TargetInfo::CreateTargetInfo( ci.getDiagnostics(), TO); ci.setTarget(TI); ci.createFileManager(); FileManager &fm = ci.getFileManager(); ci.createSourceManager(fm); SourceManager &SourceMgr = ci.getSourceManager(); ci.createPreprocessor(); ci.createASTContext(); // A Rewriter helps us manage the code rewriting task. Rewriter rw; rw.setSourceMgr(SourceMgr, ci.getLangOpts()); // Set the main file handled by the source manager to the input file. const FileEntry *fi = fm.getFile(argv[1]); SourceMgr.createMainFileID(fi); ci.getDiagnosticClient().BeginSourceFile( ci.getLangOpts(), &ci.getPreprocessor()); // Create an AST consumer instance which is going to get called by // ParseAST. MyASTConsumer astc(rw); // Parse the file to AST, registering our consumer as the AST consumer. ParseAST(ci.getPreprocessor(), &astc, ci.getASTContext()); // At this point the rewriter's buffer should be full with the rewritten // file contents. const RewriteBuffer *rwb = rw.getRewriteBufferFor(SourceMgr.getMainFileID()); llvm::outs() << string(rwb->begin(), rwb->end()); return 0; }
void SynthesizeRemovalConsumer::HandleTranslationUnit(ASTContext &C) { if (compilerInstance->getDiagnostics().hasErrorOccurred()) { return; } astContext = &C; auto TUD = C.getTranslationUnitDecl(); removeSynthesizeDirectives(TUD); processDeclContext(TUD); if (removeSet.empty()) { // nothing is removed llvm::errs() << "nothing to remove.\n"; return; } SourceManager &SM = rewriter.getSourceMgr(); FileID FID = SM.getMainFileID(); const FileEntry* F = SM.getFileEntryForID(FID); // backup the source std::string backupFilename = std::string(F->getName()) + ".bak"; std::string errInfo; llvm::raw_fd_ostream backupStream(backupFilename.c_str(), errInfo, llvm::sys::fs::F_Binary); if (!errInfo.empty()) { llvm::errs() << "Cannot write backup file: " << backupFilename << ", error info: " << errInfo << "\n"; return; } backupStream << SM.getBufferData(FID); backupStream.flush(); // write the output llvm::raw_fd_ostream outStream(F->getName(), errInfo, llvm::sys::fs::F_Binary); if (!errInfo.empty()) { llvm::errs() << "Cannot write output file: " << F->getName() << ", error info: " << errInfo << "\n"; return; } const RewriteBuffer *RB = rewriter.getRewriteBufferFor(FID); RB->write(outStream); outStream.flush(); }
/// \brief Convenience function to get rewritten content for \c Filename from /// \c Rewrites. /// /// \pre Replacements[i].getFilePath() == Replacements[i+1].getFilePath(). /// \post Replacements.empty() -> Result.empty() /// /// \param[in] Replacements Replacements to apply /// \param[in] Rewrites Rewriter to use to apply replacements. /// \param[out] Result Contents of the file after applying replacements if /// replacements were provided. /// /// \returns \li true if all replacements were applied successfully. /// \li false if at least one replacement failed to apply. static bool getRewrittenData(const std::vector<tooling::Replacement> &Replacements, Rewriter &Rewrites, std::string &Result) { if (Replacements.empty()) return true; if (!tooling::applyAllReplacements(Replacements, Rewrites)) return false; SourceManager &SM = Rewrites.getSourceMgr(); FileManager &Files = SM.getFileManager(); StringRef FileName = Replacements.begin()->getFilePath(); const clang::FileEntry *Entry = Files.getFile(FileName); assert(Entry && "Expected an existing file"); FileID ID = SM.translateFile(Entry); assert(!ID.isInvalid() && "Expected a valid FileID"); const RewriteBuffer *Buffer = Rewrites.getRewriteBufferFor(ID); Result = std::string(Buffer->begin(), Buffer->end()); return true; }
int main(int argc, char *argv[]) { if (argc != 2) { llvm::errs() << "Usage: kcov-branch-identify <filename>\n"; return 1; } // CompilerInstance will hold the instance of the Clang compiler for us, // managing the various objects needed to run the compiler. CompilerInstance TheCompInst; // Diagnostics manage problems and issues in compile TheCompInst.createDiagnostics(NULL, false); // Set target platform options // Initialize target info with the default triple for our platform. TargetOptions *TO = new TargetOptions(); TO->Triple = llvm::sys::getDefaultTargetTriple(); TargetInfo *TI = TargetInfo::CreateTargetInfo(TheCompInst.getDiagnostics(), TO); TheCompInst.setTarget(TI); // FileManager supports for file system lookup, file system caching, and directory search management. TheCompInst.createFileManager(); FileManager &FileMgr = TheCompInst.getFileManager(); // SourceManager handles loading and caching of source files into memory. TheCompInst.createSourceManager(FileMgr); SourceManager &SourceMgr = TheCompInst.getSourceManager(); //global var m_srcmgr m_srcmgr = &SourceMgr; // Prreprocessor runs within a single source file TheCompInst.createPreprocessor(); // ASTContext holds long-lived AST nodes (such as types and decls) . TheCompInst.createASTContext(); // Enable HeaderSearch option llvm::IntrusiveRefCntPtr<clang::HeaderSearchOptions> hso( new HeaderSearchOptions()); HeaderSearch headerSearch(hso, TheCompInst.getFileManager(), TheCompInst.getDiagnostics(), TheCompInst.getLangOpts(), TI); // <Warning!!> -- Platform Specific Code lives here // This depends on A) that you're running linux and // B) that you have the same GCC LIBs installed that I do. /* $ gcc -xc -E -v - .. /usr/local/include /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include-fixed /usr/include End of search list. */ const char *include_paths[] = {"/usr/local/include", "/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include", "/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include-fixed", "/usr/include"}; for (int i=0; i<4; i++) hso->AddPath(include_paths[i], clang::frontend::Angled, false, false); // </Warning!!> -- End of Platform Specific Code InitializePreprocessor(TheCompInst.getPreprocessor(), TheCompInst.getPreprocessorOpts(), *hso, TheCompInst.getFrontendOpts()); //Preprocessor &preprocessor TheCompInst.getPreprocessor(); my edit // A Rewriter helps us manage the code rewriting task. Rewriter TheRewriter; TheRewriter.setSourceMgr(SourceMgr, TheCompInst.getLangOpts()); // Set the main file handled by the source manager to the input file. const FileEntry *FileIn = FileMgr.getFile(argv[1]); string filename(argv[1]); string outputName = filename.substr(0, filename.length()-2) + "-cov.c"; SourceMgr.createMainFileID(FileIn); // Inform Diagnostics that processing of a source file is beginning. TheCompInst.getDiagnosticClient().BeginSourceFile(TheCompInst.getLangOpts(),&TheCompInst.getPreprocessor()); // Create an AST consumer instance which is going to get called by ParseAST. MyASTConsumer TheConsumer; // Parse the file to AST, registering our consumer as the AST consumer. ParseAST(TheCompInst.getPreprocessor(), &TheConsumer, TheCompInst.getASTContext()); const RewriteBuffer *RewriteBuf = TheRewriter.getRewriteBufferFor(SourceMgr.getMainFileID()); ofstream output(outputName.c_str()); output << string(RewriteBuf->begin(), RewriteBuf->end()); output.close(); //cout<<"Total number of branches: "<<countBranch<<endl; //TheConsumer.printBranchNum(); return 0; }
int main(int argc, char *argv[]) { #if 0 vector<string> args; args.push_back("tool-executable"); for (int i = 1; i < argc; ++i) { args.push_back(argv[i]); } parse_with_tool(args); return 0; #endif string user_defines; for (int i = 1; i < argc; ++i) { if (argv[i][0] == '-' && argv[i][1] == 'D') { user_defines += "#define "; char *def = argv[i]+2; char* eq_pos = strchr(def, '='); if (eq_pos) { user_defines += string(def, eq_pos - def); user_defines += " "; user_defines += string(def+1); } else { user_defines += string(def); } user_defines += "\n"; } } if (argc < 2) { llvm::errs() << "Usage: mkapi filename [-Ddefine1 -Ddefine2...]\n"; return 1; } string file(argv[1]); // CompilerInstance will hold the instance of the Clang compiler for us, // managing the various objects needed to run the compiler. CompilerInstance TheCompInst; TheCompInst.createDiagnostics(0, true); //() for clang3.3, (0,0) for clang3.2 // Initialize target info with the default triple for our platform. TargetOptions *TO = new TargetOptions(); //TODO: why on stack crash when dtor called TO->Triple = llvm::sys::getDefaultTargetTriple(); TargetInfo *TI = TargetInfo::CreateTargetInfo( TheCompInst.getDiagnostics(), TO); TheCompInst.setTarget(TI); TheCompInst.createFileManager(); FileManager &FileMgr = TheCompInst.getFileManager(); TheCompInst.createSourceManager(FileMgr); SourceManager &SourceMgr = TheCompInst.getSourceManager(); TheCompInst.createPreprocessor(); TheCompInst.createASTContext(); if (!user_defines.empty()) { clang::Preprocessor &PP = TheCompInst.getPreprocessor(); PP.setPredefines(PP.getPredefines() + user_defines); } //cout << "predefines: " << TheCompInst.getPreprocessor().getPredefines() << endl; // A Rewriter helps us manage the code rewriting task. Rewriter TheRewriter; TheRewriter.setSourceMgr(SourceMgr, TheCompInst.getLangOpts()); // Set the main file handled by the source manager to the input file. const FileEntry *FileIn = FileMgr.getFile(file); SourceMgr.createMainFileID(FileIn); TheCompInst.getDiagnosticClient().BeginSourceFile( TheCompInst.getLangOpts(), &TheCompInst.getPreprocessor()); // Create an AST consumer instance which is going to get called by // ParseAST. MkApiASTConsumer TheConsumer(TheRewriter); // Parse the file to AST, registering our consumer as the AST consumer. ParseAST(TheCompInst.getPreprocessor(), &TheConsumer, TheCompInst.getASTContext() , clang::TU_Complete); // At this point the rewriter's buffer should be full with the rewritten // file contents. #if 0 const RewriteBuffer *RewriteBuf = TheRewriter.getRewriteBufferFor(SourceMgr.getMainFileID()); llvm::outs() << string(RewriteBuf->begin(), RewriteBuf->end()); #endif std::vector<func_info> fi = TheConsumer.GetFuncInfo(); stringstream stream; for (std::vector<func_info>::const_iterator it = fi.begin(); it != fi.end(); ++it) { std::vector<std::string> params = (*it).argv; stream << "DEFINE_DLLAPI_ARG(" << params.size() << ", " << (*it).return_type << ", " << (*it).name; for (int i = 0; i < params.size(); ++i) { stream << ", " << params[i]; } stream << ")" << endl; } cout << stream.str() << endl; return 0; }
//使用的格式: ./checkMemory 被测试文件名 -- int main(int argc,const char **argv) { //----此块基本一样 start---- struct stat sb; //set compilerinstance for rewriter std::string fileName(argv[1]); if (stat(fileName.c_str(), &sb) == -1){ perror(fileName.c_str()); exit(EXIT_FAILURE); } CompilerInstance compiler; DiagnosticOptions diagnosticOptions; compiler.createDiagnostics(); //invocation可以传递任何flag给preprocessor CompilerInvocation *Invocation = new CompilerInvocation; CompilerInvocation::CreateFromArgs(*Invocation, argv + 1, argv + argc-1,compiler.getDiagnostics()); compiler.setInvocation(Invocation); //建立TargetOptions和TargetInfo,并设置好Target // Set default target triple llvm::IntrusiveRefCntPtr<TargetOptions> pto( new TargetOptions()); pto->Triple = llvm::sys::getDefaultTargetTriple(); llvm::IntrusiveRefCntPtr<TargetInfo> pti(TargetInfo::CreateTargetInfo(compiler.getDiagnostics(), pto.getPtr())); compiler.setTarget(pti.getPtr()); //FileManager,SourceManager 以及heaDREearch的Options的设置 compiler.createFileManager(); compiler.createSourceManager(compiler.getFileManager()); HeaderSearchOptions &headerSearchOptions = compiler.getHeaderSearchOpts(); headerSearchOptions.AddPath("/usr/include/c++", clang::frontend::Angled, false, false); headerSearchOptions.AddPath("/usr/local/lib/clang/3.5.0/include", clang::frontend::Angled, false, false); headerSearchOptions.AddPath("/usr/include/i386-linux-gnu", clang::frontend::Angled, false, false); headerSearchOptions.AddPath("/usr/include", clang::frontend::Angled, false, false); /* headerSearchOptions.AddPath("/usr/include", clang::frontend::Angled, false, false); */ //langOptions设置,要传给rewriter LangOptions langOpts; langOpts.GNUMode = 1; langOpts.CXXExceptions = 1; langOpts.RTTI = 1; langOpts.Bool = 1; langOpts.CPlusPlus = 1; Invocation->setLangDefaults(langOpts, clang::IK_CXX,clang::LangStandard::lang_cxx0x); //create PP compiler.createPreprocessor();//(TU_Complete);// compiler.getPreprocessorOpts().UsePredefines = false; //createASTContext compiler.createASTContext(); //set the sourceManager for rewriter rewrite.setSourceMgr(compiler.getSourceManager(), compiler.getLangOpts()); //插装文件入口 const FileEntry *pFile = compiler.getFileManager().getFile(fileName); compiler.getSourceManager().createMainFileID(pFile); compiler.getDiagnosticClient().BeginSourceFile(compiler.getLangOpts(),&compiler.getPreprocessor()); MyASTConsumer astConsumer(rewrite); //将.c转成_out.c // Convert <file>.c to <file_out>.c std::string outName (fileName); /*size_t ext = outName.rfind("."); //根据有没有找到‘。’来决定在哪里加入_out if (ext == std::string::npos) ext = outName.length(); outName.insert(ext, "_out"); */ outName.insert(outName.length(),"_out"); llvm::errs() << "Output to: " << outName << "\n"; std::string OutErrorInfo; //新建输入到新文件的流 llvm::raw_fd_ostream outFile(outName.c_str(), OutErrorInfo);//,llvm::sys::fs::F_None);//版本问题////// //----此块基本一样 end---- if (OutErrorInfo.empty()){ // Parse the AST //用PP,astConsumer,ASTContext来解释AST ParseAST(compiler.getPreprocessor(), &astConsumer, compiler.getASTContext()); compiler.getDiagnosticClient().EndSourceFile(); //建立ClangTool CommonOptionsParser OptionsParser(argc, argv);//, MyToolCategory); ClangTool Tool(OptionsParser.getCompilations(), OptionsParser.getSourcePathList()); //开始匹配 MallocVarPrinter mallocVarPrinter; MatchFinder mallocVarFinder; mallocVarFinder.addMatcher(MallocVarMatcher, &mallocVarPrinter); Tool.run(newFrontendActionFactory(&mallocVarFinder)); MallocPrinter mallocPrinter; MatchFinder mallocFinder; mallocFinder.addMatcher(MallocMatcher, &mallocPrinter); Tool.run(newFrontendActionFactory(&mallocFinder)); FreeVarPrinter freeVarPrinter; MatchFinder freeVarFinder; freeVarFinder.addMatcher(FreeVarMatcher, &freeVarPrinter); Tool.run(newFrontendActionFactory(&freeVarFinder)); FreePrinter freePrinter; MatchFinder freeFinder; freeFinder.addMatcher(FreeMatcher, &freePrinter); Tool.run(newFrontendActionFactory(&freeFinder)); const RewriteBuffer *RewriteBuf =rewrite.getRewriteBufferFor(compiler.getSourceManager().getMainFileID()); if(RewriteBuf != NULL){ #ifdef DEBUG llvm::errs() << " RewriteBuf not NULL \n"; //在文件头加上改头文件,防止没有 stdlib,stdio 而不能使用printf和exit函数 #endif outFile << "#include\"plugHead.h\"\n"; outFile << std::string(RewriteBuf->begin(), RewriteBuf->end()); }else{ #ifdef DEBUG llvm::errs() << " RewriteBuf is NULL \n"; #endif outFile << "#include\"plugHead.h\"\n"; std::ifstream infile(fileName.c_str()); if(!infile){ llvm::errs() << " fail to open the input file!\n"; exit(-1); } std::string str_in; while(std::getline(infile,str_in)){ outFile << str_in <<"\n"; } } outFile.close(); #ifdef DEBUG std::string checkStructErrorInfo; std::string checkStructFileName = "checkStruct.txt"; //新建输入到新文件的流,将已经找到的malloc过的结构体信息写入文件,供另一个处理程序读取 llvm::raw_fd_ostream csFile(checkStructFileName.c_str(),checkStructErrorInfo);//,llvm::sys::fs::F_None); if (checkStructErrorInfo.empty()){ for(unsigned int i=0;i<cpVec.size();++i){ csFile << cpVec[i].name << " " << cpVec[i].row << " " << cpVec[i].col << " " << cpVec[i].declName << " " << cpVec[i].declRow << " " << cpVec[i].declCol << "\n" ; } } csFile.close(); for(unsigned int i=0;i<cpVec.size();++i){ llvm::errs()<<cpVec[i].name<<"|"<<cpVec[i].declName<<":"<<cpVec[i].declRow<<":"<<cpVec[i].declCol<<"\n"; } #endif } else{ llvm::errs() << "Cannot open " << outName << " for writing\n"; } return 0; }
/// RewriteMacrosInInput - Implement -rewrite-macros mode. void clang::RewriteMacrosInInput(Preprocessor &PP, raw_ostream *OS) { SourceManager &SM = PP.getSourceManager(); Rewriter Rewrite; Rewrite.setSourceMgr(SM, PP.getLangOpts()); RewriteBuffer &RB = Rewrite.getEditBuffer(SM.getMainFileID()); std::vector<Token> RawTokens; LexRawTokensFromMainFile(PP, RawTokens); unsigned CurRawTok = 0; Token RawTok = GetNextRawTok(RawTokens, CurRawTok, false); // Get the first preprocessing token. PP.EnterMainSourceFile(); Token PPTok; PP.Lex(PPTok); // Preprocess the input file in parallel with raw lexing the main file. Ignore // all tokens that are preprocessed from a file other than the main file (e.g. // a header). If we see tokens that are in the preprocessed file but not the // lexed file, we have a macro expansion. If we see tokens in the lexed file // that aren't in the preprocessed view, we have macros that expand to no // tokens, or macro arguments etc. while (RawTok.isNot(tok::eof) || PPTok.isNot(tok::eof)) { SourceLocation PPLoc = SM.getExpansionLoc(PPTok.getLocation()); // If PPTok is from a different source file, ignore it. if (!SM.isFromMainFile(PPLoc)) { PP.Lex(PPTok); continue; } // If the raw file hits a preprocessor directive, they will be extra tokens // in the raw file that don't exist in the preprocsesed file. However, we // choose to preserve them in the output file and otherwise handle them // specially. if (RawTok.is(tok::hash) && RawTok.isAtStartOfLine()) { // If this is a #warning directive or #pragma mark (GNU extensions), // comment the line out. if (RawTokens[CurRawTok].is(tok::identifier)) { const IdentifierInfo *II = RawTokens[CurRawTok].getIdentifierInfo(); if (II->getName() == "warning") { // Comment out #warning. RB.InsertTextAfter(SM.getFileOffset(RawTok.getLocation()), "//"); } else if (II->getName() == "pragma" && RawTokens[CurRawTok+1].is(tok::identifier) && (RawTokens[CurRawTok+1].getIdentifierInfo()->getName() == "mark")) { // Comment out #pragma mark. RB.InsertTextAfter(SM.getFileOffset(RawTok.getLocation()), "//"); } } // Otherwise, if this is a #include or some other directive, just leave it // in the file by skipping over the line. RawTok = GetNextRawTok(RawTokens, CurRawTok, false); while (!RawTok.isAtStartOfLine() && RawTok.isNot(tok::eof)) RawTok = GetNextRawTok(RawTokens, CurRawTok, false); continue; } // Okay, both tokens are from the same file. Get their offsets from the // start of the file. unsigned PPOffs = SM.getFileOffset(PPLoc); unsigned RawOffs = SM.getFileOffset(RawTok.getLocation()); // If the offsets are the same and the token kind is the same, ignore them. if (PPOffs == RawOffs && isSameToken(RawTok, PPTok)) { RawTok = GetNextRawTok(RawTokens, CurRawTok, false); PP.Lex(PPTok); continue; } // If the PP token is farther along than the raw token, something was // deleted. Comment out the raw token. if (RawOffs <= PPOffs) { // Comment out a whole run of tokens instead of bracketing each one with // comments. Add a leading space if RawTok didn't have one. bool HasSpace = RawTok.hasLeadingSpace(); RB.InsertTextAfter(RawOffs, &" /*"[HasSpace]); unsigned EndPos; do { EndPos = RawOffs+RawTok.getLength(); RawTok = GetNextRawTok(RawTokens, CurRawTok, true); RawOffs = SM.getFileOffset(RawTok.getLocation()); if (RawTok.is(tok::comment)) { // Skip past the comment. RawTok = GetNextRawTok(RawTokens, CurRawTok, false); break; } } while (RawOffs <= PPOffs && !RawTok.isAtStartOfLine() && (PPOffs != RawOffs || !isSameToken(RawTok, PPTok))); RB.InsertTextBefore(EndPos, "*/"); continue; } // Otherwise, there was a replacement an expansion. Insert the new token // in the output buffer. Insert the whole run of new tokens at once to get // them in the right order. unsigned InsertPos = PPOffs; std::string Expansion; while (PPOffs < RawOffs) { Expansion += ' ' + PP.getSpelling(PPTok); PP.Lex(PPTok); PPLoc = SM.getExpansionLoc(PPTok.getLocation()); PPOffs = SM.getFileOffset(PPLoc); } Expansion += ' '; RB.InsertTextBefore(InsertPos, Expansion); } // Get the buffer corresponding to MainFileID. If we haven't changed it, then // we are done. if (const RewriteBuffer *RewriteBuf = Rewrite.getRewriteBufferFor(SM.getMainFileID())) { //printf("Changed:\n"); *OS << std::string(RewriteBuf->begin(), RewriteBuf->end()); } else { fprintf(stderr, "No changes\n"); } OS->flush(); }
void C2Builder::rewriterTest(SourceManager& SM, LangOptions& LangOpts) { #if 0 // FOR TESTING rename global test.aa -> bb const std::string modName = "test"; const std::string oldName = "aa"; const std::string newName = "bb"; // Step 1a: find Module const Module* M = 0; const Module* mod = findModule(modName); assert(M && "unknown module"); assert(!M->isExternal() && "cannot replace symbol in external module"); // Step 1b: find Decl Decl* D = M->findSymbol(oldName); assert(D && "unknown decl"); // Step 2a: replace Decl itself Rewriter rewriter; rewriter.setSourceMgr(SM, LangOpts); rewriter.ReplaceText(D->getLocation(), oldName.size(), newName); // Step 2b: replace all references // TODO only in mainComponent const ModuleList& mods = mainComponent->getModules(); for (unsigned m=0; m<mods.size(); m++) { const AstList& files = mods[m]->getFiles(); for (unsigned a=0; a<files.size(); a++) { AST* ast = files[a]; RefFinder finder(*ast, D); unsigned count = finder.find(); if (count) printf("replaced %d references in %s\n", count, files[i]->getFileName().c_str()); for (unsigned i=0; i<count; i++) { std::string temp = finder.locs[i].printToString(SM); printf("loc %d -> %s\n", finder.locs[i].getRawEncoding(), temp.c_str()); PresumedLoc loc = SM.getPresumedLoc(finder.locs[i]); assert(!loc.isInvalid() && "Invalid location"); printf(" -> %s:%d:%d\n", loc.getFilename(), loc.getLine(), loc.getColumn()); std::pair<FileID, unsigned> Off = SM.getDecomposedExpansionLoc(finder.locs[i]); printf("-> offset %d\n", Off.second); rewriter.ReplaceText(finder.locs[i], oldName.size(), newName); } } } // Step 3: reparse and check // TODO // print output for (unsigned m=0; m<mods.size(); m++) { const AstList& files = mods[m]->getFiles(); for (unsigned a=0; a<files.size(); a++) { AST* ast = files[a]; const RewriteBuffer *RewriteBuf = rewriter.getRewriteBufferFor(ast->fileID); if (RewriteBuf) { printf("====== %s ======\n", ast->getFileName().c_str()); llvm::outs() << std::string(RewriteBuf->begin(), RewriteBuf->end()); } } } // also works! //bool err = rewriter.overwriteChangedFiles(); //printf("errors = %d\n", err); #endif }