[cfe-commits] r108340 - in /cfe/trunk: include/clang/Frontend/PCHReader.h lib/Frontend/PCHReader.cpp test/PCH/pchpch.c test/PCH/pchpch1.h test/PCH/pchpch2.h
Sebastian Redl
sebastian.redl at getdesigned.at
Wed Jul 14 10:49:12 PDT 2010
Author: cornedbee
Date: Wed Jul 14 12:49:11 2010
New Revision: 108340
URL: http://llvm.org/viewvc/llvm-project?rev=108340&view=rev
Log:
Make PCHReader cope with PCH files containing more than one predefines buffer.
Added:
cfe/trunk/test/PCH/pchpch.c
cfe/trunk/test/PCH/pchpch1.h
cfe/trunk/test/PCH/pchpch2.h
Modified:
cfe/trunk/include/clang/Frontend/PCHReader.h
cfe/trunk/lib/Frontend/PCHReader.cpp
Modified: cfe/trunk/include/clang/Frontend/PCHReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHReader.h?rev=108340&r1=108339&r2=108340&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHReader.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHReader.h Wed Jul 14 12:49:11 2010
@@ -65,6 +65,15 @@
class PCHReader;
struct HeaderFileInfo;
+struct PCHPredefinesBlock {
+ /// \brief The file ID for this predefines buffer in a PCH file.
+ FileID BufferID;
+
+ /// \brief This predefines buffer in a PCH file.
+ llvm::StringRef Data;
+};
+typedef llvm::SmallVector<PCHPredefinesBlock, 2> PCHPredefinesBlocks;
+
/// \brief Abstract interface for callback invocations by the PCHReader.
///
/// While reading a PCH file, the PCHReader will call the methods of the
@@ -103,8 +112,7 @@
/// here.
///
/// \returns true to indicate the predefines are invalid or false otherwise.
- virtual bool ReadPredefinesBuffer(llvm::StringRef PCHPredef,
- FileID PCHBufferID,
+ virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
llvm::StringRef OriginalFileName,
std::string &SuggestedPredefines) {
return false;
@@ -131,8 +139,7 @@
virtual bool ReadLanguageOptions(const LangOptions &LangOpts);
virtual bool ReadTargetTriple(llvm::StringRef Triple);
- virtual bool ReadPredefinesBuffer(llvm::StringRef PCHPredef,
- FileID PCHBufferID,
+ virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
llvm::StringRef OriginalFileName,
std::string &SuggestedPredefines);
virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID);
@@ -483,15 +490,9 @@
~ReadingKindTracker() { Reader.ReadingKind = PrevKind; }
};
- /// \brief The file ID for the predefines buffer in the PCH file.
- FileID PCHPredefinesBufferID;
-
- /// \brief Pointer to the beginning of the predefines buffer in the
- /// PCH file.
- const char *PCHPredefines;
-
- /// \brief Length of the predefines buffer in the PCH file.
- unsigned PCHPredefinesLen;
+ /// \brief All predefines buffers in all PCH files, to be treated as if
+ /// concatenated.
+ PCHPredefinesBlocks PCHPredefinesBuffers;
/// \brief Suggested contents of the predefines buffer, after this
/// PCH file has been processed.
@@ -509,7 +510,7 @@
void MaybeAddSystemRootToFilename(std::string &Filename);
PCHReadResult ReadPCHBlock();
- bool CheckPredefinesBuffer(llvm::StringRef PCHPredef, FileID PCHBufferID);
+ bool CheckPredefinesBuffers();
bool ParseLineTable(llvm::SmallVectorImpl<uint64_t> &Record);
PCHReadResult ReadSourceManagerBlock();
PCHReadResult ReadSLocEntryRecord(unsigned ID);
Modified: cfe/trunk/lib/Frontend/PCHReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=108340&r1=108339&r2=108340&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Wed Jul 14 12:49:11 2010
@@ -140,8 +140,86 @@
return true;
}
-bool PCHValidator::ReadPredefinesBuffer(llvm::StringRef PCHPredef,
- FileID PCHBufferID,
+struct EmptyStringRef {
+ bool operator ()(const llvm::StringRef &r) const { return r.empty(); }
+};
+struct EmptyBlock {
+ bool operator ()(const PCHPredefinesBlock &r) const { return r.Data.empty(); }
+};
+
+static bool EqualConcatenations(llvm::SmallVector<llvm::StringRef, 2> L,
+ PCHPredefinesBlocks R) {
+ // First, sum up the lengths.
+ unsigned LL = 0, RL = 0;
+ for (unsigned I = 0, N = L.size(); I != N; ++I) {
+ LL += L[I].size();
+ }
+ for (unsigned I = 0, N = R.size(); I != N; ++I) {
+ RL += R[I].Data.size();
+ }
+ if (LL != RL)
+ return false;
+ if (LL == 0 && RL == 0)
+ return true;
+
+ // Kick out empty parts, they confuse the algorithm below.
+ L.erase(std::remove_if(L.begin(), L.end(), EmptyStringRef()), L.end());
+ R.erase(std::remove_if(R.begin(), R.end(), EmptyBlock()), R.end());
+
+ // Do it the hard way. At this point, both vectors must be non-empty.
+ llvm::StringRef LR = L[0], RR = R[0].Data;
+ unsigned LI = 0, RI = 0, LN = L.size(), RN = R.size();
+ for (;;) {
+ // Compare the current pieces.
+ if (LR.size() == RR.size()) {
+ // If they're the same length, it's pretty easy.
+ if (LR != RR)
+ return false;
+ // Both pieces are done, advance.
+ ++LI;
+ ++RI;
+ // If either string is done, they're both done, since they're the same
+ // length.
+ if (LI == LN) {
+ assert(RI == RN && "Strings not the same length after all?");
+ return true;
+ }
+ LR = L[LI];
+ RR = R[RI].Data;
+ } else if (LR.size() < RR.size()) {
+ // Right piece is longer.
+ if (!RR.startswith(LR))
+ return false;
+ ++LI;
+ assert(LI != LN && "Strings not the same length after all?");
+ RR = RR.substr(LR.size());
+ LR = L[LI];
+ } else {
+ // Left piece is longer.
+ if (!LR.startswith(RR))
+ return false;
+ ++RI;
+ assert(RI != RN && "Strings not the same length after all?");
+ LR = LR.substr(RR.size());
+ RR = R[RI].Data;
+ }
+ }
+}
+
+static std::pair<FileID, llvm::StringRef::size_type>
+FindMacro(const PCHPredefinesBlocks &Buffers, llvm::StringRef MacroDef) {
+ std::pair<FileID, llvm::StringRef::size_type> Res;
+ for (unsigned I = 0, N = Buffers.size(); I != N; ++I) {
+ Res.second = Buffers[I].Data.find(MacroDef);
+ if (Res.second != llvm::StringRef::npos) {
+ Res.first = Buffers[I].BufferID;
+ break;
+ }
+ }
+ return Res;
+}
+
+bool PCHValidator::ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
llvm::StringRef OriginalFileName,
std::string &SuggestedPredefines) {
// We are in the context of an implicit include, so the predefines buffer will
@@ -160,9 +238,15 @@
return true;
}
- // If the predefines is equal to the joined left and right halves, we're done!
- if (Left.size() + Right.size() == PCHPredef.size() &&
- PCHPredef.startswith(Left) && PCHPredef.endswith(Right))
+ // If the concatenation of all the PCH buffers is equal to the adjusted
+ // command line, we're done.
+ // We build a SmallVector of the command line here, because we'll eventually
+ // need to support an arbitrary amount of pieces anyway (when we have chained
+ // PCH reading).
+ llvm::SmallVector<llvm::StringRef, 2> CommandLine;
+ CommandLine.push_back(Left);
+ CommandLine.push_back(Right);
+ if (EqualConcatenations(CommandLine, Buffers))
return false;
SourceManager &SourceMgr = PP.getSourceManager();
@@ -170,7 +254,8 @@
// The predefines buffers are different. Determine what the differences are,
// and whether they require us to reject the PCH file.
llvm::SmallVector<llvm::StringRef, 8> PCHLines;
- PCHPredef.split(PCHLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+ for (unsigned I = 0, N = Buffers.size(); I != N; ++I)
+ Buffers[I].Data.split(PCHLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
llvm::SmallVector<llvm::StringRef, 8> CmdLineLines;
Left.split(CmdLineLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
@@ -235,10 +320,12 @@
<< MacroName;
// Show the definition of this macro within the PCH file.
- llvm::StringRef::size_type Offset = PCHPredef.find(Missing);
- assert(Offset != llvm::StringRef::npos && "Unable to find macro!");
- SourceLocation PCHMissingLoc = SourceMgr.getLocForStartOfFile(PCHBufferID)
- .getFileLocWithOffset(Offset);
+ std::pair<FileID, llvm::StringRef::size_type> MacroLoc =
+ FindMacro(Buffers, Missing);
+ assert(MacroLoc.second!=llvm::StringRef::npos && "Unable to find macro!");
+ SourceLocation PCHMissingLoc =
+ SourceMgr.getLocForStartOfFile(MacroLoc.first)
+ .getFileLocWithOffset(MacroLoc.second);
Reader.Diag(PCHMissingLoc, diag::note_pch_macro_defined_as) << MacroName;
ConflictingDefines = true;
@@ -256,10 +343,12 @@
}
// Show the definition of this macro within the PCH file.
- llvm::StringRef::size_type Offset = PCHPredef.find(Missing);
- assert(Offset != llvm::StringRef::npos && "Unable to find macro!");
- SourceLocation PCHMissingLoc = SourceMgr.getLocForStartOfFile(PCHBufferID)
- .getFileLocWithOffset(Offset);
+ std::pair<FileID, llvm::StringRef::size_type> MacroLoc =
+ FindMacro(Buffers, Missing);
+ assert(MacroLoc.second!=llvm::StringRef::npos && "Unable to find macro!");
+ SourceLocation PCHMissingLoc =
+ SourceMgr.getLocForStartOfFile(MacroLoc.first)
+ .getFileLocWithOffset(MacroLoc.second);
Reader.Diag(PCHMissingLoc, diag::note_using_macro_def_from_pch);
}
@@ -609,27 +698,18 @@
Diag(diag::err_fe_pch_malformed) << Msg;
}
-/// \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.
+/// \brief Check the contents of the concatenation of all predefines buffers in
+/// the PCH chain against the contents of the predefines buffer of the current
+/// compiler invocation.
///
-/// \param PCHBufferID The FileID for the PCH predefines buffer.
+/// The contents should be the same. If not, then some command-line option
+/// changed the preprocessor state and we must probably reject the PCH file.
///
/// \returns true if there was a mismatch (in which case the PCH file
/// should be ignored), or false otherwise.
-bool PCHReader::CheckPredefinesBuffer(llvm::StringRef PCHPredef,
- FileID PCHBufferID) {
+bool PCHReader::CheckPredefinesBuffers() {
if (Listener)
- return Listener->ReadPredefinesBuffer(PCHPredef, PCHBufferID,
+ return Listener->ReadPredefinesBuffer(PCHPredefinesBuffers,
ActualOriginalFileName,
SuggestedPredefines);
return false;
@@ -958,9 +1038,11 @@
FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer, ID, Offset);
if (strcmp(Name, "<built-in>") == 0) {
- PCHPredefinesBufferID = BufferID;
- PCHPredefines = BlobStart;
- PCHPredefinesLen = BlobLen - 1;
+ PCHPredefinesBlock Block = {
+ BufferID,
+ llvm::StringRef(BlobStart, BlobLen - 1)
+ };
+ PCHPredefinesBuffers.push_back(Block);
}
break;
@@ -1636,8 +1718,7 @@
}
// Check the predefines buffer.
- if (CheckPredefinesBuffer(llvm::StringRef(PCHPredefines, PCHPredefinesLen),
- PCHPredefinesBufferID))
+ if (CheckPredefinesBuffers())
return IgnorePCH;
if (PP) {
Added: cfe/trunk/test/PCH/pchpch.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/pchpch.c?rev=108340&view=auto
==============================================================================
--- cfe/trunk/test/PCH/pchpch.c (added)
+++ cfe/trunk/test/PCH/pchpch.c Wed Jul 14 12:49:11 2010
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-pch -o %t1 %S/pchpch1.h
+// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-pch -o %t2 %S/pchpch2.h -include-pch %t1
+// RUN: %clang_cc1 -triple i386-unknown-unknown -fsyntax-only %s -include-pch %t2
+
+// The purpose of this test is to make sure that a PCH created while including
+// an existing PCH can be loaded.
Added: cfe/trunk/test/PCH/pchpch1.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/pchpch1.h?rev=108340&view=auto
==============================================================================
(empty)
Added: cfe/trunk/test/PCH/pchpch2.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/pchpch2.h?rev=108340&view=auto
==============================================================================
(empty)
More information about the cfe-commits
mailing list