diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/include/clang/Basic/OnDiskHashTable.h | 18 | ||||
| -rw-r--r-- | clang/include/clang/Serialization/ASTBitCodes.h | 31 | ||||
| -rw-r--r-- | clang/include/clang/Serialization/ASTReader.h | 22 | ||||
| -rw-r--r-- | clang/include/clang/Serialization/ASTWriter.h | 26 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 164 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 136 | 
6 files changed, 362 insertions, 35 deletions
diff --git a/clang/include/clang/Basic/OnDiskHashTable.h b/clang/include/clang/Basic/OnDiskHashTable.h index 2019e27ce5d..aa3f344a6a4 100644 --- a/clang/include/clang/Basic/OnDiskHashTable.h +++ b/clang/include/clang/Basic/OnDiskHashTable.h @@ -124,8 +124,9 @@ class OnDiskChainedHashTableGenerator {      Item *next;      const uint32_t hash; -    Item(typename Info::key_type_ref k, typename Info::data_type_ref d) -    : key(k), data(d), next(0), hash(Info::ComputeHash(k)) {} +    Item(typename Info::key_type_ref k, typename Info::data_type_ref d, +         Info &InfoObj) +    : key(k), data(d), next(0), hash(InfoObj.ComputeHash(k)) {}    };    class Bucket { @@ -168,10 +169,17 @@ public:    void insert(typename Info::key_type_ref key,                typename Info::data_type_ref data) { +    Info InfoObj; +    insert(key, data, InfoObj); +  } + +  void insert(typename Info::key_type_ref key, +              typename Info::data_type_ref data, Info &InfoObj) {      ++NumEntries;      if (4*NumEntries >= 3*NumBuckets) resize(NumBuckets*2); -    insert(Buckets, NumBuckets, new (BA.Allocate<Item>()) Item(key, data)); +    insert(Buckets, NumBuckets, new (BA.Allocate<Item>()) Item(key, data, +                                                               InfoObj));    }    io::Offset Emit(llvm::raw_ostream &out) { @@ -278,8 +286,8 @@ public:        InfoPtr = &InfoObj;      using namespace io; -    const internal_key_type& iKey = Info::GetInternalKey(eKey); -    unsigned key_hash = Info::ComputeHash(iKey); +    const internal_key_type& iKey = InfoObj.GetInternalKey(eKey); +    unsigned key_hash = InfoObj.ComputeHash(iKey);      // Each bucket is just a 32-bit offset into the hash table file.      unsigned idx = key_hash & (NumBuckets - 1); diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 3156a36040a..4a3fc59e2e2 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -20,6 +20,7 @@  #include "clang/AST/Type.h"  #include "llvm/Bitcode/BitCodes.h"  #include "llvm/System/DataTypes.h" +#include "llvm/ADT/DenseMap.h"  namespace clang {    namespace serialization { @@ -81,6 +82,36 @@ namespace clang {        }      }; +    /// A structure for putting "fast"-unqualified QualTypes into a +    /// DenseMap.  This uses the standard pointer hash function. +    struct UnsafeQualTypeDenseMapInfo { +      static inline bool isEqual(QualType A, QualType B) { return A == B; } +      static inline QualType getEmptyKey() { +        return QualType::getFromOpaquePtr((void*) 1); +      } +      static inline QualType getTombstoneKey() { +        return QualType::getFromOpaquePtr((void*) 2); +      } +      static inline unsigned getHashValue(QualType T) { +        assert(!T.getLocalFastQualifiers() &&  +               "hash invalid for types with fast quals"); +        uintptr_t v = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); +        return (unsigned(v) >> 4) ^ (unsigned(v) >> 9); +      } +    }; + +    /// \brief Map that provides the ID numbers of each type within the +    /// output stream, plus those deserialized from a chained PCH. +    /// +    /// The ID numbers of types are consecutive (in order of discovery) +    /// and start at 1. 0 is reserved for NULL. When types are actually +    /// stored in the stream, the ID number is shifted by 2 bits to +    /// allow for the const/volatile qualifiers. +    /// +    /// Keys in the map never have const/volatile qualifiers. +    typedef llvm::DenseMap<QualType, TypeIdx, UnsafeQualTypeDenseMapInfo> +        TypeIdxMap; +      /// \brief An ID number that refers to an identifier in an AST      /// file.      typedef uint32_t IdentID; diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index cbc3775cefe..aff52195a9f 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -27,7 +27,6 @@  #include "llvm/ADT/APFloat.h"  #include "llvm/ADT/APInt.h"  #include "llvm/ADT/APSInt.h" -#include "llvm/ADT/DenseMap.h"  #include "llvm/ADT/OwningPtr.h"  #include "llvm/ADT/SmallVector.h"  #include "llvm/ADT/StringRef.h" @@ -315,6 +314,17 @@ private:    /// ID = (I + 1) << FastQual::Width has already been loaded    std::vector<QualType> TypesLoaded; +  /// \brief Map that provides the ID numbers of each type within the +  /// output stream, plus those deserialized from a chained PCH. +  /// +  /// The ID numbers of types are consecutive (in order of discovery) +  /// and start at 1. 0 is reserved for NULL. When types are actually +  /// stored in the stream, the ID number is shifted by 2 bits to +  /// allow for the const/volatile qualifiers. +  /// +  /// Keys in the map never have const/volatile qualifiers. +  serialization::TypeIdxMap TypeIdxs; +    /// \brief Declarations that have already been loaded from the chain.    ///    /// When the pointer at index I is non-NULL, the declaration with ID @@ -720,6 +730,16 @@ public:    /// type.    QualType GetType(serialization::TypeID ID); +  /// \brief Returns the type ID associated with the given type. +  /// If the type didn't come from the AST file the ID that is returned is +  /// marked as "doesn't exist in AST". +  serialization::TypeID GetTypeID(QualType T) const; + +  /// \brief Returns the type index associated with the given type. +  /// If the type didn't come from the AST file the index that is returned is +  /// marked as "doesn't exist in AST". +  serialization::TypeIdx GetTypeIdx(QualType T) const; +    /// \brief Resolve a declaration ID into a declaration, potentially    /// building a new declaration.    Decl *GetDecl(serialization::DeclID ID); diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index 15977efe763..9ef14925bca 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -20,7 +20,6 @@  #include "clang/Serialization/ASTBitCodes.h"  #include "clang/Serialization/ASTDeserializationListener.h"  #include "clang/Sema/SemaConsumer.h" -#include "llvm/ADT/DenseMap.h"  #include "llvm/ADT/SmallPtrSet.h"  #include "llvm/ADT/SmallVector.h"  #include "llvm/Bitcode/BitstreamWriter.h" @@ -50,24 +49,6 @@ class SourceManager;  class SwitchCase;  class TargetInfo; -/// A structure for putting "fast"-unqualified QualTypes into a -/// DenseMap.  This uses the standard pointer hash function. -struct UnsafeQualTypeDenseMapInfo { -  static inline bool isEqual(QualType A, QualType B) { return A == B; } -  static inline QualType getEmptyKey() { -    return QualType::getFromOpaquePtr((void*) 1); -  } -  static inline QualType getTombstoneKey() { -    return QualType::getFromOpaquePtr((void*) 2); -  } -  static inline unsigned getHashValue(QualType T) { -    assert(!T.getLocalFastQualifiers() &&  -           "hash invalid for types with fast quals"); -    uintptr_t v = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); -    return (unsigned(v) >> 4) ^ (unsigned(v) >> 9); -  } -}; -  /// \brief Writes an AST file containing the contents of a translation unit.  ///  /// The ASTWriter class produces a bitstream containing the serialized @@ -146,8 +127,7 @@ private:    /// allow for the const/volatile qualifiers.    ///    /// Keys in the map never have const/volatile qualifiers. -  llvm::DenseMap<QualType, serialization::TypeIdx, UnsafeQualTypeDenseMapInfo> -      TypeIdxs; +  serialization::TypeIdxMap TypeIdxs;    /// \brief Offset of each type in the bitstream, indexed by    /// the type's ID. @@ -368,13 +348,13 @@ public:    serialization::TypeID GetOrCreateTypeID(QualType T);    /// \brief Determine the type ID of an already-emitted type. -  serialization::TypeID getTypeID(QualType T); +  serialization::TypeID getTypeID(QualType T) const;    /// \brief Force a type to be emitted and get its index.    serialization::TypeIdx GetOrCreateTypeIdx(QualType T);    /// \brief Determine the type index of an already-emitted type. -  serialization::TypeIdx getTypeIdx(QualType T); +  serialization::TypeIdx getTypeIdx(QualType T) const;    /// \brief Emits a reference to a declarator info.    void AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordData &Record); diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 040277074c2..05fa7cd1156 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -704,6 +704,148 @@ public:  typedef OnDiskChainedHashTable<ASTIdentifierLookupTrait>    ASTIdentifierLookupTable; +namespace { +class ASTDeclContextNameLookupTrait { +  ASTReader &Reader; + +public: +  /// \brief Pair of begin/end iterators for DeclIDs. +  typedef std::pair<DeclID *, DeclID *> data_type; + +  /// \brief Special internal key for declaration names. +  /// The hash table creates keys for comparison; we do not create +  /// a DeclarationName for the internal key to avoid deserializing types. +  struct DeclNameKey { +    DeclarationName::NameKind Kind; +    uint64_t Data; +    DeclNameKey() : Kind((DeclarationName::NameKind)0), Data(0) { } +  }; + +  typedef DeclarationName external_key_type; +  typedef DeclNameKey internal_key_type; + +  explicit ASTDeclContextNameLookupTrait(ASTReader &Reader) : Reader(Reader) { } + +  static bool EqualKey(const internal_key_type& a, +                       const internal_key_type& b) { +    return a.Kind == b.Kind && a.Data == b.Data; +  } + +  unsigned ComputeHash(const DeclNameKey &Key) const { +    llvm::FoldingSetNodeID ID; +    ID.AddInteger(Key.Kind); + +    switch (Key.Kind) { +    case DeclarationName::Identifier: +    case DeclarationName::CXXLiteralOperatorName: +      ID.AddString(((IdentifierInfo*)Key.Data)->getName()); +      break; +    case DeclarationName::ObjCZeroArgSelector: +    case DeclarationName::ObjCOneArgSelector: +    case DeclarationName::ObjCMultiArgSelector: +      ID.AddInteger(serialization::ComputeHash(Selector(Key.Data))); +      break; +    case DeclarationName::CXXConstructorName: +    case DeclarationName::CXXDestructorName: +    case DeclarationName::CXXConversionFunctionName: +      ID.AddInteger((TypeID)Key.Data); +      break; +    case DeclarationName::CXXOperatorName: +      ID.AddInteger((OverloadedOperatorKind)Key.Data); +      break; +    case DeclarationName::CXXUsingDirective: +      break; +    } + +    return ID.ComputeHash(); +  } + +  internal_key_type GetInternalKey(const external_key_type& Name) const { +    DeclNameKey Key; +    Key.Kind = Name.getNameKind(); +    switch (Name.getNameKind()) { +    case DeclarationName::Identifier: +      Key.Data = (uint64_t)Name.getAsIdentifierInfo(); +      break; +    case DeclarationName::ObjCZeroArgSelector: +    case DeclarationName::ObjCOneArgSelector: +    case DeclarationName::ObjCMultiArgSelector: +      Key.Data = (uint64_t)Name.getObjCSelector().getAsOpaquePtr(); +      break; +    case DeclarationName::CXXConstructorName: +    case DeclarationName::CXXDestructorName: +    case DeclarationName::CXXConversionFunctionName: +      Key.Data = Reader.GetTypeID(Name.getCXXNameType()); +      break; +    case DeclarationName::CXXOperatorName: +      Key.Data = Name.getCXXOverloadedOperator(); +      break; +    case DeclarationName::CXXLiteralOperatorName: +      Key.Data = (uint64_t)Name.getCXXLiteralIdentifier(); +      break; +    case DeclarationName::CXXUsingDirective: +      break; +    } +     +    return Key; +  } + +  static std::pair<unsigned, unsigned> +  ReadKeyDataLength(const unsigned char*& d) { +    using namespace clang::io; +    unsigned KeyLen = ReadUnalignedLE16(d); +    unsigned DataLen = ReadUnalignedLE16(d); +    return std::make_pair(KeyLen, DataLen); +  } + +  internal_key_type ReadKey(const unsigned char* d, unsigned) { +    using namespace clang::io; + +    DeclNameKey Key; +    Key.Kind = (DeclarationName::NameKind)*d++; +    switch (Key.Kind) { +    case DeclarationName::Identifier: +      Key.Data = (uint64_t)Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d)); +      break; +    case DeclarationName::ObjCZeroArgSelector: +    case DeclarationName::ObjCOneArgSelector: +    case DeclarationName::ObjCMultiArgSelector: +      Key.Data =  +         (uint64_t)Reader.DecodeSelector(ReadUnalignedLE32(d)).getAsOpaquePtr(); +      break; +    case DeclarationName::CXXConstructorName: +    case DeclarationName::CXXDestructorName: +    case DeclarationName::CXXConversionFunctionName: +      Key.Data = ReadUnalignedLE32(d); // TypeID +      break; +    case DeclarationName::CXXOperatorName: +      Key.Data = *d++; // OverloadedOperatorKind +      break; +    case DeclarationName::CXXLiteralOperatorName: +      Key.Data = (uint64_t)Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d)); +      break; +    case DeclarationName::CXXUsingDirective: +      break; +    } +     +    return Key; +  } + +  data_type ReadData(internal_key_type, const unsigned char* d, +                     unsigned DataLen) { +    using namespace clang::io; +    unsigned NumDecls = ReadUnalignedLE16(d); +    DeclID *Start = (DeclID *)d; +    return std::make_pair(Start, Start + NumDecls); +  } +}; + +} // end anonymous namespace + +/// \brief The on-disk hash table used for the DeclContext's Name lookup table. +typedef OnDiskChainedHashTable<ASTDeclContextNameLookupTrait> +  ASTDeclContextNameLookupTable; +  void ASTReader::Error(const char *Msg) {    Diag(diag::err_fe_pch_malformed) << Msg;  } @@ -2825,6 +2967,7 @@ QualType ASTReader::GetType(TypeID ID) {    if (TypesLoaded[Index].isNull()) {      TypesLoaded[Index] = ReadTypeRecord(Index);      TypesLoaded[Index]->setFromAST(); +    TypeIdxs[TypesLoaded[Index]] = TypeIdx::fromTypeID(ID);      if (DeserializationListener)        DeserializationListener->TypeRead(TypeIdx::fromTypeID(ID),                                          TypesLoaded[Index]); @@ -2833,6 +2976,27 @@ QualType ASTReader::GetType(TypeID ID) {    return TypesLoaded[Index].withFastQualifiers(FastQuals);  } +TypeID ASTReader::GetTypeID(QualType T) const { +  return MakeTypeID(T, +              std::bind1st(std::mem_fun(&ASTReader::GetTypeIdx), this)); +} + +TypeIdx ASTReader::GetTypeIdx(QualType T) const { +  if (T.isNull()) +    return TypeIdx(); +  assert(!T.getLocalFastQualifiers()); + +  TypeIdxMap::const_iterator I = TypeIdxs.find(T); +  // GetTypeIdx is mostly used for computing the hash of DeclarationNames and +  // comparing keys of ASTDeclContextNameLookupTable. +  // If the type didn't come from the AST file use a specially marked index +  // so that any hash/key comparison fail since no such index is stored +  // in a AST file. +  if (I == TypeIdxs.end()) +    return TypeIdx(-1); +  return I->second; +} +  TemplateArgumentLocInfo  ASTReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,                                        llvm::BitstreamCursor &DeclsCursor, diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 716abde892d..94be24ad2c5 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -1653,6 +1653,7 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) {    // Create and write out the blob that contains selectors and the method pool.    {      OnDiskChainedHashTableGenerator<ASTMethodPoolTrait> Generator; +    ASTMethodPoolTrait Trait(*this);      // Create the on-disk hash table representation. We walk through every      // selector we've seen and look it up in the method pool. @@ -1692,7 +1693,7 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) {          // A new method pool entry.          ++NumTableEntries;        } -      Generator.insert(S, Data); +      Generator.insert(S, Data, Trait);      }      // Create the on-disk hash table in a buffer. @@ -1877,6 +1878,7 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP) {    // strings.    {      OnDiskChainedHashTableGenerator<ASTIdentifierTableTrait> Generator; +    ASTIdentifierTableTrait Trait(*this, PP);      // Look for any identifiers that were named while processing the      // headers, but are otherwise not needed. We add these to the hash @@ -1896,7 +1898,7 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP) {           ID != IDEnd; ++ID) {        assert(ID->first && "NULL identifier in identifier table");        if (!Chain || !ID->first->isFromAST()) -        Generator.insert(ID->first, ID->second); +        Generator.insert(ID->first, ID->second, Trait);      }      // Create the on-disk hash table in a buffer. @@ -1940,6 +1942,127 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP) {  }  //===----------------------------------------------------------------------===// +// DeclContext's Name Lookup Table Serialization +//===----------------------------------------------------------------------===// + +namespace { +// Trait used for the on-disk hash table used in the method pool. +class ASTDeclContextNameLookupTrait { +  ASTWriter &Writer; + +public: +  typedef DeclarationName key_type; +  typedef key_type key_type_ref; + +  typedef DeclContext::lookup_result data_type; +  typedef const data_type& data_type_ref; + +  explicit ASTDeclContextNameLookupTrait(ASTWriter &Writer) : Writer(Writer) { } + +  unsigned ComputeHash(DeclarationName Name) { +    llvm::FoldingSetNodeID ID; +    ID.AddInteger(Name.getNameKind()); + +    switch (Name.getNameKind()) { +    case DeclarationName::Identifier: +      ID.AddString(Name.getAsIdentifierInfo()->getName()); +      break; +    case DeclarationName::ObjCZeroArgSelector: +    case DeclarationName::ObjCOneArgSelector: +    case DeclarationName::ObjCMultiArgSelector: +      ID.AddInteger(serialization::ComputeHash(Name.getObjCSelector())); +      break; +    case DeclarationName::CXXConstructorName: +    case DeclarationName::CXXDestructorName: +    case DeclarationName::CXXConversionFunctionName: +      ID.AddInteger(Writer.GetOrCreateTypeID(Name.getCXXNameType())); +      break; +    case DeclarationName::CXXOperatorName: +      ID.AddInteger(Name.getCXXOverloadedOperator()); +      break; +    case DeclarationName::CXXLiteralOperatorName: +      ID.AddString(Name.getCXXLiteralIdentifier()->getName()); +    case DeclarationName::CXXUsingDirective: +      break; +    } + +    return ID.ComputeHash(); +  } + +  std::pair<unsigned,unsigned> +    EmitKeyDataLength(llvm::raw_ostream& Out, DeclarationName Name, +                      data_type_ref Lookup) { +    unsigned KeyLen = 1; +    switch (Name.getNameKind()) { +    case DeclarationName::Identifier: +    case DeclarationName::ObjCZeroArgSelector: +    case DeclarationName::ObjCOneArgSelector: +    case DeclarationName::ObjCMultiArgSelector: +    case DeclarationName::CXXConstructorName: +    case DeclarationName::CXXDestructorName: +    case DeclarationName::CXXConversionFunctionName: +    case DeclarationName::CXXLiteralOperatorName: +      KeyLen += 4; +      break; +    case DeclarationName::CXXOperatorName: +      KeyLen += 1; +      break; +    case DeclarationName::CXXUsingDirective: +      break; +    } +    clang::io::Emit16(Out, KeyLen); + +    // 2 bytes for num of decls and 4 for each DeclID. +    unsigned DataLen = 2 + 4 * (Lookup.second - Lookup.first); +    clang::io::Emit16(Out, DataLen); + +    return std::make_pair(KeyLen, DataLen); +  } + +  void EmitKey(llvm::raw_ostream& Out, DeclarationName Name, unsigned) { +    using namespace clang::io; + +    assert(Name.getNameKind() < 0x100 && "Invalid name kind ?"); +    Emit8(Out, Name.getNameKind()); +    switch (Name.getNameKind()) { +    case DeclarationName::Identifier: +      Emit32(Out, Writer.getIdentifierRef(Name.getAsIdentifierInfo())); +      break; +    case DeclarationName::ObjCZeroArgSelector: +    case DeclarationName::ObjCOneArgSelector: +    case DeclarationName::ObjCMultiArgSelector: +      Emit32(Out, Writer.getSelectorRef(Name.getObjCSelector())); +      break; +    case DeclarationName::CXXConstructorName: +    case DeclarationName::CXXDestructorName: +    case DeclarationName::CXXConversionFunctionName: +      Emit32(Out, Writer.getTypeID(Name.getCXXNameType())); +      break; +    case DeclarationName::CXXOperatorName: +      assert(Name.getCXXOverloadedOperator() < 0x100 && "Invalid operator ?"); +      Emit8(Out, Name.getCXXOverloadedOperator()); +      break; +    case DeclarationName::CXXLiteralOperatorName: +      Emit32(Out, Writer.getIdentifierRef(Name.getCXXLiteralIdentifier())); +      break; +    case DeclarationName::CXXUsingDirective: +      break; +    } +  } + +  void EmitData(llvm::raw_ostream& Out, key_type_ref, +                data_type Lookup, unsigned DataLen) { +    uint64_t Start = Out.tell(); (void)Start; +    clang::io::Emit16(Out, Lookup.second - Lookup.first); +    for (; Lookup.first != Lookup.second; ++Lookup.first) +      clang::io::Emit32(Out, Writer.GetDeclRef(*Lookup.first)); + +    assert(Out.tell() - Start == DataLen && "Data length is wrong"); +  } +}; +} // end anonymous namespace + +//===----------------------------------------------------------------------===//  // General Serialization Routines  //===----------------------------------------------------------------------===// @@ -2587,7 +2710,7 @@ TypeID ASTWriter::GetOrCreateTypeID(QualType T) {                std::bind1st(std::mem_fun(&ASTWriter::GetOrCreateTypeIdx), this));  } -TypeID ASTWriter::getTypeID(QualType T) { +TypeID ASTWriter::getTypeID(QualType T) const {    return MakeTypeID(T,                std::bind1st(std::mem_fun(&ASTWriter::getTypeIdx), this));  } @@ -2607,13 +2730,14 @@ TypeIdx ASTWriter::GetOrCreateTypeIdx(QualType T) {    return Idx;  } -TypeIdx ASTWriter::getTypeIdx(QualType T) { +TypeIdx ASTWriter::getTypeIdx(QualType T) const {    if (T.isNull())      return TypeIdx();    assert(!T.getLocalFastQualifiers()); -  assert(TypeIdxs.find(T) != TypeIdxs.end() && "Type not emitted!"); -  return TypeIdxs[T]; +  TypeIdxMap::const_iterator I = TypeIdxs.find(T); +  assert(I != TypeIdxs.end() && "Type not emitted!"); +  return I->second;  }  void ASTWriter::AddDeclRef(const Decl *D, RecordData &Record) {  | 

