]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp
Upgrade to OpenPAM Radula.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / lib / Frontend / Rewrite / FrontendActions.cpp
1 //===--- FrontendActions.cpp ----------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "clang/Rewrite/Frontend/FrontendActions.h"
11 #include "clang/AST/ASTConsumer.h"
12 #include "clang/Basic/FileManager.h"
13 #include "clang/Frontend/CompilerInstance.h"
14 #include "clang/Frontend/FrontendActions.h"
15 #include "clang/Frontend/FrontendDiagnostic.h"
16 #include "clang/Frontend/Utils.h"
17 #include "clang/Lex/Preprocessor.h"
18 #include "clang/Parse/Parser.h"
19 #include "clang/Rewrite/Frontend/ASTConsumers.h"
20 #include "clang/Rewrite/Frontend/FixItRewriter.h"
21 #include "clang/Rewrite/Frontend/Rewriters.h"
22 #include "llvm/Support/FileSystem.h"
23 #include "llvm/Support/Path.h"
24 #include "llvm/Support/raw_ostream.h"
25 #include <memory>
26 #include <utility>
27
28 using namespace clang;
29
30 //===----------------------------------------------------------------------===//
31 // AST Consumer Actions
32 //===----------------------------------------------------------------------===//
33
34 std::unique_ptr<ASTConsumer>
35 HTMLPrintAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
36   if (std::unique_ptr<raw_ostream> OS =
37           CI.createDefaultOutputFile(false, InFile))
38     return CreateHTMLPrinter(std::move(OS), CI.getPreprocessor());
39   return nullptr;
40 }
41
42 FixItAction::FixItAction() {}
43 FixItAction::~FixItAction() {}
44
45 std::unique_ptr<ASTConsumer>
46 FixItAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
47   return llvm::make_unique<ASTConsumer>();
48 }
49
50 namespace {
51 class FixItRewriteInPlace : public FixItOptions {
52 public:
53   FixItRewriteInPlace() { InPlace = true; }
54
55   std::string RewriteFilename(const std::string &Filename, int &fd) override {
56     llvm_unreachable("don't call RewriteFilename for inplace rewrites");
57   }
58 };
59
60 class FixItActionSuffixInserter : public FixItOptions {
61   std::string NewSuffix;
62
63 public:
64   FixItActionSuffixInserter(std::string NewSuffix, bool FixWhatYouCan)
65       : NewSuffix(std::move(NewSuffix)) {
66     this->FixWhatYouCan = FixWhatYouCan;
67   }
68
69   std::string RewriteFilename(const std::string &Filename, int &fd) override {
70     fd = -1;
71     SmallString<128> Path(Filename);
72     llvm::sys::path::replace_extension(Path,
73       NewSuffix + llvm::sys::path::extension(Path));
74     return Path.str();
75   }
76 };
77
78 class FixItRewriteToTemp : public FixItOptions {
79 public:
80   std::string RewriteFilename(const std::string &Filename, int &fd) override {
81     SmallString<128> Path;
82     llvm::sys::fs::createTemporaryFile(llvm::sys::path::filename(Filename),
83                                        llvm::sys::path::extension(Filename).drop_front(), fd,
84                                        Path);
85     return Path.str();
86   }
87 };
88 } // end anonymous namespace
89
90 bool FixItAction::BeginSourceFileAction(CompilerInstance &CI,
91                                         StringRef Filename) {
92   const FrontendOptions &FEOpts = getCompilerInstance().getFrontendOpts();
93   if (!FEOpts.FixItSuffix.empty()) {
94     FixItOpts.reset(new FixItActionSuffixInserter(FEOpts.FixItSuffix,
95                                                   FEOpts.FixWhatYouCan));
96   } else {
97     FixItOpts.reset(new FixItRewriteInPlace);
98     FixItOpts->FixWhatYouCan = FEOpts.FixWhatYouCan;
99   }
100   Rewriter.reset(new FixItRewriter(CI.getDiagnostics(), CI.getSourceManager(),
101                                    CI.getLangOpts(), FixItOpts.get()));
102   return true;
103 }
104
105 void FixItAction::EndSourceFileAction() {
106   // Otherwise rewrite all files.
107   Rewriter->WriteFixedFiles();
108 }
109
110 bool FixItRecompile::BeginInvocation(CompilerInstance &CI) {
111
112   std::vector<std::pair<std::string, std::string> > RewrittenFiles;
113   bool err = false;
114   {
115     const FrontendOptions &FEOpts = CI.getFrontendOpts();
116     std::unique_ptr<FrontendAction> FixAction(new SyntaxOnlyAction());
117     if (FixAction->BeginSourceFile(CI, FEOpts.Inputs[0])) {
118       std::unique_ptr<FixItOptions> FixItOpts;
119       if (FEOpts.FixToTemporaries)
120         FixItOpts.reset(new FixItRewriteToTemp());
121       else
122         FixItOpts.reset(new FixItRewriteInPlace());
123       FixItOpts->Silent = true;
124       FixItOpts->FixWhatYouCan = FEOpts.FixWhatYouCan;
125       FixItOpts->FixOnlyWarnings = FEOpts.FixOnlyWarnings;
126       FixItRewriter Rewriter(CI.getDiagnostics(), CI.getSourceManager(),
127                              CI.getLangOpts(), FixItOpts.get());
128       FixAction->Execute();
129   
130       err = Rewriter.WriteFixedFiles(&RewrittenFiles);
131     
132       FixAction->EndSourceFile();
133       CI.setSourceManager(nullptr);
134       CI.setFileManager(nullptr);
135     } else {
136       err = true;
137     }
138   }
139   if (err)
140     return false;
141   CI.getDiagnosticClient().clear();
142   CI.getDiagnostics().Reset();
143
144   PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();
145   PPOpts.RemappedFiles.insert(PPOpts.RemappedFiles.end(),
146                               RewrittenFiles.begin(), RewrittenFiles.end());
147   PPOpts.RemappedFilesKeepOriginalName = false;
148
149   return true;
150 }
151
152 #ifdef CLANG_ENABLE_OBJC_REWRITER
153
154 std::unique_ptr<ASTConsumer>
155 RewriteObjCAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
156   if (std::unique_ptr<raw_ostream> OS =
157           CI.createDefaultOutputFile(false, InFile, "cpp")) {
158     if (CI.getLangOpts().ObjCRuntime.isNonFragile())
159       return CreateModernObjCRewriter(
160           InFile, std::move(OS), CI.getDiagnostics(), CI.getLangOpts(),
161           CI.getDiagnosticOpts().NoRewriteMacros,
162           (CI.getCodeGenOpts().getDebugInfo() != codegenoptions::NoDebugInfo));
163     return CreateObjCRewriter(InFile, std::move(OS), CI.getDiagnostics(),
164                               CI.getLangOpts(),
165                               CI.getDiagnosticOpts().NoRewriteMacros);
166   }
167   return nullptr;
168 }
169
170 #endif
171
172 //===----------------------------------------------------------------------===//
173 // Preprocessor Actions
174 //===----------------------------------------------------------------------===//
175
176 void RewriteMacrosAction::ExecuteAction() {
177   CompilerInstance &CI = getCompilerInstance();
178   std::unique_ptr<raw_ostream> OS =
179       CI.createDefaultOutputFile(true, getCurrentFile());
180   if (!OS) return;
181
182   RewriteMacrosInInput(CI.getPreprocessor(), OS.get());
183 }
184
185 void RewriteTestAction::ExecuteAction() {
186   CompilerInstance &CI = getCompilerInstance();
187   std::unique_ptr<raw_ostream> OS =
188       CI.createDefaultOutputFile(false, getCurrentFile());
189   if (!OS) return;
190
191   DoRewriteTest(CI.getPreprocessor(), OS.get());
192 }
193
194 void RewriteIncludesAction::ExecuteAction() {
195   CompilerInstance &CI = getCompilerInstance();
196   std::unique_ptr<raw_ostream> OS =
197       CI.createDefaultOutputFile(true, getCurrentFile());
198   if (!OS) return;
199
200   RewriteIncludesInInput(CI.getPreprocessor(), OS.get(),
201                          CI.getPreprocessorOutputOpts());
202 }