Various minor fixes to PCH reading and writing, with general
cleanup. Aside from a minor tweak to the PCH file format, no
functionality change.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68793 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index be34942..62783b1 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -519,6 +519,13 @@
return decl_iterator();
}
+bool DeclContext::decls_empty(ASTContext &Context) const {
+ if (hasExternalLexicalStorage())
+ LoadLexicalDeclsFromExternalStorage(Context);
+
+ return !FirstDecl;
+}
+
void DeclContext::addDecl(ASTContext &Context, Decl *D) {
assert(D->getLexicalDeclContext() == this &&
"Decl inserted into wrong lexical context");
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 01a79b4..0e5b6ee 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -192,95 +192,12 @@
}
}
-/// \brief Read the type-offsets block.
-bool PCHReader::ReadTypeOffsets() {
- if (Stream.EnterSubBlock(pch::TYPE_OFFSETS_BLOCK_ID))
- return Error("Malformed block record");
-
- RecordData Record;
- while (true) {
- unsigned Code = Stream.ReadCode();
- if (Code == llvm::bitc::END_BLOCK) {
- if (Stream.ReadBlockEnd())
- return Error("Error at end of TYPE_OFFSETS 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.
- Record.clear();
- switch (Stream.ReadRecord(Code, Record)) {
- default: // Default behavior: ignore.
- break;
- case pch::TYPE_OFFSET:
- if (!TypeOffsets.empty())
- return Error("Duplicate TYPE_OFFSETS block");
- TypeOffsets.swap(Record);
- TypeAlreadyLoaded.resize(TypeOffsets.size(), false);
- break;
- }
- }
-}
-
-/// \brief Read the decl-offsets block.
-bool PCHReader::ReadDeclOffsets() {
- if (Stream.EnterSubBlock(pch::DECL_OFFSETS_BLOCK_ID))
- return Error("Malformed block record");
-
- RecordData Record;
- while (true) {
- unsigned Code = Stream.ReadCode();
- if (Code == llvm::bitc::END_BLOCK) {
- if (Stream.ReadBlockEnd())
- return Error("Error at end of DECL_OFFSETS 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.
- Record.clear();
- switch (Stream.ReadRecord(Code, Record)) {
- default: // Default behavior: ignore.
- break;
- case pch::DECL_OFFSET:
- if (!DeclOffsets.empty())
- return Error("Duplicate DECL_OFFSETS block");
- DeclOffsets.swap(Record);
- DeclAlreadyLoaded.resize(DeclOffsets.size(), false);
- break;
- }
- }
-}
-
bool PCHReader::ReadPCHBlock() {
if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID))
return Error("Malformed block record");
// Read all of the records and blocks for the PCH file.
+ RecordData Record;
while (!Stream.AtEndOfStream()) {
unsigned Code = Stream.ReadCode();
if (Code == llvm::bitc::END_BLOCK) {
@@ -302,17 +219,34 @@
if (ReadSourceManagerBlock())
return Error("Malformed source manager block");
break;
-
- case pch::TYPE_OFFSETS_BLOCK_ID:
- if (ReadTypeOffsets())
- return Error("Malformed type-offsets block");
- break;
-
- case pch::DECL_OFFSETS_BLOCK_ID:
- if (ReadDeclOffsets())
- return Error("Malformed decl-offsets block");
- break;
}
+ continue;
+ }
+
+ if (Code == llvm::bitc::DEFINE_ABBREV) {
+ Stream.ReadAbbrevRecord();
+ continue;
+ }
+
+ // Read and process a record.
+ Record.clear();
+ switch ((pch::PCHRecordTypes)Stream.ReadRecord(Code, Record)) {
+ default: // Default behavior: ignore.
+ break;
+
+ case pch::TYPE_OFFSET:
+ if (!TypeOffsets.empty())
+ return Error("Duplicate TYPE_OFFSET record in PCH file");
+ TypeOffsets.swap(Record);
+ TypeAlreadyLoaded.resize(TypeOffsets.size(), false);
+ break;
+
+ case pch::DECL_OFFSET:
+ if (!DeclOffsets.empty())
+ return Error("Duplicate DECL_OFFSET record in PCH file");
+ DeclOffsets.swap(Record);
+ DeclAlreadyLoaded.resize(DeclOffsets.size(), false);
+ break;
}
}
@@ -426,7 +360,7 @@
// FIXME: Several other kinds of types to deserialize here!
default:
- assert("Unable to deserialize this type");
+ assert(false && "Unable to deserialize this type");
break;
}
@@ -500,7 +434,7 @@
return D;
}
-QualType PCHReader::GetType(unsigned ID) {
+QualType PCHReader::GetType(pch::TypeID ID) {
unsigned Quals = ID & 0x07;
unsigned Index = ID >> 3;
@@ -550,7 +484,7 @@
return QualType(reinterpret_cast<Type *>(TypeOffsets[Index]), Quals);
}
-Decl *PCHReader::GetDecl(unsigned ID) {
+Decl *PCHReader::GetDecl(pch::DeclID ID) {
if (ID == 0)
return 0;
@@ -563,7 +497,7 @@
}
bool PCHReader::ReadDeclsLexicallyInContext(DeclContext *DC,
- llvm::SmallVectorImpl<unsigned> &Decls) {
+ llvm::SmallVectorImpl<pch::DeclID> &Decls) {
assert(DC->hasExternalLexicalStorage() &&
"DeclContext has no lexical decls in storage");
uint64_t Offset = DeclContextOffsets[DC].first;
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index 1986b59..f80d46a 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -490,7 +490,7 @@
/// \brief Write the representation of a type to the PCH stream.
void PCHWriter::WriteType(const Type *T) {
- pch::ID &ID = TypeIDs[T];
+ pch::TypeID &ID = TypeIDs[T];
if (ID == 0) // we haven't seen this type before.
ID = NextTypeID++;
@@ -547,10 +547,8 @@
// Exit the types block
S.ExitBlock();
- // Write the type offsets block
- S.EnterSubblock(pch::TYPE_OFFSETS_BLOCK_ID, 2);
+ // Write the type offsets record
S.EmitRecord(pch::TYPE_OFFSET, TypeOffsets);
- S.ExitBlock();
}
/// \brief Write the block containing all of the declaration IDs
@@ -560,7 +558,7 @@
/// bistream, or 0 if no block was written.
uint64_t PCHWriter::WriteDeclContextLexicalBlock(ASTContext &Context,
DeclContext *DC) {
- if (DC->decls_begin(Context) == DC->decls_end(Context))
+ if (DC->decls_empty(Context))
return 0;
uint64_t Offset = S.GetCurrentBitNo();
@@ -638,7 +636,7 @@
}
// Determine the ID for this declaration
- pch::ID ID = DeclIDs[D];
+ pch::DeclID ID = DeclIDs[D];
if (ID == 0)
ID = DeclIDs.size();
@@ -664,10 +662,8 @@
// Exit the declarations block
S.ExitBlock();
- // Write the declaration offsets block
- S.EnterSubblock(pch::DECL_OFFSETS_BLOCK_ID, 2);
+ // Write the declaration offsets record
S.EmitRecord(pch::DECL_OFFSET, DeclOffsets);
- S.ExitBlock();
}
PCHWriter::PCHWriter(llvm::BitstreamWriter &S)
@@ -720,7 +716,7 @@
}
if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr())) {
- pch::ID ID;
+ pch::TypeID ID;
switch (BT->getKind()) {
case BuiltinType::Void: ID = pch::PREDEF_TYPE_VOID_ID; break;
case BuiltinType::Bool: ID = pch::PREDEF_TYPE_BOOL_ID; break;
@@ -748,7 +744,7 @@
return;
}
- pch::ID &ID = TypeIDs[T.getTypePtr()];
+ pch::TypeID &ID = TypeIDs[T.getTypePtr()];
if (ID == 0) // we haven't seen this type before
ID = NextTypeID++;
@@ -762,7 +758,7 @@
return;
}
- pch::ID &ID = DeclIDs[D];
+ pch::DeclID &ID = DeclIDs[D];
if (ID == 0) {
// We haven't seen this declaration before. Give it a new ID and
// enqueue it in the list of declarations to emit.
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index b024d36..4f87b48 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -526,6 +526,16 @@
// __builtin_va_list gets redeclared in the built-in definitions
// buffer when using PCH. Don't complain about such redefinitions.
+ //
+ // FIXME: The problem here is that the __builtin_va_list declaration
+ // comes in as target-specific text in the predefines buffer, both
+ // in the generation of the PCH file and in the source file. Thus,
+ // we end up with two typedefs for the same type, which is an error
+ // in C. Our hackish solution is to allow redundant typedefs *to the
+ // same type* if the types are defined in the predefined buffer. We
+ // would like to eliminate this ugliness, perhaps by making
+ // __builtin_va_list a real, Sema-supplied declaration rather than
+ // putting its text into the predefines buffer.
if (Context.getExternalSource() &&
strcmp(SourceMgr.getBufferName(New->getLocation()), "<built-in>") == 0)
return false;