blob: b4a439d4237ea4a098d65092bcdec35b06f45452 [file] [log] [blame]
Daniel Dunbar8305d012009-11-14 10:42:46 +00001//===--- 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"
Douglas Gregordb1cde72011-11-16 00:09:06 +000012#include "clang/Lex/HeaderSearch.h"
Daniel Dunbarc72cc502010-06-11 20:10:12 +000013#include "clang/Lex/Pragma.h"
Daniel Dunbar5f3b9972009-11-14 10:42:57 +000014#include "clang/Lex/Preprocessor.h"
15#include "clang/Parse/Parser.h"
Daniel Dunbar8305d012009-11-14 10:42:46 +000016#include "clang/Basic/FileManager.h"
Daniel Dunbar8305d012009-11-14 10:42:46 +000017#include "clang/Frontend/ASTConsumers.h"
18#include "clang/Frontend/ASTUnit.h"
19#include "clang/Frontend/CompilerInstance.h"
Daniel Dunbar8305d012009-11-14 10:42:46 +000020#include "clang/Frontend/FrontendDiagnostic.h"
21#include "clang/Frontend/Utils.h"
Sebastian Redl7faa2ec2010-08-18 23:56:37 +000022#include "clang/Serialization/ASTWriter.h"
Nick Lewyckyba5f6ec2010-04-24 01:30:46 +000023#include "llvm/ADT/OwningPtr.h"
Douglas Gregor77d029f2011-12-08 19:11:24 +000024#include "llvm/Support/FileSystem.h"
Douglas Gregorf033f1d2010-07-20 20:18:03 +000025#include "llvm/Support/MemoryBuffer.h"
Daniel Dunbar8305d012009-11-14 10:42:46 +000026#include "llvm/Support/raw_ostream.h"
Douglas Gregor10efbaf2011-09-23 23:43:36 +000027#include "llvm/Support/system_error.h"
Douglas Gregor978fc9c2012-03-27 18:06:49 +000028#include <set>
Douglas Gregor10efbaf2011-09-23 23:43:36 +000029
Daniel Dunbar8305d012009-11-14 10:42:46 +000030using namespace clang;
31
Daniel Dunbar5f3b9972009-11-14 10:42:57 +000032//===----------------------------------------------------------------------===//
Daniel Dunbar27585952010-03-19 19:44:04 +000033// Custom Actions
34//===----------------------------------------------------------------------===//
35
36ASTConsumer *InitOnlyAction::CreateASTConsumer(CompilerInstance &CI,
Chris Lattner5f9e2722011-07-23 10:55:15 +000037 StringRef InFile) {
Daniel Dunbar27585952010-03-19 19:44:04 +000038 return new ASTConsumer();
39}
40
41void InitOnlyAction::ExecuteAction() {
42}
43
44//===----------------------------------------------------------------------===//
Daniel Dunbar5f3b9972009-11-14 10:42:57 +000045// AST Consumer Actions
46//===----------------------------------------------------------------------===//
47
Daniel Dunbar8305d012009-11-14 10:42:46 +000048ASTConsumer *ASTPrintAction::CreateASTConsumer(CompilerInstance &CI,
Chris Lattner5f9e2722011-07-23 10:55:15 +000049 StringRef InFile) {
50 if (raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
Daniel Dunbar36043592009-12-03 09:13:30 +000051 return CreateASTPrinter(OS);
52 return 0;
Daniel Dunbar8305d012009-11-14 10:42:46 +000053}
54
Daniel Dunbar8305d012009-11-14 10:42:46 +000055ASTConsumer *ASTDumpAction::CreateASTConsumer(CompilerInstance &CI,
Chris Lattner5f9e2722011-07-23 10:55:15 +000056 StringRef InFile) {
Daniel Dunbar8305d012009-11-14 10:42:46 +000057 return CreateASTDumper();
58}
59
John McCallf3514242010-11-24 11:21:45 +000060ASTConsumer *ASTDumpXMLAction::CreateASTConsumer(CompilerInstance &CI,
Chris Lattner5f9e2722011-07-23 10:55:15 +000061 StringRef InFile) {
62 raw_ostream *OS;
John McCallf3514242010-11-24 11:21:45 +000063 if (CI.getFrontendOpts().OutputFile.empty())
64 OS = &llvm::outs();
65 else
66 OS = CI.createDefaultOutputFile(false, InFile);
67 if (!OS) return 0;
68 return CreateASTDumperXML(*OS);
69}
70
Daniel Dunbar8305d012009-11-14 10:42:46 +000071ASTConsumer *ASTViewAction::CreateASTConsumer(CompilerInstance &CI,
Chris Lattner5f9e2722011-07-23 10:55:15 +000072 StringRef InFile) {
Daniel Dunbar8305d012009-11-14 10:42:46 +000073 return CreateASTViewer();
74}
75
76ASTConsumer *DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI,
Chris Lattner5f9e2722011-07-23 10:55:15 +000077 StringRef InFile) {
Daniel Dunbar8305d012009-11-14 10:42:46 +000078 return CreateDeclContextPrinter();
79}
80
Daniel Dunbar8305d012009-11-14 10:42:46 +000081ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI,
Chris Lattner5f9e2722011-07-23 10:55:15 +000082 StringRef InFile) {
Douglas Gregor1d715ac2010-08-03 08:14:03 +000083 std::string Sysroot;
Argyrios Kyrtzidis8e3df4d2011-02-15 17:54:22 +000084 std::string OutputFile;
Chris Lattner5f9e2722011-07-23 10:55:15 +000085 raw_ostream *OS = 0;
Douglas Gregor9293ba82011-08-25 22:35:51 +000086 if (ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile, OS))
Daniel Dunbar8305d012009-11-14 10:42:46 +000087 return 0;
Douglas Gregor1d715ac2010-08-03 08:14:03 +000088
Douglas Gregor832d6202011-07-22 16:35:34 +000089 if (!CI.getFrontendOpts().RelocatablePCH)
90 Sysroot.clear();
Douglas Gregora8cc6ce2011-11-30 04:39:39 +000091 return new PCHGenerator(CI.getPreprocessor(), OutputFile, 0, Sysroot, OS);
Douglas Gregor1d715ac2010-08-03 08:14:03 +000092}
93
94bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI,
Chris Lattner5f9e2722011-07-23 10:55:15 +000095 StringRef InFile,
Douglas Gregor1d715ac2010-08-03 08:14:03 +000096 std::string &Sysroot,
Argyrios Kyrtzidis8e3df4d2011-02-15 17:54:22 +000097 std::string &OutputFile,
Douglas Gregor9293ba82011-08-25 22:35:51 +000098 raw_ostream *&OS) {
Douglas Gregor1d715ac2010-08-03 08:14:03 +000099 Sysroot = CI.getHeaderSearchOpts().Sysroot;
100 if (CI.getFrontendOpts().RelocatablePCH && Sysroot.empty()) {
Sebastian Redl11c3dc42010-08-17 17:55:38 +0000101 CI.getDiagnostics().Report(diag::err_relocatable_without_isysroot);
Douglas Gregor1d715ac2010-08-03 08:14:03 +0000102 return true;
Daniel Dunbar8305d012009-11-14 10:42:46 +0000103 }
104
Daniel Dunbarc7a9cda2011-01-31 22:00:44 +0000105 // We use createOutputFile here because this is exposed via libclang, and we
106 // must disable the RemoveFileOnSignal behavior.
Argyrios Kyrtzidis7e909852011-07-28 00:45:10 +0000107 // We use a temporary to avoid race conditions.
Daniel Dunbarc7a9cda2011-01-31 22:00:44 +0000108 OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true,
Argyrios Kyrtzidis7e909852011-07-28 00:45:10 +0000109 /*RemoveFileOnSignal=*/false, InFile,
110 /*Extension=*/"", /*useTemporary=*/true);
Daniel Dunbar36043592009-12-03 09:13:30 +0000111 if (!OS)
Douglas Gregor1d715ac2010-08-03 08:14:03 +0000112 return true;
Daniel Dunbar36043592009-12-03 09:13:30 +0000113
Argyrios Kyrtzidis8e3df4d2011-02-15 17:54:22 +0000114 OutputFile = CI.getFrontendOpts().OutputFile;
Douglas Gregor1d715ac2010-08-03 08:14:03 +0000115 return false;
Daniel Dunbar8305d012009-11-14 10:42:46 +0000116}
117
Douglas Gregordb1cde72011-11-16 00:09:06 +0000118ASTConsumer *GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
119 StringRef InFile) {
120 std::string Sysroot;
121 std::string OutputFile;
122 raw_ostream *OS = 0;
123 if (ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile, OS))
124 return 0;
125
Douglas Gregora8cc6ce2011-11-30 04:39:39 +0000126 return new PCHGenerator(CI.getPreprocessor(), OutputFile, Module,
Douglas Gregordb1cde72011-11-16 00:09:06 +0000127 Sysroot, OS);
128}
129
Douglas Gregor261e75b2011-11-16 17:04:00 +0000130/// \brief Collect the set of header includes needed to construct the given
131/// module.
132///
133/// \param Module The module we're collecting includes from.
Douglas Gregor8075ce62011-12-06 17:15:11 +0000134///
135/// \param Includes Will be augmented with the set of #includes or #imports
136/// needed to load all of the named headers.
Douglas Gregor261e75b2011-11-16 17:04:00 +0000137static void collectModuleHeaderIncludes(const LangOptions &LangOpts,
Douglas Gregor752769f2012-01-05 00:04:05 +0000138 FileManager &FileMgr,
139 ModuleMap &ModMap,
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000140 clang::Module *Module,
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000141 SmallString<256> &Includes) {
Douglas Gregor51f564f2011-12-31 04:05:44 +0000142 // Don't collect any headers for unavailable modules.
143 if (!Module->isAvailable())
144 return;
145
Douglas Gregor8075ce62011-12-06 17:15:11 +0000146 // Add includes for each of these headers.
Douglas Gregor2f04f182012-02-02 18:42:48 +0000147 for (unsigned I = 0, N = Module->Headers.size(); I != N; ++I) {
148 if (LangOpts.ObjC1)
149 Includes += "#import \"";
150 else
151 Includes += "#include \"";
152 Includes += Module->Headers[I]->getName();
153 Includes += "\"\n";
154 }
Douglas Gregor8075ce62011-12-06 17:15:11 +0000155
Douglas Gregor10694ce2011-12-08 17:39:04 +0000156 if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader()) {
Douglas Gregor2f04f182012-02-02 18:42:48 +0000157 if (Module->Parent) {
158 // Include the umbrella header for submodules.
159 if (LangOpts.ObjC1)
160 Includes += "#import \"";
161 else
162 Includes += "#include \"";
163 Includes += UmbrellaHeader->getName();
164 Includes += "\"\n";
165 }
Douglas Gregor77d029f2011-12-08 19:11:24 +0000166 } else if (const DirectoryEntry *UmbrellaDir = Module->getUmbrellaDir()) {
Douglas Gregor752769f2012-01-05 00:04:05 +0000167 // Add all of the headers we find in this subdirectory.
Douglas Gregor77d029f2011-12-08 19:11:24 +0000168 llvm::error_code EC;
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000169 SmallString<128> DirNative;
Douglas Gregor77d029f2011-12-08 19:11:24 +0000170 llvm::sys::path::native(UmbrellaDir->getName(), DirNative);
Douglas Gregor3b29bb92011-12-12 19:13:53 +0000171 for (llvm::sys::fs::recursive_directory_iterator Dir(DirNative.str(), EC),
172 DirEnd;
Douglas Gregor77d029f2011-12-08 19:11:24 +0000173 Dir != DirEnd && !EC; Dir.increment(EC)) {
174 // Check whether this entry has an extension typically associated with
175 // headers.
176 if (!llvm::StringSwitch<bool>(llvm::sys::path::extension(Dir->path()))
177 .Cases(".h", ".H", ".hh", ".hpp", true)
178 .Default(false))
179 continue;
180
Douglas Gregor752769f2012-01-05 00:04:05 +0000181 // If this header is marked 'unavailable' in this module, don't include
182 // it.
183 if (const FileEntry *Header = FileMgr.getFile(Dir->path()))
184 if (ModMap.isHeaderInUnavailableModule(Header))
185 continue;
186
Douglas Gregor2f04f182012-02-02 18:42:48 +0000187 // Include this header umbrella header for submodules.
188 if (LangOpts.ObjC1)
189 Includes += "#import \"";
190 else
191 Includes += "#include \"";
192 Includes += Dir->path();
193 Includes += "\"\n";
Douglas Gregor77d029f2011-12-08 19:11:24 +0000194 }
Douglas Gregor261e75b2011-11-16 17:04:00 +0000195 }
196
197 // Recurse into submodules.
Douglas Gregorb7a78192012-01-04 23:32:19 +0000198 for (clang::Module::submodule_iterator Sub = Module->submodule_begin(),
199 SubEnd = Module->submodule_end();
Douglas Gregor8075ce62011-12-06 17:15:11 +0000200 Sub != SubEnd; ++Sub)
Douglas Gregor2f04f182012-02-02 18:42:48 +0000201 collectModuleHeaderIncludes(LangOpts, FileMgr, ModMap, *Sub, Includes);
Douglas Gregor261e75b2011-11-16 17:04:00 +0000202}
203
Douglas Gregordb1cde72011-11-16 00:09:06 +0000204bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
205 StringRef Filename) {
206 // Find the module map file.
207 const FileEntry *ModuleMap = CI.getFileManager().getFile(Filename);
208 if (!ModuleMap) {
209 CI.getDiagnostics().Report(diag::err_module_map_not_found)
210 << Filename;
211 return false;
212 }
213
214 // Parse the module map file.
215 HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
216 if (HS.loadModuleMapFile(ModuleMap))
217 return false;
218
219 if (CI.getLangOpts().CurrentModule.empty()) {
220 CI.getDiagnostics().Report(diag::err_missing_module_name);
221
222 // FIXME: Eventually, we could consider asking whether there was just
223 // a single module described in the module map, and use that as a
224 // default. Then it would be fairly trivial to just "compile" a module
225 // map with a single module (the common case).
226 return false;
227 }
228
229 // Dig out the module definition.
Douglas Gregore434ec72012-01-29 17:08:11 +0000230 Module = HS.lookupModule(CI.getLangOpts().CurrentModule,
231 /*AllowSearch=*/false);
Douglas Gregordb1cde72011-11-16 00:09:06 +0000232 if (!Module) {
233 CI.getDiagnostics().Report(diag::err_missing_module)
234 << CI.getLangOpts().CurrentModule << Filename;
235
236 return false;
237 }
Douglas Gregor51f564f2011-12-31 04:05:44 +0000238
239 // Check whether we can build this module at all.
240 StringRef Feature;
Douglas Gregordc58aa72012-01-30 06:01:29 +0000241 if (!Module->isAvailable(CI.getLangOpts(), CI.getTarget(), Feature)) {
Douglas Gregor51f564f2011-12-31 04:05:44 +0000242 CI.getDiagnostics().Report(diag::err_module_unavailable)
243 << Module->getFullModuleName()
244 << Feature;
245
246 return false;
247 }
248
Douglas Gregor10694ce2011-12-08 17:39:04 +0000249 // Do we have an umbrella header for this module?
250 const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader();
251
Douglas Gregor261e75b2011-11-16 17:04:00 +0000252 // Collect the set of #includes we need to build the module.
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000253 SmallString<256> HeaderContents;
Douglas Gregor752769f2012-01-05 00:04:05 +0000254 collectModuleHeaderIncludes(CI.getLangOpts(), CI.getFileManager(),
255 CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(),
Douglas Gregor2f04f182012-02-02 18:42:48 +0000256 Module, HeaderContents);
Douglas Gregor10694ce2011-12-08 17:39:04 +0000257 if (UmbrellaHeader && HeaderContents.empty()) {
Douglas Gregor261e75b2011-11-16 17:04:00 +0000258 // Simple case: we have an umbrella header and there are no additional
259 // includes, we can just parse the umbrella header directly.
Douglas Gregor1f6b2b52012-01-20 16:28:04 +0000260 setCurrentInput(FrontendInputFile(UmbrellaHeader->getName(),
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000261 getCurrentFileKind(),
262 Module->IsSystem));
Douglas Gregor261e75b2011-11-16 17:04:00 +0000263 return true;
Douglas Gregordb1cde72011-11-16 00:09:06 +0000264 }
265
Douglas Gregor261e75b2011-11-16 17:04:00 +0000266 FileManager &FileMgr = CI.getFileManager();
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000267 SmallString<128> HeaderName;
Douglas Gregor261e75b2011-11-16 17:04:00 +0000268 time_t ModTime;
Douglas Gregor10694ce2011-12-08 17:39:04 +0000269 if (UmbrellaHeader) {
Douglas Gregor261e75b2011-11-16 17:04:00 +0000270 // Read in the umbrella header.
271 // FIXME: Go through the source manager; the umbrella header may have
272 // been overridden.
273 std::string ErrorStr;
274 llvm::MemoryBuffer *UmbrellaContents
Douglas Gregor10694ce2011-12-08 17:39:04 +0000275 = FileMgr.getBufferForFile(UmbrellaHeader, &ErrorStr);
Douglas Gregor261e75b2011-11-16 17:04:00 +0000276 if (!UmbrellaContents) {
277 CI.getDiagnostics().Report(diag::err_missing_umbrella_header)
Douglas Gregor10694ce2011-12-08 17:39:04 +0000278 << UmbrellaHeader->getName() << ErrorStr;
Douglas Gregor261e75b2011-11-16 17:04:00 +0000279 return false;
280 }
281
282 // Combine the contents of the umbrella header with the automatically-
283 // generated includes.
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000284 SmallString<256> OldContents = HeaderContents;
Douglas Gregor261e75b2011-11-16 17:04:00 +0000285 HeaderContents = UmbrellaContents->getBuffer();
286 HeaderContents += "\n\n";
287 HeaderContents += "/* Module includes */\n";
288 HeaderContents += OldContents;
289
290 // Pretend that we're parsing the umbrella header.
Douglas Gregor10694ce2011-12-08 17:39:04 +0000291 HeaderName = UmbrellaHeader->getName();
292 ModTime = UmbrellaHeader->getModificationTime();
Douglas Gregor261e75b2011-11-16 17:04:00 +0000293
294 delete UmbrellaContents;
295 } else {
296 // Pick an innocuous-sounding name for the umbrella header.
297 HeaderName = Module->Name + ".h";
298 if (FileMgr.getFile(HeaderName, /*OpenFile=*/false,
299 /*CacheFailure=*/false)) {
300 // Try again!
301 HeaderName = Module->Name + "-module.h";
302 if (FileMgr.getFile(HeaderName, /*OpenFile=*/false,
303 /*CacheFailure=*/false)) {
304 // Pick something ridiculous and go with it.
305 HeaderName = Module->Name + "-module.hmod";
306 }
307 }
308 ModTime = time(0);
309 }
310
311 // Remap the contents of the header name we're using to our synthesized
312 // buffer.
313 const FileEntry *HeaderFile = FileMgr.getVirtualFile(HeaderName,
314 HeaderContents.size(),
315 ModTime);
316 llvm::MemoryBuffer *HeaderContentsBuf
317 = llvm::MemoryBuffer::getMemBufferCopy(HeaderContents);
Douglas Gregor1f6b2b52012-01-20 16:28:04 +0000318 CI.getSourceManager().overrideFileContents(HeaderFile, HeaderContentsBuf);
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000319 setCurrentInput(FrontendInputFile(HeaderName, getCurrentFileKind(),
320 Module->IsSystem));
Douglas Gregordb1cde72011-11-16 00:09:06 +0000321 return true;
322}
323
324bool GenerateModuleAction::ComputeASTConsumerArguments(CompilerInstance &CI,
325 StringRef InFile,
326 std::string &Sysroot,
327 std::string &OutputFile,
328 raw_ostream *&OS) {
329 // If no output file was provided, figure out where this module would go
330 // in the module cache.
331 if (CI.getFrontendOpts().OutputFile.empty()) {
332 HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000333 SmallString<256> ModuleFileName(HS.getModuleCachePath());
Douglas Gregordb1cde72011-11-16 00:09:06 +0000334 llvm::sys::path::append(ModuleFileName,
335 CI.getLangOpts().CurrentModule + ".pcm");
336 CI.getFrontendOpts().OutputFile = ModuleFileName.str();
337 }
338
339 // We use createOutputFile here because this is exposed via libclang, and we
340 // must disable the RemoveFileOnSignal behavior.
341 // We use a temporary to avoid race conditions.
342 OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true,
343 /*RemoveFileOnSignal=*/false, InFile,
Daniel Dunbar12f28ab2012-03-03 00:36:02 +0000344 /*Extension=*/"", /*useTemporary=*/true,
345 /*CreateMissingDirectories=*/true);
Douglas Gregordb1cde72011-11-16 00:09:06 +0000346 if (!OS)
347 return true;
348
349 OutputFile = CI.getFrontendOpts().OutputFile;
350 return false;
351}
352
Daniel Dunbar8305d012009-11-14 10:42:46 +0000353ASTConsumer *SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI,
Chris Lattner5f9e2722011-07-23 10:55:15 +0000354 StringRef InFile) {
Daniel Dunbar8305d012009-11-14 10:42:46 +0000355 return new ASTConsumer();
356}
357
Douglas Gregor978fc9c2012-03-27 18:06:49 +0000358namespace {
359 class PubnamesDumpConsumer : public ASTConsumer {
360 Preprocessor &PP;
361
362 /// \brief Determine whether the given identifier provides a 'public' name.
363 bool isPublicName(IdentifierInfo *II) {
364 // If there are any top-level declarations associated with this
365 // identifier, it is a public name.
366 if (II->getFETokenInfo<void>())
367 return true;
368
369 // If this identifier is the name of a non-builtin macro that isn't
370 // defined on the command line or implicitly by the front end, it is a
371 // public name.
372 if (II->hasMacroDefinition()) {
373 if (MacroInfo *M = PP.getMacroInfo(II))
374 if (!M->isBuiltinMacro()) {
375 SourceLocation Loc = M->getDefinitionLoc();
376 FileID File = PP.getSourceManager().getFileID(Loc);
377 if (PP.getSourceManager().getFileEntryForID(File))
378 return true;
379 }
380 }
381
382 return false;
383 }
384
385 public:
386 PubnamesDumpConsumer(Preprocessor &PP) : PP(PP) { }
387
388 virtual void HandleTranslationUnit(ASTContext &Ctx) {
389 std::set<StringRef> Pubnames;
390
391 // Add the names of any non-builtin macros.
392 for (IdentifierTable::iterator I = Ctx.Idents.begin(),
393 IEnd = Ctx.Idents.end();
394 I != IEnd; ++I) {
395 if (isPublicName(I->second))
396 Pubnames.insert(I->first());
397 }
398
399 // If there is an external identifier lookup source, consider those
400 // identifiers as well.
401 if (IdentifierInfoLookup *External
402 = Ctx.Idents.getExternalIdentifierLookup()) {
403 OwningPtr<IdentifierIterator> Iter(External->getIdentifiers());
404 do {
405 StringRef Name = Iter->Next();
406 if (Name.empty())
407 break;
408
409 if (isPublicName(PP.getIdentifierInfo(Name)))
410 Pubnames.insert(Name);
411 } while (true);
412 }
413
414 // Print the names, in lexicographical order.
415 for (std::set<StringRef>::iterator N = Pubnames.begin(),
416 NEnd = Pubnames.end();
417 N != NEnd; ++N) {
418 llvm::outs() << *N << '\n';
419 }
420 }
421 };
422}
423
424ASTConsumer *PubnamesDumpAction::CreateASTConsumer(CompilerInstance &CI,
425 StringRef InFile) {
426 return new PubnamesDumpConsumer(CI.getPreprocessor());
427}
428
Daniel Dunbar5f3b9972009-11-14 10:42:57 +0000429//===----------------------------------------------------------------------===//
430// Preprocessor Actions
431//===----------------------------------------------------------------------===//
432
433void DumpRawTokensAction::ExecuteAction() {
434 Preprocessor &PP = getCompilerInstance().getPreprocessor();
435 SourceManager &SM = PP.getSourceManager();
436
437 // Start lexing the specified input file.
Chris Lattner6e290142009-11-30 04:18:44 +0000438 const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID());
David Blaikie4e4d0842012-03-11 07:00:24 +0000439 Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOpts());
Daniel Dunbar5f3b9972009-11-14 10:42:57 +0000440 RawLex.SetKeepWhitespaceMode(true);
441
442 Token RawTok;
443 RawLex.LexFromRawLexer(RawTok);
444 while (RawTok.isNot(tok::eof)) {
445 PP.DumpToken(RawTok, true);
Daniel Dunbar33f57f82009-11-25 10:27:48 +0000446 llvm::errs() << "\n";
Daniel Dunbar5f3b9972009-11-14 10:42:57 +0000447 RawLex.LexFromRawLexer(RawTok);
448 }
449}
450
451void DumpTokensAction::ExecuteAction() {
452 Preprocessor &PP = getCompilerInstance().getPreprocessor();
453 // Start preprocessing the specified input file.
454 Token Tok;
Chris Lattnere127a0d2010-04-20 20:35:58 +0000455 PP.EnterMainSourceFile();
Daniel Dunbar5f3b9972009-11-14 10:42:57 +0000456 do {
457 PP.Lex(Tok);
458 PP.DumpToken(Tok, true);
Daniel Dunbar33f57f82009-11-25 10:27:48 +0000459 llvm::errs() << "\n";
Daniel Dunbar5f3b9972009-11-14 10:42:57 +0000460 } while (Tok.isNot(tok::eof));
461}
462
463void GeneratePTHAction::ExecuteAction() {
464 CompilerInstance &CI = getCompilerInstance();
465 if (CI.getFrontendOpts().OutputFile.empty() ||
466 CI.getFrontendOpts().OutputFile == "-") {
467 // FIXME: Don't fail this way.
468 // FIXME: Verify that we can actually seek in the given file.
Chris Lattner83e7a782010-04-07 22:58:06 +0000469 llvm::report_fatal_error("PTH requires a seekable file for output!");
Daniel Dunbar5f3b9972009-11-14 10:42:57 +0000470 }
471 llvm::raw_fd_ostream *OS =
472 CI.createDefaultOutputFile(true, getCurrentFile());
Daniel Dunbar36043592009-12-03 09:13:30 +0000473 if (!OS) return;
474
Daniel Dunbar5f3b9972009-11-14 10:42:57 +0000475 CacheTokens(CI.getPreprocessor(), OS);
476}
477
Daniel Dunbar5f3b9972009-11-14 10:42:57 +0000478void PreprocessOnlyAction::ExecuteAction() {
479 Preprocessor &PP = getCompilerInstance().getPreprocessor();
480
Daniel Dunbarc72cc502010-06-11 20:10:12 +0000481 // Ignore unknown pragmas.
Argyrios Kyrtzidis9b36c3f2010-07-13 09:07:17 +0000482 PP.AddPragmaHandler(new EmptyPragmaHandler());
Daniel Dunbarc72cc502010-06-11 20:10:12 +0000483
Daniel Dunbar5f3b9972009-11-14 10:42:57 +0000484 Token Tok;
485 // Start parsing the specified input file.
Chris Lattnere127a0d2010-04-20 20:35:58 +0000486 PP.EnterMainSourceFile();
Daniel Dunbar5f3b9972009-11-14 10:42:57 +0000487 do {
488 PP.Lex(Tok);
489 } while (Tok.isNot(tok::eof));
490}
491
Daniel Dunbar5f3b9972009-11-14 10:42:57 +0000492void PrintPreprocessedAction::ExecuteAction() {
493 CompilerInstance &CI = getCompilerInstance();
Douglas Gregor10efbaf2011-09-23 23:43:36 +0000494 // Output file may need to be set to 'Binary', to avoid converting Unix style
Steve Naroffd57d7c02010-01-05 17:33:23 +0000495 // line feeds (<LF>) to Microsoft style line feeds (<CR><LF>).
Douglas Gregor10efbaf2011-09-23 23:43:36 +0000496 //
497 // Look to see what type of line endings the file uses. If there's a
498 // CRLF, then we won't open the file up in binary mode. If there is
499 // just an LF or CR, then we will open the file up in binary mode.
500 // In this fashion, the output format should match the input format, unless
501 // the input format has inconsistent line endings.
502 //
503 // This should be a relatively fast operation since most files won't have
504 // all of their source code on a single line. However, that is still a
505 // concern, so if we scan for too long, we'll just assume the file should
506 // be opened in binary mode.
507 bool BinaryMode = true;
508 bool InvalidFile = false;
509 const SourceManager& SM = CI.getSourceManager();
510 const llvm::MemoryBuffer *Buffer = SM.getBuffer(SM.getMainFileID(),
511 &InvalidFile);
512 if (!InvalidFile) {
513 const char *cur = Buffer->getBufferStart();
514 const char *end = Buffer->getBufferEnd();
515 const char *next = (cur != end) ? cur + 1 : end;
516
517 // Limit ourselves to only scanning 256 characters into the source
518 // file. This is mostly a sanity check in case the file has no
519 // newlines whatsoever.
520 if (end - cur > 256) end = cur + 256;
521
522 while (next < end) {
523 if (*cur == 0x0D) { // CR
524 if (*next == 0x0A) // CRLF
525 BinaryMode = false;
526
527 break;
528 } else if (*cur == 0x0A) // LF
529 break;
530
531 ++cur, ++next;
532 }
533 }
534
535 raw_ostream *OS = CI.createDefaultOutputFile(BinaryMode, getCurrentFile());
Daniel Dunbar36043592009-12-03 09:13:30 +0000536 if (!OS) return;
537
Daniel Dunbar5f3b9972009-11-14 10:42:57 +0000538 DoPrintPreprocessedInput(CI.getPreprocessor(), OS,
539 CI.getPreprocessorOutputOpts());
540}
Douglas Gregorf033f1d2010-07-20 20:18:03 +0000541
542void PrintPreambleAction::ExecuteAction() {
543 switch (getCurrentFileKind()) {
544 case IK_C:
545 case IK_CXX:
546 case IK_ObjC:
547 case IK_ObjCXX:
548 case IK_OpenCL:
Peter Collingbourne895fcca2010-12-01 03:15:20 +0000549 case IK_CUDA:
Douglas Gregorf033f1d2010-07-20 20:18:03 +0000550 break;
551
552 case IK_None:
553 case IK_Asm:
554 case IK_PreprocessedC:
555 case IK_PreprocessedCXX:
556 case IK_PreprocessedObjC:
557 case IK_PreprocessedObjCXX:
558 case IK_AST:
559 case IK_LLVM_IR:
560 // We can't do anything with these.
561 return;
562 }
563
Argyrios Kyrtzidis389db162010-11-03 22:45:23 +0000564 CompilerInstance &CI = getCompilerInstance();
565 llvm::MemoryBuffer *Buffer
Chris Lattner39b49bc2010-11-23 08:35:12 +0000566 = CI.getFileManager().getBufferForFile(getCurrentFile());
Douglas Gregorf033f1d2010-07-20 20:18:03 +0000567 if (Buffer) {
Argyrios Kyrtzidis03c107a2011-08-25 20:39:19 +0000568 unsigned Preamble = Lexer::ComputePreamble(Buffer, CI.getLangOpts()).first;
Douglas Gregorf033f1d2010-07-20 20:18:03 +0000569 llvm::outs().write(Buffer->getBufferStart(), Preamble);
570 delete Buffer;
571 }
572}