clang API Documentation

Frontend/Rewrite/FrontendActions.cpp
Go to the documentation of this file.
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 }