aboutsummaryrefslogtreecommitdiff
path: root/lib/Frontend/ASTUnit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Frontend/ASTUnit.cpp')
-rw-r--r--lib/Frontend/ASTUnit.cpp72
1 files changed, 56 insertions, 16 deletions
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index 77a414772a..7ff3cdc5b9 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -46,6 +46,20 @@ ASTUnit::~ASTUnit() {
CleanTemporaryFiles();
if (!PreambleFile.empty())
PreambleFile.eraseFromDisk();
+
+ // 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;
+ }
}
void ASTUnit::CleanTemporaryFiles() {
@@ -371,6 +385,17 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
// Create the source manager.
Clang.setSourceManager(&getSourceManager());
+ // 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();
+ }
+
llvm::OwningPtr<TopLevelDeclTrackerAction> Act;
Act.reset(new TopLevelDeclTrackerAction(*this));
if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
@@ -388,6 +413,11 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
Target.reset(Clang.takeTarget());
Act->EndSourceFile();
+
+ // Remove the overridden buffer we used for the preamble.
+ if (OverrideMainBuffer)
+ PreprocessorOpts.eraseRemappedFile(
+ PreprocessorOpts.remapped_file_buffer_end() - 1);
Clang.takeDiagnosticClient();
@@ -395,6 +425,11 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
return false;
error:
+ // Remove the overridden buffer we used for the preamble.
+ if (OverrideMainBuffer)
+ PreprocessorOpts.eraseRemappedFile(
+ PreprocessorOpts.remapped_file_buffer_end() - 1);
+
Clang.takeSourceManager();
Clang.takeFileManager();
Clang.takeDiagnosticClient();
@@ -424,8 +459,10 @@ static std::string GetPreamblePCHPath() {
return P.str();
}
-/// \brief Compute the preamble for the main file, providing
-std::pair<llvm::MemoryBuffer *, unsigned>
+/// \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> >
ASTUnit::ComputePreamble(CompilerInvocation &Invocation, bool &CreatedBuffer) {
FrontendOptions &FrontendOpts = Invocation.getFrontendOpts();
PreprocessorOptions &PreprocessorOpts
@@ -455,7 +492,8 @@ ASTUnit::ComputePreamble(CompilerInvocation &Invocation, bool &CreatedBuffer) {
Buffer = llvm::MemoryBuffer::getFile(M->second);
if (!Buffer)
- return std::make_pair((llvm::MemoryBuffer*)0, 0);
+ return std::make_pair((llvm::MemoryBuffer*)0,
+ std::make_pair(0, true));
CreatedBuffer = true;
// Remove this remapping. We've captured the buffer already.
@@ -495,7 +533,7 @@ ASTUnit::ComputePreamble(CompilerInvocation &Invocation, bool &CreatedBuffer) {
if (!Buffer) {
Buffer = llvm::MemoryBuffer::getFile(FrontendOpts.Inputs[0].second);
if (!Buffer)
- return std::make_pair((llvm::MemoryBuffer*)0, 0);
+ return std::make_pair((llvm::MemoryBuffer*)0, std::make_pair(0, true));
CreatedBuffer = true;
}
@@ -512,9 +550,8 @@ static llvm::MemoryBuffer *CreatePaddedMainFileBuffer(llvm::MemoryBuffer *Old,
memcpy(const_cast<char*>(Result->getBufferStart()),
Old->getBufferStart(), Old->getBufferSize());
memset(const_cast<char*>(Result->getBufferStart()) + Old->getBufferSize(),
- ' ', NewSize - Old->getBufferSize() - 2);
- const_cast<char*>(Result->getBufferEnd())[-2] = '\n';
- const_cast<char*>(Result->getBufferEnd())[-1] = 0;
+ ' ', NewSize - Old->getBufferSize() - 1);
+ const_cast<char*>(Result->getBufferEnd())[-1] = '\n';
if (DeleteOld)
delete Old;
@@ -542,10 +579,10 @@ llvm::MemoryBuffer *ASTUnit::BuildPrecompiledPreamble() {
= PreambleInvocation.getPreprocessorOpts();
bool CreatedPreambleBuffer = false;
- std::pair<llvm::MemoryBuffer *, unsigned> NewPreamble
+ std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> > NewPreamble
= ComputePreamble(PreambleInvocation, CreatedPreambleBuffer);
- if (!NewPreamble.second) {
+ if (!NewPreamble.second.first) {
// 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();
@@ -564,10 +601,11 @@ llvm::MemoryBuffer *ASTUnit::BuildPrecompiledPreamble() {
// 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.
- if (Preamble.size() == NewPreamble.second &&
+ if (Preamble.size() == NewPreamble.second.first &&
+ PreambleEndsAtStartOfLine == NewPreamble.second.second &&
NewPreamble.first->getBufferSize() < PreambleReservedSize-2 &&
memcmp(&Preamble[0], NewPreamble.first->getBufferStart(),
- NewPreamble.second) == 0) {
+ NewPreamble.second.first) == 0) {
// 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.
@@ -593,7 +631,7 @@ llvm::MemoryBuffer *ASTUnit::BuildPrecompiledPreamble() {
// grows.
PreambleReservedSize = NewPreamble.first->getBufferSize();
if (PreambleReservedSize < 4096)
- PreambleReservedSize = 8192;
+ PreambleReservedSize = 8191;
else
PreambleReservedSize *= 2;
@@ -603,14 +641,15 @@ llvm::MemoryBuffer *ASTUnit::BuildPrecompiledPreamble() {
memcpy(const_cast<char*>(PreambleBuffer->getBufferStart()),
NewPreamble.first->getBufferStart(), Preamble.size());
memset(const_cast<char*>(PreambleBuffer->getBufferStart()) + Preamble.size(),
- ' ', PreambleReservedSize - Preamble.size() - 2);
- const_cast<char*>(PreambleBuffer->getBufferEnd())[-1] = 0;
- const_cast<char*>(PreambleBuffer->getBufferEnd())[-2] = '\n';
+ ' ', PreambleReservedSize - Preamble.size() - 1);
+ const_cast<char*>(PreambleBuffer->getBufferEnd())[-1] = '\n';
// Save the preamble text for later; we'll need to compare against it for
// subsequent reparses.
Preamble.assign(NewPreamble.first->getBufferStart(),
- NewPreamble.first->getBufferStart() + NewPreamble.second);
+ NewPreamble.first->getBufferStart()
+ + NewPreamble.second.first);
+ PreambleEndsAtStartOfLine = NewPreamble.second.second;
// Remap the main source file to the preamble buffer.
llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].second);
@@ -734,6 +773,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
AST->CaptureDiagnostics = CaptureDiagnostics;
AST->OnlyLocalDecls = OnlyLocalDecls;
AST->Invocation.reset(CI);
+ CI->getPreprocessorOpts().RetainRemappedFileBuffers = true;
llvm::MemoryBuffer *OverrideMainBuffer = 0;
if (PrecompilePreamble)