]> granicus.if.org Git - clang/commitdiff
Various minor fixes to PCH reading and writing, with general
authorDouglas Gregor <dgregor@apple.com>
Fri, 10 Apr 2009 17:25:41 +0000 (17:25 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 10 Apr 2009 17:25:41 +0000 (17:25 +0000)
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

include/clang/AST/DeclBase.h
include/clang/AST/DeclContextInternals.h
include/clang/AST/ExternalASTSource.h
include/clang/Frontend/PCHBitCodes.h
include/clang/Frontend/PCHReader.h
include/clang/Frontend/PCHWriter.h
lib/AST/DeclBase.cpp
lib/Frontend/PCHReader.cpp
lib/Frontend/PCHWriter.cpp
lib/Sema/SemaDecl.cpp
test/PCH/variables.c

index 46af4ec6b60cb7dd471eee755966754738112127..d05b5a597eb5dc1328ee43d3b78aeca6b46508d3 100644 (file)
@@ -549,6 +549,7 @@ public:
   /// this context. 
   decl_iterator decls_begin(ASTContext &Context) const;
   decl_iterator decls_end(ASTContext &Context) const;
+  bool decls_empty(ASTContext &Context) const;
 
   /// specific_decl_iterator - Iterates over a subrange of
   /// declarations stored in a DeclContext, providing only those that
index 7489413be89c5cde4d84f5fed913d1dbb199eb02..6a905be4a7e2a5985bd7e15d4af985c6db3e82b3 100644 (file)
@@ -112,7 +112,7 @@ public:
     if (VectorTy *Vector = getAsVector())
       delete Vector;
 
-    if (Vec.size() == 0)
+    if (Vec.empty())
       Data = 0;
     else
       Data = (Vec[0] << 2) | DK_DeclID;
index 17fa72612ff86ea5fd703e8c145409c68666acdd..f8b3c4db4d1e148fd08b8005439c1eb585dab3fa 100644 (file)
@@ -16,7 +16,6 @@
 #include "clang/AST/DeclarationName.h"
 #include "clang/AST/Type.h"
 #include "llvm/ADT/SmallVector.h"
-
 namespace clang {
 
 class Decl;
index 00bd1cfac26d97c67cef4ac347320fb1d88ad810..e4e50e3aa6b7e132f986d1d787b892b15e9d8560 100644 (file)
 
 namespace clang {
   namespace pch {
-    const int IDBits = 32;
-    typedef uint32_t ID;
+    /// \brief An ID number that refers to a declaration in a PCH file.
+    ///
+    /// The ID numbers of types are consecutive (in order of
+    /// discovery) and start at 2. 0 is reserved for NULL, and 1 is
+    /// reserved for the translation unit declaration.
+    typedef uint32_t DeclID;
+
+    /// \brief An ID number that refers to a type in a PCH file.
+    ///
+    /// The ID of a type is partitioned into two parts: the lower
+    /// three bits are used to store the const/volatile/restrict
+    /// qualifiers (as with QualType) and the upper bits provide a
+    /// type index. The type index values are partitioned into two
+    /// sets. The values below NUM_PREDEF_TYPE_IDs are predefined type
+    /// IDs (based on the PREDEF_TYPE_*_ID constants), with 0 as a
+    /// placeholder for "no type". Values from NUM_PREDEF_TYPE_IDs are
+    /// other types that have serialized representations.
+    typedef uint32_t TypeID;
 
     /// \brief Describes the various kinds of blocks that occur within
     /// a PCH file.
@@ -48,23 +64,39 @@ namespace clang {
       /// types used within the PCH file.
       TYPES_BLOCK_ID,
 
-      /// \brief The block containing the offsets of all of the types
-      /// used within the PCH.
-      ///
-      /// The offsets in this block point into the block identified by
-      /// TYPES_BLOCK_ID, and are indexed by the type ID.
-      TYPE_OFFSETS_BLOCK_ID,
-
       /// \brief The block containing the definitions of all of the
       /// declarations stored in the PCH file.
-      DECLS_BLOCK_ID,
+      DECLS_BLOCK_ID
+    };
 
-      /// \brief The block containing the offsets of all of the
-      /// declarations stored within the PCH file.
+    /// \brief Record types that occur within the PCH block itself.
+    enum PCHRecordTypes {
+      /// \brief Offset of each type within the types block.
       ///
-      /// The offsets in this block point into the block identified by
-      /// DECLS_BLOCK_ID, and are indexed by the decaration ID.
-      DECL_OFFSETS_BLOCK_ID
+      /// The TYPE_OFFSET constant describes the record that occurs
+      /// within the block identified by TYPE_OFFSETS_BLOCK_ID within
+      /// the PCH file. The record itself is an array of offsets that
+      /// point into the types block (identified by TYPES_BLOCK_ID in
+      /// the PCH file). The index into the array is based on the ID
+      /// of a type. For a given type ID @c T, the lower three bits of
+      /// @c T are its qualifiers (const, volatile, restrict), as in
+      /// the QualType class. The upper bits, after being shifted and
+      /// subtracting NUM_PREDEF_TYPE_IDS, are used to index into the
+      /// TYPE_OFFSET block to determine the offset of that type's
+      /// corresponding record within the TYPES_BLOCK_ID block.
+      TYPE_OFFSET = 1,
+      
+      /// \brief Record code for the offsets of each decl.
+      ///
+      /// The DECL_OFFSET constant describes the record that occurs
+      /// within the block identifier by DECL_OFFSETS_BLOCK_ID within
+      /// the PCH file. The record itself is an array of offsets that
+      /// point into the declarations block (identified by
+      /// DECLS_BLOCK_ID). The declaration ID is an index into this
+      /// record, after subtracting one to account for the use of
+      /// declaration ID 0 for a NULL declaration pointer. Index 0 is
+      /// reserved for the translation unit declaration.
+      DECL_OFFSET = 2
     };
 
     /// \brief Record types used within a source manager block.
@@ -209,20 +241,6 @@ namespace clang {
 
     /// \brief Record code for the offsets of each type.
     ///
-    /// The TYPE_OFFSET constant describes the record that occurs
-    /// within the block identified by TYPE_OFFSETS_BLOCK_ID within
-    /// the PCH file. The record itself is an array of offsets that
-    /// point into the types block (identified by TYPES_BLOCK_ID in
-    /// the PCH file). The index into the array is based on the ID of
-    /// a type. For a given type ID @c T, the lower three bits of @c T
-    /// are its qualifiers (const, volatile, restrict), as in the
-    /// QualType class. The upper bits, after being shifted and
-    /// subtracting NUM_PREDEF_TYPE_IDS, are used to index into the
-    /// TYPE_OFFSET block to determine the offset of that type's
-    /// corresponding record within the TYPES_BLOCK_ID block.
-    enum TypeOffsetCode {
-      TYPE_OFFSET = 1
-    };
 
     /// \brief Record codes for each kind of declaration.
     ///
@@ -255,21 +273,6 @@ namespace clang {
       /// into a DeclContext via DeclContext::lookup.
       DECL_CONTEXT_VISIBLE
     };
-
-    /// \brief Record code for the offsets of each decl.
-    ///
-    /// The DECL_OFFSET constant describes the record that occurs
-    /// within the block identifier by DECL_OFFSETS_BLOCK_ID within
-    /// the PCH file. The record itself is an array of offsets that
-    /// point into the declarations block (identified by
-    /// DECLS_BLOCK_ID). The declaration ID is an index into this
-    /// record, after subtracting one to account for the use of
-    /// declaration ID 0 for a NULL declaration pointer. Index 0 is
-    /// reserved for the translation unit declaration.
-    enum DeclOffsetCode {
-      DECL_OFFSET = 1
-    };
-
     /// @}
   }
 } // end namespace clang
index fe7632896e9230918c2f4b2a119e8b4da2818db9..52354e3eb3a37fa1da5e82a9c2289c69a46f380e 100644 (file)
@@ -16,6 +16,7 @@
 #include "clang/AST/DeclarationName.h"
 #include "clang/AST/ExternalASTSource.h"
 #include "clang/AST/Type.h"
+#include "clang/Frontend/PCHBitCodes.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/ADT/SmallVector.h"
@@ -100,8 +101,6 @@ class PCHReader : public ExternalASTSource {
 
   bool ReadPCHBlock();
   bool ReadSourceManagerBlock();
-  bool ReadTypeOffsets();
-  bool ReadDeclOffsets();
 
   QualType ReadTypeRecord(uint64_t Offset);
   void LoadedDecl(unsigned Index, Decl *D);
@@ -122,11 +121,11 @@ public:
 
   /// \brief Resolve a type ID into a type, potentially building a new
   /// type.
-  virtual QualType GetType(unsigned ID);
+  virtual QualType GetType(pch::TypeID ID);
 
   /// \brief Resolve a declaration ID into a declaration, potentially
   /// building a new declaration.
-  virtual Decl *GetDecl(unsigned ID);
+  virtual Decl *GetDecl(pch::DeclID ID);
 
   /// \brief Read all of the declarations lexically stored in a
   /// declaration context.
index 01eb2b0a77428b9cace45f23b42d37de0b98e22f..a560857be217a319411779ac0b802f422046838b 100644 (file)
@@ -50,7 +50,7 @@ class PCHWriter {
   /// The ID numbers of declarations are consecutive (in order of
   /// discovery) and start at 2. 1 is reserved for the translation
   /// unit, while 0 is reserved for NULL.
-  llvm::DenseMap<const Decl *, pch::ID> DeclIDs;
+  llvm::DenseMap<const Decl *, pch::DeclID> DeclIDs;
 
   /// \brief Offset of each declaration in the bitstream, indexed by
   /// the declaration's ID.
@@ -67,14 +67,14 @@ class PCHWriter {
   /// and start at 1. 0 is reserved for NULL. When types are actually
   /// stored in the stream, the ID number is shifted by 3 bits to
   /// allow for the const/volatile/restrict qualifiers.
-  llvm::DenseMap<const Type *, pch::ID> TypeIDs;
+  llvm::DenseMap<const Type *, pch::TypeID> TypeIDs;
 
   /// \brief Offset of each type in the bitstream, indexed by
   /// the type's ID.
   llvm::SmallVector<uint64_t, 16> TypeOffsets;
 
   /// \brief The type ID that will be assigned to the next new type.
-  unsigned NextTypeID;
+  pch::TypeID NextTypeID;
 
   void WriteSourceManagerBlock(SourceManager &SourceMgr);
   void WritePreprocessor(Preprocessor &PP);
index be349428ecfda5992e0fcf256119c9c0a45858e9..62783b140f91363075852bd0aa0882b808be40cd 100644 (file)
@@ -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");
index 01a79b44d98b5ad8cf160dd0eca3da9972a86ef0..0e5b6ee8aa2e0ce6e40a10f011e40ba94168df79 100644 (file)
@@ -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;
index 1986b5945fb4c39d19e1b90ac2682c721c9dd6a9..f80d46ab5d9de061e73559a38dca2554d35af3a4 100644 (file)
@@ -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.
index b024d36acc36a67fbe7c822e25fb9a2f4a48049a..4f87b48eff0cd062078d3a5a0967d8dd4afa9f34 100644 (file)
@@ -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;
index a5283f92ad3edb67fbafaa6aa73fe614d7bb91f1..ffb9ec08c0ea4e350094bfa22d49fb38e7185165 100644 (file)
@@ -1,5 +1,5 @@
-// RUN: clang-cc -emit-pch -o %t %S/variables.h &&
-// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s 
+// RUN: clang-cc -emit-pch -triple=i686-apple-darwin9 -o %t %S/variables.h &&
+// RUN: clang-cc -triple=i686-apple-darwin9 -include-pch %t -fsyntax-only -verify %s 
 
 int *ip2 = &x;
 float *fp = &ip; // expected-warning{{incompatible pointer types}}