/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/tools/clang/lib/Frontend/FrontendActions.cpp
Line | Count | Source (jump to first uncovered line) |
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/Frontend/FrontendActions.h" |
11 | | #include "clang/AST/ASTConsumer.h" |
12 | | #include "clang/Basic/FileManager.h" |
13 | | #include "clang/Frontend/ASTConsumers.h" |
14 | | #include "clang/Frontend/CompilerInstance.h" |
15 | | #include "clang/Frontend/FrontendDiagnostic.h" |
16 | | #include "clang/Frontend/MultiplexConsumer.h" |
17 | | #include "clang/Frontend/Utils.h" |
18 | | #include "clang/Lex/HeaderSearch.h" |
19 | | #include "clang/Lex/Preprocessor.h" |
20 | | #include "clang/Lex/PreprocessorOptions.h" |
21 | | #include "clang/Serialization/ASTReader.h" |
22 | | #include "clang/Serialization/ASTWriter.h" |
23 | | #include "llvm/Support/FileSystem.h" |
24 | | #include "llvm/Support/MemoryBuffer.h" |
25 | | #include "llvm/Support/Path.h" |
26 | | #include "llvm/Support/raw_ostream.h" |
27 | | #include <memory> |
28 | | #include <system_error> |
29 | | |
30 | | using namespace clang; |
31 | | |
32 | | //===----------------------------------------------------------------------===// |
33 | | // Custom Actions |
34 | | //===----------------------------------------------------------------------===// |
35 | | |
36 | | std::unique_ptr<ASTConsumer> |
37 | 0 | InitOnlyAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { |
38 | 0 | return llvm::make_unique<ASTConsumer>(); |
39 | 0 | } |
40 | | |
41 | 0 | void InitOnlyAction::ExecuteAction() { |
42 | 0 | } |
43 | | |
44 | | //===----------------------------------------------------------------------===// |
45 | | // AST Consumer Actions |
46 | | //===----------------------------------------------------------------------===// |
47 | | |
48 | | std::unique_ptr<ASTConsumer> |
49 | 196 | ASTPrintAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { |
50 | 196 | if (std::unique_ptr<raw_ostream> OS = |
51 | 196 | CI.createDefaultOutputFile(false, InFile)) |
52 | 196 | return CreateASTPrinter(std::move(OS), CI.getFrontendOpts().ASTDumpFilter); |
53 | 0 | return nullptr; |
54 | 0 | } |
55 | | |
56 | | std::unique_ptr<ASTConsumer> |
57 | 101 | ASTDumpAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { |
58 | 101 | return CreateASTDumper(CI.getFrontendOpts().ASTDumpFilter, |
59 | 101 | CI.getFrontendOpts().ASTDumpDecls, |
60 | 101 | CI.getFrontendOpts().ASTDumpAll, |
61 | 101 | CI.getFrontendOpts().ASTDumpLookups); |
62 | 101 | } |
63 | | |
64 | | std::unique_ptr<ASTConsumer> |
65 | 0 | ASTDeclListAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { |
66 | 0 | return CreateASTDeclNodeLister(); |
67 | 0 | } |
68 | | |
69 | | std::unique_ptr<ASTConsumer> |
70 | 0 | ASTViewAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { |
71 | 0 | return CreateASTViewer(); |
72 | 0 | } |
73 | | |
74 | | std::unique_ptr<ASTConsumer> |
75 | | DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI, |
76 | 2 | StringRef InFile) { |
77 | 2 | return CreateDeclContextPrinter(); |
78 | 2 | } |
79 | | |
80 | | std::unique_ptr<ASTConsumer> |
81 | 691 | GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { |
82 | 691 | std::string Sysroot; |
83 | 691 | std::string OutputFile; |
84 | 691 | std::unique_ptr<raw_pwrite_stream> OS = |
85 | 691 | ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile); |
86 | 691 | if (!OS) |
87 | 0 | return nullptr; |
88 | 691 | |
89 | 691 | if (691 !CI.getFrontendOpts().RelocatablePCH691 ) |
90 | 690 | Sysroot.clear(); |
91 | 691 | |
92 | 691 | auto Buffer = std::make_shared<PCHBuffer>(); |
93 | 691 | std::vector<std::unique_ptr<ASTConsumer>> Consumers; |
94 | 691 | Consumers.push_back(llvm::make_unique<PCHGenerator>( |
95 | 691 | CI.getPreprocessor(), OutputFile, Sysroot, |
96 | 691 | Buffer, CI.getFrontendOpts().ModuleFileExtensions, |
97 | 691 | /*AllowASTWithErrors*/CI.getPreprocessorOpts().AllowPCHWithCompilerErrors, |
98 | 691 | /*IncludeTimestamps*/ |
99 | 691 | +CI.getFrontendOpts().IncludeTimestamps)); |
100 | 691 | Consumers.push_back(CI.getPCHContainerWriter().CreatePCHContainerGenerator( |
101 | 691 | CI, InFile, OutputFile, std::move(OS), Buffer)); |
102 | 691 | |
103 | 691 | return llvm::make_unique<MultiplexConsumer>(std::move(Consumers)); |
104 | 691 | } |
105 | | |
106 | | std::unique_ptr<raw_pwrite_stream> |
107 | | GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI, |
108 | | StringRef InFile, |
109 | | std::string &Sysroot, |
110 | 768 | std::string &OutputFile) { |
111 | 768 | Sysroot = CI.getHeaderSearchOpts().Sysroot; |
112 | 768 | if (CI.getFrontendOpts().RelocatablePCH && 768 Sysroot.empty()1 ) { |
113 | 0 | CI.getDiagnostics().Report(diag::err_relocatable_without_isysroot); |
114 | 0 | return nullptr; |
115 | 0 | } |
116 | 768 | |
117 | 768 | // We use createOutputFile here because this is exposed via libclang, and we |
118 | 768 | // must disable the RemoveFileOnSignal behavior. |
119 | 768 | // We use a temporary to avoid race conditions. |
120 | 768 | std::unique_ptr<raw_pwrite_stream> OS = |
121 | 768 | CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true, |
122 | 768 | /*RemoveFileOnSignal=*/false, InFile, |
123 | 768 | /*Extension=*/"", /*useTemporary=*/true); |
124 | 768 | if (!OS) |
125 | 0 | return nullptr; |
126 | 768 | |
127 | 768 | OutputFile = CI.getFrontendOpts().OutputFile; |
128 | 768 | return OS; |
129 | 768 | } |
130 | | |
131 | 691 | bool GeneratePCHAction::shouldEraseOutputFiles() { |
132 | 691 | if (getCompilerInstance().getPreprocessorOpts().AllowPCHWithCompilerErrors) |
133 | 1 | return false; |
134 | 690 | return ASTFrontendAction::shouldEraseOutputFiles(); |
135 | 690 | } |
136 | | |
137 | 691 | bool GeneratePCHAction::BeginSourceFileAction(CompilerInstance &CI) { |
138 | 691 | CI.getLangOpts().CompilingPCH = true; |
139 | 691 | return true; |
140 | 691 | } |
141 | | |
142 | | std::unique_ptr<ASTConsumer> |
143 | | GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI, |
144 | 1.29k | StringRef InFile) { |
145 | 1.29k | std::unique_ptr<raw_pwrite_stream> OS = CreateOutputFile(CI, InFile); |
146 | 1.29k | if (!OS) |
147 | 0 | return nullptr; |
148 | 1.29k | |
149 | 1.29k | std::string OutputFile = CI.getFrontendOpts().OutputFile; |
150 | 1.29k | std::string Sysroot; |
151 | 1.29k | |
152 | 1.29k | auto Buffer = std::make_shared<PCHBuffer>(); |
153 | 1.29k | std::vector<std::unique_ptr<ASTConsumer>> Consumers; |
154 | 1.29k | |
155 | 1.29k | Consumers.push_back(llvm::make_unique<PCHGenerator>( |
156 | 1.29k | CI.getPreprocessor(), OutputFile, Sysroot, |
157 | 1.29k | Buffer, CI.getFrontendOpts().ModuleFileExtensions, |
158 | 1.29k | /*AllowASTWithErrors=*/false, |
159 | 1.29k | /*IncludeTimestamps=*/ |
160 | 1.29k | +CI.getFrontendOpts().BuildingImplicitModule)); |
161 | 1.29k | Consumers.push_back(CI.getPCHContainerWriter().CreatePCHContainerGenerator( |
162 | 1.29k | CI, InFile, OutputFile, std::move(OS), Buffer)); |
163 | 1.29k | return llvm::make_unique<MultiplexConsumer>(std::move(Consumers)); |
164 | 1.29k | } |
165 | | |
166 | | bool GenerateModuleFromModuleMapAction::BeginSourceFileAction( |
167 | 1.27k | CompilerInstance &CI) { |
168 | 1.27k | if (!CI.getLangOpts().Modules1.27k ) { |
169 | 1 | CI.getDiagnostics().Report(diag::err_module_build_requires_fmodules); |
170 | 1 | return false; |
171 | 1 | } |
172 | 1.27k | |
173 | 1.27k | return GenerateModuleAction::BeginSourceFileAction(CI); |
174 | 1.27k | } |
175 | | |
176 | | std::unique_ptr<raw_pwrite_stream> |
177 | | GenerateModuleFromModuleMapAction::CreateOutputFile(CompilerInstance &CI, |
178 | 1.27k | StringRef InFile) { |
179 | 1.27k | // If no output file was provided, figure out where this module would go |
180 | 1.27k | // in the module cache. |
181 | 1.27k | if (CI.getFrontendOpts().OutputFile.empty()1.27k ) { |
182 | 44 | StringRef ModuleMapFile = CI.getFrontendOpts().OriginalModuleMap; |
183 | 44 | if (ModuleMapFile.empty()) |
184 | 44 | ModuleMapFile = InFile; |
185 | 44 | |
186 | 44 | HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); |
187 | 44 | CI.getFrontendOpts().OutputFile = |
188 | 44 | HS.getCachedModuleFileName(CI.getLangOpts().CurrentModule, |
189 | 44 | ModuleMapFile); |
190 | 44 | } |
191 | 1.27k | |
192 | 1.27k | // We use createOutputFile here because this is exposed via libclang, and we |
193 | 1.27k | // must disable the RemoveFileOnSignal behavior. |
194 | 1.27k | // We use a temporary to avoid race conditions. |
195 | 1.27k | return CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true, |
196 | 1.27k | /*RemoveFileOnSignal=*/false, InFile, |
197 | 1.27k | /*Extension=*/"", /*useTemporary=*/true, |
198 | 1.27k | /*CreateMissingDirectories=*/true); |
199 | 1.27k | } |
200 | | |
201 | | bool GenerateModuleInterfaceAction::BeginSourceFileAction( |
202 | 27 | CompilerInstance &CI) { |
203 | 27 | if (!CI.getLangOpts().ModulesTS27 ) { |
204 | 0 | CI.getDiagnostics().Report(diag::err_module_interface_requires_modules_ts); |
205 | 0 | return false; |
206 | 0 | } |
207 | 27 | |
208 | 27 | CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleInterface); |
209 | 27 | |
210 | 27 | return GenerateModuleAction::BeginSourceFileAction(CI); |
211 | 27 | } |
212 | | |
213 | | std::unique_ptr<raw_pwrite_stream> |
214 | | GenerateModuleInterfaceAction::CreateOutputFile(CompilerInstance &CI, |
215 | 27 | StringRef InFile) { |
216 | 27 | return CI.createDefaultOutputFile(/*Binary=*/true, InFile, "pcm"); |
217 | 27 | } |
218 | | |
219 | 7.57k | SyntaxOnlyAction::~SyntaxOnlyAction() { |
220 | 7.57k | } |
221 | | |
222 | | std::unique_ptr<ASTConsumer> |
223 | 7.69k | SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { |
224 | 7.69k | return llvm::make_unique<ASTConsumer>(); |
225 | 7.69k | } |
226 | | |
227 | | std::unique_ptr<ASTConsumer> |
228 | | DumpModuleInfoAction::CreateASTConsumer(CompilerInstance &CI, |
229 | 5 | StringRef InFile) { |
230 | 5 | return llvm::make_unique<ASTConsumer>(); |
231 | 5 | } |
232 | | |
233 | | std::unique_ptr<ASTConsumer> |
234 | 7 | VerifyPCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { |
235 | 7 | return llvm::make_unique<ASTConsumer>(); |
236 | 7 | } |
237 | | |
238 | 7 | void VerifyPCHAction::ExecuteAction() { |
239 | 7 | CompilerInstance &CI = getCompilerInstance(); |
240 | 7 | bool Preamble = CI.getPreprocessorOpts().PrecompiledPreambleBytes.first != 0; |
241 | 7 | const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot; |
242 | 7 | std::unique_ptr<ASTReader> Reader(new ASTReader( |
243 | 7 | CI.getPreprocessor(), &CI.getASTContext(), CI.getPCHContainerReader(), |
244 | 7 | CI.getFrontendOpts().ModuleFileExtensions, |
245 | 7 | Sysroot.empty() ? ""0 : Sysroot.c_str()7 , |
246 | 7 | /*DisableValidation*/ false, |
247 | 7 | /*AllowPCHWithCompilerErrors*/ false, |
248 | 7 | /*AllowConfigurationMismatch*/ true, |
249 | 7 | /*ValidateSystemInputs*/ true)); |
250 | 7 | |
251 | 7 | Reader->ReadAST(getCurrentFile(), |
252 | 0 | Preamble ? serialization::MK_Preamble |
253 | 7 | : serialization::MK_PCH, |
254 | 7 | SourceLocation(), |
255 | 7 | ASTReader::ARR_ConfigurationMismatch); |
256 | 7 | } |
257 | | |
258 | | namespace { |
259 | | /// \brief AST reader listener that dumps module information for a module |
260 | | /// file. |
261 | | class DumpModuleInfoListener : public ASTReaderListener { |
262 | | llvm::raw_ostream &Out; |
263 | | |
264 | | public: |
265 | 5 | DumpModuleInfoListener(llvm::raw_ostream &Out) : Out(Out) { } |
266 | | |
267 | | #define DUMP_BOOLEAN(Value, Text) \ |
268 | 630 | Out.indent(4) << Text << ": " << (Value? 630 "Yes"117 : "No"513 ) << "\n" |
269 | | |
270 | 5 | bool ReadFullVersionInformation(StringRef FullVersion) override { |
271 | 5 | Out.indent(2) |
272 | 5 | << "Generated by " |
273 | 5 | << (FullVersion == getClangFullRepositoryVersion()? "this" |
274 | 0 | : "a different") |
275 | 5 | << " Clang: " << FullVersion << "\n"; |
276 | 5 | return ASTReaderListener::ReadFullVersionInformation(FullVersion); |
277 | 5 | } |
278 | | |
279 | 5 | void ReadModuleName(StringRef ModuleName) override { |
280 | 5 | Out.indent(2) << "Module name: " << ModuleName << "\n"; |
281 | 5 | } |
282 | 5 | void ReadModuleMapFile(StringRef ModuleMapPath) override { |
283 | 5 | Out.indent(2) << "Module map file: " << ModuleMapPath << "\n"; |
284 | 5 | } |
285 | | |
286 | | bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain, |
287 | 5 | bool AllowCompatibleDifferences) override { |
288 | 5 | Out.indent(2) << "Language options:\n"; |
289 | 5 | #define LANGOPT(Name, Bits, Default, Description) \ |
290 | 505 | DUMP_BOOLEAN(LangOpts.Name, Description); |
291 | 5 | #define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ |
292 | 45 | Out.indent(4) << Description << ": " \ |
293 | 45 | << static_cast<unsigned>(LangOpts.get##Name()) << "\n"; |
294 | 5 | #define VALUE_LANGOPT(Name, Bits, Default, Description) \ |
295 | 35 | Out.indent(4) << Description << ": " << LangOpts.Name << "\n"; |
296 | 5 | #define BENIGN_LANGOPT(Name, Bits, Default, Description) |
297 | 5 | #define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) |
298 | 5 | #include "clang/Basic/LangOptions.def" |
299 | 5 | |
300 | 5 | if (!LangOpts.ModuleFeatures.empty()5 ) { |
301 | 4 | Out.indent(4) << "Module features:\n"; |
302 | 4 | for (StringRef Feature : LangOpts.ModuleFeatures) |
303 | 4 | Out.indent(6) << Feature << "\n"; |
304 | 4 | } |
305 | 5 | |
306 | 5 | return false; |
307 | 5 | } |
308 | | |
309 | | bool ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain, |
310 | 5 | bool AllowCompatibleDifferences) override { |
311 | 5 | Out.indent(2) << "Target options:\n"; |
312 | 5 | Out.indent(4) << " Triple: " << TargetOpts.Triple << "\n"; |
313 | 5 | Out.indent(4) << " CPU: " << TargetOpts.CPU << "\n"; |
314 | 5 | Out.indent(4) << " ABI: " << TargetOpts.ABI << "\n"; |
315 | 5 | |
316 | 5 | if (!TargetOpts.FeaturesAsWritten.empty()5 ) { |
317 | 0 | Out.indent(4) << "Target features:\n"; |
318 | 0 | for (unsigned I = 0, N = TargetOpts.FeaturesAsWritten.size(); |
319 | 0 | I != N0 ; ++I0 ) { |
320 | 0 | Out.indent(6) << TargetOpts.FeaturesAsWritten[I] << "\n"; |
321 | 0 | } |
322 | 0 | } |
323 | 5 | |
324 | 5 | return false; |
325 | 5 | } |
326 | | |
327 | | bool ReadDiagnosticOptions(IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, |
328 | 5 | bool Complain) override { |
329 | 5 | Out.indent(2) << "Diagnostic options:\n"; |
330 | 95 | #define DIAGOPT(Name, Bits, Default) DUMP_BOOLEAN(DiagOpts->Name, #Name); |
331 | 5 | #define ENUM_DIAGOPT(Name, Type, Bits, Default) \ |
332 | 15 | Out.indent(4) << #Name << ": " << DiagOpts->get##Name() << "\n"; |
333 | 5 | #define VALUE_DIAGOPT(Name, Bits, Default) \ |
334 | 45 | Out.indent(4) << #Name << ": " << DiagOpts->Name << "\n"; |
335 | 5 | #include "clang/Basic/DiagnosticOptions.def" |
336 | 5 | |
337 | 5 | Out.indent(4) << "Diagnostic flags:\n"; |
338 | 5 | for (const std::string &Warning : DiagOpts->Warnings) |
339 | 4 | Out.indent(6) << "-W" << Warning << "\n"; |
340 | 5 | for (const std::string &Remark : DiagOpts->Remarks) |
341 | 0 | Out.indent(6) << "-R" << Remark << "\n"; |
342 | 5 | |
343 | 5 | return false; |
344 | 5 | } |
345 | | |
346 | | bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, |
347 | | StringRef SpecificModuleCachePath, |
348 | 5 | bool Complain) override { |
349 | 5 | Out.indent(2) << "Header search options:\n"; |
350 | 5 | Out.indent(4) << "System root [-isysroot=]: '" << HSOpts.Sysroot << "'\n"; |
351 | 5 | Out.indent(4) << "Resource dir [ -resource-dir=]: '" << HSOpts.ResourceDir << "'\n"; |
352 | 5 | Out.indent(4) << "Module Cache: '" << SpecificModuleCachePath << "'\n"; |
353 | 5 | DUMP_BOOLEAN(HSOpts.UseBuiltinIncludes, |
354 | 5 | "Use builtin include directories [-nobuiltininc]"); |
355 | 5 | DUMP_BOOLEAN(HSOpts.UseStandardSystemIncludes, |
356 | 5 | "Use standard system include directories [-nostdinc]"); |
357 | 5 | DUMP_BOOLEAN(HSOpts.UseStandardCXXIncludes, |
358 | 5 | "Use standard C++ include directories [-nostdinc++]"); |
359 | 5 | DUMP_BOOLEAN(HSOpts.UseLibcxx, |
360 | 5 | "Use libc++ (rather than libstdc++) [-stdlib=]"); |
361 | 5 | return false; |
362 | 5 | } |
363 | | |
364 | | bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, |
365 | | bool Complain, |
366 | 5 | std::string &SuggestedPredefines) override { |
367 | 5 | Out.indent(2) << "Preprocessor options:\n"; |
368 | 5 | DUMP_BOOLEAN(PPOpts.UsePredefines, |
369 | 5 | "Uses compiler/target-specific predefines [-undef]"); |
370 | 5 | DUMP_BOOLEAN(PPOpts.DetailedRecord, |
371 | 5 | "Uses detailed preprocessing record (for indexing)"); |
372 | 5 | |
373 | 5 | if (!PPOpts.Macros.empty()5 ) { |
374 | 4 | Out.indent(4) << "Predefined macros:\n"; |
375 | 4 | } |
376 | 5 | |
377 | 5 | for (std::vector<std::pair<std::string, bool/*isUndef*/> >::const_iterator |
378 | 5 | I = PPOpts.Macros.begin(), IEnd = PPOpts.Macros.end(); |
379 | 13 | I != IEnd13 ; ++I8 ) { |
380 | 8 | Out.indent(6); |
381 | 8 | if (I->second) |
382 | 0 | Out << "-U"; |
383 | 8 | else |
384 | 8 | Out << "-D"; |
385 | 8 | Out << I->first << "\n"; |
386 | 8 | } |
387 | 5 | return false; |
388 | 5 | } |
389 | | |
390 | | /// Indicates that a particular module file extension has been read. |
391 | | void readModuleFileExtension( |
392 | 2 | const ModuleFileExtensionMetadata &Metadata) override { |
393 | 2 | Out.indent(2) << "Module file extension '" |
394 | 2 | << Metadata.BlockName << "' " << Metadata.MajorVersion |
395 | 2 | << "." << Metadata.MinorVersion; |
396 | 2 | if (!Metadata.UserInfo.empty()2 ) { |
397 | 2 | Out << ": "; |
398 | 2 | Out.write_escaped(Metadata.UserInfo); |
399 | 2 | } |
400 | 2 | |
401 | 2 | Out << "\n"; |
402 | 2 | } |
403 | | #undef DUMP_BOOLEAN |
404 | | }; |
405 | | } |
406 | | |
407 | 5 | bool DumpModuleInfoAction::BeginInvocation(CompilerInstance &CI) { |
408 | 5 | // The Object file reader also supports raw ast files and there is no point in |
409 | 5 | // being strict about the module file format in -module-file-info mode. |
410 | 5 | CI.getHeaderSearchOpts().ModuleFormat = "obj"; |
411 | 5 | return true; |
412 | 5 | } |
413 | | |
414 | 5 | void DumpModuleInfoAction::ExecuteAction() { |
415 | 5 | // Set up the output file. |
416 | 5 | std::unique_ptr<llvm::raw_fd_ostream> OutFile; |
417 | 5 | StringRef OutputFileName = getCompilerInstance().getFrontendOpts().OutputFile; |
418 | 5 | if (!OutputFileName.empty() && 5 OutputFileName != "-"0 ) { |
419 | 0 | std::error_code EC; |
420 | 0 | OutFile.reset(new llvm::raw_fd_ostream(OutputFileName.str(), EC, |
421 | 0 | llvm::sys::fs::F_Text)); |
422 | 0 | } |
423 | 5 | llvm::raw_ostream &Out = OutFile.get()? *OutFile.get()0 : llvm::outs()5 ; |
424 | 5 | |
425 | 5 | Out << "Information for module file '" << getCurrentFile() << "':\n"; |
426 | 5 | auto &FileMgr = getCompilerInstance().getFileManager(); |
427 | 5 | auto Buffer = FileMgr.getBufferForFile(getCurrentFile()); |
428 | 5 | StringRef Magic = (*Buffer)->getMemBufferRef().getBuffer(); |
429 | 5 | bool IsRaw = (Magic.size() >= 4 && Magic[0] == 'C'5 && Magic[1] == 'P'3 && |
430 | 5 | Magic[2] == 'C'3 && Magic[3] == 'H'3 ); |
431 | 5 | Out << " Module format: " << (IsRaw ? "raw"3 : "obj"2 ) << "\n"; |
432 | 5 | |
433 | 5 | Preprocessor &PP = getCompilerInstance().getPreprocessor(); |
434 | 5 | DumpModuleInfoListener Listener(Out); |
435 | 5 | HeaderSearchOptions &HSOpts = |
436 | 5 | PP.getHeaderSearchInfo().getHeaderSearchOpts(); |
437 | 5 | ASTReader::readASTFileControlBlock( |
438 | 5 | getCurrentFile(), FileMgr, getCompilerInstance().getPCHContainerReader(), |
439 | 5 | /*FindModuleFileExtensions=*/true, Listener, |
440 | 5 | HSOpts.ModulesValidateDiagnosticOptions); |
441 | 5 | } |
442 | | |
443 | | //===----------------------------------------------------------------------===// |
444 | | // Preprocessor Actions |
445 | | //===----------------------------------------------------------------------===// |
446 | | |
447 | 0 | void DumpRawTokensAction::ExecuteAction() { |
448 | 0 | Preprocessor &PP = getCompilerInstance().getPreprocessor(); |
449 | 0 | SourceManager &SM = PP.getSourceManager(); |
450 | 0 |
|
451 | 0 | // Start lexing the specified input file. |
452 | 0 | const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID()); |
453 | 0 | Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOpts()); |
454 | 0 | RawLex.SetKeepWhitespaceMode(true); |
455 | 0 |
|
456 | 0 | Token RawTok; |
457 | 0 | RawLex.LexFromRawLexer(RawTok); |
458 | 0 | while (RawTok.isNot(tok::eof)0 ) { |
459 | 0 | PP.DumpToken(RawTok, true); |
460 | 0 | llvm::errs() << "\n"; |
461 | 0 | RawLex.LexFromRawLexer(RawTok); |
462 | 0 | } |
463 | 0 | } |
464 | | |
465 | 3 | void DumpTokensAction::ExecuteAction() { |
466 | 3 | Preprocessor &PP = getCompilerInstance().getPreprocessor(); |
467 | 3 | // Start preprocessing the specified input file. |
468 | 3 | Token Tok; |
469 | 3 | PP.EnterMainSourceFile(); |
470 | 7 | do { |
471 | 7 | PP.Lex(Tok); |
472 | 7 | PP.DumpToken(Tok, true); |
473 | 7 | llvm::errs() << "\n"; |
474 | 7 | } while (Tok.isNot(tok::eof)); |
475 | 3 | } |
476 | | |
477 | 5 | void GeneratePTHAction::ExecuteAction() { |
478 | 5 | CompilerInstance &CI = getCompilerInstance(); |
479 | 5 | std::unique_ptr<raw_pwrite_stream> OS = |
480 | 5 | CI.createDefaultOutputFile(true, getCurrentFile()); |
481 | 5 | if (!OS) |
482 | 0 | return; |
483 | 5 | |
484 | 5 | CacheTokens(CI.getPreprocessor(), OS.get()); |
485 | 5 | } |
486 | | |
487 | 35 | void PreprocessOnlyAction::ExecuteAction() { |
488 | 35 | Preprocessor &PP = getCompilerInstance().getPreprocessor(); |
489 | 35 | |
490 | 35 | // Ignore unknown pragmas. |
491 | 35 | PP.IgnorePragmas(); |
492 | 35 | |
493 | 35 | Token Tok; |
494 | 35 | // Start parsing the specified input file. |
495 | 35 | PP.EnterMainSourceFile(); |
496 | 336 | do { |
497 | 336 | PP.Lex(Tok); |
498 | 336 | } while (Tok.isNot(tok::eof)); |
499 | 35 | } |
500 | | |
501 | 1.97k | void PrintPreprocessedAction::ExecuteAction() { |
502 | 1.97k | CompilerInstance &CI = getCompilerInstance(); |
503 | 1.97k | // Output file may need to be set to 'Binary', to avoid converting Unix style |
504 | 1.97k | // line feeds (<LF>) to Microsoft style line feeds (<CR><LF>). |
505 | 1.97k | // |
506 | 1.97k | // Look to see what type of line endings the file uses. If there's a |
507 | 1.97k | // CRLF, then we won't open the file up in binary mode. If there is |
508 | 1.97k | // just an LF or CR, then we will open the file up in binary mode. |
509 | 1.97k | // In this fashion, the output format should match the input format, unless |
510 | 1.97k | // the input format has inconsistent line endings. |
511 | 1.97k | // |
512 | 1.97k | // This should be a relatively fast operation since most files won't have |
513 | 1.97k | // all of their source code on a single line. However, that is still a |
514 | 1.97k | // concern, so if we scan for too long, we'll just assume the file should |
515 | 1.97k | // be opened in binary mode. |
516 | 1.97k | bool BinaryMode = true; |
517 | 1.97k | bool InvalidFile = false; |
518 | 1.97k | const SourceManager& SM = CI.getSourceManager(); |
519 | 1.97k | const llvm::MemoryBuffer *Buffer = SM.getBuffer(SM.getMainFileID(), |
520 | 1.97k | &InvalidFile); |
521 | 1.97k | if (!InvalidFile1.97k ) { |
522 | 1.97k | const char *cur = Buffer->getBufferStart(); |
523 | 1.97k | const char *end = Buffer->getBufferEnd(); |
524 | 1.97k | const char *next = (cur != end) ? cur + 11.71k : end259 ; |
525 | 1.97k | |
526 | 1.97k | // Limit ourselves to only scanning 256 characters into the source |
527 | 1.97k | // file. This is mostly a sanity check in case the file has no |
528 | 1.97k | // newlines whatsoever. |
529 | 1.97k | if (end - cur > 2561.97k ) end = cur + 2561.62k ; |
530 | 1.97k | |
531 | 134k | while (next < end134k ) { |
532 | 133k | if (*cur == 0x0D133k ) { // CR |
533 | 1 | if (*next == 0x0A) // CRLF |
534 | 1 | BinaryMode = false; |
535 | 1 | |
536 | 1 | break; |
537 | 133k | } else if (133k *cur == 0x0A133k ) // LF |
538 | 1.71k | break; |
539 | 132k | |
540 | 132k | ++cur; |
541 | 132k | ++next; |
542 | 132k | } |
543 | 1.97k | } |
544 | 1.97k | |
545 | 1.97k | std::unique_ptr<raw_ostream> OS = |
546 | 1.97k | CI.createDefaultOutputFile(BinaryMode, getCurrentFile()); |
547 | 1.97k | if (!OS1.97k ) return1 ; |
548 | 1.96k | |
549 | 1.96k | // If we're preprocessing a module map, start by dumping the contents of the |
550 | 1.96k | // module itself before switching to the input buffer. |
551 | 1.96k | auto &Input = getCurrentInput(); |
552 | 1.96k | if (Input.getKind().getFormat() == InputKind::ModuleMap1.96k ) { |
553 | 5 | if (Input.isFile()5 ) { |
554 | 5 | (*OS) << "# 1 \""; |
555 | 5 | OS->write_escaped(Input.getFile()); |
556 | 5 | (*OS) << "\"\n"; |
557 | 5 | } |
558 | 5 | // FIXME: Include additional information here so that we don't need the |
559 | 5 | // original source files to exist on disk. |
560 | 5 | getCurrentModule()->print(*OS); |
561 | 5 | (*OS) << "#pragma clang module contents\n"; |
562 | 5 | } |
563 | 1.97k | |
564 | 1.97k | DoPrintPreprocessedInput(CI.getPreprocessor(), OS.get(), |
565 | 1.97k | CI.getPreprocessorOutputOpts()); |
566 | 1.97k | } |
567 | | |
568 | 2 | void PrintPreambleAction::ExecuteAction() { |
569 | 2 | switch (getCurrentFileKind().getLanguage()) { |
570 | 2 | case InputKind::C: |
571 | 2 | case InputKind::CXX: |
572 | 2 | case InputKind::ObjC: |
573 | 2 | case InputKind::ObjCXX: |
574 | 2 | case InputKind::OpenCL: |
575 | 2 | case InputKind::CUDA: |
576 | 2 | break; |
577 | 2 | |
578 | 0 | case InputKind::Unknown: |
579 | 0 | case InputKind::Asm: |
580 | 0 | case InputKind::LLVM_IR: |
581 | 0 | case InputKind::RenderScript: |
582 | 0 | // We can't do anything with these. |
583 | 0 | return; |
584 | 2 | } |
585 | 2 | |
586 | 2 | // We don't expect to find any #include directives in a preprocessed input. |
587 | 2 | if (2 getCurrentFileKind().isPreprocessed()2 ) |
588 | 0 | return; |
589 | 2 | |
590 | 2 | CompilerInstance &CI = getCompilerInstance(); |
591 | 2 | auto Buffer = CI.getFileManager().getBufferForFile(getCurrentFile()); |
592 | 2 | if (Buffer2 ) { |
593 | 2 | unsigned Preamble = |
594 | 2 | Lexer::ComputePreamble((*Buffer)->getBuffer(), CI.getLangOpts()).Size; |
595 | 2 | llvm::outs().write((*Buffer)->getBufferStart(), Preamble); |
596 | 2 | } |
597 | 2 | } |