forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			225 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			225 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===--- FrontendActions.cpp ----------------------------------------------===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "clang/Frontend/FrontendActions.h"
 | |
| #include "clang/AST/ASTConsumer.h"
 | |
| #include "clang/Lex/Pragma.h"
 | |
| #include "clang/Lex/Preprocessor.h"
 | |
| #include "clang/Parse/Parser.h"
 | |
| #include "clang/Basic/FileManager.h"
 | |
| #include "clang/Frontend/ASTConsumers.h"
 | |
| #include "clang/Frontend/ASTUnit.h"
 | |
| #include "clang/Frontend/CompilerInstance.h"
 | |
| #include "clang/Frontend/FrontendDiagnostic.h"
 | |
| #include "clang/Frontend/Utils.h"
 | |
| #include "clang/Serialization/ASTWriter.h"
 | |
| #include "llvm/ADT/OwningPtr.h"
 | |
| #include "llvm/Support/MemoryBuffer.h"
 | |
| #include "llvm/Support/raw_ostream.h"
 | |
| using namespace clang;
 | |
| 
 | |
| //===----------------------------------------------------------------------===//
 | |
| // Custom Actions
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| ASTConsumer *InitOnlyAction::CreateASTConsumer(CompilerInstance &CI,
 | |
|                                                llvm::StringRef InFile) {
 | |
|   return new ASTConsumer();
 | |
| }
 | |
| 
 | |
| void InitOnlyAction::ExecuteAction() {
 | |
| }
 | |
| 
 | |
| //===----------------------------------------------------------------------===//
 | |
| // AST Consumer Actions
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| ASTConsumer *ASTPrintAction::CreateASTConsumer(CompilerInstance &CI,
 | |
|                                                llvm::StringRef InFile) {
 | |
|   if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
 | |
|     return CreateASTPrinter(OS);
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| ASTConsumer *ASTDumpAction::CreateASTConsumer(CompilerInstance &CI,
 | |
|                                               llvm::StringRef InFile) {
 | |
|   return CreateASTDumper();
 | |
| }
 | |
| 
 | |
| ASTConsumer *ASTDumpXMLAction::CreateASTConsumer(CompilerInstance &CI,
 | |
|                                                  llvm::StringRef InFile) {
 | |
|   llvm::raw_ostream *OS;
 | |
|   if (CI.getFrontendOpts().OutputFile.empty())
 | |
|     OS = &llvm::outs();
 | |
|   else
 | |
|     OS = CI.createDefaultOutputFile(false, InFile);
 | |
|   if (!OS) return 0;
 | |
|   return CreateASTDumperXML(*OS);
 | |
| }
 | |
| 
 | |
| ASTConsumer *ASTViewAction::CreateASTConsumer(CompilerInstance &CI,
 | |
|                                               llvm::StringRef InFile) {
 | |
|   return CreateASTViewer();
 | |
| }
 | |
| 
 | |
| ASTConsumer *DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI,
 | |
|                                                        llvm::StringRef InFile) {
 | |
|   return CreateDeclContextPrinter();
 | |
| }
 | |
| 
 | |
| ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI,
 | |
|                                                   llvm::StringRef InFile) {
 | |
|   std::string Sysroot;
 | |
|   std::string OutputFile;
 | |
|   llvm::raw_ostream *OS = 0;
 | |
|   bool Chaining;
 | |
|   if (ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile, OS, Chaining))
 | |
|     return 0;
 | |
| 
 | |
|   const char *isysroot = CI.getFrontendOpts().RelocatablePCH ?
 | |
|                              Sysroot.c_str() : 0;  
 | |
|   return new PCHGenerator(CI.getPreprocessor(), OutputFile, Chaining, isysroot, OS);
 | |
| }
 | |
| 
 | |
| bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI,
 | |
|                                                     llvm::StringRef InFile,
 | |
|                                                     std::string &Sysroot,
 | |
|                                                     std::string &OutputFile,
 | |
|                                                     llvm::raw_ostream *&OS,
 | |
|                                                     bool &Chaining) {
 | |
|   Sysroot = CI.getHeaderSearchOpts().Sysroot;
 | |
|   if (CI.getFrontendOpts().RelocatablePCH && Sysroot.empty()) {
 | |
|     CI.getDiagnostics().Report(diag::err_relocatable_without_isysroot);
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   // We use createOutputFile here because this is exposed via libclang, and we
 | |
|   // must disable the RemoveFileOnSignal behavior.
 | |
|   OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true,
 | |
|                            /*RemoveFileOnSignal=*/false, InFile);
 | |
|   if (!OS)
 | |
|     return true;
 | |
| 
 | |
|   OutputFile = CI.getFrontendOpts().OutputFile;
 | |
|   Chaining = CI.getInvocation().getFrontendOpts().ChainedPCH &&
 | |
|              !CI.getPreprocessorOpts().ImplicitPCHInclude.empty();
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| ASTConsumer *SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI,
 | |
|                                                  llvm::StringRef InFile) {
 | |
|   return new ASTConsumer();
 | |
| }
 | |
