diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp | 264 |
1 files changed, 264 insertions, 0 deletions
diff --git a/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp b/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp new file mode 100644 index 0000000..6f84da9 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp @@ -0,0 +1,264 @@ +//===--- 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" +#include "llvm/Support/system_error.h" + +using namespace clang; + +//===----------------------------------------------------------------------===// +// Custom Actions +//===----------------------------------------------------------------------===// + +ASTConsumer *InitOnlyAction::CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) { + return new ASTConsumer(); +} + +void InitOnlyAction::ExecuteAction() { +} + +//===----------------------------------------------------------------------===// +// AST Consumer Actions +//===----------------------------------------------------------------------===// + +ASTConsumer *ASTPrintAction::CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) { + if (raw_ostream *OS = CI.createDefaultOutputFile(false, InFile)) + return CreateASTPrinter(OS); + return 0; +} + +ASTConsumer *ASTDumpAction::CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) { + return CreateASTDumper(); +} + +ASTConsumer *ASTDumpXMLAction::CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) { + 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, + StringRef InFile) { + return CreateASTViewer(); +} + +ASTConsumer *DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) { + return CreateDeclContextPrinter(); +} + +ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) { + std::string Sysroot; + std::string OutputFile; + raw_ostream *OS = 0; + if (ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile, OS)) + return 0; + + if (!CI.getFrontendOpts().RelocatablePCH) + Sysroot.clear(); + return new PCHGenerator(CI.getPreprocessor(), OutputFile, MakeModule, + Sysroot, OS); +} + +bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI, + StringRef InFile, + std::string &Sysroot, + std::string &OutputFile, + raw_ostream *&OS) { + 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. + // We use a temporary to avoid race conditions. + OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true, + /*RemoveFileOnSignal=*/false, InFile, + /*Extension=*/"", /*useTemporary=*/true); + if (!OS) + return true; + + OutputFile = CI.getFrontendOpts().OutputFile; + return false; +} + +ASTConsumer *SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI, + 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 may need to be set to 'Binary', to avoid converting Unix style + // line feeds (<LF>) to Microsoft style line feeds (<CR><LF>). + // + // Look to see what type of line endings the file uses. If there's a + // CRLF, then we won't open the file up in binary mode. If there is + // just an LF or CR, then we will open the file up in binary mode. + // In this fashion, the output format should match the input format, unless + // the input format has inconsistent line endings. + // + // This should be a relatively fast operation since most files won't have + // all of their source code on a single line. However, that is still a + // concern, so if we scan for too long, we'll just assume the file should + // be opened in binary mode. + bool BinaryMode = true; + bool InvalidFile = false; + const SourceManager& SM = CI.getSourceManager(); + const llvm::MemoryBuffer *Buffer = SM.getBuffer(SM.getMainFileID(), + &InvalidFile); + if (!InvalidFile) { + const char *cur = Buffer->getBufferStart(); + const char *end = Buffer->getBufferEnd(); + const char *next = (cur != end) ? cur + 1 : end; + + // Limit ourselves to only scanning 256 characters into the source + // file. This is mostly a sanity check in case the file has no + // newlines whatsoever. + if (end - cur > 256) end = cur + 256; + + while (next < end) { + if (*cur == 0x0D) { // CR + if (*next == 0x0A) // CRLF + BinaryMode = false; + + break; + } else if (*cur == 0x0A) // LF + break; + + ++cur, ++next; + } + } + + raw_ostream *OS = CI.createDefaultOutputFile(BinaryMode, 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, CI.getLangOpts()).first; + llvm::outs().write(Buffer->getBufferStart(), Preamble); + delete Buffer; + } +} |