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/Frontend/FrontendActions.h" 00011 #include "clang/AST/ASTConsumer.h" 00012 #include "clang/Basic/FileManager.h" 00013 #include "clang/Frontend/CompilerInstance.h" 00014 #include "clang/Frontend/FrontendActions.h" 00015 #include "clang/Frontend/FrontendDiagnostic.h" 00016 #include "clang/Frontend/Utils.h" 00017 #include "clang/Lex/Preprocessor.h" 00018 #include "clang/Parse/Parser.h" 00019 #include "clang/Rewrite/Frontend/ASTConsumers.h" 00020 #include "clang/Rewrite/Frontend/FixItRewriter.h" 00021 #include "clang/Rewrite/Frontend/Rewriters.h" 00022 #include "llvm/Support/FileSystem.h" 00023 #include "llvm/Support/Path.h" 00024 #include "llvm/Support/raw_ostream.h" 00025 #include <memory> 00026 00027 using namespace clang; 00028 00029 //===----------------------------------------------------------------------===// 00030 // AST Consumer Actions 00031 //===----------------------------------------------------------------------===// 00032 00033 std::unique_ptr<ASTConsumer> 00034 HTMLPrintAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { 00035 if (raw_ostream *OS = CI.createDefaultOutputFile(false, InFile)) 00036 return CreateHTMLPrinter(OS, CI.getPreprocessor()); 00037 return nullptr; 00038 } 00039 00040 FixItAction::FixItAction() {} 00041 FixItAction::~FixItAction() {} 00042 00043 std::unique_ptr<ASTConsumer> 00044 FixItAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { 00045 return llvm::make_unique<ASTConsumer>(); 00046 } 00047 00048 namespace { 00049 class FixItRewriteInPlace : public FixItOptions { 00050 public: 00051 std::string RewriteFilename(const std::string &Filename, int &fd) override { 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) override { 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) override { 00078 SmallString<128> Path; 00079 llvm::sys::fs::createTemporaryFile(llvm::sys::path::filename(Filename), 00080 llvm::sys::path::extension(Filename), fd, 00081 Path); 00082 return Path.str(); 00083 } 00084 }; 00085 } // end anonymous namespace 00086 00087 bool FixItAction::BeginSourceFileAction(CompilerInstance &CI, 00088 StringRef Filename) { 00089 const FrontendOptions &FEOpts = getCompilerInstance().getFrontendOpts(); 00090 if (!FEOpts.FixItSuffix.empty()) { 00091 FixItOpts.reset(new FixItActionSuffixInserter(FEOpts.FixItSuffix, 00092 FEOpts.FixWhatYouCan)); 00093 } else { 00094 FixItOpts.reset(new FixItRewriteInPlace); 00095 FixItOpts->FixWhatYouCan = FEOpts.FixWhatYouCan; 00096 } 00097 Rewriter.reset(new FixItRewriter(CI.getDiagnostics(), CI.getSourceManager(), 00098 CI.getLangOpts(), FixItOpts.get())); 00099 return true; 00100 } 00101 00102 void FixItAction::EndSourceFileAction() { 00103 // Otherwise rewrite all files. 00104 Rewriter->WriteFixedFiles(); 00105 } 00106 00107 bool FixItRecompile::BeginInvocation(CompilerInstance &CI) { 00108 00109 std::vector<std::pair<std::string, std::string> > RewrittenFiles; 00110 bool err = false; 00111 { 00112 const FrontendOptions &FEOpts = CI.getFrontendOpts(); 00113 std::unique_ptr<FrontendAction> FixAction(new SyntaxOnlyAction()); 00114 if (FixAction->BeginSourceFile(CI, FEOpts.Inputs[0])) { 00115 std::unique_ptr<FixItOptions> FixItOpts; 00116 if (FEOpts.FixToTemporaries) 00117 FixItOpts.reset(new FixItRewriteToTemp()); 00118 else 00119 FixItOpts.reset(new FixItRewriteInPlace()); 00120 FixItOpts->Silent = true; 00121 FixItOpts->FixWhatYouCan = FEOpts.FixWhatYouCan; 00122 FixItOpts->FixOnlyWarnings = FEOpts.FixOnlyWarnings; 00123 FixItRewriter Rewriter(CI.getDiagnostics(), CI.getSourceManager(), 00124 CI.getLangOpts(), FixItOpts.get()); 00125 FixAction->Execute(); 00126 00127 err = Rewriter.WriteFixedFiles(&RewrittenFiles); 00128 00129 FixAction->EndSourceFile(); 00130 CI.setSourceManager(nullptr); 00131 CI.setFileManager(nullptr); 00132 } else { 00133 err = true; 00134 } 00135 } 00136 if (err) 00137 return false; 00138 CI.getDiagnosticClient().clear(); 00139 CI.getDiagnostics().Reset(); 00140 00141 PreprocessorOptions &PPOpts = CI.getPreprocessorOpts(); 00142 PPOpts.RemappedFiles.insert(PPOpts.RemappedFiles.end(), 00143 RewrittenFiles.begin(), RewrittenFiles.end()); 00144 PPOpts.RemappedFilesKeepOriginalName = false; 00145 00146 return true; 00147 } 00148 00149 #ifdef CLANG_ENABLE_OBJC_REWRITER 00150 00151 std::unique_ptr<ASTConsumer> 00152 RewriteObjCAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { 00153 if (raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "cpp")) { 00154 if (CI.getLangOpts().ObjCRuntime.isNonFragile()) 00155 return CreateModernObjCRewriter(InFile, OS, 00156 CI.getDiagnostics(), CI.getLangOpts(), 00157 CI.getDiagnosticOpts().NoRewriteMacros, 00158 (CI.getCodeGenOpts().getDebugInfo() != 00159 CodeGenOptions::NoDebugInfo)); 00160 return CreateObjCRewriter(InFile, OS, 00161 CI.getDiagnostics(), CI.getLangOpts(), 00162 CI.getDiagnosticOpts().NoRewriteMacros); 00163 } 00164 return nullptr; 00165 } 00166 00167 #endif 00168 00169 //===----------------------------------------------------------------------===// 00170 // Preprocessor Actions 00171 //===----------------------------------------------------------------------===// 00172 00173 void RewriteMacrosAction::ExecuteAction() { 00174 CompilerInstance &CI = getCompilerInstance(); 00175 raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile()); 00176 if (!OS) return; 00177 00178 RewriteMacrosInInput(CI.getPreprocessor(), OS); 00179 } 00180 00181 void RewriteTestAction::ExecuteAction() { 00182 CompilerInstance &CI = getCompilerInstance(); 00183 raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile()); 00184 if (!OS) return; 00185 00186 DoRewriteTest(CI.getPreprocessor(), OS); 00187 } 00188 00189 void RewriteIncludesAction::ExecuteAction() { 00190 CompilerInstance &CI = getCompilerInstance(); 00191 raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile()); 00192 if (!OS) return; 00193 00194 RewriteIncludesInInput(CI.getPreprocessor(), OS, 00195 CI.getPreprocessorOutputOpts()); 00196 }