| 
 | |
| //===----------------------------------------------------------------------===//
 | |
| // Preprocessor Actions
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| void DumpRawTokensAction::ExecuteAction() {
 | |
|   Preprocessor &PP = getCompilerInstance().getPreprocessor();
 | |
|   SourceManager &SM = PP.getSourceManager();
 | |
| 
 | |
|   // Start lexing the specified input file.
 | |
|   const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID());
 | |
|   Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOptions());
 | |
|   RawLex.SetKeepWhitespaceMode(true);
 | |
| 
 | |
|   Token RawTok;
 | |
|   RawLex.LexFromRawLexer(RawTok);
 | |
|   while (RawTok.isNot(tok::eof)) {
 | |
|     PP.DumpToken(RawTok, true);
 | |
|     llvm::errs() << "\n";
 | |
|     RawLex.LexFromRawLexer(RawTok);
 | |
|   }
 | |
| }
 | |
| 
 | |
| void DumpTokensAction::ExecuteAction() {
 | |
|   Preprocessor &PP = getCompilerInstance().getPreprocessor();
 | |
|   // Start preprocessing the specified input file.
 | |
|   Token Tok;
 | |
|   PP.EnterMainSourceFile();
 | |
|   do {
 | |
|     PP.Lex(Tok);
 | |
|     PP.DumpToken(Tok, true);
 | |
|     llvm::errs() << "\n";
 | |
|   } while (Tok.isNot(tok::eof));
 | |
| }
 | |
| 
 | |
| void GeneratePTHAction::ExecuteAction() {
 | |
|   CompilerInstance &CI = getCompilerInstance();
 | |
|   if (CI.getFrontendOpts().OutputFile.empty() ||
 | |
|       CI.getFrontendOpts().OutputFile == "-") {
 | |
|     // FIXME: Don't fail this way.
 | |
|     // FIXME: Verify that we can actually seek in the given file.
 | |
|     llvm::report_fatal_error("PTH requires a seekable file for output!");
 | |
|   }
 | |
|   llvm::raw_fd_ostream *OS =
 | |
|     CI.createDefaultOutputFile(true, getCurrentFile());
 | |
|   if (!OS) return;
 | |
| 
 | |
|   CacheTokens(CI.getPreprocessor(), OS);
 | |
| }
 | |
| 
 | |
| void PreprocessOnlyAction::ExecuteAction() {
 | |
|   Preprocessor &PP = getCompilerInstance().getPreprocessor();
 | |
| 
 | |
|   // Ignore unknown pragmas.
 | |
|   PP.AddPragmaHandler(new EmptyPragmaHandler());
 | |
| 
 | |
|   Token Tok;
 | |
|   // Start parsing the specified input file.
 | |
|   PP.EnterMainSourceFile();
 | |
|   do {
 | |
|     PP.Lex(Tok);
 | |
|   } while (Tok.isNot(tok::eof));
 | |
| }
 | |
| 
 | |
| void PrintPreprocessedAction::ExecuteAction() {
 | |
|   CompilerInstance &CI = getCompilerInstance();
 | |
|   // Output file needs to be set to 'Binary', to avoid converting Unix style
 | |
|   // line feeds (<LF>) to Microsoft style line feeds (<CR><LF>).
 | |
|   llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile());
 | |
|   if (!OS) return;
 | |
| 
 | |
|   DoPrintPreprocessedInput(CI.getPreprocessor(), OS,
 | |
|                            CI.getPreprocessorOutputOpts());
 | |
| }
 | |
| 
 | |
| void PrintPreambleAction::ExecuteAction() {
 | |
|   switch (getCurrentFileKind()) {
 | |
|   case IK_C:
 | |
|   case IK_CXX:
 | |
|   case IK_ObjC:
 | |
|   case IK_ObjCXX:
 | |
|   case IK_OpenCL:
 | |
|   case IK_CUDA:
 | |
|     break;
 | |
|       
 | |
|   case IK_None:
 | |
|   case IK_Asm:
 | |
|   case IK_PreprocessedC:
 | |
|   case IK_PreprocessedCXX:
 | |
|   case IK_PreprocessedObjC:
 | |
|   case IK_PreprocessedObjCXX:
 | |
|   case IK_AST:
 | |
|   case IK_LLVM_IR:
 | |
|     // We can't do anything with these.
 | |
|     return;
 | |
|   }
 | |
|   
 | |
|   CompilerInstance &CI = getCompilerInstance();
 | |
|   llvm::MemoryBuffer *Buffer
 | |
|       = CI.getFileManager().getBufferForFile(getCurrentFile());
 | |
|   if (Buffer) {
 | |
|     unsigned Preamble = Lexer::ComputePreamble(Buffer).first;
 | |
|     llvm::outs().write(Buffer->getBufferStart(), Preamble);
 | |
|     delete Buffer;
 | |
|   }
 | |
| }
 |