r233052 - [modules] Deserialize CXXCtorInitializer list for a constructor lazily.

Argyrios Kyrtzidis kyrtzidis at apple.com
Tue Mar 24 10:01:47 PDT 2015


Hi Richard,

There is an internal-for-testing clang option ‘-error-on-deserialized-decl’ intended for testing that we haven’t deserialized something unnecessarily, would it be applicable to be used for your recent changes along with the appropriate test cases ?

> On Mar 23, 2015, at 11:36 PM, Richard Smith <richard-llvm at metafoo.co.uk> wrote:
> 
> Author: rsmith
> Date: Tue Mar 24 01:36:48 2015
> New Revision: 233052
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=233052&view=rev
> Log:
> [modules] Deserialize CXXCtorInitializer list for a constructor lazily.
> 
> Previously we'd deserialize the list of mem-initializers for a constructor when
> we deserialized the declaration of the constructor. That could trigger a
> significant amount of unnecessary work (pulling in all base classes
> recursively, for a start) and was causing problems for the modules buildbot due
> to cyclic deserializations. We now deserialize these on demand.
> 
> This creates a certain amount of duplication with the handling of
> CXXBaseSpecifiers; I'll look into reducing that next.
> 
> Modified:
>    cfe/trunk/include/clang/AST/DeclCXX.h
>    cfe/trunk/include/clang/AST/DeclObjC.h
>    cfe/trunk/include/clang/AST/ExternalASTSource.h
>    cfe/trunk/include/clang/Sema/MultiplexExternalSemaSource.h
>    cfe/trunk/include/clang/Serialization/ASTBitCodes.h
>    cfe/trunk/include/clang/Serialization/ASTReader.h
>    cfe/trunk/include/clang/Serialization/ASTWriter.h
>    cfe/trunk/include/clang/Serialization/Module.h
>    cfe/trunk/lib/AST/DeclCXX.cpp
>    cfe/trunk/lib/AST/DeclObjC.cpp
>    cfe/trunk/lib/AST/ExternalASTSource.cpp
>    cfe/trunk/lib/Frontend/ChainedIncludesSource.cpp
>    cfe/trunk/lib/Sema/MultiplexExternalSemaSource.cpp
>    cfe/trunk/lib/Serialization/ASTReader.cpp
>    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
>    cfe/trunk/lib/Serialization/ASTWriter.cpp
>    cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
>    cfe/trunk/lib/Serialization/Module.cpp
> 
> Modified: cfe/trunk/include/clang/AST/DeclCXX.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=233052&r1=233051&r2=233052&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/DeclCXX.h (original)
> +++ cfe/trunk/include/clang/AST/DeclCXX.h Tue Mar 24 01:36:48 2015
> @@ -2149,7 +2149,7 @@ class CXXConstructorDecl : public CXXMet
>   /// \name Support for base and member initializers.
>   /// \{
>   /// \brief The arguments used to initialize the base or member.
> -  CXXCtorInitializer **CtorInitializers;
> +  LazyCXXCtorInitializersPtr CtorInitializers;
>   unsigned NumCtorInitializers;
>   /// \}
> 
> @@ -2188,7 +2188,7 @@ public:
>   typedef CXXCtorInitializer **init_iterator;
> 
>   /// \brief Iterates through the member/base initializer list.
> -  typedef CXXCtorInitializer * const * init_const_iterator;
> +  typedef CXXCtorInitializer *const *init_const_iterator;
> 
>   typedef llvm::iterator_range<init_iterator> init_range;
>   typedef llvm::iterator_range<init_const_iterator> init_const_range;
> @@ -2199,17 +2199,20 @@ public:
>   }
> 
>   /// \brief Retrieve an iterator to the first initializer.
> -  init_iterator       init_begin()       { return CtorInitializers; }
> +  init_iterator init_begin() {
> +    const auto *ConstThis = this;
> +    return const_cast<init_iterator>(ConstThis->init_begin());
> +  }
>   /// \brief Retrieve an iterator to the first initializer.
> -  init_const_iterator init_begin() const { return CtorInitializers; }
> +  init_const_iterator init_begin() const;
> 
>   /// \brief Retrieve an iterator past the last initializer.
>   init_iterator       init_end()       {
> -    return CtorInitializers + NumCtorInitializers;
> +    return init_begin() + NumCtorInitializers;
>   }
>   /// \brief Retrieve an iterator past the last initializer.
>   init_const_iterator init_end() const {
> -    return CtorInitializers + NumCtorInitializers;
> +    return init_begin() + NumCtorInitializers;
>   }
> 
>   typedef std::reverse_iterator<init_iterator> init_reverse_iterator;
> @@ -2240,14 +2243,14 @@ public:
>     NumCtorInitializers = numCtorInitializers;
>   }
> 
> -  void setCtorInitializers(CXXCtorInitializer ** initializers) {
> -    CtorInitializers = initializers;
> +  void setCtorInitializers(CXXCtorInitializer **Initializers) {
> +    CtorInitializers = Initializers;
>   }
> 
>   /// \brief Determine whether this constructor is a delegating constructor.
>   bool isDelegatingConstructor() const {
>     return (getNumCtorInitializers() == 1) &&
> -      CtorInitializers[0]->isDelegatingInitializer();
> +           init_begin()[0]->isDelegatingInitializer();
>   }
> 
>   /// \brief When this constructor delegates to another, retrieve the target.
> 
> Modified: cfe/trunk/include/clang/AST/DeclObjC.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=233052&r1=233051&r2=233052&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/DeclObjC.h (original)
> +++ cfe/trunk/include/clang/AST/DeclObjC.h Tue Mar 24 01:36:48 2015
> @@ -2002,8 +2002,8 @@ class ObjCImplementationDecl : public Ob
>   SourceLocation IvarRBraceLoc;
> 
>   /// Support for ivar initialization.
> -  /// IvarInitializers - The arguments used to initialize the ivars
> -  CXXCtorInitializer **IvarInitializers;
> +  /// \brief The arguments used to initialize the ivars
> +  LazyCXXCtorInitializersPtr IvarInitializers;
>   unsigned NumIvarInitializers;
> 
>   /// Do the ivars of this class require initialization other than
> @@ -2052,17 +2052,20 @@ public:
>   }
> 
>   /// init_begin() - Retrieve an iterator to the first initializer.
> -  init_iterator       init_begin()       { return IvarInitializers; }
> +  init_iterator init_begin() {
> +    const auto *ConstThis = this;
> +    return const_cast<init_iterator>(ConstThis->init_begin());
> +  }
>   /// begin() - Retrieve an iterator to the first initializer.
> -  init_const_iterator init_begin() const { return IvarInitializers; }
> +  init_const_iterator init_begin() const;
> 
>   /// init_end() - Retrieve an iterator past the last initializer.
>   init_iterator       init_end()       {
> -    return IvarInitializers + NumIvarInitializers;
> +    return init_begin() + NumIvarInitializers;
>   }
>   /// end() - Retrieve an iterator past the last initializer.
>   init_const_iterator init_end() const {
> -    return IvarInitializers + NumIvarInitializers;
> +    return init_begin() + NumIvarInitializers;
>   }
>   /// getNumArgs - Number of ivars which must be initialized.
>   unsigned getNumIvarInitializers() const {
> 
> Modified: cfe/trunk/include/clang/AST/ExternalASTSource.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExternalASTSource.h?rev=233052&r1=233051&r2=233052&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/ExternalASTSource.h (original)
> +++ cfe/trunk/include/clang/AST/ExternalASTSource.h Tue Mar 24 01:36:48 2015
> @@ -22,6 +22,7 @@ namespace clang {
> 
> class ASTConsumer;
> class CXXBaseSpecifier;
> +class CXXCtorInitializer;
> class DeclarationName;
> class ExternalSemaSource; // layering violation required for downcasting
> class FieldDecl;
> @@ -121,6 +122,12 @@ public:
>   /// The default implementation of this method is a no-op.
>   virtual Stmt *GetExternalDeclStmt(uint64_t Offset);
> 
> +  /// \brief Resolve the offset of a set of C++ constructor initializers in
> +  /// the decl stream into an array of initializers.
> +  ///
> +  /// The default implementation of this method is a no-op.
> +  virtual CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset);
> +
>   /// \brief Resolve the offset of a set of C++ base specifiers in the decl
>   /// stream into an array of specifiers.
>   ///
> @@ -553,8 +560,13 @@ typedef LazyOffsetPtr<Stmt, uint64_t, &E
> typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl>
>   LazyDeclPtr;
> 
> +/// \brief A lazy pointer to a set of CXXCtorInitializers.
> +typedef LazyOffsetPtr<CXXCtorInitializer *, uint64_t,
> +                      &ExternalASTSource::GetExternalCXXCtorInitializers>
> +  LazyCXXCtorInitializersPtr;
> +
> /// \brief A lazy pointer to a set of CXXBaseSpecifiers.
> -typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t, 
> +typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t,
>                       &ExternalASTSource::GetExternalCXXBaseSpecifiers>
>   LazyCXXBaseSpecifiersPtr;
> 
> 
> Modified: cfe/trunk/include/clang/Sema/MultiplexExternalSemaSource.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/MultiplexExternalSemaSource.h?rev=233052&r1=233051&r2=233052&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/MultiplexExternalSemaSource.h (original)
> +++ cfe/trunk/include/clang/Sema/MultiplexExternalSemaSource.h Tue Mar 24 01:36:48 2015
> @@ -86,10 +86,14 @@ public:
>   /// stream into an array of specifiers.
>   CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) override;
> 
> +  /// \brief Resolve a handle to a list of ctor initializers into the list of
> +  /// initializers themselves.
> +  CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset) override;
> +
>   /// \brief Find all declarations with the given name in the
>   /// given context.
> -  bool
> -  FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) override;
> +  bool FindExternalVisibleDeclsByName(const DeclContext *DC,
> +                                      DeclarationName Name) override;
> 
>   /// \brief Ensures that the table of all visible declarations inside this
>   /// context is up to date.
> 
> Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=233052&r1=233051&r2=233052&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
> +++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Tue Mar 24 01:36:48 2015
> @@ -149,7 +149,11 @@ namespace clang {
>     /// \brief An ID number that refers to a set of CXXBaseSpecifiers in an 
>     /// AST file.
>     typedef uint32_t CXXBaseSpecifiersID;
> -    
> +
> +    /// \brief An ID number that refers to a list of CXXCtorInitializers in an
> +    /// AST file.
> +    typedef uint32_t CXXCtorInitializersID;
> +
>     /// \brief An ID number that refers to an entity in the detailed
>     /// preprocessing record.
>     typedef uint32_t PreprocessedEntityID;
> @@ -555,6 +559,10 @@ namespace clang {
> 
>       /// \brief Record code for potentially unused local typedef names.
>       UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES = 52,
> +
> +      /// \brief Record code for the table of offsets to CXXCtorInitializers
> +      /// lists.
> +      CXX_CTOR_INITIALIZERS_OFFSETS = 53,
>     };
> 
>     /// \brief Record types used within a source manager block.
> @@ -1074,6 +1082,8 @@ namespace clang {
>       DECL_STATIC_ASSERT,
>       /// \brief A record containing CXXBaseSpecifiers.
>       DECL_CXX_BASE_SPECIFIERS,
> +      /// \brief A record containing CXXCtorInitializers.
> +      DECL_CXX_CTOR_INITIALIZERS,
>       /// \brief A IndirectFieldDecl record.
>       DECL_INDIRECTFIELD,
>       /// \brief A NonTypeTemplateParmDecl record that stores an expanded
> 
> Modified: cfe/trunk/include/clang/Serialization/ASTReader.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=233052&r1=233051&r2=233052&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Serialization/ASTReader.h (original)
> +++ cfe/trunk/include/clang/Serialization/ASTReader.h Tue Mar 24 01:36:48 2015
> @@ -943,9 +943,6 @@ private:
>   /// passing decls to consumer.
>   bool PassingDeclsToConsumer;
> 
> -  /// Number of CXX base specifiers currently loaded
> -  unsigned NumCXXBaseSpecifiersLoaded;
> -
>   /// \brief The set of identifiers that were read while the AST reader was
>   /// (recursively) loading declarations.
>   ///
> @@ -1583,11 +1580,6 @@ public:
>     return Result;
>   }
> 
> -  /// \brief Returns the number of C++ base specifiers found in the chain.
> -  unsigned getTotalNumCXXBaseSpecifiers() const {
> -    return NumCXXBaseSpecifiersLoaded;
> -  }
> -
>   /// \brief Reads a TemplateArgumentLocInfo appropriate for the
>   /// given TemplateArgument kind.
>   TemplateArgumentLocInfo
> @@ -1993,10 +1985,18 @@ public:
>                                         const RecordData &Record,unsigned &Idx);
> 
>   /// \brief Read a CXXCtorInitializer array.
> -  std::pair<CXXCtorInitializer **, unsigned>
> +  CXXCtorInitializer **
>   ReadCXXCtorInitializers(ModuleFile &F, const RecordData &Record,
>                           unsigned &Idx);
> 
> +  /// \brief Read a CXXCtorInitializers ID from the given record and
> +  /// return its global bit offset.
> +  uint64_t ReadCXXCtorInitializersRef(ModuleFile &M, const RecordData &Record,
> +                                      unsigned &Idx);
> +
> +  /// \brief Read the contents of a CXXCtorInitializer array.
> +  CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset) override;
> +
>   /// \brief Read a source location from raw form.
>   SourceLocation ReadSourceLocation(ModuleFile &ModuleFile, unsigned Raw) const {
>     SourceLocation Loc = SourceLocation::getFromRawEncoding(Raw);
> 
> Modified: cfe/trunk/include/clang/Serialization/ASTWriter.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=233052&r1=233051&r2=233052&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Serialization/ASTWriter.h (original)
> +++ cfe/trunk/include/clang/Serialization/ASTWriter.h Tue Mar 24 01:36:48 2015
> @@ -415,7 +415,7 @@ private:
>   unsigned NumVisibleDeclContexts;
> 
>   /// \brief The offset of each CXXBaseSpecifier set within the AST.
> -  SmallVector<uint32_t, 4> CXXBaseSpecifiersOffsets;
> +  SmallVector<uint32_t, 16> CXXBaseSpecifiersOffsets;
> 
>   /// \brief The first ID number we can use for our own base specifiers.
>   serialization::CXXBaseSpecifiersID FirstCXXBaseSpecifiersID;
> @@ -443,6 +443,33 @@ private:
>   /// in the order they should be written.
>   SmallVector<QueuedCXXBaseSpecifiers, 2> CXXBaseSpecifiersToWrite;
> 
> +  /// \brief The offset of each CXXCtorInitializer list within the AST.
> +  SmallVector<uint32_t, 16> CXXCtorInitializersOffsets;
> +
> +  /// \brief The first ID number we can use for our own ctor initializers.
> +  serialization::CXXCtorInitializersID FirstCXXCtorInitializersID;
> +
> +  /// \brief The ctor initializers ID that will be assigned to the next new
> +  /// list of C++ ctor initializers.
> +  serialization::CXXCtorInitializersID NextCXXCtorInitializersID;
> +
> +  /// \brief A set of C++ ctor initializers that is queued to be written
> +  /// into the AST file.
> +  struct QueuedCXXCtorInitializers {
> +    QueuedCXXCtorInitializers() : ID() {}
> +
> +    QueuedCXXCtorInitializers(serialization::CXXCtorInitializersID ID,
> +                              ArrayRef<CXXCtorInitializer*> Inits)
> +        : ID(ID), Inits(Inits) {}
> +
> +    serialization::CXXCtorInitializersID ID;
> +    ArrayRef<CXXCtorInitializer*> Inits;
> +  };
> +
> +  /// \brief Queue of C++ ctor initializers to be written to the AST file,
> +  /// in the order they should be written.
> +  SmallVector<QueuedCXXCtorInitializers, 2> CXXCtorInitializersToWrite;
> +
>   /// \brief A mapping from each known submodule to its ID number, which will
>   /// be a positive integer.
>   llvm::DenseMap<Module *, unsigned> SubmoduleIDs;
> @@ -471,6 +498,7 @@ private:
>   void WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag,
>                                      bool isModule);
>   void WriteCXXBaseSpecifiersOffsets();
> +  void WriteCXXCtorInitializersOffsets();
> 
>   unsigned TypeExtQualAbbrev;
>   unsigned TypeFunctionProtoAbbrev;
> @@ -675,6 +703,11 @@ public:
>   void AddCXXBaseSpecifier(const CXXBaseSpecifier &Base,
>                            RecordDataImpl &Record);
> 
> +  /// \brief Emit the ID for a CXXCtorInitializer array and register the array
> +  /// for later serialization.
> +  void AddCXXCtorInitializersRef(ArrayRef<CXXCtorInitializer *> Inits,
> +                                 RecordDataImpl &Record);
> +
>   /// \brief Emit a CXXCtorInitializer array.
>   void AddCXXCtorInitializers(
>                              const CXXCtorInitializer * const *CtorInitializers,
> @@ -747,6 +780,18 @@ public:
>   /// via \c AddCXXBaseSpecifiersRef().
>   void FlushCXXBaseSpecifiers();
> 
> +  /// \brief Flush all of the C++ constructor initializer lists that have been
> +  /// added via \c AddCXXCtorInitializersRef().
> +  void FlushCXXCtorInitializers();
> +
> +  /// \brief Flush all pending records that are tacked onto the end of
> +  /// decl and decl update records.
> +  void FlushPendingAfterDecl() {
> +    FlushStmts();
> +    FlushCXXBaseSpecifiers();
> +    FlushCXXCtorInitializers();
> +  }
> +
>   /// \brief Record an ID for the given switch-case statement.
>   unsigned RecordSwitchCaseID(SwitchCase *S);
> 
> 
> Modified: cfe/trunk/include/clang/Serialization/Module.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/Module.h?rev=233052&r1=233051&r2=233052&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Serialization/Module.h (original)
> +++ cfe/trunk/include/clang/Serialization/Module.h Tue Mar 24 01:36:48 2015
> @@ -404,6 +404,13 @@ public:
>   /// indexed by the C++ base specifier set ID (-1).
>   const uint32_t *CXXBaseSpecifiersOffsets;
> 
> +  /// \brief The number of C++ ctor initializer lists in this AST file.
> +  unsigned LocalNumCXXCtorInitializers;
> +
> +  /// \brief Offset of each C++ ctor initializer list within the bitstream,
> +  /// indexed by the C++ ctor initializer list ID minus 1.
> +  const uint32_t *CXXCtorInitializersOffsets;
> +
>   typedef llvm::DenseMap<const DeclContext *, DeclContextInfo>
>   DeclContextInfosMap;
> 
> 
> Modified: cfe/trunk/lib/AST/DeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=233052&r1=233051&r2=233052&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/DeclCXX.cpp (original)
> +++ cfe/trunk/lib/AST/DeclCXX.cpp Tue Mar 24 01:36:48 2015
> @@ -1739,6 +1739,10 @@ CXXConstructorDecl::Create(ASTContext &C
>                                         isImplicitlyDeclared, isConstexpr);
> }
> 
> +CXXConstructorDecl::init_const_iterator CXXConstructorDecl::init_begin() const {
> +  return CtorInitializers.get(getASTContext().getExternalSource());
> +}
> +
> CXXConstructorDecl *CXXConstructorDecl::getTargetConstructor() const {
>   assert(isDelegatingConstructor() && "Not a delegating constructor!");
>   Expr *E = (*init_begin())->getInit()->IgnoreImplicit();
> 
> Modified: cfe/trunk/lib/AST/DeclObjC.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=233052&r1=233051&r2=233052&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/DeclObjC.cpp (original)
> +++ cfe/trunk/lib/AST/DeclObjC.cpp Tue Mar 24 01:36:48 2015
> @@ -1820,6 +1820,11 @@ void ObjCImplementationDecl::setIvarInit
>   }
> }
> 
> +ObjCImplementationDecl::init_const_iterator
> +ObjCImplementationDecl::init_begin() const {
> +  return IvarInitializers.get(getASTContext().getExternalSource());
> +}
> +
> raw_ostream &clang::operator<<(raw_ostream &OS,
>                                const ObjCImplementationDecl &ID) {
>   OS << ID.getName();
> 
> Modified: cfe/trunk/lib/AST/ExternalASTSource.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExternalASTSource.cpp?rev=233052&r1=233051&r2=233052&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/ExternalASTSource.cpp (original)
> +++ cfe/trunk/lib/AST/ExternalASTSource.cpp Tue Mar 24 01:36:48 2015
> @@ -66,6 +66,11 @@ Stmt *ExternalASTSource::GetExternalDecl
>   return nullptr;
> }
> 
> +CXXCtorInitializer **
> +ExternalASTSource::GetExternalCXXCtorInitializers(uint64_t Offset) {
> +  return nullptr;
> +}
> +
> CXXBaseSpecifier *
> ExternalASTSource::GetExternalCXXBaseSpecifiers(uint64_t Offset) {
>   return nullptr;
> 
> Modified: cfe/trunk/lib/Frontend/ChainedIncludesSource.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/ChainedIncludesSource.cpp?rev=233052&r1=233051&r2=233052&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Frontend/ChainedIncludesSource.cpp (original)
> +++ cfe/trunk/lib/Frontend/ChainedIncludesSource.cpp Tue Mar 24 01:36:48 2015
> @@ -43,6 +43,7 @@ protected:
>   Selector GetExternalSelector(uint32_t ID) override;
>   uint32_t GetNumExternalSelectors() override;
>   Stmt *GetExternalDeclStmt(uint64_t Offset) override;
> +  CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset) override;
>   CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) override;
>   bool FindExternalVisibleDeclsByName(const DeclContext *DC,
>                                       DeclarationName Name) override;
> @@ -232,6 +233,10 @@ CXXBaseSpecifier *
> ChainedIncludesSource::GetExternalCXXBaseSpecifiers(uint64_t Offset) {
>   return getFinalReader().GetExternalCXXBaseSpecifiers(Offset);
> }
> +CXXCtorInitializer **
> +ChainedIncludesSource::GetExternalCXXCtorInitializers(uint64_t Offset) {
> +  return getFinalReader().GetExternalCXXCtorInitializers(Offset);
> +}
> bool
> ChainedIncludesSource::FindExternalVisibleDeclsByName(const DeclContext *DC,
>                                                       DeclarationName Name) {
> 
> Modified: cfe/trunk/lib/Sema/MultiplexExternalSemaSource.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/MultiplexExternalSemaSource.cpp?rev=233052&r1=233051&r2=233052&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/MultiplexExternalSemaSource.cpp (original)
> +++ cfe/trunk/lib/Sema/MultiplexExternalSemaSource.cpp Tue Mar 24 01:36:48 2015
> @@ -86,6 +86,14 @@ CXXBaseSpecifier *MultiplexExternalSemaS
>   return nullptr;
> }
> 
> +CXXCtorInitializer **
> +MultiplexExternalSemaSource::GetExternalCXXCtorInitializers(uint64_t Offset) {
> +  for (auto *S : Sources)
> +    if (auto *R = S->GetExternalCXXCtorInitializers(Offset))
> +      return R;
> +  return nullptr;
> +}
> +
> bool MultiplexExternalSemaSource::
> FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) {
>   bool AnyDeclsFound = false;
> 
> Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=233052&r1=233051&r2=233052&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTReader.cpp Tue Mar 24 01:36:48 2015
> @@ -3204,16 +3204,26 @@ ASTReader::ReadASTBlock(ModuleFile &F, u
>     case OBJC_CATEGORIES:
>       F.ObjCCategories.swap(Record);
>       break;
> -        
> +
>     case CXX_BASE_SPECIFIER_OFFSETS: {
>       if (F.LocalNumCXXBaseSpecifiers != 0) {
>         Error("duplicate CXX_BASE_SPECIFIER_OFFSETS record in AST file");
>         return Failure;
>       }
> -      
> +
>       F.LocalNumCXXBaseSpecifiers = Record[0];
>       F.CXXBaseSpecifiersOffsets = (const uint32_t *)Blob.data();
> -      NumCXXBaseSpecifiersLoaded += F.LocalNumCXXBaseSpecifiers;
> +      break;
> +    }
> +
> +    case CXX_CTOR_INITIALIZERS_OFFSETS: {
> +      if (F.LocalNumCXXCtorInitializers != 0) {
> +        Error("duplicate CXX_CTOR_INITIALIZERS_OFFSETS record in AST file");
> +        return Failure;
> +      }
> +
> +      F.LocalNumCXXCtorInitializers = Record[0];
> +      F.CXXCtorInitializersOffsets = (const uint32_t *)Blob.data();
>       break;
>     }
> 
> @@ -6187,6 +6197,38 @@ void ASTReader::CompleteRedeclChain(cons
>   }
> }
> 
> +uint64_t ASTReader::ReadCXXCtorInitializersRef(ModuleFile &M,
> +                                               const RecordData &Record,
> +                                               unsigned &Idx) {
> +  if (Idx >= Record.size() || Record[Idx] > M.LocalNumCXXCtorInitializers) {
> +    Error("malformed AST file: missing C++ ctor initializers");
> +    return 0;
> +  }
> +
> +  unsigned LocalID = Record[Idx++];
> +  return getGlobalBitOffset(M, M.CXXCtorInitializersOffsets[LocalID - 1]);
> +}
> +
> +CXXCtorInitializer **
> +ASTReader::GetExternalCXXCtorInitializers(uint64_t Offset) {
> +  RecordLocation Loc = getLocalBitOffset(Offset);
> +  BitstreamCursor &Cursor = Loc.F->DeclsCursor;
> +  SavedStreamPosition SavedPosition(Cursor);
> +  Cursor.JumpToBit(Loc.Offset);
> +  ReadingKindTracker ReadingKind(Read_Decl, *this);
> +
> +  RecordData Record;
> +  unsigned Code = Cursor.ReadCode();
> +  unsigned RecCode = Cursor.readRecord(Code, Record);
> +  if (RecCode != DECL_CXX_CTOR_INITIALIZERS) {
> +    Error("malformed AST file: missing C++ ctor initializers");
> +    return nullptr;
> +  }
> +
> +  unsigned Idx = 0;
> +  return ReadCXXCtorInitializers(*Loc.F, Record, Idx);
> +}
> +
> uint64_t ASTReader::readCXXBaseSpecifiers(ModuleFile &M,
>                                           const RecordData &Record,
>                                           unsigned &Idx) {
> @@ -7918,92 +7960,89 @@ ASTReader::ReadCXXBaseSpecifier(ModuleFi
>   return Result;
> }
> 
> -std::pair<CXXCtorInitializer **, unsigned>
> +CXXCtorInitializer **
> ASTReader::ReadCXXCtorInitializers(ModuleFile &F, const RecordData &Record,
>                                    unsigned &Idx) {
> -  CXXCtorInitializer **CtorInitializers = nullptr;
>   unsigned NumInitializers = Record[Idx++];
> -  if (NumInitializers) {
> -    CtorInitializers
> -        = new (Context) CXXCtorInitializer*[NumInitializers];
> -    for (unsigned i=0; i != NumInitializers; ++i) {
> -      TypeSourceInfo *TInfo = nullptr;
> -      bool IsBaseVirtual = false;
> -      FieldDecl *Member = nullptr;
> -      IndirectFieldDecl *IndirectMember = nullptr;
> -
> -      CtorInitializerType Type = (CtorInitializerType)Record[Idx++];
> -      switch (Type) {
> -      case CTOR_INITIALIZER_BASE:
> -        TInfo = GetTypeSourceInfo(F, Record, Idx);
> -        IsBaseVirtual = Record[Idx++];
> -        break;
> -          
> -      case CTOR_INITIALIZER_DELEGATING:
> -        TInfo = GetTypeSourceInfo(F, Record, Idx);
> -        break;
> +  assert(NumInitializers && "wrote ctor initializers but have no inits");
> +  auto **CtorInitializers = new (Context) CXXCtorInitializer*[NumInitializers];
> +  for (unsigned i = 0; i != NumInitializers; ++i) {
> +    TypeSourceInfo *TInfo = nullptr;
> +    bool IsBaseVirtual = false;
> +    FieldDecl *Member = nullptr;
> +    IndirectFieldDecl *IndirectMember = nullptr;
> 
> -       case CTOR_INITIALIZER_MEMBER:
> -        Member = ReadDeclAs<FieldDecl>(F, Record, Idx);
> -        break;
> +    CtorInitializerType Type = (CtorInitializerType)Record[Idx++];
> +    switch (Type) {
> +    case CTOR_INITIALIZER_BASE:
> +      TInfo = GetTypeSourceInfo(F, Record, Idx);
> +      IsBaseVirtual = Record[Idx++];
> +      break;
> 
> -       case CTOR_INITIALIZER_INDIRECT_MEMBER:
> -        IndirectMember = ReadDeclAs<IndirectFieldDecl>(F, Record, Idx);
> -        break;
> -      }
> +    case CTOR_INITIALIZER_DELEGATING:
> +      TInfo = GetTypeSourceInfo(F, Record, Idx);
> +      break;
> 
> -      SourceLocation MemberOrEllipsisLoc = ReadSourceLocation(F, Record, Idx);
> -      Expr *Init = ReadExpr(F);
> -      SourceLocation LParenLoc = ReadSourceLocation(F, Record, Idx);
> -      SourceLocation RParenLoc = ReadSourceLocation(F, Record, Idx);
> -      bool IsWritten = Record[Idx++];
> -      unsigned SourceOrderOrNumArrayIndices;
> -      SmallVector<VarDecl *, 8> Indices;
> -      if (IsWritten) {
> -        SourceOrderOrNumArrayIndices = Record[Idx++];
> -      } else {
> -        SourceOrderOrNumArrayIndices = Record[Idx++];
> -        Indices.reserve(SourceOrderOrNumArrayIndices);
> -        for (unsigned i=0; i != SourceOrderOrNumArrayIndices; ++i)
> -          Indices.push_back(ReadDeclAs<VarDecl>(F, Record, Idx));
> -      }
> -
> -      CXXCtorInitializer *BOMInit;
> -      if (Type == CTOR_INITIALIZER_BASE) {
> -        BOMInit = new (Context) CXXCtorInitializer(Context, TInfo, IsBaseVirtual,
> -                                             LParenLoc, Init, RParenLoc,
> -                                             MemberOrEllipsisLoc);
> -      } else if (Type == CTOR_INITIALIZER_DELEGATING) {
> -        BOMInit = new (Context) CXXCtorInitializer(Context, TInfo, LParenLoc,
> -                                                   Init, RParenLoc);
> -      } else if (IsWritten) {
> -        if (Member)
> -          BOMInit = new (Context) CXXCtorInitializer(Context, Member, MemberOrEllipsisLoc,
> -                                               LParenLoc, Init, RParenLoc);
> -        else 
> -          BOMInit = new (Context) CXXCtorInitializer(Context, IndirectMember,
> -                                               MemberOrEllipsisLoc, LParenLoc,
> -                                               Init, RParenLoc);
> +     case CTOR_INITIALIZER_MEMBER:
> +      Member = ReadDeclAs<FieldDecl>(F, Record, Idx);
> +      break;
> +
> +     case CTOR_INITIALIZER_INDIRECT_MEMBER:
> +      IndirectMember = ReadDeclAs<IndirectFieldDecl>(F, Record, Idx);
> +      break;
> +    }
> +
> +    SourceLocation MemberOrEllipsisLoc = ReadSourceLocation(F, Record, Idx);
> +    Expr *Init = ReadExpr(F);
> +    SourceLocation LParenLoc = ReadSourceLocation(F, Record, Idx);
> +    SourceLocation RParenLoc = ReadSourceLocation(F, Record, Idx);
> +    bool IsWritten = Record[Idx++];
> +    unsigned SourceOrderOrNumArrayIndices;
> +    SmallVector<VarDecl *, 8> Indices;
> +    if (IsWritten) {
> +      SourceOrderOrNumArrayIndices = Record[Idx++];
> +    } else {
> +      SourceOrderOrNumArrayIndices = Record[Idx++];
> +      Indices.reserve(SourceOrderOrNumArrayIndices);
> +      for (unsigned i=0; i != SourceOrderOrNumArrayIndices; ++i)
> +        Indices.push_back(ReadDeclAs<VarDecl>(F, Record, Idx));
> +    }
> +
> +    CXXCtorInitializer *BOMInit;
> +    if (Type == CTOR_INITIALIZER_BASE) {
> +      BOMInit = new (Context)
> +          CXXCtorInitializer(Context, TInfo, IsBaseVirtual, LParenLoc, Init,
> +                             RParenLoc, MemberOrEllipsisLoc);
> +    } else if (Type == CTOR_INITIALIZER_DELEGATING) {
> +      BOMInit = new (Context)
> +          CXXCtorInitializer(Context, TInfo, LParenLoc, Init, RParenLoc);
> +    } else if (IsWritten) {
> +      if (Member)
> +        BOMInit = new (Context) CXXCtorInitializer(
> +            Context, Member, MemberOrEllipsisLoc, LParenLoc, Init, RParenLoc);
> +      else
> +        BOMInit = new (Context)
> +            CXXCtorInitializer(Context, IndirectMember, MemberOrEllipsisLoc,
> +                               LParenLoc, Init, RParenLoc);
> +    } else {
> +      if (IndirectMember) {
> +        assert(Indices.empty() && "Indirect field improperly initialized");
> +        BOMInit = new (Context)
> +            CXXCtorInitializer(Context, IndirectMember, MemberOrEllipsisLoc,
> +                               LParenLoc, Init, RParenLoc);
>       } else {
> -        if (IndirectMember) {
> -          assert(Indices.empty() && "Indirect field improperly initialized");
> -          BOMInit = new (Context) CXXCtorInitializer(Context, IndirectMember,
> -                                                     MemberOrEllipsisLoc, LParenLoc,
> -                                                     Init, RParenLoc);
> -        } else {
> -          BOMInit = CXXCtorInitializer::Create(Context, Member, MemberOrEllipsisLoc,
> -                                               LParenLoc, Init, RParenLoc,
> -                                               Indices.data(), Indices.size());
> -        }
> +        BOMInit = CXXCtorInitializer::Create(
> +            Context, Member, MemberOrEllipsisLoc, LParenLoc, Init, RParenLoc,
> +            Indices.data(), Indices.size());
>       }
> -
> -      if (IsWritten)
> -        BOMInit->setSourceOrder(SourceOrderOrNumArrayIndices);
> -      CtorInitializers[i] = BOMInit;
>     }
> +
> +    if (IsWritten)
> +      BOMInit->setSourceOrder(SourceOrderOrNumArrayIndices);
> +    CtorInitializers[i] = BOMInit;
>   }
> 
> -  return std::make_pair(CtorInitializers, NumInitializers);
> +  return CtorInitializers;
> }
> 
> NestedNameSpecifier *
> @@ -8680,8 +8719,7 @@ ASTReader::ASTReader(Preprocessor &PP, A
>       NumLexicalDeclContextsRead(0), TotalLexicalDeclContexts(0),
>       NumVisibleDeclContextsRead(0), TotalVisibleDeclContexts(0),
>       TotalModulesSizeInBits(0), NumCurrentElementsDeserializing(0),
> -      PassingDeclsToConsumer(false), NumCXXBaseSpecifiersLoaded(0),
> -      ReadingKind(Read_None) {
> +      PassingDeclsToConsumer(false), ReadingKind(Read_None) {
>   SourceMgr.setExternalSLocEntrySource(this);
> }
> 
> 
> Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=233052&r1=233051&r2=233052&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Tue Mar 24 01:36:48 2015
> @@ -405,6 +405,12 @@ void ASTDeclReader::Visit(Decl *D) {
>     // module).
>     // FIXME: Can we diagnose ODR violations somehow?
>     if (Record[Idx++]) {
> +      if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) {
> +        CD->NumCtorInitializers = Record[Idx++];
> +        if (CD->NumCtorInitializers)
> +          CD->CtorInitializers =
> +              Reader.ReadCXXCtorInitializersRef(F, Record, Idx);
> +      }
>       Reader.PendingBodies[FD] = GetCurrentCursorOffset();
>       HasPendingBody = true;
>     }
> @@ -992,8 +998,9 @@ void ASTDeclReader::VisitObjCImplementat
>   D->setIvarRBraceLoc(ReadSourceLocation(Record, Idx));
>   D->setHasNonZeroConstructors(Record[Idx++]);
>   D->setHasDestructors(Record[Idx++]);
> -  std::tie(D->IvarInitializers, D->NumIvarInitializers) =
> -      Reader.ReadCXXCtorInitializers(F, Record, Idx);
> +  D->NumIvarInitializers = Record[Idx++];
> +  if (D->NumIvarInitializers)
> +    D->IvarInitializers = Reader.ReadCXXCtorInitializersRef(F, Record, Idx);
> }
> 
> 
> @@ -1623,9 +1630,6 @@ void ASTDeclReader::VisitCXXConstructorD
>     if (D->isCanonicalDecl())
>       D->setInheritedConstructor(CD);
>   D->IsExplicitSpecified = Record[Idx++];
> -  // FIXME: We should defer loading this until we need the constructor's body.
> -  std::tie(D->CtorInitializers, D->NumCtorInitializers) =
> -      Reader.ReadCXXCtorInitializers(F, Record, Idx);
> }
> 
> void ASTDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
> @@ -3146,6 +3150,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID I
>   case DECL_CXX_BASE_SPECIFIERS:
>     Error("attempt to read a C++ base-specifier record as a declaration");
>     return nullptr;
> +  case DECL_CXX_CTOR_INITIALIZERS:
> +    Error("attempt to read a C++ ctor initializer record as a declaration");
> +    return nullptr;
>   case DECL_IMPORT:
>     // Note: last entry of the ImportDecl record is the number of stored source 
>     // locations.
> @@ -3649,9 +3656,12 @@ void ASTDeclReader::UpdateDecl(Decl *D,
>         });
>       }
>       FD->setInnerLocStart(Reader.ReadSourceLocation(ModuleFile, Record, Idx));
> -      if (auto *CD = dyn_cast<CXXConstructorDecl>(FD))
> -        std::tie(CD->CtorInitializers, CD->NumCtorInitializers) =
> -            Reader.ReadCXXCtorInitializers(ModuleFile, Record, Idx);
> +      if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) {
> +        CD->NumCtorInitializers = Record[Idx++];
> +        if (CD->NumCtorInitializers)
> +          CD->CtorInitializers =
> +              Reader.ReadCXXCtorInitializersRef(F, Record, Idx);
> +      }
>       // Store the offset of the body so we can lazily load it later.
>       Reader.PendingBodies[FD] = GetCurrentCursorOffset();
>       HasPendingBody = true;
> 
> Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=233052&r1=233051&r2=233052&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Tue Mar 24 01:36:48 2015
> @@ -2694,6 +2694,29 @@ void ASTWriter::WritePragmaDiagnosticMap
>     Stream.EmitRecord(DIAG_PRAGMA_MAPPINGS, Record);
> }
> 
> +void ASTWriter::WriteCXXCtorInitializersOffsets() {
> +  if (CXXCtorInitializersOffsets.empty())
> +    return;
> +
> +  RecordData Record;
> +
> +  // Create a blob abbreviation for the C++ ctor initializer offsets.
> +  using namespace llvm;
> +
> +  BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
> +  Abbrev->Add(BitCodeAbbrevOp(CXX_CTOR_INITIALIZERS_OFFSETS));
> +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // size
> +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
> +  unsigned CtorInitializersOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
> +
> +  // Write the base specifier offsets table.
> +  Record.clear();
> +  Record.push_back(CXX_CTOR_INITIALIZERS_OFFSETS);
> +  Record.push_back(CXXCtorInitializersOffsets.size());
> +  Stream.EmitRecordWithBlob(CtorInitializersOffsetAbbrev, Record,
> +                            data(CXXCtorInitializersOffsets));
> +}
> +
> void ASTWriter::WriteCXXBaseSpecifiersOffsets() {
>   if (CXXBaseSpecifiersOffsets.empty())
>     return;
> @@ -4154,7 +4177,8 @@ ASTWriter::ASTWriter(llvm::BitstreamWrit
>       FirstSelectorID(NUM_PREDEF_SELECTOR_IDS), NextSelectorID(FirstSelectorID),
>       CollectedStmts(&StmtsToEmit), NumStatements(0), NumMacros(0),
>       NumLexicalDeclContexts(0), NumVisibleDeclContexts(0),
> -      NextCXXBaseSpecifiersID(1), TypeExtQualAbbrev(0),
> +      NextCXXBaseSpecifiersID(1), NextCXXCtorInitializersID(1),
> +      TypeExtQualAbbrev(0),
>       TypeFunctionProtoAbbrev(0), DeclParmVarAbbrev(0),
>       DeclContextLexicalAbbrev(0), DeclContextVisibleLookupAbbrev(0),
>       UpdateVisibleAbbrev(0), DeclRecordAbbrev(0), DeclTypedefAbbrev(0),
> @@ -4559,6 +4583,7 @@ void ASTWriter::WriteASTCore(Sema &SemaR
>   if (!DeclUpdatesOffsetsRecord.empty())
>     Stream.EmitRecord(DECL_UPDATE_OFFSETS, DeclUpdatesOffsetsRecord);
>   WriteCXXBaseSpecifiersOffsets();
> +  WriteCXXCtorInitializersOffsets();
>   WriteFileDeclIDsMap();
>   WriteSourceManagerBlock(Context.getSourceManager(), PP);
> 
> @@ -4818,11 +4843,7 @@ void ASTWriter::WriteDeclUpdatesBlocks(R
> 
>     Stream.EmitRecord(DECL_UPDATES, Record);
> 
> -    // Flush any statements that were written as part of this update record.
> -    FlushStmts();
> -
> -    // Flush C++ base specifiers, if there are any.
> -    FlushCXXBaseSpecifiers();
> +    FlushPendingAfterDecl();
>   }
> }
> 
> @@ -4934,8 +4955,16 @@ void ASTWriter::AddCXXTemporary(const CX
>   AddDeclRef(Temp->getDestructor(), Record);
> }
> 
> +void ASTWriter::AddCXXCtorInitializersRef(ArrayRef<CXXCtorInitializer *> Inits,
> +                                          RecordDataImpl &Record) {
> +  assert(!Inits.empty() && "Empty ctor initializer sets are not recorded");
> +  CXXCtorInitializersToWrite.push_back(
> +      QueuedCXXCtorInitializers(NextCXXCtorInitializersID, Inits));
> +  Record.push_back(NextCXXCtorInitializersID++);
> +}
> +
> void ASTWriter::AddCXXBaseSpecifiersRef(CXXBaseSpecifier const *Bases,
> -                                      CXXBaseSpecifier const *BasesEnd,
> +                                        CXXBaseSpecifier const *BasesEnd,
>                                         RecordDataImpl &Record) {
>   assert(Bases != BasesEnd && "Empty base-specifier sets are not recorded");
>   CXXBaseSpecifiersToWrite.push_back(
> @@ -5496,7 +5525,8 @@ void ASTWriter::AddCXXBaseSpecifier(cons
> 
> void ASTWriter::FlushCXXBaseSpecifiers() {
>   RecordData Record;
> -  for (unsigned I = 0, N = CXXBaseSpecifiersToWrite.size(); I != N; ++I) {
> +  unsigned N = CXXBaseSpecifiersToWrite.size();
> +  for (unsigned I = 0; I != N; ++I) {
>     Record.clear();
> 
>     // Record the offset of this base-specifier set.
> @@ -5520,6 +5550,8 @@ void ASTWriter::FlushCXXBaseSpecifiers()
>     FlushStmts();
>   }
> 
> +  assert(N == CXXBaseSpecifiersToWrite.size() &&
> +         "added more base specifiers while writing base specifiers");
>   CXXBaseSpecifiersToWrite.clear();
> }
> 
> @@ -5561,6 +5593,35 @@ void ASTWriter::AddCXXCtorInitializers(
>   }
> }
> 
> +void ASTWriter::FlushCXXCtorInitializers() {
> +  RecordData Record;
> +
> +  unsigned N = CXXCtorInitializersToWrite.size();
> +  for (auto &Init : CXXCtorInitializersToWrite) {
> +    Record.clear();
> +
> +    // Record the offset of this mem-initializer list.
> +    unsigned Index = Init.ID - 1;
> +    if (Index == CXXCtorInitializersOffsets.size())
> +      CXXCtorInitializersOffsets.push_back(Stream.GetCurrentBitNo());
> +    else {
> +      if (Index > CXXCtorInitializersOffsets.size())
> +        CXXCtorInitializersOffsets.resize(Index + 1);
> +      CXXCtorInitializersOffsets[Index] = Stream.GetCurrentBitNo();
> +    }
> +
> +    AddCXXCtorInitializers(Init.Inits.data(), Init.Inits.size(), Record);
> +    Stream.EmitRecord(serialization::DECL_CXX_CTOR_INITIALIZERS, Record);
> +
> +    // Flush any expressions that were written as part of the initializers.
> +    FlushStmts();
> +  }
> +
> +  assert(N == CXXCtorInitializersToWrite.size() &&
> +         "added more ctor initializers while writing ctor initializers");
> +  CXXCtorInitializersToWrite.clear();
> +}
> +
> void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Record) {
>   auto &Data = D->data();
>   Record.push_back(Data.IsLambda);
> 
> Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=233052&r1=233051&r2=233052&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Tue Mar 24 01:36:48 2015
> @@ -133,9 +133,12 @@ namespace clang {
> 
>     void AddFunctionDefinition(const FunctionDecl *FD) {
>       assert(FD->doesThisDeclarationHaveABody());
> -      if (auto *CD = dyn_cast<CXXConstructorDecl>(FD))
> -        Writer.AddCXXCtorInitializers(CD->CtorInitializers,
> -                                      CD->NumCtorInitializers, Record);
> +      if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) {
> +        Record.push_back(CD->NumCtorInitializers);
> +        if (CD->NumCtorInitializers)
> +          Writer.AddCXXCtorInitializersRef(
> +              llvm::makeArrayRef(CD->init_begin(), CD->init_end()), Record);
> +      }
>       Writer.AddStmt(FD->getBody());
>     }
> 
> @@ -209,7 +212,7 @@ void ASTDeclWriter::Visit(Decl *D) {
>   if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
>     Record.push_back(FD->doesThisDeclarationHaveABody());
>     if (FD->doesThisDeclarationHaveABody())
> -      Writer.AddStmt(FD->getBody());
> +      AddFunctionDefinition(FD);
>   }
> }
> 
> @@ -711,8 +714,10 @@ void ASTDeclWriter::VisitObjCImplementat
>   Writer.AddSourceLocation(D->getIvarRBraceLoc(), Record);
>   Record.push_back(D->hasNonZeroConstructors());
>   Record.push_back(D->hasDestructors());
> -  Writer.AddCXXCtorInitializers(D->IvarInitializers, D->NumIvarInitializers,
> -                                Record);
> +  Record.push_back(D->NumIvarInitializers);
> +  if (D->NumIvarInitializers)
> +    Writer.AddCXXCtorInitializersRef(
> +        llvm::makeArrayRef(D->init_begin(), D->init_end()), Record);
>   Code = serialization::DECL_OBJC_IMPLEMENTATION;
> }
> 
> @@ -1120,8 +1125,6 @@ void ASTDeclWriter::VisitCXXConstructorD
> 
>   Writer.AddDeclRef(D->getInheritedConstructor(), Record);
>   Record.push_back(D->IsExplicitSpecified);
> -  Writer.AddCXXCtorInitializers(D->CtorInitializers, D->NumCtorInitializers,
> -                                Record);
> 
>   Code = serialization::DECL_CXX_CONSTRUCTOR;
> }
> @@ -2066,12 +2069,10 @@ void ASTWriter::WriteDecl(ASTContext &Co
>                             D->getDeclKindName() + "'");
>   Stream.EmitRecord(W.Code, Record, W.AbbrevToUse);
> 
> -  // Flush any expressions that were written as part of this declaration.
> -  FlushStmts();
> -  
> -  // Flush C++ base specifiers, if there are any.
> -  FlushCXXBaseSpecifiers();
> -  
> +  // Flush any expressions, base specifiers, and ctor initializers that
> +  // were written as part of this declaration.
> +  FlushPendingAfterDecl();
> +
>   // Note declarations that should be deserialized eagerly so that we can add
>   // them to a record in the AST file later.
>   if (isRequiredDecl(D, Context))
> 
> Modified: cfe/trunk/lib/Serialization/Module.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/Module.cpp?rev=233052&r1=233051&r2=233052&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Serialization/Module.cpp (original)
> +++ cfe/trunk/lib/Serialization/Module.cpp Tue Mar 24 01:36:48 2015
> @@ -38,6 +38,7 @@ ModuleFile::ModuleFile(ModuleKind Kind,
>     SelectorLookupTableData(nullptr), SelectorLookupTable(nullptr),
>     LocalNumDecls(0), DeclOffsets(nullptr), BaseDeclID(0),
>     LocalNumCXXBaseSpecifiers(0), CXXBaseSpecifiersOffsets(nullptr),
> +    LocalNumCXXCtorInitializers(0), CXXCtorInitializersOffsets(nullptr),
>     FileSortedDecls(nullptr), NumFileSortedDecls(0),
>     RedeclarationsMap(nullptr), LocalNumRedeclarationsInMap(0),
>     ObjCCategoriesMap(nullptr), LocalNumObjCCategoriesInMap(0),
> 
> 
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits





More information about the cfe-commits mailing list