aboutsummaryrefslogtreecommitdiff
path: root/lib/Frontend
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Frontend')
-rw-r--r--lib/Frontend/PCHReader.cpp169
-rw-r--r--lib/Frontend/PCHWriter.cpp2
2 files changed, 137 insertions, 34 deletions
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index eaba610137..345e673b47 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -116,27 +116,109 @@ static bool Error(const char *Str) {
return true;
}
+/// \brief Check the contents of the predefines buffer against the
+/// contents of the predefines buffer used to build the PCH file.
+///
+/// The contents of the two predefines buffers should be the same. If
+/// not, then some command-line option changed the preprocessor state
+/// and we must reject the PCH file.
+///
+/// \param PCHPredef The start of the predefines buffer in the PCH
+/// file.
+///
+/// \param PCHPredefLen The length of the predefines buffer in the PCH
+/// file.
+///
+/// \param PCHBufferID The FileID for the PCH predefines buffer.
+///
+/// \returns true if there was a mismatch (in which case the PCH file
+/// should be ignored), or false otherwise.
+bool PCHReader::CheckPredefinesBuffer(const char *PCHPredef,
+ unsigned PCHPredefLen,
+ FileID PCHBufferID) {
+ const char *Predef = PP.getPredefines().c_str();
+ unsigned PredefLen = PP.getPredefines().size();
+
+ // If the two predefines buffers compare equal, we're done!.
+ if (PredefLen == PCHPredefLen &&
+ strncmp(Predef, PCHPredef, PCHPredefLen) == 0)
+ return false;
+
+ // The predefines buffers are different. Produce a reasonable
+ // diagnostic showing where they are different.
+
+ // The source locations (potentially in the two different predefines
+ // buffers)
+ SourceLocation Loc1, Loc2;
+ SourceManager &SourceMgr = PP.getSourceManager();
+
+ // Create a source buffer for our predefines string, so
+ // that we can build a diagnostic that points into that
+ // source buffer.
+ FileID BufferID;
+ if (Predef && Predef[0]) {
+ llvm::MemoryBuffer *Buffer
+ = llvm::MemoryBuffer::getMemBuffer(Predef, Predef + PredefLen,
+ "<built-in>");
+ BufferID = SourceMgr.createFileIDForMemBuffer(Buffer);
+ }
+
+ unsigned MinLen = std::min(PredefLen, PCHPredefLen);
+ std::pair<const char *, const char *> Locations
+ = std::mismatch(Predef, Predef + MinLen, PCHPredef);
+
+ if (Locations.first != Predef + MinLen) {
+ // We found the location in the two buffers where there is a
+ // difference. Form source locations to point there (in both
+ // buffers).
+ unsigned Offset = Locations.first - Predef;
+ Loc1 = SourceMgr.getLocForStartOfFile(BufferID)
+ .getFileLocWithOffset(Offset);
+ Loc2 = SourceMgr.getLocForStartOfFile(PCHBufferID)
+ .getFileLocWithOffset(Offset);
+ } else if (PredefLen > PCHPredefLen) {
+ Loc1 = SourceMgr.getLocForStartOfFile(BufferID)
+ .getFileLocWithOffset(MinLen);
+ } else {
+ Loc1 = SourceMgr.getLocForStartOfFile(PCHBufferID)
+ .getFileLocWithOffset(MinLen);
+ }
+
+ Diag(Loc1, diag::warn_pch_preprocessor);
+ if (Loc2.isValid())
+ Diag(Loc2, diag::note_predef_in_pch);
+ Diag(diag::note_ignoring_pch) << FileName;
+ return true;
+}
+
/// \brief Read the source manager block
-bool PCHReader::ReadSourceManagerBlock() {
+PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() {
using namespace SrcMgr;
- if (Stream.EnterSubBlock(pch::SOURCE_MANAGER_BLOCK_ID))
- return Error("Malformed source manager block record");
+ if (Stream.EnterSubBlock(pch::SOURCE_MANAGER_BLOCK_ID)) {
+ Error("Malformed source manager block record");
+ return Failure;
+ }
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 (Stream.ReadBlockEnd()) {
+ Error("Error at end of Source Manager block");
+ return Failure;
+ }
+
+ return Success;
}
if (Code == llvm::bitc::ENTER_SUBBLOCK) {
// No known subblocks, always skip them.
Stream.ReadSubBlockID();
- if (Stream.SkipBlock())
- return Error("Malformed block record");
+ if (Stream.SkipBlock()) {
+ Error("Malformed block record");
+ return Failure;
+ }
continue;
}
@@ -172,9 +254,15 @@ bool PCHReader::ReadSourceManagerBlock() {
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));
+ llvm::MemoryBuffer *Buffer
+ = llvm::MemoryBuffer::getMemBuffer(BlobStart,
+ BlobStart + BlobLen - 1,
+ Name);
+ FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer);
+
+ if (strcmp(Name, "<built-in>") == 0
+ && CheckPredefinesBuffer(BlobStart, BlobLen - 1, BufferID))
+ return IgnorePCH;
break;
}
@@ -329,9 +417,16 @@ PCHReader::PCHReadResult PCHReader::ReadPCHBlock() {
break;
case pch::SOURCE_MANAGER_BLOCK_ID:
- if (ReadSourceManagerBlock()) {
+ switch (ReadSourceManagerBlock()) {
+ case Success:
+ break;
+
+ case Failure:
Error("Malformed source manager block");
return Failure;
+
+ case IgnorePCH:
+ return IgnorePCH;
}
break;
@@ -400,15 +495,17 @@ PCHReader::PCHReadResult PCHReader::ReadPCHBlock() {
PCHReader::~PCHReader() { }
-bool PCHReader::ReadPCH(const std::string &FileName) {
+PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
// Set the PCH file name.
this->FileName = FileName;
// Open the PCH file.
std::string ErrStr;
Buffer.reset(llvm::MemoryBuffer::getFile(FileName.c_str(), &ErrStr));
- if (!Buffer)
- return Error(ErrStr.c_str());
+ if (!Buffer) {
+ Error(ErrStr.c_str());
+ return IgnorePCH;
+ }
// Initialize the stream
Stream.init((const unsigned char *)Buffer->getBufferStart(),
@@ -418,24 +515,30 @@ bool PCHReader::ReadPCH(const std::string &FileName) {
if (Stream.Read(8) != 'C' ||
Stream.Read(8) != 'P' ||
Stream.Read(8) != 'C' ||
- Stream.Read(8) != 'H')
- return Error("Not a PCH file");
+ Stream.Read(8) != 'H') {
+ Error("Not a PCH file");
+ return IgnorePCH;
+ }
// We expect a number of well-defined blocks, though we don't necessarily
// need to understand them all.
while (!Stream.AtEndOfStream()) {
unsigned Code = Stream.ReadCode();
- if (Code != llvm::bitc::ENTER_SUBBLOCK)
- return Error("Invalid record at top-level");
+ if (Code != llvm::bitc::ENTER_SUBBLOCK) {
+ Error("Invalid record at top-level");
+ return Failure;
+ }
unsigned BlockID = Stream.ReadSubBlockID();
// We only know the PCH subblock ID.
switch (BlockID) {
case llvm::bitc::BLOCKINFO_BLOCK_ID:
- if (Stream.ReadBlockInfoBlock())
- return Error("Malformed BlockInfoBlock");
+ if (Stream.ReadBlockInfoBlock()) {
+ Error("Malformed BlockInfoBlock");
+ return Failure;
+ }
break;
case pch::PCH_BLOCK_ID:
switch (ReadPCHBlock()) {
@@ -443,18 +546,20 @@ bool PCHReader::ReadPCH(const std::string &FileName) {
break;
case Failure:
- return true;
+ return Failure;
case IgnorePCH:
// FIXME: We could consider reading through to the end of this
// PCH block, skipping subblocks, to see if there are other
// PCH blocks elsewhere.
- return false;
+ return IgnorePCH;
}
break;
default:
- if (Stream.SkipBlock())
- return Error("Malformed block record");
+ if (Stream.SkipBlock()) {
+ Error("Malformed block record");
+ return Failure;
+ }
break;
}
}
@@ -462,13 +567,7 @@ bool PCHReader::ReadPCH(const std::string &FileName) {
// Load the translation unit declaration
ReadDeclRecord(DeclOffsets[0], 0);
- // If everything looks like it will be ok, then the PCH file load succeeded.
- // Since the PCH file contains everything that is in the preprocessor's
- // predefines buffer (and we validated that they are the same) clear out the
- // predefines buffer so that it doesn't get processed again.
- PP.setPredefines("");
-
- return false;
+ return Success;
}
/// \brief Parse the record that corresponds to a LangOptions data
@@ -875,7 +974,11 @@ PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) {
}
DiagnosticBuilder PCHReader::Diag(unsigned DiagID) {
- return PP.getDiagnostics().Report(FullSourceLoc(SourceLocation(),
+ return Diag(SourceLocation(), DiagID);
+}
+
+DiagnosticBuilder PCHReader::Diag(SourceLocation Loc, unsigned DiagID) {
+ return PP.getDiagnostics().Report(FullSourceLoc(Loc,
Context.getSourceManager()),
DiagID);
}
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index 09080d640b..4963ea1160 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -872,7 +872,7 @@ void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {
}
if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr())) {
- pch::TypeID ID;
+ pch::TypeID ID = 0;
switch (BT->getKind()) {
case BuiltinType::Void: ID = pch::PREDEF_TYPE_VOID_ID; break;
case BuiltinType::Bool: ID = pch::PREDEF_TYPE_BOOL_ID; break;