diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/DeclBase.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Frontend/PCHReader.cpp | 126 | ||||
-rw-r--r-- | clang/lib/Frontend/PCHWriter.cpp | 20 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 10 |
4 files changed, 55 insertions, 108 deletions
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index be349428ecf..62783b140f9 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -519,6 +519,13 @@ DeclContext::decl_iterator DeclContext::decls_end(ASTContext &Context) const { 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/clang/lib/Frontend/PCHReader.cpp b/clang/lib/Frontend/PCHReader.cpp index 01a79b44d98..0e5b6ee8aa2 100644 --- a/clang/lib/Frontend/PCHReader.cpp +++ b/clang/lib/Frontend/PCHReader.cpp @@ -192,129 +192,63 @@ bool PCHReader::ReadSourceManagerBlock() { } } -/// \brief Read the type-offsets block. -bool PCHReader::ReadTypeOffsets() { - if (Stream.EnterSubBlock(pch::TYPE_OFFSETS_BLOCK_ID)) +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 (true) { + while (!Stream.AtEndOfStream()) { unsigned Code = Stream.ReadCode(); if (Code == llvm::bitc::END_BLOCK) { if (Stream.ReadBlockEnd()) - return Error("Error at end of TYPE_OFFSETS block"); + return Error("Error at end of module 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"); + switch (Stream.ReadSubBlockID()) { + case pch::DECLS_BLOCK_ID: // Skip decls block (lazily loaded) + case pch::TYPES_BLOCK_ID: // Skip types block (lazily loaded) + default: // Skip unknown content. + if (Stream.SkipBlock()) + return Error("Malformed block record"); + break; + + case pch::SOURCE_MANAGER_BLOCK_ID: + if (ReadSourceManagerBlock()) + return Error("Malformed source manager block"); + break; + } continue; } - + if (Code == llvm::bitc::DEFINE_ABBREV) { Stream.ReadAbbrevRecord(); continue; } - - // Read a record. + + // Read and process a record. Record.clear(); - switch (Stream.ReadRecord(Code, Record)) { + switch ((pch::PCHRecordTypes)Stream.ReadRecord(Code, Record)) { default: // Default behavior: ignore. break; + case pch::TYPE_OFFSET: if (!TypeOffsets.empty()) - return Error("Duplicate TYPE_OFFSETS block"); + return Error("Duplicate TYPE_OFFSET record in PCH file"); 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"); + return Error("Duplicate DECL_OFFSET record in PCH file"); 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. - while (!Stream.AtEndOfStream()) { - unsigned Code = Stream.ReadCode(); - if (Code == llvm::bitc::END_BLOCK) { - if (Stream.ReadBlockEnd()) - return Error("Error at end of module block"); - return false; - } - - if (Code == llvm::bitc::ENTER_SUBBLOCK) { - switch (Stream.ReadSubBlockID()) { - case pch::DECLS_BLOCK_ID: // Skip decls block (lazily loaded) - case pch::TYPES_BLOCK_ID: // Skip types block (lazily loaded) - default: // Skip unknown content. - if (Stream.SkipBlock()) - 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()) - return Error("Malformed type-offsets block"); - break; - - case pch::DECL_OFFSETS_BLOCK_ID: - if (ReadDeclOffsets()) - return Error("Malformed decl-offsets block"); - break; - } - } - } return Error("Premature end of bitstream"); } @@ -426,7 +360,7 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { // 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 @@ Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) { 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 @@ QualType PCHReader::GetType(unsigned ID) { 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 @@ Decl *PCHReader::GetDecl(unsigned ID) { } 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/clang/lib/Frontend/PCHWriter.cpp b/clang/lib/Frontend/PCHWriter.cpp index 1986b5945fb..f80d46ab5d9 100644 --- a/clang/lib/Frontend/PCHWriter.cpp +++ b/clang/lib/Frontend/PCHWriter.cpp @@ -490,7 +490,7 @@ void PCHWriter::WritePreprocessor(Preprocessor &PP) { /// \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 @@ void PCHWriter::WriteTypesBlock(ASTContext &Context) { // 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 @@ void PCHWriter::WriteTypesBlock(ASTContext &Context) { /// 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 @@ void PCHWriter::WriteDeclsBlock(ASTContext &Context) { } // 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 @@ void PCHWriter::WriteDeclsBlock(ASTContext &Context) { // 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 @@ void PCHWriter::AddTypeRef(QualType T, RecordData &Record) { } 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 @@ void PCHWriter::AddTypeRef(QualType T, RecordData &Record) { 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 @@ void PCHWriter::AddDeclRef(const Decl *D, RecordData &Record) { 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/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index b024d36acc3..4f87b48eff0 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -526,6 +526,16 @@ bool Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) { // __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; |