clang API Documentation
00001 //===--- FrontendActions.cpp ----------------------------------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #include "clang/Rewrite/FrontendActions.h" 00011 #include "clang/AST/ASTConsumer.h" 00012 #include "clang/Lex/Preprocessor.h" 00013 #include "clang/Parse/Parser.h" 00014 #include "clang/Basic/FileManager.h" 00015 #include "clang/Frontend/FrontendActions.h" 00016 #include "clang/Frontend/CompilerInstance.h" 00017 #include "clang/Frontend/FrontendDiagnostic.h" 00018 #include "clang/Frontend/Utils.h" 00019 #include "clang/Rewrite/ASTConsumers.h" 00020 #include "clang/Rewrite/FixItRewriter.h" 00021 #include "clang/Rewrite/Rewriters.h" 00022 #include "llvm/ADT/OwningPtr.h" 00023 #include "llvm/Support/raw_ostream.h" 00024 #include "llvm/Support/Path.h" 00025 #include "llvm/Support/FileSystem.h" 00026 00027 using namespace clang; 00028 00029 //===----------------------------------------------------------------------===// 00030 // AST Consumer Actions 00031 //===----------------------------------------------------------------------===// 00032 00033 ASTConsumer *HTMLPrintAction::CreateASTConsumer(CompilerInstance &CI, 00034 StringRef InFile) { 00035 if (raw_ostream *OS = CI.createDefaultOutputFile(false, InFile)) 00036 return CreateHTMLPrinter(OS, CI.getPreprocessor()); 00037 return 0; 00038 } 00039 00040 FixItAction::FixItAction() {} 00041 FixItAction::~FixItAction() {} 00042 00043 ASTConsumer *FixItAction::CreateASTConsumer(CompilerInstance &CI, 00044 StringRef InFile) { 00045 return new ASTConsumer(); 00046 } 00047 00048 namespace { 00049 class FixItRewriteInPlace : public FixItOptions { 00050 public: 00051 std::string RewriteFilename(const std::string &Filename, int &fd) { 00052 fd = -1; 00053 return Filename; 00054 } 00055 }; 00056 00057 class FixItActionSuffixInserter : public FixItOptions { 00058 std::string NewSuffix; 00059 00060 public: 00061 FixItActionSuffixInserter(std::string NewSuffix, bool FixWhatYouCan) 00062 : NewSuffix(NewSuffix) { 00063 this->FixWhatYouCan = FixWhatYouCan; 00064 } 00065 00066 std::string RewriteFilename(const std::string &Filename, int &fd) { 00067 fd = -1; 00068 SmallString<128> Path(Filename); 00069 llvm::sys::path::replace_extension(Path, 00070 NewSuffix + llvm::sys::path::extension(Path)); 00071 return Path.str(); 00072 } 00073 }; 00074 00075 class FixItRewriteToTemp : public FixItOptions { 00076 public: 00077 std::string RewriteFilename(const std::string &Filename, int &fd) { 00078 SmallString<128> Path; 00079 Path = llvm::sys::path::filename(Filename); 00080 Path += "-%%%%%%%%"; 00081 Path += llvm::sys::path::extension(Filename); 00082 SmallString<128> NewPath; 00083 llvm::sys::fs::unique_file(Path.str(), fd, NewPath); 00084 return NewPath.str(); 00085 } 00086 }; 00087 } // end anonymous namespace 00088 00089 bool FixItAction::BeginSourceFileAction(CompilerInstance &CI, 00090 StringRef Filename) { 00091 const FrontendOptions &FEOpts = getCompilerInstance().getFrontendOpts(); 00092 if (!FEOpts.FixItSuffix.empty()) { 00093 FixItOpts.reset(new FixItActionSuffixInserter(FEOpts.FixItSuffix, 00094 FEOpts.FixWhatYouCan)); 00095 } else { 00096 FixItOpts.reset(new FixItRewriteInPlace); 00097 FixItOpts->FixWhatYouCan = FEOpts.FixWhatYouCan; 00098 } 00099 Rewriter.reset(new FixItRewriter(CI.getDiagnostics(), CI.getSourceManager(), 00100 CI.getLangOpts(), FixItOpts.get())); 00101 return true; 00102 } 00103 00104 void FixItAction::EndSourceFileAction() { 00105 // Otherwise rewrite all files. 00106 Rewriter->WriteFixedFiles(); 00107 } 00108 00109 bool FixItRecompile::BeginInvocation(CompilerInstance &CI) { 00110 00111 std::vector<std::pair<std::string, std::string> > RewrittenFiles; 00112 bool err = false; 00113 { 00114 const FrontendOptions &FEOpts = CI.getFrontendOpts(); 00115 OwningPtr<FrontendAction> FixAction(new SyntaxOnlyAction()); 00116 if (FixAction->BeginSourceFile(CI, FEOpts.Inputs[0])) { 00117 OwningPtr<FixItOptions> FixItOpts; 00118 if (FEOpts.FixToTemporaries) 00119 FixItOpts.reset(new FixItRewriteToTemp()); 00120 else 00121 FixItOpts.reset(new FixItRewriteInPlace()); 00122 FixItOpts->Silent = true; 00123 FixItOpts->FixWhatYouCan = FEOpts.FixWhatYouCan; 00124 FixItOpts->FixOnlyWarnings = FEOpts.FixOnlyWarnings; 00125 FixItRewriter Rewriter(CI.getDiagnostics(), CI.getSourceManager(), 00126 CI.getLangOpts(), FixItOpts.get()); 00127 FixAction->Execute(); 00128 00129 err = Rewriter.WriteFixedFiles(&RewrittenFiles); 00130 00131 FixAction->EndSourceFile(); 00132 CI.setSourceManager(0); 00133 CI.setFileManager(0); 00134 } else { 00135 err = true; 00136 } 00137 } 00138 if (err) 00139 return false; 00140 CI.getDiagnosticClient().clear(); 00141 CI.getDiagnostics().Reset(); 00142 00143 PreprocessorOptions &PPOpts = CI.getPreprocessorOpts(); 00144 PPOpts.RemappedFiles.insert(PPOpts.RemappedFiles.end(), 00145 RewrittenFiles.begin(), RewrittenFiles.end()); 00146 PPOpts.RemappedFilesKeepOriginalName = false; 00147 00148 return true; 00149 } 00150 00151 //===----------------------------------------------------------------------===// 00152 // Preprocessor Actions 00153 //===----------------------------------------------------------------------===// 00154 00155 ASTConsumer *RewriteObjCAction::CreateASTConsumer(CompilerInstance &CI, 00156 StringRef InFile) { 00157 if (raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "cpp")) { 00158 if (CI.getLangOpts().ObjCNonFragileABI) 00159 return CreateModernObjCRewriter(InFile, OS, 00160 CI.getDiagnostics(), CI.getLangOpts(), 00161 CI.getDiagnosticOpts().NoRewriteMacros); 00162 return CreateObjCRewriter(InFile, OS, 00163 CI.getDiagnostics(), CI.getLangOpts(), 00164 CI.getDiagnosticOpts().NoRewriteMacros); 00165 } 00166 return 0; 00167 } 00168 00169 void RewriteMacrosAction::ExecuteAction() { 00170 CompilerInstance &CI = getCompilerInstance(); 00171 raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile()); 00172 if (!OS) return; 00173 00174 RewriteMacrosInInput(CI.getPreprocessor(), OS); 00175 } 00176 00177 void RewriteTestAction::ExecuteAction() { 00178 CompilerInstance &CI = getCompilerInstance(); 00179 raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile()); 00180 if (!OS) return; 00181 00182 DoRewriteTest(CI.getPreprocessor(), OS); 00183 }