2009-11-14 18:42:46 +08:00
|
|
|
//===--- 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"
|
2010-06-12 04:10:12 +08:00
|
|
|
#include "clang/Lex/Pragma.h"
|
2009-11-14 18:42:57 +08:00
|
|
|
#include "clang/Lex/Preprocessor.h"
|
|
|
|
#include "clang/Parse/Parser.h"
|
2009-11-14 18:42:46 +08:00
|
|
|
#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"
|
2010-08-19 07:56:37 +08:00
|
|
|
#include "clang/Serialization/ASTWriter.h"
|
2010-04-24 09:30:46 +08:00
|
|
|
#include "llvm/ADT/OwningPtr.h"
|
2010-07-21 04:18:03 +08:00
|
|
|
#include "llvm/Support/MemoryBuffer.h"
|
2009-11-14 18:42:46 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
using namespace clang;
|
|
|
|
|
2010-03-20 03:44:04 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Custom Actions
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
ASTConsumer *InitOnlyAction::CreateASTConsumer(CompilerInstance &CI,
|
|
|
|
llvm::StringRef InFile) {
|
|
|
|
return new ASTConsumer();
|
|
|
|
}
|
|
|
|
|
|
|
|
void InitOnlyAction::ExecuteAction() {
|
|
|
|
}
|
|
|
|
|
2009-11-14 18:42:57 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// AST Consumer Actions
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-11-14 18:42:46 +08:00
|
|
|
ASTConsumer *ASTPrintAction::CreateASTConsumer(CompilerInstance &CI,
|
|
|
|
llvm::StringRef InFile) {
|
2009-12-03 17:13:30 +08:00
|
|
|
if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
|
|
|
|
return CreateASTPrinter(OS);
|
|
|
|
return 0;
|
2009-11-14 18:42:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ASTConsumer *ASTPrintXMLAction::CreateASTConsumer(CompilerInstance &CI,
|
|
|
|
llvm::StringRef InFile) {
|
2009-12-03 17:13:30 +08:00
|
|
|
if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "xml"))
|
|
|
|
return CreateASTPrinterXML(OS);
|
|
|
|
return 0;
|
2009-11-14 18:42:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ASTConsumer *ASTDumpAction::CreateASTConsumer(CompilerInstance &CI,
|
|
|
|
llvm::StringRef InFile) {
|
|
|
|
return CreateASTDumper();
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
2010-08-03 16:14:03 +08:00
|
|
|
std::string Sysroot;
|
|
|
|
llvm::raw_ostream *OS = 0;
|
|
|
|
bool Chaining;
|
|
|
|
if (ComputeASTConsumerArguments(CI, InFile, Sysroot, OS, Chaining))
|
2009-11-14 18:42:46 +08:00
|
|
|
return 0;
|
2010-08-03 16:14:03 +08:00
|
|
|
|
|
|
|
const char *isysroot = CI.getFrontendOpts().RelocatablePCH ?
|
|
|
|
Sysroot.c_str() : 0;
|
|
|
|
return new PCHGenerator(CI.getPreprocessor(), Chaining, isysroot, OS);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI,
|
|
|
|
llvm::StringRef InFile,
|
|
|
|
std::string &Sysroot,
|
|
|
|
llvm::raw_ostream *&OS,
|
|
|
|
bool &Chaining) {
|
|
|
|
Sysroot = CI.getHeaderSearchOpts().Sysroot;
|
|
|
|
if (CI.getFrontendOpts().RelocatablePCH && Sysroot.empty()) {
|
2010-08-18 01:55:38 +08:00
|
|
|
CI.getDiagnostics().Report(diag::err_relocatable_without_isysroot);
|
2010-08-03 16:14:03 +08:00
|
|
|
return true;
|
2009-11-14 18:42:46 +08:00
|
|
|
}
|
|
|
|
|
2010-08-03 16:14:03 +08:00
|
|
|
OS = CI.createDefaultOutputFile(true, InFile);
|
2009-12-03 17:13:30 +08:00
|
|
|
if (!OS)
|
2010-08-03 16:14:03 +08:00
|
|
|
return true;
|
2009-12-03 17:13:30 +08:00
|
|
|
|
2010-08-03 16:14:03 +08:00
|
|
|
Chaining = CI.getInvocation().getFrontendOpts().ChainedPCH &&
|
|
|
|
!CI.getPreprocessorOpts().ImplicitPCHInclude.empty();
|
|
|
|
return false;
|
2009-11-14 18:42:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ASTConsumer *InheritanceViewAction::CreateASTConsumer(CompilerInstance &CI,
|
|
|
|
llvm::StringRef InFile) {
|
|
|
|
return CreateInheritanceViewer(CI.getFrontendOpts().ViewClassInheritance);
|
|
|
|
}
|
|
|
|
|
|
|
|
ASTConsumer *SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI,
|
|
|
|
llvm::StringRef InFile) {
|
|
|
|
return new ASTConsumer();
|
|
|
|
}
|
|
|
|
|
2009-11-14 18:42:57 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Preprocessor Actions
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
void DumpRawTokensAction::ExecuteAction() {
|
|
|
|
Preprocessor &PP = getCompilerInstance().getPreprocessor();
|
|
|
|
SourceManager &SM = PP.getSourceManager();
|
|
|
|
|
|
|
|
// Start lexing the specified input file.
|
2009-11-30 12:18:44 +08:00
|
|
|
const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID());
|
|
|
|
Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOptions());
|
2009-11-14 18:42:57 +08:00
|
|
|
RawLex.SetKeepWhitespaceMode(true);
|
|
|
|
|
|
|
|
Token RawTok;
|
|
|
|
RawLex.LexFromRawLexer(RawTok);
|
|
|
|
while (RawTok.isNot(tok::eof)) {
|
|
|
|
PP.DumpToken(RawTok, true);
|
2009-11-25 18:27:48 +08:00
|
|
|
llvm::errs() << "\n";
|
2009-11-14 18:42:57 +08:00
|
|
|
RawLex.LexFromRawLexer(RawTok);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DumpTokensAction::ExecuteAction() {
|
|
|
|
Preprocessor &PP = getCompilerInstance().getPreprocessor();
|
|
|
|
// Start preprocessing the specified input file.
|
|
|
|
Token Tok;
|
2010-04-21 04:35:58 +08:00
|
|
|
PP.EnterMainSourceFile();
|
2009-11-14 18:42:57 +08:00
|
|
|
do {
|
|
|
|
PP.Lex(Tok);
|
|
|
|
PP.DumpToken(Tok, true);
|
2009-11-25 18:27:48 +08:00
|
|
|
llvm::errs() << "\n";
|
2009-11-14 18:42:57 +08:00
|
|
|
} 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.
|
2010-04-08 06:58:06 +08:00
|
|
|
llvm::report_fatal_error("PTH requires a seekable file for output!");
|
2009-11-14 18:42:57 +08:00
|
|
|
}
|
|
|
|
llvm::raw_fd_ostream *OS =
|
|
|
|
CI.createDefaultOutputFile(true, getCurrentFile());
|
2009-12-03 17:13:30 +08:00
|
|
|
if (!OS) return;
|
|
|
|
|
2009-11-14 18:42:57 +08:00
|
|
|
CacheTokens(CI.getPreprocessor(), OS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PreprocessOnlyAction::ExecuteAction() {
|
|
|
|
Preprocessor &PP = getCompilerInstance().getPreprocessor();
|
|
|
|
|
2010-06-12 04:10:12 +08:00
|
|
|
// Ignore unknown pragmas.
|
2010-07-13 17:07:17 +08:00
|
|
|
PP.AddPragmaHandler(new EmptyPragmaHandler());
|
2010-06-12 04:10:12 +08:00
|
|
|
|
2009-11-14 18:42:57 +08:00
|
|
|
Token Tok;
|
|
|
|
// Start parsing the specified input file.
|
2010-04-21 04:35:58 +08:00
|
|
|
PP.EnterMainSourceFile();
|
2009-11-14 18:42:57 +08:00
|
|
|
do {
|
|
|
|
PP.Lex(Tok);
|
|
|
|
} while (Tok.isNot(tok::eof));
|
|
|
|
}
|
|
|
|
|
|
|
|
void PrintPreprocessedAction::ExecuteAction() {
|
|
|
|
CompilerInstance &CI = getCompilerInstance();
|
2010-01-06 01:33:23 +08:00
|
|
|
// 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());
|
2009-12-03 17:13:30 +08:00
|
|
|
if (!OS) return;
|
|
|
|
|
2009-11-14 18:42:57 +08:00
|
|
|
DoPrintPreprocessedInput(CI.getPreprocessor(), OS,
|
|
|
|
CI.getPreprocessorOutputOpts());
|
|
|
|
}
|
2010-07-21 04:18:03 +08:00
|
|
|
|
|
|
|
void PrintPreambleAction::ExecuteAction() {
|
|
|
|
switch (getCurrentFileKind()) {
|
|
|
|
case IK_C:
|
|
|
|
case IK_CXX:
|
|
|
|
case IK_ObjC:
|
|
|
|
case IK_ObjCXX:
|
|
|
|
case IK_OpenCL:
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::MemoryBuffer *Buffer = llvm::MemoryBuffer::getFile(getCurrentFile());
|
|
|
|
if (Buffer) {
|
Introduce basic support for loading a precompiled preamble while
reparsing an ASTUnit. When saving a preamble, create a buffer larger
than the actual file we're working with but fill everything from the
end of the preamble to the end of the file with spaces (so the lexer
will quickly skip them). When we load the file, create a buffer of the
same size, filling it with the file and then spaces. Then, instruct
the lexer to start lexing after the preamble, therefore continuing the
parse from the spot where the preamble left off.
It's now possible to perform a simple preamble build + parse (+
reparse) with ASTUnit. However, one has to disable a bunch of checking
in the PCH reader to do so. That part isn't committed; it will likely
be handled with some other kind of flag (e.g., -fno-validate-pch).
As part of this, fix some issues with null termination of the memory
buffers created for the preamble; we were trying to explicitly
NULL-terminate them, even though they were also getting implicitly
NULL terminated, leading to excess warnings about NULL characters in
source files.
llvm-svn: 109445
2010-07-27 05:36:20 +08:00
|
|
|
unsigned Preamble = Lexer::ComputePreamble(Buffer).first;
|
2010-07-21 04:18:03 +08:00
|
|
|
llvm::outs().write(Buffer->getBufferStart(), Preamble);
|
|
|
|
delete Buffer;
|
|
|
|
}
|
|
|
|
}
|