2009-06-20 16:27:14 +08:00
|
|
|
//===--- ASTUnit.cpp - ASTUnit utility ------------------------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// ASTUnit Implementation.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-06-20 16:08:23 +08:00
|
|
|
#include "clang/Frontend/ASTUnit.h"
|
|
|
|
#include "clang/Frontend/PCHReader.h"
|
|
|
|
#include "clang/AST/ASTContext.h"
|
2009-12-01 17:51:01 +08:00
|
|
|
#include "clang/AST/ASTConsumer.h"
|
2009-06-20 16:08:23 +08:00
|
|
|
#include "clang/AST/DeclVisitor.h"
|
|
|
|
#include "clang/AST/StmtVisitor.h"
|
2009-12-02 11:23:45 +08:00
|
|
|
#include "clang/Driver/Compilation.h"
|
|
|
|
#include "clang/Driver/Driver.h"
|
|
|
|
#include "clang/Driver/Job.h"
|
|
|
|
#include "clang/Driver/Tool.h"
|
2009-12-01 17:51:01 +08:00
|
|
|
#include "clang/Frontend/CompilerInstance.h"
|
|
|
|
#include "clang/Frontend/FrontendActions.h"
|
2009-12-02 11:23:45 +08:00
|
|
|
#include "clang/Frontend/FrontendDiagnostic.h"
|
2009-12-01 17:51:01 +08:00
|
|
|
#include "clang/Frontend/FrontendOptions.h"
|
2009-06-20 16:08:23 +08:00
|
|
|
#include "clang/Lex/HeaderSearch.h"
|
|
|
|
#include "clang/Lex/Preprocessor.h"
|
2009-11-15 14:48:46 +08:00
|
|
|
#include "clang/Basic/TargetOptions.h"
|
2009-06-20 16:08:23 +08:00
|
|
|
#include "clang/Basic/TargetInfo.h"
|
|
|
|
#include "clang/Basic/Diagnostic.h"
|
2010-01-23 08:14:00 +08:00
|
|
|
#include "llvm/Support/MemoryBuffer.h"
|
2009-12-02 11:23:45 +08:00
|
|
|
#include "llvm/System/Host.h"
|
2009-10-18 19:34:14 +08:00
|
|
|
#include "llvm/System/Path.h"
|
2010-07-23 08:33:23 +08:00
|
|
|
#include <cstdlib>
|
2010-07-23 10:15:08 +08:00
|
|
|
#include <cstdio>
|
2009-06-20 16:08:23 +08:00
|
|
|
using namespace clang;
|
|
|
|
|
2010-04-06 05:10:19 +08:00
|
|
|
ASTUnit::ASTUnit(bool _MainFileIsAST)
|
2010-07-20 05:46:24 +08:00
|
|
|
: CaptureDiagnostics(false), MainFileIsAST(_MainFileIsAST),
|
|
|
|
ConcurrencyCheckValue(CheckUnlocked) { }
|
2010-04-06 05:10:19 +08:00
|
|
|
|
2009-12-01 17:51:01 +08:00
|
|
|
ASTUnit::~ASTUnit() {
|
2010-03-06 05:16:25 +08:00
|
|
|
ConcurrencyCheckValue = CheckLocked;
|
2010-07-20 05:46:24 +08:00
|
|
|
CleanTemporaryFiles();
|
2010-07-24 07:58:40 +08:00
|
|
|
if (!PreambleFile.empty())
|
|
|
|
PreambleFile.eraseFromDisk();
|
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
|
|
|
|
|
|
|
// Free the buffers associated with remapped files. We are required to
|
|
|
|
// perform this operation here because we explicitly request that the
|
|
|
|
// compiler instance *not* free these buffers for each invocation of the
|
|
|
|
// parser.
|
|
|
|
if (Invocation.get()) {
|
|
|
|
PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
|
|
|
|
for (PreprocessorOptions::remapped_file_buffer_iterator
|
|
|
|
FB = PPOpts.remapped_file_buffer_begin(),
|
|
|
|
FBEnd = PPOpts.remapped_file_buffer_end();
|
|
|
|
FB != FBEnd;
|
|
|
|
++FB)
|
|
|
|
delete FB->second;
|
|
|
|
}
|
2010-07-20 05:46:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void ASTUnit::CleanTemporaryFiles() {
|
2010-02-19 07:35:40 +08:00
|
|
|
for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
|
|
|
|
TemporaryFiles[I].eraseFromDisk();
|
2010-07-20 05:46:24 +08:00
|
|
|
TemporaryFiles.clear();
|
2009-10-16 06:23:48 +08:00
|
|
|
}
|
2009-06-20 16:08:23 +08:00
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
/// \brief Gathers information from PCHReader that will be used to initialize
|
|
|
|
/// a Preprocessor.
|
2009-11-28 18:07:24 +08:00
|
|
|
class PCHInfoCollector : public PCHReaderListener {
|
2009-06-20 16:08:23 +08:00
|
|
|
LangOptions &LangOpt;
|
|
|
|
HeaderSearch &HSI;
|
|
|
|
std::string &TargetTriple;
|
|
|
|
std::string &Predefines;
|
|
|
|
unsigned &Counter;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-20 16:08:23 +08:00
|
|
|
unsigned NumHeaderInfos;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-20 16:08:23 +08:00
|
|
|
public:
|
|
|
|
PCHInfoCollector(LangOptions &LangOpt, HeaderSearch &HSI,
|
|
|
|
std::string &TargetTriple, std::string &Predefines,
|
|
|
|
unsigned &Counter)
|
|
|
|
: LangOpt(LangOpt), HSI(HSI), TargetTriple(TargetTriple),
|
|
|
|
Predefines(Predefines), Counter(Counter), NumHeaderInfos(0) {}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-20 16:08:23 +08:00
|
|
|
virtual bool ReadLanguageOptions(const LangOptions &LangOpts) {
|
|
|
|
LangOpt = LangOpts;
|
|
|
|
return false;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-11-11 08:52:11 +08:00
|
|
|
virtual bool ReadTargetTriple(llvm::StringRef Triple) {
|
2009-06-20 16:08:23 +08:00
|
|
|
TargetTriple = Triple;
|
|
|
|
return false;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-07-15 07:29:55 +08:00
|
|
|
virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
|
2009-11-11 13:29:04 +08:00
|
|
|
llvm::StringRef OriginalFileName,
|
2009-06-20 16:08:23 +08:00
|
|
|
std::string &SuggestedPredefines) {
|
2010-07-15 07:29:55 +08:00
|
|
|
Predefines = Buffers[0].Data;
|
|
|
|
for (unsigned I = 1, N = Buffers.size(); I != N; ++I) {
|
|
|
|
Predefines += Buffers[I].Data;
|
|
|
|
}
|
2009-06-20 16:08:23 +08:00
|
|
|
return false;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-03-17 03:09:18 +08:00
|
|
|
virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID) {
|
2009-06-20 16:08:23 +08:00
|
|
|
HSI.setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-20 16:08:23 +08:00
|
|
|
virtual void ReadCounter(unsigned Value) {
|
|
|
|
Counter = Value;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2010-02-19 02:08:43 +08:00
|
|
|
class StoredDiagnosticClient : public DiagnosticClient {
|
|
|
|
llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags;
|
|
|
|
|
|
|
|
public:
|
|
|
|
explicit StoredDiagnosticClient(
|
|
|
|
llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags)
|
|
|
|
: StoredDiags(StoredDiags) { }
|
|
|
|
|
|
|
|
virtual void HandleDiagnostic(Diagnostic::Level Level,
|
|
|
|
const DiagnosticInfo &Info);
|
|
|
|
};
|
|
|
|
|
|
|
|
/// \brief RAII object that optionally captures diagnostics, if
|
|
|
|
/// there is no diagnostic client to capture them already.
|
|
|
|
class CaptureDroppedDiagnostics {
|
|
|
|
Diagnostic &Diags;
|
|
|
|
StoredDiagnosticClient Client;
|
|
|
|
DiagnosticClient *PreviousClient;
|
|
|
|
|
|
|
|
public:
|
|
|
|
CaptureDroppedDiagnostics(bool RequestCapture, Diagnostic &Diags,
|
|
|
|
llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags)
|
|
|
|
: Diags(Diags), Client(StoredDiags), PreviousClient(Diags.getClient())
|
|
|
|
{
|
|
|
|
if (RequestCapture || Diags.getClient() == 0)
|
|
|
|
Diags.setClient(&Client);
|
|
|
|
}
|
|
|
|
|
|
|
|
~CaptureDroppedDiagnostics() {
|
|
|
|
Diags.setClient(PreviousClient);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2009-06-20 16:08:23 +08:00
|
|
|
} // anonymous namespace
|
|
|
|
|
2010-02-19 02:08:43 +08:00
|
|
|
void StoredDiagnosticClient::HandleDiagnostic(Diagnostic::Level Level,
|
|
|
|
const DiagnosticInfo &Info) {
|
|
|
|
StoredDiags.push_back(StoredDiagnostic(Level, Info));
|
|
|
|
}
|
|
|
|
|
2009-09-04 02:19:54 +08:00
|
|
|
const std::string &ASTUnit::getOriginalSourceFileName() {
|
2009-12-02 16:44:16 +08:00
|
|
|
return OriginalSourceFile;
|
2009-09-04 02:19:54 +08:00
|
|
|
}
|
2009-06-20 16:08:23 +08:00
|
|
|
|
2009-10-16 06:23:48 +08:00
|
|
|
const std::string &ASTUnit::getPCHFileName() {
|
2009-12-03 05:47:43 +08:00
|
|
|
assert(isMainFileAST() && "Not an ASTUnit from a PCH file!");
|
2010-01-31 00:23:25 +08:00
|
|
|
return static_cast<PCHReader *>(Ctx->getExternalSource())->getFileName();
|
2009-10-16 06:23:48 +08:00
|
|
|
}
|
|
|
|
|
2009-06-20 16:08:23 +08:00
|
|
|
ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
|
2010-04-06 07:52:57 +08:00
|
|
|
llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
|
2009-10-17 08:34:24 +08:00
|
|
|
bool OnlyLocalDecls,
|
2010-01-23 08:14:00 +08:00
|
|
|
RemappedFile *RemappedFiles,
|
2010-02-19 02:08:43 +08:00
|
|
|
unsigned NumRemappedFiles,
|
|
|
|
bool CaptureDiagnostics) {
|
2010-04-06 05:10:19 +08:00
|
|
|
llvm::OwningPtr<ASTUnit> AST(new ASTUnit(true));
|
|
|
|
|
2010-04-06 07:52:57 +08:00
|
|
|
if (!Diags.getPtr()) {
|
2010-04-06 05:10:19 +08:00
|
|
|
// No diagnostics engine was provided, so create our own diagnostics object
|
|
|
|
// with the default options.
|
|
|
|
DiagnosticOptions DiagOpts;
|
2010-04-06 07:52:57 +08:00
|
|
|
Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
|
2010-04-06 05:10:19 +08:00
|
|
|
}
|
2010-07-20 05:46:24 +08:00
|
|
|
|
|
|
|
AST->CaptureDiagnostics = CaptureDiagnostics;
|
2009-10-17 04:01:17 +08:00
|
|
|
AST->OnlyLocalDecls = OnlyLocalDecls;
|
2010-04-06 07:52:57 +08:00
|
|
|
AST->Diagnostics = Diags;
|
2010-04-06 05:10:19 +08:00
|
|
|
AST->FileMgr.reset(new FileManager);
|
|
|
|
AST->SourceMgr.reset(new SourceManager(AST->getDiagnostics()));
|
2009-10-19 22:34:22 +08:00
|
|
|
AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager()));
|
2009-06-20 16:08:23 +08:00
|
|
|
|
2010-02-19 02:08:43 +08:00
|
|
|
// If requested, capture diagnostics in the ASTUnit.
|
2010-04-06 05:10:19 +08:00
|
|
|
CaptureDroppedDiagnostics Capture(CaptureDiagnostics, AST->getDiagnostics(),
|
2010-04-06 02:10:21 +08:00
|
|
|
AST->StoredDiagnostics);
|
2010-02-19 02:08:43 +08:00
|
|
|
|
2010-01-23 08:14:00 +08:00
|
|
|
for (unsigned I = 0; I != NumRemappedFiles; ++I) {
|
|
|
|
// Create the file entry for the file that we're mapping from.
|
|
|
|
const FileEntry *FromFile
|
|
|
|
= AST->getFileManager().getVirtualFile(RemappedFiles[I].first,
|
|
|
|
RemappedFiles[I].second->getBufferSize(),
|
|
|
|
0);
|
|
|
|
if (!FromFile) {
|
2010-04-06 05:10:19 +08:00
|
|
|
AST->getDiagnostics().Report(diag::err_fe_remap_missing_from_file)
|
2010-01-23 08:14:00 +08:00
|
|
|
<< RemappedFiles[I].first;
|
2010-02-27 09:32:48 +08:00
|
|
|
delete RemappedFiles[I].second;
|
2010-01-23 08:14:00 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Override the contents of the "from" file with the contents of
|
|
|
|
// the "to" file.
|
|
|
|
AST->getSourceManager().overrideFileContents(FromFile,
|
|
|
|
RemappedFiles[I].second);
|
|
|
|
}
|
|
|
|
|
2009-06-20 16:08:23 +08:00
|
|
|
// Gather Info for preprocessor construction later on.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-20 16:08:23 +08:00
|
|
|
LangOptions LangInfo;
|
|
|
|
HeaderSearch &HeaderInfo = *AST->HeaderInfo.get();
|
|
|
|
std::string TargetTriple;
|
|
|
|
std::string Predefines;
|
|
|
|
unsigned Counter;
|
|
|
|
|
2009-09-03 13:59:50 +08:00
|
|
|
llvm::OwningPtr<PCHReader> Reader;
|
2009-06-20 16:08:23 +08:00
|
|
|
llvm::OwningPtr<ExternalASTSource> Source;
|
|
|
|
|
2009-10-20 05:44:57 +08:00
|
|
|
Reader.reset(new PCHReader(AST->getSourceManager(), AST->getFileManager(),
|
2010-04-06 05:10:19 +08:00
|
|
|
AST->getDiagnostics()));
|
2009-09-03 13:59:35 +08:00
|
|
|
Reader->setListener(new PCHInfoCollector(LangInfo, HeaderInfo, TargetTriple,
|
|
|
|
Predefines, Counter));
|
|
|
|
|
|
|
|
switch (Reader->ReadPCH(Filename)) {
|
2009-06-20 16:08:23 +08:00
|
|
|
case PCHReader::Success:
|
|
|
|
break;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-20 16:08:23 +08:00
|
|
|
case PCHReader::Failure:
|
2009-06-26 02:22:30 +08:00
|
|
|
case PCHReader::IgnorePCH:
|
2010-04-06 05:10:19 +08:00
|
|
|
AST->getDiagnostics().Report(diag::err_fe_unable_to_load_pch);
|
2009-06-20 16:08:23 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-12-02 16:44:16 +08:00
|
|
|
AST->OriginalSourceFile = Reader->getOriginalSourceFile();
|
|
|
|
|
2009-06-20 16:08:23 +08:00
|
|
|
// PCH loaded successfully. Now create the preprocessor.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-20 16:08:23 +08:00
|
|
|
// Get information about the target being compiled for.
|
2009-11-15 14:48:46 +08:00
|
|
|
//
|
|
|
|
// FIXME: This is broken, we should store the TargetOptions in the PCH.
|
|
|
|
TargetOptions TargetOpts;
|
|
|
|
TargetOpts.ABI = "";
|
2010-06-11 09:06:47 +08:00
|
|
|
TargetOpts.CXXABI = "itanium";
|
2009-11-15 14:48:46 +08:00
|
|
|
TargetOpts.CPU = "";
|
|
|
|
TargetOpts.Features.clear();
|
|
|
|
TargetOpts.Triple = TargetTriple;
|
2010-04-06 05:10:19 +08:00
|
|
|
AST->Target.reset(TargetInfo::CreateTargetInfo(AST->getDiagnostics(),
|
|
|
|
TargetOpts));
|
|
|
|
AST->PP.reset(new Preprocessor(AST->getDiagnostics(), LangInfo,
|
|
|
|
*AST->Target.get(),
|
2009-09-21 11:03:39 +08:00
|
|
|
AST->getSourceManager(), HeaderInfo));
|
2009-06-20 16:08:23 +08:00
|
|
|
Preprocessor &PP = *AST->PP.get();
|
|
|
|
|
2009-09-21 11:03:47 +08:00
|
|
|
PP.setPredefines(Reader->getSuggestedPredefines());
|
2009-06-20 16:08:23 +08:00
|
|
|
PP.setCounterValue(Counter);
|
2009-09-03 13:59:35 +08:00
|
|
|
Reader->setPreprocessor(PP);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-20 16:08:23 +08:00
|
|
|
// Create and initialize the ASTContext.
|
|
|
|
|
|
|
|
AST->Ctx.reset(new ASTContext(LangInfo,
|
2009-09-21 11:03:39 +08:00
|
|
|
AST->getSourceManager(),
|
2009-06-20 16:08:23 +08:00
|
|
|
*AST->Target.get(),
|
|
|
|
PP.getIdentifierTable(),
|
|
|
|
PP.getSelectorTable(),
|
|
|
|
PP.getBuiltinInfo(),
|
|
|
|
/* size_reserve = */0));
|
|
|
|
ASTContext &Context = *AST->Ctx.get();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-03 13:59:35 +08:00
|
|
|
Reader->InitializeContext(Context);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-20 16:08:23 +08:00
|
|
|
// Attach the PCH reader to the AST context as an external AST
|
|
|
|
// source, so that declarations will be deserialized from the
|
|
|
|
// PCH file as needed.
|
2009-09-03 13:59:35 +08:00
|
|
|
Source.reset(Reader.take());
|
2009-06-20 16:08:23 +08:00
|
|
|
Context.setExternalSource(Source);
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
return AST.take();
|
2009-06-20 16:08:23 +08:00
|
|
|
}
|
2009-12-01 17:51:01 +08:00
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
2009-12-04 16:17:33 +08:00
|
|
|
class TopLevelDeclTrackerConsumer : public ASTConsumer {
|
|
|
|
ASTUnit &Unit;
|
|
|
|
|
|
|
|
public:
|
|
|
|
TopLevelDeclTrackerConsumer(ASTUnit &_Unit) : Unit(_Unit) {}
|
|
|
|
|
|
|
|
void HandleTopLevelDecl(DeclGroupRef D) {
|
2010-05-04 04:16:35 +08:00
|
|
|
for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it) {
|
|
|
|
Decl *D = *it;
|
|
|
|
// FIXME: Currently ObjC method declarations are incorrectly being
|
|
|
|
// reported as top-level declarations, even though their DeclContext
|
|
|
|
// is the containing ObjC @interface/@implementation. This is a
|
|
|
|
// fundamental problem in the parser right now.
|
|
|
|
if (isa<ObjCMethodDecl>(D))
|
|
|
|
continue;
|
|
|
|
Unit.getTopLevelDecls().push_back(D);
|
|
|
|
}
|
2009-12-04 16:17:33 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class TopLevelDeclTrackerAction : public ASTFrontendAction {
|
|
|
|
public:
|
|
|
|
ASTUnit &Unit;
|
|
|
|
|
2009-12-01 17:51:01 +08:00
|
|
|
virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
|
|
|
|
llvm::StringRef InFile) {
|
2009-12-04 16:17:33 +08:00
|
|
|
return new TopLevelDeclTrackerConsumer(Unit);
|
2009-12-01 17:51:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
2009-12-04 16:17:33 +08:00
|
|
|
TopLevelDeclTrackerAction(ASTUnit &_Unit) : Unit(_Unit) {}
|
|
|
|
|
2009-12-01 17:51:01 +08:00
|
|
|
virtual bool hasCodeCompletionSupport() const { return false; }
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2010-07-20 05:46:24 +08:00
|
|
|
/// Parse the source file into a translation unit using the given compiler
|
|
|
|
/// invocation, replacing the current translation unit.
|
|
|
|
///
|
|
|
|
/// \returns True if a failure occurred that causes the ASTUnit not to
|
|
|
|
/// contain any translation-unit information, false otherwise.
|
2010-07-24 08:38:13 +08:00
|
|
|
bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
|
2010-07-20 05:46:24 +08:00
|
|
|
if (!Invocation.get())
|
|
|
|
return true;
|
|
|
|
|
2009-12-01 17:51:01 +08:00
|
|
|
// Create the compiler instance to use for building the AST.
|
2009-12-02 16:43:56 +08:00
|
|
|
CompilerInstance Clang;
|
2010-07-20 05:46:24 +08:00
|
|
|
Clang.setInvocation(Invocation.take());
|
|
|
|
OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second;
|
|
|
|
|
|
|
|
// Set up diagnostics.
|
|
|
|
Clang.setDiagnostics(&getDiagnostics());
|
|
|
|
Clang.setDiagnosticClient(getDiagnostics().getClient());
|
2010-04-06 05:10:19 +08:00
|
|
|
|
2009-12-01 17:51:01 +08:00
|
|
|
// Create the target instance.
|
|
|
|
Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
|
|
|
|
Clang.getTargetOpts()));
|
2010-02-19 02:08:43 +08:00
|
|
|
if (!Clang.hasTarget()) {
|
|
|
|
Clang.takeDiagnosticClient();
|
2010-07-20 05:46:24 +08:00
|
|
|
return true;
|
2010-02-19 02:08:43 +08:00
|
|
|
}
|
2010-07-20 05:46:24 +08:00
|
|
|
|
2009-12-01 17:51:01 +08:00
|
|
|
// Inform the target of the language options.
|
|
|
|
//
|
|
|
|
// FIXME: We shouldn't need to do this, the target should be immutable once
|
|
|
|
// created. This complexity should be lifted elsewhere.
|
|
|
|
Clang.getTarget().setForcedLangOptions(Clang.getLangOpts());
|
2010-07-20 05:46:24 +08:00
|
|
|
|
2009-12-01 17:51:01 +08:00
|
|
|
assert(Clang.getFrontendOpts().Inputs.size() == 1 &&
|
|
|
|
"Invocation must have exactly one source file!");
|
2010-06-08 07:22:09 +08:00
|
|
|
assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST &&
|
2009-12-01 17:51:01 +08:00
|
|
|
"FIXME: AST inputs not yet supported here!");
|
2010-06-08 07:26:47 +08:00
|
|
|
assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
|
|
|
|
"IR inputs not support here!");
|
2009-12-01 17:51:01 +08:00
|
|
|
|
2010-07-20 05:46:24 +08:00
|
|
|
// Configure the various subsystems.
|
|
|
|
// FIXME: Should we retain the previous file manager?
|
|
|
|
FileMgr.reset(new FileManager);
|
|
|
|
SourceMgr.reset(new SourceManager(getDiagnostics()));
|
|
|
|
Ctx.reset();
|
|
|
|
PP.reset();
|
|
|
|
|
|
|
|
// Clear out old caches and data.
|
|
|
|
TopLevelDecls.clear();
|
|
|
|
StoredDiagnostics.clear();
|
|
|
|
CleanTemporaryFiles();
|
|
|
|
PreprocessedEntitiesByFile.clear();
|
|
|
|
|
2010-02-19 02:08:43 +08:00
|
|
|
// Capture any diagnostics that would otherwise be dropped.
|
|
|
|
CaptureDroppedDiagnostics Capture(CaptureDiagnostics,
|
|
|
|
Clang.getDiagnostics(),
|
2010-07-20 05:46:24 +08:00
|
|
|
StoredDiagnostics);
|
|
|
|
|
2009-12-01 17:51:01 +08:00
|
|
|
// Create a file manager object to provide access to and cache the filesystem.
|
2010-07-20 05:46:24 +08:00
|
|
|
Clang.setFileManager(&getFileManager());
|
|
|
|
|
2009-12-01 17:51:01 +08:00
|
|
|
// Create the source manager.
|
2010-07-20 05:46:24 +08:00
|
|
|
Clang.setSourceManager(&getSourceManager());
|
|
|
|
|
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
|
|
|
// If the main file has been overridden due to the use of a preamble,
|
|
|
|
// make that override happen and introduce the preamble.
|
|
|
|
PreprocessorOptions &PreprocessorOpts = Clang.getPreprocessorOpts();
|
|
|
|
if (OverrideMainBuffer) {
|
|
|
|
PreprocessorOpts.addRemappedFile(OriginalSourceFile, OverrideMainBuffer);
|
|
|
|
PreprocessorOpts.PrecompiledPreambleBytes.first = Preamble.size();
|
|
|
|
PreprocessorOpts.PrecompiledPreambleBytes.second
|
|
|
|
= PreambleEndsAtStartOfLine;
|
|
|
|
PreprocessorOpts.ImplicitPCHInclude = PreambleFile.str();
|
2010-07-27 08:27:13 +08:00
|
|
|
PreprocessorOpts.DisablePCHValidation = true;
|
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
|
|
|
}
|
|
|
|
|
2010-07-20 05:46:24 +08:00
|
|
|
llvm::OwningPtr<TopLevelDeclTrackerAction> Act;
|
|
|
|
Act.reset(new TopLevelDeclTrackerAction(*this));
|
2009-12-04 16:17:33 +08:00
|
|
|
if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
|
2010-06-08 07:23:06 +08:00
|
|
|
Clang.getFrontendOpts().Inputs[0].first))
|
2009-12-01 17:51:01 +08:00
|
|
|
goto error;
|
2010-07-20 05:46:24 +08:00
|
|
|
|
2009-12-04 16:17:33 +08:00
|
|
|
Act->Execute();
|
2010-07-20 05:46:24 +08:00
|
|
|
|
2009-12-02 05:57:33 +08:00
|
|
|
// Steal the created target, context, and preprocessor, and take back the
|
|
|
|
// source and file managers.
|
2010-07-20 05:46:24 +08:00
|
|
|
Ctx.reset(Clang.takeASTContext());
|
|
|
|
PP.reset(Clang.takePreprocessor());
|
2009-12-01 17:51:01 +08:00
|
|
|
Clang.takeSourceManager();
|
|
|
|
Clang.takeFileManager();
|
2010-07-20 05:46:24 +08:00
|
|
|
Target.reset(Clang.takeTarget());
|
|
|
|
|
2009-12-04 16:17:33 +08:00
|
|
|
Act->EndSourceFile();
|
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
|
|
|
|
|
|
|
// Remove the overridden buffer we used for the preamble.
|
2010-07-27 08:27:13 +08:00
|
|
|
if (OverrideMainBuffer) {
|
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
|
|
|
PreprocessorOpts.eraseRemappedFile(
|
|
|
|
PreprocessorOpts.remapped_file_buffer_end() - 1);
|
2010-07-27 08:27:13 +08:00
|
|
|
PreprocessorOpts.DisablePCHValidation = true;
|
|
|
|
}
|
2010-07-20 05:46:24 +08:00
|
|
|
|
2009-12-01 17:51:01 +08:00
|
|
|
Clang.takeDiagnosticClient();
|
2010-07-20 05:46:24 +08:00
|
|
|
|
|
|
|
Invocation.reset(Clang.takeInvocation());
|
|
|
|
return false;
|
|
|
|
|
2009-12-01 17:51:01 +08:00
|
|
|
error:
|
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
|
|
|
// Remove the overridden buffer we used for the preamble.
|
2010-07-27 08:27:13 +08:00
|
|
|
if (OverrideMainBuffer) {
|
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
|
|
|
PreprocessorOpts.eraseRemappedFile(
|
|
|
|
PreprocessorOpts.remapped_file_buffer_end() - 1);
|
2010-07-27 08:27:13 +08:00
|
|
|
PreprocessorOpts.DisablePCHValidation = true;
|
|
|
|
}
|
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
|
|
|
|
2009-12-01 17:51:01 +08:00
|
|
|
Clang.takeSourceManager();
|
|
|
|
Clang.takeFileManager();
|
|
|
|
Clang.takeDiagnosticClient();
|
2010-07-20 05:46:24 +08:00
|
|
|
Invocation.reset(Clang.takeInvocation());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-07-23 08:33:23 +08:00
|
|
|
/// \brief Simple function to retrieve a path for a preamble precompiled header.
|
|
|
|
static std::string GetPreamblePCHPath() {
|
|
|
|
// FIXME: This is lame; sys::Path should provide this function (in particular,
|
|
|
|
// it should know how to find the temporary files dir).
|
|
|
|
// FIXME: This is really lame. I copied this code from the Driver!
|
|
|
|
std::string Error;
|
|
|
|
const char *TmpDir = ::getenv("TMPDIR");
|
|
|
|
if (!TmpDir)
|
|
|
|
TmpDir = ::getenv("TEMP");
|
|
|
|
if (!TmpDir)
|
|
|
|
TmpDir = ::getenv("TMP");
|
|
|
|
if (!TmpDir)
|
|
|
|
TmpDir = "/tmp";
|
|
|
|
llvm::sys::Path P(TmpDir);
|
|
|
|
P.appendComponent("preamble");
|
|
|
|
if (P.createTemporaryFileOnDisk())
|
|
|
|
return std::string();
|
|
|
|
|
|
|
|
P.appendSuffix("pch");
|
|
|
|
return P.str();
|
|
|
|
}
|
|
|
|
|
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
|
|
|
/// \brief Compute the preamble for the main file, providing the source buffer
|
|
|
|
/// that corresponds to the main file along with a pair (bytes, start-of-line)
|
|
|
|
/// that describes the preamble.
|
|
|
|
std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> >
|
2010-07-24 07:58:40 +08:00
|
|
|
ASTUnit::ComputePreamble(CompilerInvocation &Invocation, bool &CreatedBuffer) {
|
|
|
|
FrontendOptions &FrontendOpts = Invocation.getFrontendOpts();
|
2010-07-23 08:33:23 +08:00
|
|
|
PreprocessorOptions &PreprocessorOpts
|
2010-07-24 07:58:40 +08:00
|
|
|
= Invocation.getPreprocessorOpts();
|
|
|
|
CreatedBuffer = false;
|
|
|
|
|
2010-07-23 08:33:23 +08:00
|
|
|
// Try to determine if the main file has been remapped, either from the
|
|
|
|
// command line (to another file) or directly through the compiler invocation
|
|
|
|
// (to a memory buffer).
|
2010-07-24 07:58:40 +08:00
|
|
|
llvm::MemoryBuffer *Buffer = 0;
|
2010-07-23 08:33:23 +08:00
|
|
|
llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].second);
|
|
|
|
if (const llvm::sys::FileStatus *MainFileStatus = MainFilePath.getFileStatus()) {
|
|
|
|
// Check whether there is a file-file remapping of the main file
|
|
|
|
for (PreprocessorOptions::remapped_file_iterator
|
2010-07-24 07:58:40 +08:00
|
|
|
M = PreprocessorOpts.remapped_file_begin(),
|
|
|
|
E = PreprocessorOpts.remapped_file_end();
|
2010-07-23 08:33:23 +08:00
|
|
|
M != E;
|
|
|
|
++M) {
|
|
|
|
llvm::sys::PathWithStatus MPath(M->first);
|
|
|
|
if (const llvm::sys::FileStatus *MStatus = MPath.getFileStatus()) {
|
|
|
|
if (MainFileStatus->uniqueID == MStatus->uniqueID) {
|
|
|
|
// We found a remapping. Try to load the resulting, remapped source.
|
2010-07-24 07:58:40 +08:00
|
|
|
if (CreatedBuffer) {
|
2010-07-23 08:33:23 +08:00
|
|
|
delete Buffer;
|
2010-07-24 07:58:40 +08:00
|
|
|
CreatedBuffer = false;
|
|
|
|
}
|
|
|
|
|
2010-07-23 08:33:23 +08:00
|
|
|
Buffer = llvm::MemoryBuffer::getFile(M->second);
|
|
|
|
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
|
|
|
return std::make_pair((llvm::MemoryBuffer*)0,
|
|
|
|
std::make_pair(0, true));
|
2010-07-24 07:58:40 +08:00
|
|
|
CreatedBuffer = true;
|
2010-07-23 08:33:23 +08:00
|
|
|
|
2010-07-24 07:58:40 +08:00
|
|
|
// Remove this remapping. We've captured the buffer already.
|
2010-07-23 08:33:23 +08:00
|
|
|
M = PreprocessorOpts.eraseRemappedFile(M);
|
|
|
|
E = PreprocessorOpts.remapped_file_end();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check whether there is a file-buffer remapping. It supercedes the
|
|
|
|
// file-file remapping.
|
|
|
|
for (PreprocessorOptions::remapped_file_buffer_iterator
|
|
|
|
M = PreprocessorOpts.remapped_file_buffer_begin(),
|
|
|
|
E = PreprocessorOpts.remapped_file_buffer_end();
|
|
|
|
M != E;
|
|
|
|
++M) {
|
|
|
|
llvm::sys::PathWithStatus MPath(M->first);
|
|
|
|
if (const llvm::sys::FileStatus *MStatus = MPath.getFileStatus()) {
|
|
|
|
if (MainFileStatus->uniqueID == MStatus->uniqueID) {
|
|
|
|
// We found a remapping.
|
2010-07-24 07:58:40 +08:00
|
|
|
if (CreatedBuffer) {
|
2010-07-23 08:33:23 +08:00
|
|
|
delete Buffer;
|
2010-07-24 07:58:40 +08:00
|
|
|
CreatedBuffer = false;
|
|
|
|
}
|
2010-07-23 08:33:23 +08:00
|
|
|
|
2010-07-24 07:58:40 +08:00
|
|
|
Buffer = const_cast<llvm::MemoryBuffer *>(M->second);
|
|
|
|
|
|
|
|
// Remove this remapping. We've captured the buffer already.
|
2010-07-23 08:33:23 +08:00
|
|
|
M = PreprocessorOpts.eraseRemappedFile(M);
|
|
|
|
E = PreprocessorOpts.remapped_file_buffer_end();
|
|
|
|
}
|
|
|
|
}
|
2010-07-24 07:58:40 +08:00
|
|
|
}
|
2010-07-23 08:33:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// If the main source file was not remapped, load it now.
|
|
|
|
if (!Buffer) {
|
|
|
|
Buffer = llvm::MemoryBuffer::getFile(FrontendOpts.Inputs[0].second);
|
|
|
|
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
|
|
|
return std::make_pair((llvm::MemoryBuffer*)0, std::make_pair(0, true));
|
2010-07-24 07:58:40 +08:00
|
|
|
|
|
|
|
CreatedBuffer = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return std::make_pair(Buffer, Lexer::ComputePreamble(Buffer));
|
|
|
|
}
|
|
|
|
|
2010-07-24 08:38:13 +08:00
|
|
|
static llvm::MemoryBuffer *CreatePaddedMainFileBuffer(llvm::MemoryBuffer *Old,
|
|
|
|
bool DeleteOld,
|
|
|
|
unsigned NewSize,
|
|
|
|
llvm::StringRef NewName) {
|
|
|
|
llvm::MemoryBuffer *Result
|
|
|
|
= llvm::MemoryBuffer::getNewUninitMemBuffer(NewSize, NewName);
|
|
|
|
memcpy(const_cast<char*>(Result->getBufferStart()),
|
|
|
|
Old->getBufferStart(), Old->getBufferSize());
|
|
|
|
memset(const_cast<char*>(Result->getBufferStart()) + Old->getBufferSize(),
|
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
|
|
|
' ', NewSize - Old->getBufferSize() - 1);
|
|
|
|
const_cast<char*>(Result->getBufferEnd())[-1] = '\n';
|
2010-07-24 08:38:13 +08:00
|
|
|
|
|
|
|
if (DeleteOld)
|
|
|
|
delete Old;
|
|
|
|
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2010-07-24 07:58:40 +08:00
|
|
|
/// \brief Attempt to build or re-use a precompiled preamble when (re-)parsing
|
|
|
|
/// the source file.
|
|
|
|
///
|
|
|
|
/// This routine will compute the preamble of the main source file. If a
|
|
|
|
/// non-trivial preamble is found, it will precompile that preamble into a
|
|
|
|
/// precompiled header so that the precompiled preamble can be used to reduce
|
|
|
|
/// reparsing time. If a precompiled preamble has already been constructed,
|
|
|
|
/// this routine will determine if it is still valid and, if so, avoid
|
|
|
|
/// rebuilding the precompiled preamble.
|
|
|
|
///
|
2010-07-24 08:38:13 +08:00
|
|
|
/// \returns If the precompiled preamble can be used, returns a newly-allocated
|
|
|
|
/// buffer that should be used in place of the main file when doing so.
|
|
|
|
/// Otherwise, returns a NULL pointer.
|
|
|
|
llvm::MemoryBuffer *ASTUnit::BuildPrecompiledPreamble() {
|
2010-07-24 07:58:40 +08:00
|
|
|
CompilerInvocation PreambleInvocation(*Invocation);
|
|
|
|
FrontendOptions &FrontendOpts = PreambleInvocation.getFrontendOpts();
|
|
|
|
PreprocessorOptions &PreprocessorOpts
|
|
|
|
= PreambleInvocation.getPreprocessorOpts();
|
|
|
|
|
|
|
|
bool CreatedPreambleBuffer = false;
|
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
|
|
|
std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> > NewPreamble
|
2010-07-24 07:58:40 +08:00
|
|
|
= ComputePreamble(PreambleInvocation, CreatedPreambleBuffer);
|
|
|
|
|
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
|
|
|
if (!NewPreamble.second.first) {
|
2010-07-24 07:58:40 +08:00
|
|
|
// We couldn't find a preamble in the main source. Clear out the current
|
|
|
|
// preamble, if we have one. It's obviously no good any more.
|
|
|
|
Preamble.clear();
|
|
|
|
if (!PreambleFile.empty()) {
|
|
|
|
PreambleFile.eraseFromDisk();
|
|
|
|
PreambleFile.clear();
|
|
|
|
}
|
|
|
|
if (CreatedPreambleBuffer)
|
|
|
|
delete NewPreamble.first;
|
|
|
|
|
2010-07-24 08:38:13 +08:00
|
|
|
return 0;
|
2010-07-23 08:33:23 +08:00
|
|
|
}
|
|
|
|
|
2010-07-24 07:58:40 +08:00
|
|
|
if (!Preamble.empty()) {
|
|
|
|
// We've previously computed a preamble. Check whether we have the same
|
|
|
|
// preamble now that we did before, and that there's enough space in
|
|
|
|
// the main-file buffer within the precompiled preamble to fit the
|
|
|
|
// new main file.
|
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
|
|
|
if (Preamble.size() == NewPreamble.second.first &&
|
|
|
|
PreambleEndsAtStartOfLine == NewPreamble.second.second &&
|
2010-07-24 08:42:07 +08:00
|
|
|
NewPreamble.first->getBufferSize() < PreambleReservedSize-2 &&
|
2010-07-24 07:58:40 +08:00
|
|
|
memcmp(&Preamble[0], NewPreamble.first->getBufferStart(),
|
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
|
|
|
NewPreamble.second.first) == 0) {
|
2010-07-24 07:58:40 +08:00
|
|
|
// The preamble has not changed. We may be able to re-use the precompiled
|
|
|
|
// preamble.
|
|
|
|
// FIXME: Check that none of the files used by the preamble have changed.
|
|
|
|
|
2010-07-24 08:38:13 +08:00
|
|
|
|
2010-07-24 07:58:40 +08:00
|
|
|
// Okay! Re-use the precompiled preamble.
|
2010-07-24 08:38:13 +08:00
|
|
|
return CreatePaddedMainFileBuffer(NewPreamble.first,
|
|
|
|
CreatedPreambleBuffer,
|
|
|
|
PreambleReservedSize,
|
|
|
|
FrontendOpts.Inputs[0].second);
|
2010-07-24 07:58:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// We can't reuse the previously-computed preamble. Build a new one.
|
|
|
|
Preamble.clear();
|
|
|
|
PreambleFile.eraseFromDisk();
|
|
|
|
}
|
|
|
|
|
|
|
|
// We did not previously compute a preamble, or it can't be reused anyway.
|
2010-07-23 08:33:23 +08:00
|
|
|
|
|
|
|
// Create a new buffer that stores the preamble. The buffer also contains
|
|
|
|
// extra space for the original contents of the file (which will be present
|
|
|
|
// when we actually parse the file) along with more room in case the file
|
2010-07-24 07:58:40 +08:00
|
|
|
// grows.
|
|
|
|
PreambleReservedSize = NewPreamble.first->getBufferSize();
|
|
|
|
if (PreambleReservedSize < 4096)
|
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
|
|
|
PreambleReservedSize = 8191;
|
2010-07-23 08:33:23 +08:00
|
|
|
else
|
2010-07-24 07:58:40 +08:00
|
|
|
PreambleReservedSize *= 2;
|
|
|
|
|
2010-07-23 08:33:23 +08:00
|
|
|
llvm::MemoryBuffer *PreambleBuffer
|
2010-07-24 07:58:40 +08:00
|
|
|
= llvm::MemoryBuffer::getNewUninitMemBuffer(PreambleReservedSize,
|
2010-07-23 08:33:23 +08:00
|
|
|
FrontendOpts.Inputs[0].second);
|
|
|
|
memcpy(const_cast<char*>(PreambleBuffer->getBufferStart()),
|
2010-07-24 07:58:40 +08:00
|
|
|
NewPreamble.first->getBufferStart(), Preamble.size());
|
|
|
|
memset(const_cast<char*>(PreambleBuffer->getBufferStart()) + Preamble.size(),
|
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
|
|
|
' ', PreambleReservedSize - Preamble.size() - 1);
|
|
|
|
const_cast<char*>(PreambleBuffer->getBufferEnd())[-1] = '\n';
|
2010-07-24 08:42:07 +08:00
|
|
|
|
2010-07-24 07:58:40 +08:00
|
|
|
// Save the preamble text for later; we'll need to compare against it for
|
|
|
|
// subsequent reparses.
|
|
|
|
Preamble.assign(NewPreamble.first->getBufferStart(),
|
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
|
|
|
NewPreamble.first->getBufferStart()
|
|
|
|
+ NewPreamble.second.first);
|
|
|
|
PreambleEndsAtStartOfLine = NewPreamble.second.second;
|
2010-07-23 08:33:23 +08:00
|
|
|
|
|
|
|
// Remap the main source file to the preamble buffer.
|
2010-07-24 07:58:40 +08:00
|
|
|
llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].second);
|
2010-07-23 08:33:23 +08:00
|
|
|
PreprocessorOpts.addRemappedFile(MainFilePath.str(), PreambleBuffer);
|
|
|
|
|
|
|
|
// Tell the compiler invocation to generate a temporary precompiled header.
|
|
|
|
FrontendOpts.ProgramAction = frontend::GeneratePCH;
|
|
|
|
// FIXME: Set ChainedPCH, once it is ready.
|
|
|
|
// FIXME: Generate the precompiled header into memory?
|
2010-07-24 07:58:40 +08:00
|
|
|
if (PreambleFile.isEmpty())
|
|
|
|
FrontendOpts.OutputFile = GetPreamblePCHPath();
|
|
|
|
else
|
|
|
|
FrontendOpts.OutputFile = PreambleFile.str();
|
2010-07-23 08:33:23 +08:00
|
|
|
|
|
|
|
// Create the compiler instance to use for building the precompiled preamble.
|
|
|
|
CompilerInstance Clang;
|
|
|
|
Clang.setInvocation(&PreambleInvocation);
|
|
|
|
OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second;
|
|
|
|
|
|
|
|
// Set up diagnostics.
|
|
|
|
Clang.setDiagnostics(&getDiagnostics());
|
|
|
|
Clang.setDiagnosticClient(getDiagnostics().getClient());
|
|
|
|
|
|
|
|
// Create the target instance.
|
|
|
|
Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
|
|
|
|
Clang.getTargetOpts()));
|
|
|
|
if (!Clang.hasTarget()) {
|
|
|
|
Clang.takeDiagnosticClient();
|
2010-07-24 07:58:40 +08:00
|
|
|
llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
|
|
|
|
Preamble.clear();
|
|
|
|
if (CreatedPreambleBuffer)
|
|
|
|
delete NewPreamble.first;
|
|
|
|
|
2010-07-24 08:38:13 +08:00
|
|
|
return 0;
|
2010-07-23 08:33:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Inform the target of the language options.
|
|
|
|
//
|
|
|
|
// FIXME: We shouldn't need to do this, the target should be immutable once
|
|
|
|
// created. This complexity should be lifted elsewhere.
|
|
|
|
Clang.getTarget().setForcedLangOptions(Clang.getLangOpts());
|
|
|
|
|
|
|
|
assert(Clang.getFrontendOpts().Inputs.size() == 1 &&
|
|
|
|
"Invocation must have exactly one source file!");
|
|
|
|
assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST &&
|
|
|
|
"FIXME: AST inputs not yet supported here!");
|
|
|
|
assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
|
|
|
|
"IR inputs not support here!");
|
|
|
|
|
|
|
|
// Clear out old caches and data.
|
|
|
|
StoredDiagnostics.clear();
|
|
|
|
|
|
|
|
// Capture any diagnostics that would otherwise be dropped.
|
|
|
|
CaptureDroppedDiagnostics Capture(CaptureDiagnostics,
|
|
|
|
Clang.getDiagnostics(),
|
|
|
|
StoredDiagnostics);
|
|
|
|
|
|
|
|
// Create a file manager object to provide access to and cache the filesystem.
|
|
|
|
Clang.setFileManager(new FileManager);
|
|
|
|
|
|
|
|
// Create the source manager.
|
|
|
|
Clang.setSourceManager(new SourceManager(getDiagnostics()));
|
|
|
|
|
|
|
|
// FIXME: Eventually, we'll have to track top-level declarations here, too.
|
|
|
|
llvm::OwningPtr<GeneratePCHAction> Act;
|
|
|
|
Act.reset(new GeneratePCHAction);
|
|
|
|
if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
|
|
|
|
Clang.getFrontendOpts().Inputs[0].first)) {
|
|
|
|
Clang.takeDiagnosticClient();
|
|
|
|
Clang.takeInvocation();
|
2010-07-24 07:58:40 +08:00
|
|
|
llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
|
|
|
|
Preamble.clear();
|
|
|
|
if (CreatedPreambleBuffer)
|
|
|
|
delete NewPreamble.first;
|
|
|
|
|
2010-07-24 08:38:13 +08:00
|
|
|
return 0;
|
2010-07-23 08:33:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Act->Execute();
|
|
|
|
Act->EndSourceFile();
|
|
|
|
Clang.takeDiagnosticClient();
|
|
|
|
Clang.takeInvocation();
|
|
|
|
|
2010-07-24 07:58:40 +08:00
|
|
|
if (Diagnostics->getNumErrors() > 0) {
|
|
|
|
// There were errors parsing the preamble, so no precompiled header was
|
|
|
|
// generated. Forget that we even tried.
|
|
|
|
// FIXME: Should we leave a note for ourselves to try again?
|
|
|
|
llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
|
|
|
|
Preamble.clear();
|
|
|
|
if (CreatedPreambleBuffer)
|
|
|
|
delete NewPreamble.first;
|
|
|
|
|
2010-07-24 08:38:13 +08:00
|
|
|
return 0;
|
2010-07-24 07:58:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Keep track of the preamble we precompiled.
|
|
|
|
PreambleFile = FrontendOpts.OutputFile;
|
2010-07-23 08:33:23 +08:00
|
|
|
fprintf(stderr, "Preamble PCH: %s\n", FrontendOpts.OutputFile.c_str());
|
2010-07-24 08:38:13 +08:00
|
|
|
return CreatePaddedMainFileBuffer(NewPreamble.first,
|
|
|
|
CreatedPreambleBuffer,
|
|
|
|
PreambleReservedSize,
|
|
|
|
FrontendOpts.Inputs[0].second);
|
2010-07-23 08:33:23 +08:00
|
|
|
}
|
2010-07-20 05:46:24 +08:00
|
|
|
|
|
|
|
ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
|
|
|
|
llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
|
|
|
|
bool OnlyLocalDecls,
|
2010-07-23 08:33:23 +08:00
|
|
|
bool CaptureDiagnostics,
|
|
|
|
bool PrecompilePreamble) {
|
2010-07-20 05:46:24 +08:00
|
|
|
if (!Diags.getPtr()) {
|
|
|
|
// No diagnostics engine was provided, so create our own diagnostics object
|
|
|
|
// with the default options.
|
|
|
|
DiagnosticOptions DiagOpts;
|
|
|
|
Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create the AST unit.
|
|
|
|
llvm::OwningPtr<ASTUnit> AST;
|
|
|
|
AST.reset(new ASTUnit(false));
|
|
|
|
AST->Diagnostics = Diags;
|
|
|
|
AST->CaptureDiagnostics = CaptureDiagnostics;
|
|
|
|
AST->OnlyLocalDecls = OnlyLocalDecls;
|
|
|
|
AST->Invocation.reset(CI);
|
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
|
|
|
CI->getPreprocessorOpts().RetainRemappedFileBuffers = true;
|
2010-07-20 05:46:24 +08:00
|
|
|
|
2010-07-24 08:38:13 +08:00
|
|
|
llvm::MemoryBuffer *OverrideMainBuffer = 0;
|
2010-07-23 08:33:23 +08:00
|
|
|
if (PrecompilePreamble)
|
2010-07-24 08:38:13 +08:00
|
|
|
OverrideMainBuffer = AST->BuildPrecompiledPreamble();
|
2010-07-23 08:33:23 +08:00
|
|
|
|
2010-07-24 08:38:13 +08:00
|
|
|
if (!AST->Parse(OverrideMainBuffer))
|
2010-07-20 05:46:24 +08:00
|
|
|
return AST.take();
|
|
|
|
|
2010-07-24 08:38:13 +08:00
|
|
|
delete OverrideMainBuffer;
|
2009-12-01 17:51:01 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2009-12-02 11:23:45 +08:00
|
|
|
|
|
|
|
ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
|
|
|
|
const char **ArgEnd,
|
2010-04-06 07:52:57 +08:00
|
|
|
llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
|
2009-12-13 11:46:13 +08:00
|
|
|
llvm::StringRef ResourceFilesPath,
|
2009-12-02 11:23:45 +08:00
|
|
|
bool OnlyLocalDecls,
|
2010-01-23 08:14:00 +08:00
|
|
|
RemappedFile *RemappedFiles,
|
2010-02-19 02:08:43 +08:00
|
|
|
unsigned NumRemappedFiles,
|
2010-07-23 08:33:23 +08:00
|
|
|
bool CaptureDiagnostics,
|
|
|
|
bool PrecompilePreamble) {
|
2010-04-06 07:52:57 +08:00
|
|
|
if (!Diags.getPtr()) {
|
2010-04-06 05:10:19 +08:00
|
|
|
// No diagnostics engine was provided, so create our own diagnostics object
|
|
|
|
// with the default options.
|
|
|
|
DiagnosticOptions DiagOpts;
|
2010-04-06 07:52:57 +08:00
|
|
|
Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
|
2010-04-06 05:10:19 +08:00
|
|
|
}
|
|
|
|
|
2009-12-02 11:23:45 +08:00
|
|
|
llvm::SmallVector<const char *, 16> Args;
|
|
|
|
Args.push_back("<clang>"); // FIXME: Remove dummy argument.
|
|
|
|
Args.insert(Args.end(), ArgBegin, ArgEnd);
|
|
|
|
|
|
|
|
// FIXME: Find a cleaner way to force the driver into restricted modes. We
|
|
|
|
// also want to force it to use clang.
|
|
|
|
Args.push_back("-fsyntax-only");
|
|
|
|
|
2009-12-13 11:46:13 +08:00
|
|
|
// FIXME: We shouldn't have to pass in the path info.
|
2010-07-19 08:44:04 +08:00
|
|
|
driver::Driver TheDriver("clang", llvm::sys::getHostTriple(),
|
2010-04-06 05:10:19 +08:00
|
|
|
"a.out", false, false, *Diags);
|
2010-01-25 08:44:02 +08:00
|
|
|
|
|
|
|
// Don't check that inputs exist, they have been remapped.
|
|
|
|
TheDriver.setCheckInputsExist(false);
|
|
|
|
|
2009-12-02 11:23:45 +08:00
|
|
|
llvm::OwningPtr<driver::Compilation> C(
|
|
|
|
TheDriver.BuildCompilation(Args.size(), Args.data()));
|
|
|
|
|
|
|
|
// We expect to get back exactly one command job, if we didn't something
|
|
|
|
// failed.
|
|
|
|
const driver::JobList &Jobs = C->getJobs();
|
|
|
|
if (Jobs.size() != 1 || !isa<driver::Command>(Jobs.begin())) {
|
|
|
|
llvm::SmallString<256> Msg;
|
|
|
|
llvm::raw_svector_ostream OS(Msg);
|
|
|
|
C->PrintJob(OS, C->getJobs(), "; ", true);
|
2010-04-06 05:10:19 +08:00
|
|
|
Diags->Report(diag::err_fe_expected_compiler_job) << OS.str();
|
2009-12-02 11:23:45 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const driver::Command *Cmd = cast<driver::Command>(*Jobs.begin());
|
|
|
|
if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") {
|
2010-04-06 05:10:19 +08:00
|
|
|
Diags->Report(diag::err_fe_expected_clang_command);
|
2009-12-02 11:23:45 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const driver::ArgStringList &CCArgs = Cmd->getArguments();
|
2010-01-31 05:47:16 +08:00
|
|
|
llvm::OwningPtr<CompilerInvocation> CI(new CompilerInvocation);
|
2010-04-20 00:39:44 +08:00
|
|
|
CompilerInvocation::CreateFromArgs(*CI,
|
|
|
|
const_cast<const char **>(CCArgs.data()),
|
|
|
|
const_cast<const char **>(CCArgs.data()) +
|
2010-07-23 08:33:23 +08:00
|
|
|
CCArgs.size(),
|
2010-04-06 05:10:19 +08:00
|
|
|
*Diags);
|
2009-12-13 11:45:58 +08:00
|
|
|
|
2010-01-23 08:14:00 +08:00
|
|
|
// Override any files that need remapping
|
|
|
|
for (unsigned I = 0; I != NumRemappedFiles; ++I)
|
2010-01-31 05:47:16 +08:00
|
|
|
CI->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
|
2010-02-16 09:55:04 +08:00
|
|
|
RemappedFiles[I].second);
|
2010-01-23 08:14:00 +08:00
|
|
|
|
2009-12-15 08:06:45 +08:00
|
|
|
// Override the resources path.
|
2010-01-31 05:47:16 +08:00
|
|
|
CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
|
2009-12-02 11:23:45 +08:00
|
|
|
|
2010-02-16 09:55:04 +08:00
|
|
|
CI->getFrontendOpts().DisableFree = true;
|
2010-02-19 02:08:43 +08:00
|
|
|
return LoadFromCompilerInvocation(CI.take(), Diags, OnlyLocalDecls,
|
2010-07-23 08:33:23 +08:00
|
|
|
CaptureDiagnostics, PrecompilePreamble);
|
2009-12-02 11:23:45 +08:00
|
|
|
}
|
2010-07-20 05:46:24 +08:00
|
|
|
|
|
|
|
bool ASTUnit::Reparse(RemappedFile *RemappedFiles, unsigned NumRemappedFiles) {
|
|
|
|
if (!Invocation.get())
|
|
|
|
return true;
|
|
|
|
|
2010-07-24 07:58:40 +08:00
|
|
|
// If we have a preamble file lying around, build or reuse the precompiled
|
|
|
|
// preamble.
|
2010-07-24 08:38:13 +08:00
|
|
|
llvm::MemoryBuffer *OverrideMainBuffer = 0;
|
2010-07-24 07:58:40 +08:00
|
|
|
if (!PreambleFile.empty())
|
2010-07-24 08:38:13 +08:00
|
|
|
OverrideMainBuffer = BuildPrecompiledPreamble();
|
2010-07-24 07:58:40 +08:00
|
|
|
|
2010-07-20 05:46:24 +08:00
|
|
|
// Clear out the diagnostics state.
|
|
|
|
getDiagnostics().Reset();
|
|
|
|
|
|
|
|
// Remap files.
|
|
|
|
Invocation->getPreprocessorOpts().clearRemappedFiles();
|
|
|
|
for (unsigned I = 0; I != NumRemappedFiles; ++I)
|
|
|
|
Invocation->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
|
2010-07-24 07:58:40 +08:00
|
|
|
RemappedFiles[I].second);
|
|
|
|
|
|
|
|
// Parse the sources
|
2010-07-24 08:38:13 +08:00
|
|
|
bool Result = Parse(OverrideMainBuffer);
|
|
|
|
delete OverrideMainBuffer;
|
2010-07-24 07:58:40 +08:00
|
|
|
return Result;
|
2010-07-20 05:46:24 +08:00
|
|
|
}
|