aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/SourceManager.h17
-rw-r--r--include/clang/Frontend/PCHBitCodes.h40
-rw-r--r--include/clang/Frontend/PCHReader.h9
-rw-r--r--include/clang/Frontend/PCHWriter.h2
-rw-r--r--include/clang/Lex/Preprocessor.h1
-rw-r--r--lib/Frontend/PCHReader.cpp85
-rw-r--r--lib/Frontend/PCHWriter.cpp152
-rw-r--r--lib/Lex/Preprocessor.cpp4
-rw-r--r--test/PCH/variables.c4
-rw-r--r--test/PCH/variables.h11
-rw-r--r--tools/clang-cc/clang-cc.cpp27
11 files changed, 340 insertions, 12 deletions
diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h
index d068e44f7c..dcf344e412 100644
--- a/include/clang/Basic/SourceManager.h
+++ b/include/clang/Basic/SourceManager.h
@@ -183,7 +183,7 @@ namespace SrcMgr {
unsigned SpellingLoc;
/// InstantiationLocStart/InstantiationLocEnd - In a macro expansion, these
- /// indicate the start and end of the instantiation. In object-line macros,
+ /// indicate the start and end of the instantiation. In object-like macros,
/// these will be the same. In a function-like macro instantiation, the
/// start will be the identifier and the end will be the ')'.
unsigned InstantiationLocStart, InstantiationLocEnd;
@@ -610,7 +610,20 @@ public:
/// Read - Reconstitute a SourceManager from Bitcode.
static SourceManager* CreateAndRegister(llvm::Deserializer& S,
FileManager &FMgr);
-
+
+ // Iteration over the source location entry table.
+ typedef std::vector<SrcMgr::SLocEntry>::const_iterator sloc_entry_iterator;
+
+ sloc_entry_iterator sloc_entry_begin() const {
+ return SLocEntryTable.begin();
+ }
+
+ sloc_entry_iterator sloc_entry_end() const {
+ return SLocEntryTable.end();
+ }
+
+ unsigned sloc_entry_size() const { return SLocEntryTable.size(); }
+
private:
friend class SrcMgr::ContentCache; // Used for deserialization.
diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h
index 8835098361..00bd1cfac2 100644
--- a/include/clang/Frontend/PCHBitCodes.h
+++ b/include/clang/Frontend/PCHBitCodes.h
@@ -31,7 +31,19 @@ namespace clang {
/// \brief The PCH block, which acts as a container around the
/// full PCH block.
PCH_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID,
-
+
+ /// \brief The block containing information about the language
+ /// options used to build this precompiled header.
+ LANGUAGE_OPTIONS_BLOCK_ID,
+
+ /// \brief The block containing information about the source
+ /// manager.
+ SOURCE_MANAGER_BLOCK_ID,
+
+ /// \brief The block containing information about the
+ /// preprocessor.
+ PREPROCESSOR_BLOCK_ID,
+
/// \brief The block containing the definitions of all of the
/// types used within the PCH file.
TYPES_BLOCK_ID,
@@ -55,6 +67,30 @@ namespace clang {
DECL_OFFSETS_BLOCK_ID
};
+ /// \brief Record types used within a source manager block.
+ enum SourceManagerRecordTypes {
+ /// \brief Describes a source location entry (SLocEntry) for a
+ /// file.
+ SM_SLOC_FILE_ENTRY = 1,
+ /// \brief Describes a source location entry (SLocEntry) for a
+ /// buffer.
+ SM_SLOC_BUFFER_ENTRY = 2,
+ /// \brief Describes a blob that contains the data for a buffer
+ /// entry. This kind of record always directly follows a
+ /// SM_SLOC_BUFFER_ENTRY record.
+ SM_SLOC_BUFFER_BLOB = 3,
+ /// \brief Describes a source location entry (SLocEntry) for a
+ /// macro instantiation.
+ SM_SLOC_INSTANTIATION_ENTRY = 4
+ };
+
+ /// \defgroup PCHAST Precompiled header AST constants
+ ///
+ /// The constants in this group describe various components of the
+ /// abstract syntax tree within a precompiled header.
+ ///
+ /// @{
+
/// \brief Predefined type IDs.
///
/// These type IDs correspond to predefined types in the AST
@@ -233,6 +269,8 @@ namespace clang {
enum DeclOffsetCode {
DECL_OFFSET = 1
};
+
+ /// @}
}
} // end namespace clang
diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h
index 1338d3c03b..fe7632896e 100644
--- a/include/clang/Frontend/PCHReader.h
+++ b/include/clang/Frontend/PCHReader.h
@@ -34,6 +34,7 @@ namespace clang {
class ASTContext;
class Decl;
class DeclContext;
+class Preprocessor;
/// \brief Reads a precompiled head containing the contents of a
/// translation unit.
@@ -48,6 +49,9 @@ class DeclContext;
/// required when traversing the AST. Only those AST nodes that are
/// actually required will be de-serialized.
class PCHReader : public ExternalASTSource {
+ /// \brief The preprocessor that will be loading the source file.
+ Preprocessor &PP;
+
/// \brief The AST context into which we'll read the PCH file.
ASTContext &Context;
@@ -95,6 +99,7 @@ class PCHReader : public ExternalASTSource {
DeclContextOffsetsMap DeclContextOffsets;
bool ReadPCHBlock();
+ bool ReadSourceManagerBlock();
bool ReadTypeOffsets();
bool ReadDeclOffsets();
@@ -108,7 +113,9 @@ class PCHReader : public ExternalASTSource {
public:
typedef llvm::SmallVector<uint64_t, 64> RecordData;
- PCHReader(ASTContext &Context) : Context(Context), Buffer() { }
+ PCHReader(Preprocessor &PP, ASTContext &Context)
+ : PP(PP), Context(Context), Buffer() { }
+
~PCHReader();
bool ReadPCH(const std::string &FileName);
diff --git a/include/clang/Frontend/PCHWriter.h b/include/clang/Frontend/PCHWriter.h
index 99876e9002..9b5f15ecf7 100644
--- a/include/clang/Frontend/PCHWriter.h
+++ b/include/clang/Frontend/PCHWriter.h
@@ -30,6 +30,7 @@ namespace llvm {
namespace clang {
class ASTContext;
+class SourceManager;
/// \brief Writes a precompiled header containing the contents of a
/// translation unit.
@@ -74,6 +75,7 @@ class PCHWriter {
/// \brief The type ID that will be assigned to the next new type.
unsigned NextTypeID;
+ void WriteSourceManagerBlock(SourceManager &SourceMgr);
void WriteType(const Type *T);
void WriteTypesBlock(ASTContext &Context);
uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC);
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index 0e16ef8287..68cb372c47 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -782,6 +782,7 @@ class PreprocessorFactory {
public:
virtual ~PreprocessorFactory();
virtual Preprocessor* CreatePreprocessor() = 0;
+ virtual bool FinishInitialization(Preprocessor *PP);
};
} // end namespace clang
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index d366cddf17..01a79b44d9 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -15,6 +15,9 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Type.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/FileManager.h"
#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -111,6 +114,84 @@ static bool Error(const char *Str) {
return true;
}
+/// \brief Read the source manager block
+bool PCHReader::ReadSourceManagerBlock() {
+ using namespace SrcMgr;
+ if (Stream.EnterSubBlock(pch::SOURCE_MANAGER_BLOCK_ID))
+ return Error("Malformed source manager block record");
+
+ SourceManager &SourceMgr = Context.getSourceManager();
+ RecordData Record;
+ while (true) {
+ unsigned Code = Stream.ReadCode();
+ if (Code == llvm::bitc::END_BLOCK) {
+ if (Stream.ReadBlockEnd())
+ return Error("Error at end of Source Manager block");
+ return false;
+ }
+
+ if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+ // No known subblocks, always skip them.
+ Stream.ReadSubBlockID();
+ if (Stream.SkipBlock())
+ return Error("Malformed block record");
+ continue;
+ }
+
+ if (Code == llvm::bitc::DEFINE_ABBREV) {
+ Stream.ReadAbbrevRecord();
+ continue;
+ }
+
+ // Read a record.
+ const char *BlobStart;
+ unsigned BlobLen;
+ Record.clear();
+ switch (Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
+ default: // Default behavior: ignore.
+ break;
+
+ case pch::SM_SLOC_FILE_ENTRY: {
+ // FIXME: We would really like to delay the creation of this
+ // FileEntry until it is actually required, e.g., when producing
+ // a diagnostic with a source location in this file.
+ const FileEntry *File
+ = PP.getFileManager().getFile(BlobStart, BlobStart + BlobLen);
+ // FIXME: Error recovery if file cannot be found.
+ SourceMgr.createFileID(File,
+ SourceLocation::getFromRawEncoding(Record[1]),
+ (CharacteristicKind)Record[2]);
+ break;
+ }
+
+ case pch::SM_SLOC_BUFFER_ENTRY: {
+ const char *Name = BlobStart;
+ unsigned Code = Stream.ReadCode();
+ Record.clear();
+ unsigned RecCode = Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen);
+ assert(RecCode == pch::SM_SLOC_BUFFER_BLOB && "Ill-formed PCH file");
+ SourceMgr.createFileIDForMemBuffer(
+ llvm::MemoryBuffer::getMemBuffer(BlobStart, BlobStart + BlobLen - 1,
+ Name));
+ break;
+ }
+
+ case pch::SM_SLOC_INSTANTIATION_ENTRY: {
+ SourceLocation SpellingLoc
+ = SourceLocation::getFromRawEncoding(Record[1]);
+ SourceMgr.createInstantiationLoc(
+ SpellingLoc,
+ SourceLocation::getFromRawEncoding(Record[2]),
+ SourceLocation::getFromRawEncoding(Record[3]),
+ Lexer::MeasureTokenLength(SpellingLoc,
+ SourceMgr));
+ break;
+ }
+
+ }
+ }
+}
+
/// \brief Read the type-offsets block.
bool PCHReader::ReadTypeOffsets() {
if (Stream.EnterSubBlock(pch::TYPE_OFFSETS_BLOCK_ID))
@@ -217,6 +298,10 @@ bool PCHReader::ReadPCHBlock() {
return Error("Malformed block record");
break;
+ case pch::SOURCE_MANAGER_BLOCK_ID:
+ if (ReadSourceManagerBlock())
+ return Error("Malformed source manager block");
+ break;
case pch::TYPE_OFFSETS_BLOCK_ID:
if (ReadTypeOffsets())
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index 39936b34f5..d4961e4e74 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -17,8 +17,11 @@
#include "clang/AST/DeclContextInternals.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/Type.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
#include "llvm/Bitcode/BitstreamWriter.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/MemoryBuffer.h"
using namespace clang;
@@ -323,6 +326,154 @@ void PCHDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
// PCHWriter Implementation
//===----------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+// Source Manager Serialization
+//===----------------------------------------------------------------------===//
+
+/// \brief Create an abbreviation for the SLocEntry that refers to a
+/// file.
+static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &S) {
+ using namespace llvm;
+ BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_FILE_ENTRY));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives
+ // FIXME: Need an actual encoding for the line directives; maybe
+ // this should be an array?
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
+ return S.EmitAbbrev(Abbrev);
+}
+
+/// \brief Create an abbreviation for the SLocEntry that refers to a
+/// buffer.
+static unsigned CreateSLocBufferAbbrev(llvm::BitstreamWriter &S) {
+ using namespace llvm;
+ BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_BUFFER_ENTRY));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Buffer name blob
+ return S.EmitAbbrev(Abbrev);
+}
+
+/// \brief Create an abbreviation for the SLocEntry that refers to a
+/// buffer's blob.
+static unsigned CreateSLocBufferBlobAbbrev(llvm::BitstreamWriter &S) {
+ using namespace llvm;
+ BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_BUFFER_BLOB));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Blob
+ return S.EmitAbbrev(Abbrev);
+}
+
+/// \brief Create an abbreviation for the SLocEntry that refers to an
+/// buffer.
+static unsigned CreateSLocInstantiationAbbrev(llvm::BitstreamWriter &S) {
+ using namespace llvm;
+ BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_INSTANTIATION_ENTRY));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Spelling location
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Start location
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // End location
+ return S.EmitAbbrev(Abbrev);
+}
+
+/// \brief Writes the block containing the serialized form of the
+/// source manager.
+///
+/// TODO: We should probably use an on-disk hash table (stored in a
+/// blob), indexed based on the file name, so that we only create
+/// entries for files that we actually need. In the common case (no
+/// errors), we probably won't have to create file entries for any of
+/// the files in the AST.
+void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr) {
+ // Enter the types block
+ S.EnterSubblock(pch::SOURCE_MANAGER_BLOCK_ID, 3);
+
+ // Abbreviations for the various kinds of source-location entries.
+ int SLocFileAbbrv = -1;
+ int SLocBufferAbbrv = -1;
+ int SLocBufferBlobAbbrv = -1;
+ int SLocInstantiationAbbrv = -1;
+
+ // Write out the source location entry table. We skip the first
+ // entry, which is always the same dummy entry.
+ RecordData Record;
+ for (SourceManager::sloc_entry_iterator
+ SLoc = SourceMgr.sloc_entry_begin() + 1,
+ SLocEnd = SourceMgr.sloc_entry_end();
+ SLoc != SLocEnd; ++SLoc) {
+ // Figure out which record code to use.
+ unsigned Code;
+ if (SLoc->isFile()) {
+ if (SLoc->getFile().getContentCache()->Entry)
+ Code = pch::SM_SLOC_FILE_ENTRY;
+ else
+ Code = pch::SM_SLOC_BUFFER_ENTRY;
+ } else
+ Code = pch::SM_SLOC_INSTANTIATION_ENTRY;
+ Record.push_back(Code);
+
+ Record.push_back(SLoc->getOffset());
+ if (SLoc->isFile()) {
+ const SrcMgr::FileInfo &File = SLoc->getFile();
+ Record.push_back(File.getIncludeLoc().getRawEncoding());
+ Record.push_back(File.getFileCharacteristic()); // FIXME: stable encoding
+ Record.push_back(File.hasLineDirectives()); // FIXME: encode the
+ // line directives?
+
+ const SrcMgr::ContentCache *Content = File.getContentCache();
+ if (Content->Entry) {
+ // The source location entry is a file. The blob associated
+ // with this entry is the file name.
+ if (SLocFileAbbrv == -1)
+ SLocFileAbbrv = CreateSLocFileAbbrev(S);
+ S.EmitRecordWithBlob(SLocFileAbbrv, Record,
+ Content->Entry->getName(),
+ strlen(Content->Entry->getName()));
+ } else {
+ // The source location entry is a buffer. The blob associated
+ // with this entry contains the contents of the buffer.
+ if (SLocBufferAbbrv == -1) {
+ SLocBufferAbbrv = CreateSLocBufferAbbrev(S);
+ SLocBufferBlobAbbrv = CreateSLocBufferBlobAbbrev(S);
+ }
+
+ // We add one to the size so that we capture the trailing NULL
+ // that is required by llvm::MemoryBuffer::getMemBuffer (on
+ // the reader side).
+ const llvm::MemoryBuffer *Buffer = Content->getBuffer();
+ const char *Name = Buffer->getBufferIdentifier();
+ S.EmitRecordWithBlob(SLocBufferAbbrv, Record, Name, strlen(Name) + 1);
+ Record.clear();
+ Record.push_back(pch::SM_SLOC_BUFFER_BLOB);
+ S.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record,
+ Buffer->getBufferStart(),
+ Buffer->getBufferSize() + 1);
+ }
+ } else {
+ // The source location entry is an instantiation.
+ const SrcMgr::InstantiationInfo &Inst = SLoc->getInstantiation();
+ Record.push_back(Inst.getSpellingLoc().getRawEncoding());
+ Record.push_back(Inst.getInstantiationLocStart().getRawEncoding());
+ Record.push_back(Inst.getInstantiationLocEnd().getRawEncoding());
+
+ if (SLocInstantiationAbbrv == -1)
+ SLocInstantiationAbbrv = CreateSLocInstantiationAbbrev(S);
+ S.EmitRecordWithAbbrev(SLocInstantiationAbbrv, Record);
+ }
+
+ Record.clear();
+ }
+
+ S.ExitBlock();
+}
+
/// \brief Write the representation of a type to the PCH stream.
void PCHWriter::WriteType(const Type *T) {
pch::ID &ID = TypeIDs[T];
@@ -521,6 +672,7 @@ void PCHWriter::WritePCH(ASTContext &Context) {
// Write the remaining PCH contents.
S.EnterSubblock(pch::PCH_BLOCK_ID, 2);
+ WriteSourceManagerBlock(Context.getSourceManager());
WriteTypesBlock(Context);
WriteDeclsBlock(Context);
S.ExitBlock();
diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp
index 452a04ccb3..a594ad9c5d 100644
--- a/lib/Lex/Preprocessor.cpp
+++ b/lib/Lex/Preprocessor.cpp
@@ -45,6 +45,10 @@ using namespace clang;
PreprocessorFactory::~PreprocessorFactory() {}
+bool PreprocessorFactory::FinishInitialization(Preprocessor *PP) {
+ return false;
+}
+
Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts,
TargetInfo &target, SourceManager &SM,
HeaderSearch &Headers,
diff --git a/test/PCH/variables.c b/test/PCH/variables.c
index 2981a6796a..a5283f92ad 100644
--- a/test/PCH/variables.c
+++ b/test/PCH/variables.c
@@ -3,4 +3,8 @@
int *ip2 = &x;
float *fp = &ip; // expected-warning{{incompatible pointer types}}
+// FIXME:variables.h expected-note{{previous}}
+double z; // expected-error{{redefinition}}
+
+//double VeryHappy; // FIXME: xpected-error{{redefinition}}
diff --git a/test/PCH/variables.h b/test/PCH/variables.h
index 442b5f64df..4c5012d68b 100644
--- a/test/PCH/variables.h
+++ b/test/PCH/variables.h
@@ -1,5 +1,12 @@
// RUN: clang-cc -emit-pch -o variables.h.pch variables.h
-extern int x;
+// Do not mess with the whitespace in this file. It's important.
extern float y;
-extern int *ip;
+extern int *ip, x;
+
float z;
+
+
+
+#define MAKE_HAPPY(X) X##Happy
+int MAKE_HAPPY(Very);
+
diff --git a/tools/clang-cc/clang-cc.cpp b/tools/clang-cc/clang-cc.cpp
index f8c44d6f7d..258076836a 100644
--- a/tools/clang-cc/clang-cc.cpp
+++ b/tools/clang-cc/clang-cc.cpp
@@ -1379,22 +1379,26 @@ public:
PP->setPTHManager(PTHMgr.take());
}
+ return PP.take();
+ }
+
+ virtual bool FinishInitialization(Preprocessor *PP) {
if (InitializePreprocessor(*PP, InitializeSourceMgr, InFile)) {
- return NULL;
+ return true;
}
/// FIXME: PP can only handle one callback
if (ProgAction != PrintPreprocessedInput) {
std::string ErrStr;
- bool DFG = CreateDependencyFileGen(PP.get(), ErrStr);
+ bool DFG = CreateDependencyFileGen(PP, ErrStr);
if (!DFG && !ErrStr.empty()) {
fprintf(stderr, "%s", ErrStr.c_str());
- return NULL;
+ return true;
}
}
InitializeSourceMgr = false;
- return PP.take();
+ return false;
}
};
}
@@ -1697,13 +1701,20 @@ static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF,
if (!ImplicitIncludePCH.empty()) {
// The user has asked us to include a precompiled header. Load
// the precompiled header into the AST context.
- llvm::OwningPtr<PCHReader> Reader(
- new clang::PCHReader(*ContextOwner.get()));
+ llvm::OwningPtr<PCHReader>
+ Reader(new clang::PCHReader(PP, *ContextOwner.get()));
if (Reader->ReadPCH(ImplicitIncludePCH))
return;
llvm::OwningPtr<ExternalASTSource> Source(Reader.take());
ContextOwner->setExternalSource(Source);
+
+ // Finish preprocessor initialization. We do this now (rather
+ // than earlier) because this initialization creates new source
+ // location entries in the source manager, which must come after
+ // the source location entries for the PCH file.
+ if (PPF.FinishInitialization(&PP))
+ return;
}
ParseAST(PP, Consumer.get(), *ContextOwner.get(), Stats);
@@ -1912,6 +1923,10 @@ int main(int argc, char **argv) {
if (!PP)
continue;
+ if (ImplicitIncludePCH.empty()
+ && PPFactory.FinishInitialization(PP.get()))
+ continue;
+
// Create the HTMLDiagnosticsClient if we are using one. Otherwise,
// always reset to using TextDiagClient.
llvm::OwningPtr<DiagnosticClient> TmpClient;