r192494 - Adds Microsoft compatiable C++ record layout code to clang.

Reid Kleckner rnk at google.com
Fri Oct 11 15:10:31 PDT 2013


Should've been fixed in r192495:
http://bb.pgr.jp/builders/ninja-clang-i686-msc17-R/builds/5434

Same failure was reported here:
http://bb.pgr.jp/builders/ninja-clang-i686-msc17-R/builds/5433


On Fri, Oct 11, 2013 at 3:00 PM, jahanian <fjahanian at apple.com> wrote:

> We are experiencing VS buildbot failures after this patch went in. These
> three tests are failing.
>
> Testing Time: 47.63s
>   ********************
>   Failing Tests (3):
>       Clang :: Analysis/inlining/dyn-dispatch-bifurcate.cpp
>       Clang :: SemaCXX/primary-base.cpp
>       Clang :: SemaCXX/warn-reinterpret-base-class.cpp
>
> They all give error having to do with what it says is illegal use of
> reinterpret_cast.
>
> - Fariborz
>
> On Oct 11, 2013, at 1:19 PM, Warren Hunt <whunt at google.com> wrote:
>
> > Author: whunt
> > Date: Fri Oct 11 15:19:00 2013
> > New Revision: 192494
> >
> > URL: http://llvm.org/viewvc/llvm-project?rev=192494&view=rev
> > Log:
> > Adds Microsoft compatiable C++ record layout code to clang.
> >
> >
> > Modified:
> >    cfe/trunk/include/clang/AST/ASTContext.h
> >    cfe/trunk/include/clang/AST/RecordLayout.h
> >    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> >    cfe/trunk/lib/AST/RecordLayout.cpp
> >    cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
> >    cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp
> >    cfe/trunk/lib/CodeGen/MicrosoftVBTables.cpp
> >    cfe/trunk/lib/Sema/SemaDecl.cpp
> >    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> >    cfe/trunk/test/CodeGen/pr2394.c
> >    cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp
> >    cfe/trunk/test/Coverage/codegen-next.m
> >    cfe/trunk/test/PCH/rdar10830559.cpp
> >    cfe/trunk/test/Sema/ms_class_layout.cpp
> >    cfe/trunk/test/SemaCXX/ms_struct.cpp
> >
> > Modified: cfe/trunk/include/clang/AST/ASTContext.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=192494&r1=192493&r2=192494&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/AST/ASTContext.h (original)
> > +++ cfe/trunk/include/clang/AST/ASTContext.h Fri Oct 11 15:19:00 2013
> > @@ -1660,6 +1660,7 @@ public:
> >   /// record (struct/union/class) \p D, which indicates its size and
> field
> >   /// position information.
> >   const ASTRecordLayout &getASTRecordLayout(const RecordDecl *D) const;
> > +  const ASTRecordLayout *BuildMicrosoftASTRecordLayout(const RecordDecl
> *D) const;
> >
> >   /// \brief Get or compute information about the layout of the specified
> >   /// Objective-C interface.
> >
> > Modified: cfe/trunk/include/clang/AST/RecordLayout.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecordLayout.h?rev=192494&r1=192493&r2=192494&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/AST/RecordLayout.h (original)
> > +++ cfe/trunk/include/clang/AST/RecordLayout.h Fri Oct 11 15:19:00 2013
> > @@ -93,7 +93,20 @@ private:
> >     /// HasOwnVFPtr - Does this class provide a virtual function table
> >     /// (vtable in Itanium, vftbl in Microsoft) that is independent from
> >     /// its base classes?
> > -    bool HasOwnVFPtr; // TODO: stash this somewhere more efficient
> > +    bool HasOwnVFPtr : 1;
> > +
> > +    /// HasVFPtr - Does this class have a vftable at all (could be
> inherited
> > +    /// from its primary base.)
> > +    bool HasVFPtr : 1;
> > +
> > +    /// HasOwnVBPtr - Does this class provide a virtual function table
> > +    /// (vtable in Itanium, VBtbl in Microsoft) that is independent from
> > +    /// its base classes?
> > +    bool HasOwnVBPtr : 1;
> > +
> > +    /// AlignAfterVBases - Force appropriate alignment after virtual
> bases are
> > +    /// laid out in MS-C++-ABI.
> > +    bool AlignAfterVBases : 1;
> >
> >     /// PrimaryBase - The primary base info for this record.
> >     llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> PrimaryBase;
> > @@ -122,13 +135,15 @@ private:
> >   typedef CXXRecordLayoutInfo::BaseOffsetsMapTy BaseOffsetsMapTy;
> >   ASTRecordLayout(const ASTContext &Ctx,
> >                   CharUnits size, CharUnits alignment,
> > -                  bool hasOwnVFPtr, CharUnits vbptroffset,
> > +                  bool hasOwnVFPtr, bool hasVFPtr, bool hasOwnVBPtr,
> > +                  CharUnits vbptroffset,
> >                   CharUnits datasize,
> >                   const uint64_t *fieldoffsets, unsigned fieldcount,
> >                   CharUnits nonvirtualsize, CharUnits nonvirtualalign,
> >                   CharUnits SizeOfLargestEmptySubobject,
> >                   const CXXRecordDecl *PrimaryBase,
> >                   bool IsPrimaryBaseVirtual,
> > +                  bool ForceAlign,
> >                   const BaseOffsetsMapTy& BaseOffsets,
> >                   const VBaseOffsetsMapTy& VBaseOffsets);
> >
> > @@ -226,6 +241,35 @@ public:
> >     return CXXInfo->HasOwnVFPtr;
> >   }
> >
> > +  /// hasVFPtr - Does this class have a virtual function table pointer.
> > +  bool hasVFPtr() const {
> > +    assert(CXXInfo && "Record layout does not have C++ specific info!");
> > +    return CXXInfo->HasVFPtr;
> > +  }
> > +
> > +  /// hasOwnVBPtr - Does this class provide its own virtual-base
> > +  /// table pointer, rather than inheriting one from a primary base
> > +  /// class?
> > +  ///
> > +  /// This implies that the ABI has no primary base class, meaning
> > +  /// that it has no base classes that are suitable under the conditions
> > +  /// of the ABI.
> > +  bool hasOwnVBPtr() const {
> > +    assert(CXXInfo && "Record layout does not have C++ specific info!");
> > +    return CXXInfo->HasOwnVBPtr;
> > +  }
> > +
> > +  /// hasVBPtr - Does this class have a virtual function table pointer.
> > +  bool hasVBPtr() const {
> > +    assert(CXXInfo && "Record layout does not have C++ specific info!");
> > +    return !CXXInfo->VBPtrOffset.isNegative();
> > +  }
> > +
> > +  bool getAlignAfterVBases() const {
> > +    assert(CXXInfo && "Record layout does not have C++ specific info!");
> > +    return CXXInfo->AlignAfterVBases;
> > +  }
> > +
> >   /// getVBPtrOffset - Get the offset for virtual base table pointer.
> >   /// This is only meaningful with the Microsoft ABI.
> >   CharUnits getVBPtrOffset() const {
> >
> > Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=192494&r1=192493&r2=192494&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> > +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Oct 11
> 15:19:00 2013
> > @@ -463,6 +463,7 @@ def warn_pragma_pack_show : Warning<"val
> > def warn_pragma_pack_pop_identifer_and_alignment : Warning<
> >   "specifying both a name and alignment to 'pop' is undefined">;
> > def warn_pragma_pack_pop_failed : Warning<"#pragma pack(pop, ...)
> failed: %0">;
> > +def warn_pragma_ms_struct_failed : Warning<"#pramga ms_struct can not
> be used with dynamic classes or structures">, InGroup<IgnoredAttributes>;
> >
> > def warn_pragma_unused_undeclared_var : Warning<
> >   "undeclared variable %0 used as an argument for '#pragma unused'">;
> >
> > Modified: cfe/trunk/lib/AST/RecordLayout.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayout.cpp?rev=192494&r1=192493&r2=192494&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/AST/RecordLayout.cpp (original)
> > +++ cfe/trunk/lib/AST/RecordLayout.cpp Fri Oct 11 15:19:00 2013
> > @@ -43,7 +43,9 @@ ASTRecordLayout::ASTRecordLayout(const A
> > // Constructor for C++ records.
> > ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx,
> >                                  CharUnits size, CharUnits alignment,
> > -                                 bool hasOwnVFPtr, CharUnits
> vbptroffset,
> > +                                 bool hasOwnVFPtr, bool hasVFPtr,
> > +                                 bool hasOwnVBPtr,
> > +                                 CharUnits vbptroffset,
> >                                  CharUnits datasize,
> >                                  const uint64_t *fieldoffsets,
> >                                  unsigned fieldcount,
> > @@ -52,6 +54,7 @@ ASTRecordLayout::ASTRecordLayout(const A
> >                                  CharUnits SizeOfLargestEmptySubobject,
> >                                  const CXXRecordDecl *PrimaryBase,
> >                                  bool IsPrimaryBaseVirtual,
> > +                                 bool AlignAfterVBases,
> >                                  const BaseOffsetsMapTy& BaseOffsets,
> >                                  const VBaseOffsetsMapTy& VBaseOffsets)
> >   : Size(size), DataSize(datasize), Alignment(alignment),
> FieldOffsets(0),
> > @@ -71,6 +74,10 @@ ASTRecordLayout::ASTRecordLayout(const A
> >   CXXInfo->VBaseOffsets = VBaseOffsets;
> >   CXXInfo->HasOwnVFPtr = hasOwnVFPtr;
> >   CXXInfo->VBPtrOffset = vbptroffset;
> > +  CXXInfo->HasVFPtr = hasVFPtr;
> > +  CXXInfo->HasOwnVBPtr = hasOwnVBPtr;
> > +  CXXInfo->AlignAfterVBases = AlignAfterVBases;
> > +
> >
> > #ifndef NDEBUG
> >     if (const CXXRecordDecl *PrimaryBase = getPrimaryBase()) {
> >
> > Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=192494&r1=192493&r2=192494&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
> > +++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Fri Oct 11 15:19:00 2013
> > @@ -604,6 +604,10 @@ protected:
> >   /// pointer, as opposed to inheriting one from a primary base class.
> >   bool HasOwnVFPtr;
> >
> > +  /// HasOwnVBPtr - Whether the class provides its own vbtbl
> > +  /// pointer, as opposed to inheriting one from a base class. Only for
> MS.
> > +  bool HasOwnVBPtr;
> > +
> >   /// VBPtrOffset - Virtual base table offset. Only for MS layout.
> >   CharUnits VBPtrOffset;
> >
> > @@ -654,6 +658,7 @@ protected:
> >       NonVirtualAlignment(CharUnits::One()),
> >       PrimaryBase(0), PrimaryBaseIsVirtual(false),
> >       HasOwnVFPtr(false),
> > +      HasOwnVBPtr(false),
> >       VBPtrOffset(CharUnits::fromQuantity(-1)),
> >       FirstNearlyEmptyVBase(0) { }
> >
> > @@ -1074,8 +1079,10 @@ RecordLayoutBuilder::LayoutNonVirtualBas
> >       cast<CXXRecordDecl>(I->getType()->castAs<RecordType>()->getDecl());
> >
> >     // Remember if this base has virtual bases itself.
> > -    if (BaseDecl->getNumVBases())
> > +    if (BaseDecl->getNumVBases()) {
> > +      const ASTRecordLayout &Layout =
> Context.getASTRecordLayout(BaseDecl);
> >       HasNonVirtualBaseWithVBTable = true;
> > +    }
> >
> >     // Skip the primary base, because we've already laid it out.  The
> >     // !PrimaryBaseIsVirtual check is required because we might have a
> > @@ -1116,6 +1123,7 @@ RecordLayoutBuilder::LayoutNonVirtualBas
> >     PtrAlign = std::max(PtrAlign, Alignment);
> >
> >     EnsureVTablePointerAlignment(PtrAlign);
> > +    HasOwnVBPtr = true;
> >     VBPtrOffset = getSize();
> >     setSize(getSize() + PtrWidth);
> >     setDataSize(getSize());
> > @@ -2338,6 +2346,704 @@ static bool mustSkipTailPadding(TargetCX
> >   llvm_unreachable("bad tail-padding use kind");
> > }
> >
> > +static bool isMsLayout(const RecordDecl* D) {
> > +  return (D->getASTContext().getTargetInfo().getCXXABI().isMicrosoft()
> ||
> > +          D->getASTContext().getTargetInfo().getTriple().getOS() ==
> > +          llvm::Triple::Win32) &&
> > +          D->getASTContext().getTargetInfo().getPointerWidth(0) == 32;
> > +  // FIXME: we intend to enable 64 bit mode once it's been verified.
> > +}
> > +
> > +// This section contains an implementation of struct layout that is, up
> to the
> > +// included tests, compatible with cl.exe (2012).  The layout produced
> is
> > +// significantly different than those produced by the Itanium ABI.
>  Here we note
> > +// the most important differences.
> > +//
> > +// * The alignment of bitfields in unions is ignored when computing the
> > +//   alignment of the union.
> > +// * The existance of zero-width bitfield that occurs after anything
> other than
> > +//   a non-zero length bitfield is ignored.
> > +// * The Itanium equivalent vtable pointers are split into a vfptr
> (virtual
> > +//   function pointer) and a vbptr (virtual base pointer).  They can
> each be
> > +//   shared with a, non-virtual bases. These bases need not be the
> same.  vfptrs always occur at offset 0.  vbptrs can occur at an
> > +//   arbitrary offset and are placed after non-virtual bases but before
> fields.
> > +// * Virtual bases sometimes require a 'vtordisp' field that is laid
> out before
> > +//   the virtual base and is used in conjunction with virtual overrides
> during
> > +//   construction and destruction.
> > +// * vfptrs are allocated in a block of memory equal to the alignment
> of the
> > +//   fields and non-virtual bases at offset 0.
> > +// * vbptrs are allocated in a block of memory equal to the alignment
> of the
> > +//   fields and non-virtual bases.  This block is at a potentially
> unaligned offset.  If the
> > +//   allocation slot is unaligned and the alignment is less than or
> equal to the
> > +//   pointer size, additional space is allocated so that the pointer
> can be aligned properly.  This causes very strange effects on the placement
> of objects after the allocated block. (see
> > +//   the code).
> > +// * vtordisps are allocated in a block of memory with size and
> alignment equal
> > +//   to the alignment of the completed structure (before applying
> __declspec(
> > +//   align())).  The vtordisp always occur at the end of the allocation
> block, immediately prior to the virtual base.
> > +// * The last zero sized non-virtual base is allocated after the
> placement of
> > +//   vbptr if one exists and can be placed at the end of the struct,
> potentially
> > +//   aliasing either the first member or another struct allocated after
> this
> > +//   one.
> > +// * The last zero size virtual base may be placed at the end of the
> struct.
> > +//   and can potentially alias a zero sized type in the next struct.
> > +
> > +namespace {
> > +struct MicrosoftRecordLayoutBuilder {
> > +  typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
> BaseOffsetsMapTy;
> > +  MicrosoftRecordLayoutBuilder(const ASTContext &Context) :
> Context(Context) {}
> > +private:
> > +  MicrosoftRecordLayoutBuilder(const MicrosoftRecordLayoutBuilder &)
> > +  LLVM_DELETED_FUNCTION;
> > +  void operator=(const MicrosoftRecordLayoutBuilder &)
> LLVM_DELETED_FUNCTION;
> > +public:
> > +
> > +  void layout(const RecordDecl *RD);
> > +  void cxxLayout(const CXXRecordDecl *RD);
> > +  /// \brief Initializes size and alignment and honors some flags.
> > +  void initializeLayout(const RecordDecl *RD);
> > +  /// \brief Initialized C++ layout, compute alignment and virtual
> alignment and
> > +  /// existance of vfptrs and vbptrs.  Alignment is needed before the
> vfptr is
> > +  /// laid out.
> > +  void initializeCXXLayout(const CXXRecordDecl *RD);
> > +  void layoutVFPtr(const CXXRecordDecl *RD);
> > +  void layoutNonVirtualBases(const CXXRecordDecl *RD);
> > +  void layoutNonVirtualBase(const CXXRecordDecl *RD);
> > +  void layoutVBPtr(const CXXRecordDecl *RD);
> > +  /// \brief Lays out the fields of the record.  Also rounds size up to
> > +  /// alignment.
> > +  void layoutFields(const RecordDecl *RD);
> > +  void layoutField(const FieldDecl *FD);
> > +  void layoutBitField(const FieldDecl *FD);
> > +  /// \brief Lays out a single zero-width bit-field in the record and
> handles
> > +  /// special cases associated with zero-width bit-fields.
> > +  void layoutZeroWidthBitField(const FieldDecl *FD);
> > +  void layoutVirtualBases(const CXXRecordDecl *RD);
> > +  void layoutVirtualBase(const CXXRecordDecl *RD, bool HasVtordisp);
> > +  /// \brief Flushes the lazy virtual base and conditionally rounds up
> to
> > +  /// alignment.
> > +  void finalizeCXXLayout(const CXXRecordDecl *RD);
> > +  void honorDeclspecAlign(const RecordDecl *RD);
> > +
> > +  /// \brief Updates the alignment of the type.  This function doesn't
> take any
> > +  /// properties (such as packedness) into account.
>  getAdjustedFieldInfo()
> > +  /// adjustes for packedness.
> > +  void updateAlignment(CharUnits NewAlignment) {
> > +    Alignment = std::max(Alignment, NewAlignment);
> > +  }
> > +  /// \brief Gets the size and alignment taking attributes into account.
> > +  std::pair<CharUnits, CharUnits> getAdjustedFieldInfo(const FieldDecl
> *FD);
> > +  /// \brief Places a field at offset 0.
> > +  void placeFieldAtZero() { FieldOffsets.push_back(0); }
> > +  /// \brief Places a field at an offset in CharUnits.
> > +  void placeFieldAtOffset(CharUnits FieldOffset) {
> > +    FieldOffsets.push_back(Context.toBits(FieldOffset));
> > +  }
> > +  /// \brief Places a bitfield at a bit offset.
> > +  void placeFieldAtBitOffset(uint64_t FieldOffset) {
> > +    FieldOffsets.push_back(FieldOffset);
> > +  }
> > +  /// \brief Compute the set of virtual bases for which vtordisps are
> required.
> > +  llvm::SmallPtrSet<const CXXRecordDecl *, 2>
> > +  computeVtorDispSet(const CXXRecordDecl *RD);
> > +
> > +  const ASTContext &Context;
> > +  /// \brief The size of the record being laid out.
> > +  CharUnits Size;
> > +  /// \brief The current alignment of the record layout.
> > +  CharUnits Alignment;
> > +  /// \brief The collection of field offsets.
> > +  SmallVector<uint64_t, 16> FieldOffsets;
> > +  /// \brief The maximum allowed field alignment. This is set by
> #pragma pack.
> > +  CharUnits MaxFieldAlignment;
> > +  /// \brief Alignment does not occur for virtual bases unless something
> > +  /// forces it to by explicitly using __declspec(align())
> > +  bool AlignAfterVBases : 1;
> > +  bool IsUnion : 1;
> > +  /// \brief True if the last field laid out was a bitfield and was not
> 0
> > +  /// width.
> > +  bool LastFieldIsNonZeroWidthBitfield : 1;
> > +  /// \brief The size of the allocation of the currently active
> bitfield.
> > +  /// This value isn't meaningful unless LastFieldIsNonZeroWidthBitfield
> > +  /// is true.
> > +  CharUnits CurrentBitfieldSize;
> > +  /// \brief The number of remaining bits in our last bitfield
> allocation.
> > +  /// This value isn't meaningful unless
> LastFieldIsNonZeroWidthBitfield is
> > +  /// true.
> > +  unsigned RemainingBitsInField;
> > +
> > +  /// \brief The data alignment of the record layout.
> > +  CharUnits DataSize;
> > +  /// \brief The alignment of the non-virtual portion of the record
> layout
> > +  /// including. Only used for C++ layouts.
> > +  CharUnits NonVirtualAlignment;
> > +  /// \brief The additional alignment imposed by the virtual bases.
> > +  CharUnits VirtualAlignment;
> > +  /// \brief The primary base class (if one exists).
> > +  const CXXRecordDecl *PrimaryBase;
> > +  /// \brief The class we share our vb-pointer with.
> > +  const CXXRecordDecl *SharedVBPtrBase;
> > +  /// \brief True if the class has a (not necessarily its own) vftable
> pointer.
> > +  bool HasVFPtr : 1;
> > +  /// \brief True if the class has a (not necessarily its own) vbtable
> pointer.
> > +  bool HasVBPtr : 1;
> > +  /// \brief Offset to the virtual base table pointer (if one exists).
> > +  CharUnits VBPtrOffset;
> > +  /// \brief Base classes and their offsets in the record.
> > +  BaseOffsetsMapTy Bases;
> > +  /// \brief virtual base classes and their offsets in the record.
> > +  ASTRecordLayout::VBaseOffsetsMapTy VBases;
> > +  /// \brief The size of a pointer.
> > +  CharUnits PointerSize;
> > +  /// \brief The alignment of a pointer.
> > +  CharUnits PointerAlignment;
> > +  /// \brief Holds an empty base we haven't yet laid out.
> > +  const CXXRecordDecl *LazyEmptyBase;
> > +};
> > +} // namespace
> > +
> > +std::pair<CharUnits, CharUnits>
> > +MicrosoftRecordLayoutBuilder::getAdjustedFieldInfo(const FieldDecl *FD)
> {
> > +  std::pair<CharUnits, CharUnits> FieldInfo;
> > +  if (FD->getType()->isIncompleteArrayType()) {
> > +    // This is a flexible array member; we can't directly
> > +    // query getTypeInfo about these, so we figure it out here.
> > +    // Flexible array members don't have any size, but they
> > +    // have to be aligned appropriately for their element type.
> > +    FieldInfo.first = CharUnits::Zero();
> > +    const ArrayType *ATy = Context.getAsArrayType(FD->getType());
> > +    FieldInfo.second =
> Context.getTypeAlignInChars(ATy->getElementType());
> > +  } else if (const ReferenceType *RT =
> FD->getType()->getAs<ReferenceType>()) {
> > +    unsigned AS = RT->getPointeeType().getAddressSpace();
> > +    FieldInfo.first = Context
> > +
>  .toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(AS));
> > +    FieldInfo.second = Context
> > +
>  .toCharUnitsFromBits(Context.getTargetInfo().getPointerAlign(AS));
> > +  } else
> > +    FieldInfo = Context.getTypeInfoInChars(FD->getType());
> > +
> > +  // If we're not on win32 and using ms_struct the field alignment will
> be wrong
> > +  // for 64 bit types, so we fix that here.
> > +  if (FD->getASTContext().getTargetInfo().getTriple().getOS() !=
> > +      llvm::Triple::Win32) {
> > +    QualType T = Context.getBaseElementType(FD->getType());
> > +    if (const BuiltinType *BTy = T->getAs<BuiltinType>()) {
> > +      CharUnits TypeSize = Context.getTypeSizeInChars(BTy);
> > +      if (TypeSize > FieldInfo.second)
> > +        FieldInfo.second = TypeSize;
> > +    }
> > +  }
> > +
> > +  // Respect packed attribute.
> > +  if (FD->hasAttr<PackedAttr>())
> > +    FieldInfo.second = CharUnits::One();
> > +  // Respect pack pragma.
> > +  else if (!MaxFieldAlignment.isZero())
> > +    FieldInfo.second = std::min(FieldInfo.second, MaxFieldAlignment);
> > +  // Respect alignment attributes.
> > +  if (unsigned fieldAlign = FD->getMaxAlignment()) {
> > +    CharUnits FieldAlign = Context.toCharUnitsFromBits(fieldAlign);
> > +    AlignAfterVBases = true;
> > +    FieldInfo.second = std::max(FieldInfo.second, FieldAlign);
> > +  }
> > +  return FieldInfo;
> > +}
> > +
> > +void MicrosoftRecordLayoutBuilder::initializeLayout(const RecordDecl
> *RD) {
> > +  IsUnion = RD->isUnion();
> > +
> > +  Size = CharUnits::Zero();
> > +  Alignment = CharUnits::One();
> > +  AlignAfterVBases = false;
> > +
> > +  // Compute the maximum field alignment.
> > +  MaxFieldAlignment = CharUnits::Zero();
> > +  // Honor the default struct packing maximum alignment flag.
> > +  if (unsigned DefaultMaxFieldAlignment =
> Context.getLangOpts().PackStruct)
> > +    MaxFieldAlignment =
> CharUnits::fromQuantity(DefaultMaxFieldAlignment);
> > +  // Honor the packing attribute.
> > +  if (const MaxFieldAlignmentAttr *MFAA =
> RD->getAttr<MaxFieldAlignmentAttr>())
> > +    MaxFieldAlignment =
> Context.toCharUnitsFromBits(MFAA->getAlignment());
> > +  // Packed attribute forces max field alignment to be 1.
> > +  if (RD->hasAttr<PackedAttr>())
> > +    MaxFieldAlignment = CharUnits::One();
> > +}
> > +
> > +void MicrosoftRecordLayoutBuilder::layout(const RecordDecl *RD) {
> > +  initializeLayout(RD);
> > +  layoutFields(RD);
> > +  honorDeclspecAlign(RD);
> > +}
> > +
> > +void MicrosoftRecordLayoutBuilder::cxxLayout(const CXXRecordDecl *RD) {
> > +  initializeLayout(RD);
> > +  initializeCXXLayout(RD);
> > +  layoutVFPtr(RD);
> > +  layoutNonVirtualBases(RD);
> > +  layoutVBPtr(RD);
> > +  layoutFields(RD);
> > +  DataSize = Size;
> > +  NonVirtualAlignment = Alignment;
> > +  layoutVirtualBases(RD);
> > +  finalizeCXXLayout(RD);
> > +  honorDeclspecAlign(RD);
> > +}
> > +
> > +void
> > +MicrosoftRecordLayoutBuilder::initializeCXXLayout(const CXXRecordDecl
> *RD) {
> > +  // Calculate pointer size and alignment.
> > +  PointerSize =
> > +
>  Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
> > +  PointerAlignment = PointerSize;
> > +  if (!MaxFieldAlignment.isZero())
> > +    PointerAlignment = std::min(PointerAlignment, MaxFieldAlignment);
> > +
> > +  // Initialize information about the bases.
> > +  HasVBPtr = false;
> > +  HasVFPtr = false;
> > +  SharedVBPtrBase = 0;
> > +  PrimaryBase = 0;
> > +  VirtualAlignment = CharUnits::One();
> > +
> > +  // If the record has a dynamic base class, attempt to choose a
> primary base
> > +  // class. It is the first (in direct base class order) non-virtual
> dynamic
> > +  // base class, if one exists.
> > +  for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
> > +                                                e = RD->bases_end();
> > +       i != e; ++i) {
> > +    const CXXRecordDecl *BaseDecl =
> > +
>  cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
> > +    const ASTRecordLayout &Layout =
> Context.getASTRecordLayout(BaseDecl);
> > +    // Handle forced alignment.
> > +    if (Layout.getAlignAfterVBases())
> > +      AlignAfterVBases = true;
> > +    // Handle virtual bases.
> > +    if (i->isVirtual()) {
> > +      VirtualAlignment = std::max(VirtualAlignment,
> Layout.getAlignment());
> > +      HasVBPtr = true;
> > +      continue;
> > +    }
> > +    // We located a primary base class!
> > +    if (!PrimaryBase && Layout.hasVFPtr()) {
> > +      PrimaryBase = BaseDecl;
> > +      HasVFPtr = true;
> > +    }
> > +    // We located a base to share a VBPtr with!
> > +    if (!SharedVBPtrBase && Layout.hasVBPtr()) {
> > +      SharedVBPtrBase = BaseDecl;
> > +      HasVBPtr = true;
> > +    }
> > +    updateAlignment(Layout.getAlignment());
> > +  }
> > +
> > +  // Use LayoutFields to compute the alignment of the fields.  The
> layout
> > +  // is discarded.  This is the simplest way to get all of the bit-field
> > +  // behavior correct and is not actually very expensive.
> > +  layoutFields(RD);
> > +  Size = CharUnits::Zero();
> > +  FieldOffsets.clear();
> > +}
> > +
> > +void MicrosoftRecordLayoutBuilder::layoutVFPtr(const CXXRecordDecl *RD)
> {
> > +  // If we have a primary base then our VFPtr was already laid out
> > +  if (PrimaryBase)
> > +    return;
> > +
> > +  // Look at all of our methods to determine if we need a VFPtr.  We
> need a
> > +  // vfptr if we define a new virtual function.
> > +  if (!HasVFPtr && RD->isDynamicClass())
> > +    for (CXXRecordDecl::method_iterator i = RD->method_begin(),
> > +                                        e = RD->method_end();
> > +         !HasVFPtr && i != e; ++i)
> > +      HasVFPtr = i->isVirtual() && i->size_overridden_methods() == 0;
> > +  if (!HasVFPtr)
> > +    return;
> > +
> > +  // MSVC potentially over-aligns the vf-table pointer by giving it
> > +  // the max alignment of all the non-virtual data in the class.  The
> resulting
> > +  // layout is essentially { vftbl, { nvdata } }.  This is completely
> > +  // unnecessary, but we're not here to pass judgment.
> > +  Size += Alignment;
> > +  updateAlignment(PointerAlignment);
> > +}
> > +
> > +void
> > +MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(const CXXRecordDecl
> *RD) {
> > +  LazyEmptyBase = 0;
> > +
> > +  // Lay out the primary base first.
> > +  if (PrimaryBase)
> > +    layoutNonVirtualBase(PrimaryBase);
> > +
> > +  // Iterate through the bases and lay out the non-virtual ones.
> > +  for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
> > +                                                e = RD->bases_end();
> > +       i != e; ++i) {
> > +    if (i->isVirtual())
> > +      continue;
> > +    const CXXRecordDecl *BaseDecl =
> > +
>  cast<CXXRecordDecl>(i->getType()->castAs<RecordType>()->getDecl());
> > +    if (BaseDecl != PrimaryBase)
> > +      layoutNonVirtualBase(BaseDecl);
> > +  }
> > +}
> > +
> > +void
> > +MicrosoftRecordLayoutBuilder::layoutNonVirtualBase(const CXXRecordDecl
> *RD) {
> > +  const ASTRecordLayout *Layout = RD ? &Context.getASTRecordLayout(RD)
> : 0;
> > +
> > +  // If we have a lazy empty base we haven't laid out yet, do that now.
> > +  if (LazyEmptyBase) {
> > +    const ASTRecordLayout &LazyLayout =
> > +        Context.getASTRecordLayout(LazyEmptyBase);
> > +    Size = Size.RoundUpToAlignment(LazyLayout.getAlignment());
> > +    Bases.insert(std::make_pair(LazyEmptyBase, Size));
> > +    // Empty bases only consume space when followed by another empty
> base.
> > +    if (RD && Layout->getNonVirtualSize().isZero())
> > +      Size++;
> > +    LazyEmptyBase = 0;
> > +  }
> > +
> > +  // RD is null when flushing the final lazy base.
> > +  if (!RD)
> > +    return;
> > +
> > +  if (Layout->getNonVirtualSize().isZero()) {
> > +    LazyEmptyBase = RD;
> > +    return;
> > +  }
> > +
> > +  // Insert the base here.
> > +  CharUnits BaseOffset =
> Size.RoundUpToAlignment(Layout->getAlignment());
> > +  Bases.insert(std::make_pair(RD, BaseOffset));
> > +  Size = BaseOffset + Layout->getDataSize();
> > +  // Note: we don't update alignment here because it was accounted
> > +  // for during initalization.
> > +}
> > +
> > +void MicrosoftRecordLayoutBuilder::layoutVBPtr(const CXXRecordDecl *RD)
> {
> > +  if (!HasVBPtr)
> > +    VBPtrOffset = CharUnits::fromQuantity(-1);
> > +  else if (SharedVBPtrBase) {
> > +    const ASTRecordLayout &Layout =
> Context.getASTRecordLayout(SharedVBPtrBase);
> > +    VBPtrOffset = Bases[SharedVBPtrBase] + Layout.getVBPtrOffset();
> > +  } else {
> > +    updateAlignment(PointerAlignment);
> > +    VBPtrOffset = Size.RoundUpToAlignment(PointerAlignment);
> > +
> > +    if (Alignment == PointerAlignment && Size % PointerAlignment) {
> > +      CharUnits x = Size + Alignment + Alignment;
> > +      Size = VBPtrOffset + Alignment;
> > +      // Handle strange padding rules.  I have no explanation for why
> the
> > +      // virtual base is padded in such an odd way.  My guess is that
> they
> > +      // always Add 2 * Alignment and incorrectly round down to the
> appropriate
> > +      // alignment.  It's important to get this case correct because it
> impacts
> > +      // the layout of the first member of the struct.
> > +
> > +      RecordDecl::field_iterator FieldBegin = RD->field_begin();
> > +      if (FieldBegin != RD->field_end())
> > +        Size += CharUnits::fromQuantity(
> > +            x % getAdjustedFieldInfo(*FieldBegin).second);
> > +    } else
> > +      Size += Alignment;
> > +  }
> > +
> > +  // Flush the lazy empty base.
> > +  layoutNonVirtualBase(0);
> > +}
> > +
> > +void MicrosoftRecordLayoutBuilder::layoutFields(const RecordDecl *RD) {
> > +  LastFieldIsNonZeroWidthBitfield = false;
> > +  for (RecordDecl::field_iterator Field = RD->field_begin(),
> > +                                  FieldEnd = RD->field_end();
> > +       Field != FieldEnd; ++Field)
> > +    layoutField(*Field);
> > +  Size = Size.RoundUpToAlignment(Alignment);
> > +}
> > +
> > +void MicrosoftRecordLayoutBuilder::layoutField(const FieldDecl *FD) {
> > +  if (FD->isBitField()) {
> > +    layoutBitField(FD);
> > +    return;
> > +  }
> > +  LastFieldIsNonZeroWidthBitfield = false;
> > +
> > +  std::pair<CharUnits, CharUnits> FieldInfo = getAdjustedFieldInfo(FD);
> > +  CharUnits FieldSize = FieldInfo.first;
> > +  CharUnits FieldAlign = FieldInfo.second;
> > +
> > +  updateAlignment(FieldAlign);
> > +  if (IsUnion) {
> > +    placeFieldAtZero();
> > +    Size = std::max(Size, FieldSize);
> > +  } else {
> > +    // Round up the current record size to the field's alignment
> boundary.
> > +    CharUnits FieldOffset = Size.RoundUpToAlignment(FieldAlign);
> > +    placeFieldAtOffset(FieldOffset);
> > +    Size = FieldOffset + FieldSize;
> > +  }
> > +}
> > +
> > +void MicrosoftRecordLayoutBuilder::layoutBitField(const FieldDecl *FD) {
> > +  unsigned Width = FD->getBitWidthValue(Context);
> > +  if (Width == 0) {
> > +    layoutZeroWidthBitField(FD);
> > +    return;
> > +  }
> > +
> > +  std::pair<CharUnits, CharUnits> FieldInfo = getAdjustedFieldInfo(FD);
> > +  CharUnits FieldSize = FieldInfo.first;
> > +  CharUnits FieldAlign = FieldInfo.second;
> > +
> > +  // Clamp the bitfield to a containable size for the sake of being able
> > +  // to lay them out.  Sema will throw an error.
> > +  if (Width > Context.toBits(FieldSize))
> > +    Width = Context.toBits(FieldSize);
> > +
> > +  // Check to see if this bitfield fits into an existing allocation.
>  Note:
> > +  // MSVC refuses to pack bitfields of formal types with different sizes
> > +  // into the same allocation.
> > +  if (!IsUnion && LastFieldIsNonZeroWidthBitfield &&
> > +      CurrentBitfieldSize == FieldSize && Width <=
> RemainingBitsInField) {
> > +    placeFieldAtBitOffset(Context.toBits(Size) - RemainingBitsInField);
> > +    RemainingBitsInField -= Width;
> > +    return;
> > +  }
> > +
> > +  LastFieldIsNonZeroWidthBitfield = true;
> > +  CurrentBitfieldSize = FieldSize;
> > +  if (IsUnion) {
> > +    placeFieldAtZero();
> > +    Size = std::max(Size, FieldSize);
> > +    // TODO: Add a Sema warning that MS ignores bitfield alignment in
> unions.
> > +  } else {
> > +    // Allocate a new block of memory and place the bitfield in it.
> > +    CharUnits FieldOffset = Size.RoundUpToAlignment(FieldAlign);
> > +    placeFieldAtOffset(FieldOffset);
> > +    Size = FieldOffset + FieldSize;
> > +    updateAlignment(FieldAlign);
> > +    RemainingBitsInField = Context.toBits(FieldSize) - Width;
> > +  }
> > +}
> > +
> > +void
> > +MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(const FieldDecl
> *FD) {
> > +  // Zero-width bitfields are ignored unless they follow a
> non-zero-width
> > +  // bitfield.
> > +  std::pair<CharUnits, CharUnits> FieldInfo = getAdjustedFieldInfo(FD);
> > +  CharUnits FieldSize = FieldInfo.first;
> > +  CharUnits FieldAlign = FieldInfo.second;
> > +
> > +  if (!LastFieldIsNonZeroWidthBitfield) {
> > +    placeFieldAtOffset(IsUnion ? CharUnits::Zero() : Size);
> > +    // TODO: Add a Sema warning that MS ignores alignment for zero
> > +    // sized bitfields that occur after zero-size bitfields or non
> bitfields.
> > +    return;
> > +  }
> > +
> > +  LastFieldIsNonZeroWidthBitfield = false;
> > +  if (IsUnion) {
> > +    placeFieldAtZero();
> > +    Size = std::max(Size, FieldSize);
> > +  } else {
> > +    // Round up the current record size to the field's alignment
> boundary.
> > +    CharUnits FieldOffset = Size.RoundUpToAlignment(FieldAlign);
> > +    placeFieldAtOffset(FieldOffset);
> > +    Size = FieldOffset;
> > +    updateAlignment(FieldAlign);
> > +  }
> > +}
> > +
> > +void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const
> CXXRecordDecl *RD) {
> > +  if (!HasVBPtr)
> > +    return;
> > +
> > +  updateAlignment(VirtualAlignment);
> > +
> > +  // Zero-sized v-bases obey the alignment attribute so apply it here.
>  The
> > +  // alignment attribute is normally accounted for in FinalizeLayout.
> > +  if (unsigned MaxAlign = RD->getMaxAlignment())
> > +    updateAlignment(Context.toCharUnitsFromBits(MaxAlign));
> > +
> > +  llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtordisp =
> > +      computeVtorDispSet(RD);
> > +
> > +  // Iterate through the virtual bases and lay them out.
> > +  for (CXXRecordDecl::base_class_const_iterator i = RD->vbases_begin(),
> > +                                                e = RD->vbases_end();
> > +       i != e; ++i) {
> > +    const CXXRecordDecl *BaseDecl =
> > +
>  cast<CXXRecordDecl>(i->getType()->castAs<RecordType>()->getDecl());
> > +    layoutVirtualBase(BaseDecl, HasVtordisp.count(BaseDecl));
> > +  }
> > +}
> > +
> > +void MicrosoftRecordLayoutBuilder::layoutVirtualBase(const
> CXXRecordDecl *RD,
> > +                                                     bool HasVtordisp) {
> > +  if (LazyEmptyBase) {
> > +    const ASTRecordLayout &LazyLayout =
> > +        Context.getASTRecordLayout(LazyEmptyBase);
> > +    Size = Size.RoundUpToAlignment(LazyLayout.getAlignment());
> > +    VBases.insert(
> > +        std::make_pair(LazyEmptyBase, ASTRecordLayout::VBaseInfo(Size,
> false)));
> > +    // Empty bases only consume space when followed by another empty
> base.
> > +    // The space consumed is in an Alignment sized/aligned block and
> the v-base
> > +    // is placed at its alignment offset into the chunk, unless its
> alignment
> > +    // is less than the size of a pointer, at which it is placed at
> pointer
> > +    // width offset in the chunck.  We have no idea why.
> > +    if (RD &&
> Context.getASTRecordLayout(RD).getNonVirtualSize().isZero())
> > +      Size = Size.RoundUpToAlignment(Alignment) + PointerSize;
> > +    LazyEmptyBase = 0;
> > +  }
> > +
> > +  // RD is null when flushing the final lazy virtual base.
> > +  if (!RD)
> > +    return;
> > +
> > +  const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
> > +  if (Layout.getNonVirtualSize().isZero() && !HasVtordisp) {
> > +    LazyEmptyBase = RD;
> > +    return;
> > +  }
> > +
> > +  CharUnits BaseNVSize = Layout.getNonVirtualSize();
> > +  CharUnits BaseAlign = Layout.getAlignment();
> > +
> > +  if (HasVtordisp)
> > +    Size = Size.RoundUpToAlignment(Alignment) + PointerSize;
> > +  Size = Size.RoundUpToAlignment(BaseAlign);
> > +
> > +  // Insert the base here.
> > +  CharUnits BaseOffset = Size.RoundUpToAlignment(BaseAlign);
> > +  VBases.insert(
> > +      std::make_pair(RD, ASTRecordLayout::VBaseInfo(BaseOffset,
> HasVtordisp)));
> > +  Size = BaseOffset + BaseNVSize;
> > +  // Note: we don't update alignment here because it was accounted for
> in
> > +  // InitializeLayout.
> > +}
> > +
> > +void MicrosoftRecordLayoutBuilder::finalizeCXXLayout(const
> CXXRecordDecl *RD) {
> > +  // Flush the lazy virtual base.
> > +  layoutVirtualBase(0, false);
> > +
> > +  if (RD->vbases_begin() == RD->vbases_end() || AlignAfterVBases)
> > +    Size = Size.RoundUpToAlignment(Alignment);
> > +
> > +  if (Size.isZero())
> > +    Size = Alignment;
> > +}
> > +
> > +void MicrosoftRecordLayoutBuilder::honorDeclspecAlign(const RecordDecl
> *RD) {
> > +  if (unsigned MaxAlign = RD->getMaxAlignment()) {
> > +    AlignAfterVBases = true;
> > +    updateAlignment(Context.toCharUnitsFromBits(MaxAlign));
> > +    Size = Size.RoundUpToAlignment(Alignment);
> > +  }
> > +}
> > +
> > +static bool
> > +RequiresVtordisp(const llvm::SmallPtrSet<const CXXRecordDecl *, 2>
> &HasVtordisp,
> > +                 const CXXRecordDecl *RD) {
> > +  if (HasVtordisp.count(RD))
> > +    return true;
> > +  // If any of a virtual bases non-virtual bases (recursively) requires
> a
> > +  // vtordisp than so does this virtual base.
> > +  for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
> > +                                                e = RD->bases_end();
> > +       i != e; ++i)
> > +    if (!i->isVirtual() &&
> > +        RequiresVtordisp(
> > +            HasVtordisp,
> > +
>  cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl())))
> > +      return true;
> > +  return false;
> > +}
> > +
> > +llvm::SmallPtrSet<const CXXRecordDecl *, 2>
> > +MicrosoftRecordLayoutBuilder::computeVtorDispSet(const CXXRecordDecl
> *RD) {
> > +  llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtordisp;
> > +
> > +  // If any of our bases need a vtordisp for this type, so do we.
>  Check our
> > +  // direct bases for vtordisp requirements.
> > +  for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
> > +                                                e = RD->bases_end();
> > +       i != e; ++i) {
> > +    const CXXRecordDecl *BaseDecl =
> > +
>  cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
> > +    const ASTRecordLayout &Layout =
> Context.getASTRecordLayout(BaseDecl);
> > +    for (ASTRecordLayout::VBaseOffsetsMapTy::const_iterator
> > +             bi = Layout.getVBaseOffsetsMap().begin(),
> > +             be = Layout.getVBaseOffsetsMap().end();
> > +         bi != be; ++bi)
> > +      if (bi->second.hasVtorDisp())
> > +        HasVtordisp.insert(bi->first);
> > +  }
> > +
> > +  // If we define a constructor or destructor and override a function
> that is
> > +  // defined in a virtual base's vtable, that virtual bases need a
> vtordisp.
> > +  // Here we collect a list of classes with vtables for which our
> virtual bases
> > +  // actually live.  The virtual bases with this property will require
> > +  // vtordisps.  In addition, virtual bases that contain non-virtual
> bases that
> > +  // define functions we override also require vtordisps, this case is
> checked
> > +  // explicitly below.
> > +  if (RD->hasUserDeclaredConstructor() ||
> RD->hasUserDeclaredDestructor()) {
> > +    llvm::SmallPtrSet<const CXXMethodDecl *, 8> Work;
> > +    // Seed the working set with our non-destructor virtual methods.
> > +    for (CXXRecordDecl::method_iterator i = RD->method_begin(),
> > +                                        e = RD->method_end();
> > +         i != e; ++i)
> > +      if ((*i)->isVirtual() && (*i) != RD->getDestructor())
> > +        Work.insert(*i);
> > +    while (!Work.empty()) {
> > +      const CXXMethodDecl *MD = *Work.begin();
> > +      CXXMethodDecl::method_iterator i = MD->begin_overridden_methods(),
> > +                                     e = MD->end_overridden_methods();
> > +      if (i == e)
> > +        // If a virtual method has no-overrides it lives in its
> parent's vtable.
> > +        HasVtordisp.insert(MD->getParent());
> > +      else
> > +        Work.insert(i, e);
> > +      // We've finished processing this element, remove it from the
> working set.
> > +      Work.erase(MD);
> > +    }
> > +  }
> > +
> > +  // Re-check all of our vbases for vtordisp requirements (in case their
> > +  // non-virtual bases have vtordisp requirements).
> > +  for (CXXRecordDecl::base_class_const_iterator i = RD->vbases_begin(),
> > +                                                e = RD->vbases_end();
> > +       i != e; ++i) {
> > +    const CXXRecordDecl *BaseDecl =  i->getType()->getAsCXXRecordDecl();
> > +    if (!HasVtordisp.count(BaseDecl) && RequiresVtordisp(HasVtordisp,
> BaseDecl))
> > +      HasVtordisp.insert(BaseDecl);
> > +  }
> > +
> > +  return HasVtordisp;
> > +}
> > +
> > +/// \brief Get or compute information about the layout of the specified
> record
> > +/// (struct/union/class), which indicates its size and field position
> > +/// information.
> > +const ASTRecordLayout *
> > +ASTContext::BuildMicrosoftASTRecordLayout(const RecordDecl *D) const {
> > +  MicrosoftRecordLayoutBuilder Builder(*this);
> > +  if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
> > +    Builder.cxxLayout(RD);
> > +    return new (*this) ASTRecordLayout(
> > +        *this, Builder.Size, Builder.Alignment,
> > +        Builder.HasVFPtr && !Builder.PrimaryBase, Builder.HasVFPtr,
> > +        Builder.HasVBPtr && !Builder.SharedVBPtrBase,
> Builder.VBPtrOffset,
> > +        Builder.DataSize, Builder.FieldOffsets.data(),
> > +        Builder.FieldOffsets.size(), Builder.DataSize,
> > +        Builder.NonVirtualAlignment, CharUnits::Zero(),
> Builder.PrimaryBase,
> > +        false, Builder.AlignAfterVBases, Builder.Bases, Builder.VBases);
> > +  } else {
> > +    Builder.layout(D);
> > +    return new (*this) ASTRecordLayout(
> > +        *this, Builder.Size, Builder.Alignment, Builder.Size,
> > +        Builder.FieldOffsets.data(), Builder.FieldOffsets.size());
> > +  }
> > +}
> > +
> > /// getASTRecordLayout - Get or compute information about the layout of
> the
> > /// specified record (struct/union/class), which indicates its size and
> field
> > /// position information.
> > @@ -2362,27 +3068,15 @@ ASTContext::getASTRecordLayout(const Rec
> >   const ASTRecordLayout *Entry = ASTRecordLayouts[D];
> >   if (Entry) return *Entry;
> >
> > -  const ASTRecordLayout *NewEntry;
> > +  const ASTRecordLayout *NewEntry = 0;
> >
> > -  if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
> > +  if (isMsLayout(D) && !D->getASTContext().getExternalSource()) {
> > +    NewEntry = BuildMicrosoftASTRecordLayout(D);
> > +  } else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
> >     EmptySubobjectMap EmptySubobjects(*this, RD);
> >     RecordLayoutBuilder Builder(*this, &EmptySubobjects);
> >     Builder.Layout(RD);
> >
> > -    // MSVC gives the vb-table pointer an alignment equal to that of
> > -    // the non-virtual part of the structure.  That's an inherently
> > -    // multi-pass operation.  If our first pass doesn't give us
> > -    // adequate alignment, try again with the specified minimum
> > -    // alignment.  This is *much* more maintainable than computing the
> > -    // alignment in advance in a separately-coded pass; it's also
> > -    // significantly more efficient in the common case where the
> > -    // vb-table doesn't need extra padding.
> > -    if (Builder.VBPtrOffset != CharUnits::fromQuantity(-1) &&
> > -        (Builder.VBPtrOffset % Builder.NonVirtualAlignment) != 0) {
> > -      Builder.resetWithTargetAlignment(Builder.NonVirtualAlignment);
> > -      Builder.Layout(RD);
> > -    }
> > -
> >     // In certain situations, we are allowed to lay out objects in the
> >     // tail-padding of base classes.  This is ABI-dependent.
> >     // FIXME: this should be stored in the record layout.
> > @@ -2394,11 +3088,12 @@ ASTContext::getASTRecordLayout(const Rec
> >       skipTailPadding ? Builder.getSize() : Builder.getDataSize();
> >     CharUnits NonVirtualSize =
> >       skipTailPadding ? DataSize : Builder.NonVirtualSize;
> > -
> >     NewEntry =
> >       new (*this) ASTRecordLayout(*this, Builder.getSize(),
> >                                   Builder.Alignment,
> >                                   Builder.HasOwnVFPtr,
> > +                                  RD->isDynamicClass(),
> > +                                  Builder.HasOwnVBPtr,
> >                                   Builder.VBPtrOffset,
> >                                   DataSize,
> >                                   Builder.FieldOffsets.data(),
> > @@ -2408,6 +3103,7 @@ ASTContext::getASTRecordLayout(const Rec
> >
> EmptySubobjects.SizeOfLargestEmptySubobject,
> >                                   Builder.PrimaryBase,
> >                                   Builder.PrimaryBaseIsVirtual,
> > +                                  true,
> >                                   Builder.Bases, Builder.VBases);
> >   } else {
> >     RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0);
> > @@ -2564,16 +3260,19 @@ static void DumpCXXRecordLayout(raw_ostr
> >   IndentLevel++;
> >
> >   const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
> > -  bool HasVfptr = Layout.hasOwnVFPtr();
> > -  bool HasVbptr = Layout.getVBPtrOffset() !=
> CharUnits::fromQuantity(-1);
> > +  bool HasOwnVFPtr = Layout.hasOwnVFPtr();
> > +  bool HasOwnVBPtr = Layout.hasOwnVBPtr();
> >
> >   // Vtable pointer.
> > -  if (RD->isDynamicClass() && !PrimaryBase &&
> > -      !C.getTargetInfo().getCXXABI().isMicrosoft()) {
> > +  if (RD->isDynamicClass() && !PrimaryBase && !isMsLayout(RD)) {
> >     PrintOffset(OS, Offset, IndentLevel);
> >     OS << '(' << *RD << " vtable pointer)\n";
> > +  } else if (HasOwnVFPtr) {
> > +    PrintOffset(OS, Offset, IndentLevel);
> > +    // vfptr (for Microsoft C++ ABI)
> > +    OS << '(' << *RD << " vftable pointer)\n";
> >   }
> > -
> > +
> >   // Dump (non-virtual) bases
> >   for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
> >          E = RD->bases_end(); I != E; ++I) {
> > @@ -2592,12 +3291,8 @@ static void DumpCXXRecordLayout(raw_ostr
> >                         /*IncludeVirtualBases=*/false);
> >   }
> >
> > -  // vfptr and vbptr (for Microsoft C++ ABI)
> > -  if (HasVfptr) {
> > -    PrintOffset(OS, Offset, IndentLevel);
> > -    OS << '(' << *RD << " vftable pointer)\n";
> > -  }
> > -  if (HasVbptr) {
> > +  // vbptr (for Microsoft C++ ABI)
> > +  if (HasOwnVBPtr) {
> >     PrintOffset(OS, Offset + Layout.getVBPtrOffset(), IndentLevel);
> >     OS << '(' << *RD << " vbtable pointer)\n";
> >   }
> > @@ -2650,7 +3345,8 @@ static void DumpCXXRecordLayout(raw_ostr
> >
> >   PrintIndentNoOffset(OS, IndentLevel - 1);
> >   OS << "[sizeof=" << Layout.getSize().getQuantity();
> > -  OS << ", dsize=" << Layout.getDataSize().getQuantity();
> > +  if (!isMsLayout(RD))
> > +    OS << ", dsize=" << Layout.getDataSize().getQuantity();
> >   OS << ", align=" << Layout.getAlignment().getQuantity() << '\n';
> >
> >   PrintIndentNoOffset(OS, IndentLevel - 1);
> > @@ -2677,7 +3373,8 @@ void ASTContext::DumpRecordLayout(const
> >   OS << "\nLayout: ";
> >   OS << "<ASTRecordLayout\n";
> >   OS << "  Size:" << toBits(Info.getSize()) << "\n";
> > -  OS << "  DataSize:" << toBits(Info.getDataSize()) << "\n";
> > +  if (!isMsLayout(RD))
> > +    OS << "  DataSize:" << toBits(Info.getDataSize()) << "\n";
> >   OS << "  Alignment:" << toBits(Info.getAlignment()) << "\n";
> >   OS << "  FieldOffsets: [";
> >   for (unsigned i = 0, e = Info.getFieldCount(); i != e; ++i) {
> >
> > Modified: cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp?rev=192494&r1=192493&r2=192494&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp (original)
> > +++ cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp Fri Oct 11 15:19:00
> 2013
> > @@ -696,7 +696,7 @@ CGRecordLayoutBuilder::LayoutNonVirtualB
> >   }
> >
> >   // Add a vb-table pointer if the layout insists.
> > -  if (Layout.getVBPtrOffset() != CharUnits::fromQuantity(-1)) {
> > +    if (Layout.hasOwnVBPtr()) {
> >     CharUnits VBPtrOffset = Layout.getVBPtrOffset();
> >     llvm::Type *Vbptr =
> llvm::Type::getInt32PtrTy(Types.getLLVMContext());
> >     AppendPadding(VBPtrOffset, getTypeAlignment(Vbptr));
> >
> > Modified: cfe/trunk/lib/CodeGen/MicrosoftVBTables.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftVBTables.cpp?rev=192494&r1=192493&r2=192494&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/CodeGen/MicrosoftVBTables.cpp (original)
> > +++ cfe/trunk/lib/CodeGen/MicrosoftVBTables.cpp Fri Oct 11 15:19:00 2013
> > @@ -54,10 +54,6 @@ void VBTableBuilder::enumerateVBTables(V
> >   }
> > }
> >
> > -bool VBTableBuilder::hasVBPtr(const CXXRecordDecl *RD) {
> > -  const ASTRecordLayout &Layout =
> CGM.getContext().getASTRecordLayout(RD);
> > -  return Layout.getVBPtrOffset().getQuantity() != -1;
> > -}
> >
> > void VBTableBuilder::findUnambiguousPaths(const CXXRecordDecl
> *ReusingBase,
> >                                           BaseSubobject CurSubobject,
> > @@ -65,10 +61,11 @@ void VBTableBuilder::findUnambiguousPath
> >   size_t PathsStart = Paths.size();
> >   bool ReuseVBPtrFromBase = true;
> >   const CXXRecordDecl *CurBase = CurSubobject.getBase();
> > +  const ASTRecordLayout &Layout =
> CGM.getContext().getASTRecordLayout(CurBase);
> >
> >   // If this base has a vbptr, then we've found a path.  These are not
> full
> >   // paths, so we don't use CXXBasePath.
> > -  if (hasVBPtr(CurBase)) {
> > +  if (Layout.hasOwnVBPtr()) {
> >     ReuseVBPtrFromBase = false;
> >     VBTablePath *Info = new VBTablePath(
> >       VBTableInfo(ReusingBase, CurSubobject, /*GV=*/0));
> > @@ -76,7 +73,6 @@ void VBTableBuilder::findUnambiguousPath
> >   }
> >
> >   // Recurse onto any bases which themselves have virtual bases.
> > -  const ASTRecordLayout &Layout =
> CGM.getContext().getASTRecordLayout(CurBase);
> >   for (CXXRecordDecl::base_class_const_iterator I =
> CurBase->bases_begin(),
> >        E = CurBase->bases_end(); I != E; ++I) {
> >     const CXXRecordDecl *Base = I->getType()->getAsCXXRecordDecl();
> >
> > Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=192494&r1=192493&r2=192494&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Oct 11 15:19:00 2013
> > @@ -11503,8 +11503,7 @@ Decl *Sema::ActOnIvar(Scope *S,
> >
> >   if (BitWidth) {
> >     // 6.7.2.1p3, 6.7.2.1p4
> > -    BitWidth =
> > -        VerifyBitField(Loc, II, T, /*IsMsStruct=*/false,
> BitWidth).take();
> > +    BitWidth = VerifyBitField(Loc, II, T, /*IsMsStruct*/false,
> BitWidth).take();
> >     if (!BitWidth)
> >       D.setInvalidType();
> >   } else {
> >
> > Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=192494&r1=192493&r2=192494&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Oct 11 15:19:00 2013
> > @@ -4451,6 +4451,13 @@ void Sema::CheckCompletedCXXClass(CXXRec
> >     }
> >   }
> >
> > +  // Check to see if we're trying to lay out a struct using the
> ms_struct
> > +  // attribute that is dynamic.
> > +  if (Record->isMsStruct(Context) && Record->isDynamicClass()) {
> > +    Diag(Record->getLocation(), diag::warn_pragma_ms_struct_failed);
> > +    Record->dropAttr<MsStructAttr>();
> > +  }
> > +
> >   // Declare inheriting constructors. We do this eagerly here because:
> >   // - The standard requires an eager diagnostic for conflicting
> inheriting
> >   //   constructors from different classes.
> >
> > Modified: cfe/trunk/test/CodeGen/pr2394.c
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/pr2394.c?rev=192494&r1=192493&r2=192494&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/CodeGen/pr2394.c (original)
> > +++ cfe/trunk/test/CodeGen/pr2394.c Fri Oct 11 15:19:00 2013
> > @@ -1,4 +1,4 @@
> > -// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
> > +// RUN: %clang_cc1 %s -triple i386-apple-darwin10 -emit-llvm -o - |
> FileCheck %s
> > struct __attribute((packed)) x {int a : 24;};
> > int a(struct x* g) {
> >   // CHECK: load i24
> >
> > Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp?rev=192494&r1=192493&r2=192494&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp (original)
> > +++ cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp Fri Oct 11
> 15:19:00 2013
> > @@ -156,7 +156,9 @@ C::C() {
> >   // CHECK-NEXT: %[[vbptr_off:.*]] = getelementptr inbounds i8*
> %[[this_i8]], i64 0
> >   // CHECK-NEXT: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to [2 x
> i32]**
> >   // CHECK-NEXT: store [2 x i32]* @"\01??_8C at constructors@@7B@", [2 x
> i32]** %[[vbptr]]
> > -  // CHECK-NEXT: bitcast %"struct.constructors::C"* %{{.*}} to
> %"struct.constructors::A"*
> > +  // CHECK-NEXT: bitcast %"struct.constructors::C"* %{{.*}} to i8*
> > +  // CHECK-NEXT: getelementptr inbounds i8* %{{.*}}, i64 4
> > +  // CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"*
> >   // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"*
> @"\01??0A at constructors@@QAE at XZ"(%"struct.constructors::A"* %{{.*}})
> >   // CHECK-NEXT: br label %[[SKIP_VBASES]]
> >   //
> > @@ -189,7 +191,9 @@ D::D() {
> >   // CHECK-NEXT: %[[vbptr_off:.*]] = getelementptr inbounds i8*
> %[[this_i8]], i64 0
> >   // CHECK-NEXT: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to [2 x
> i32]**
> >   // CHECK-NEXT: store [2 x i32]* @"\01??_8D at constructors@@7B@", [2 x
> i32]** %[[vbptr]]
> > -  // CHECK-NEXT: bitcast %"struct.constructors::D"* %{{.*}} to
> %"struct.constructors::A"*
> > +  // CHECK-NEXT: bitcast %"struct.constructors::D"* %{{.*}} to i8*
> > +  // CHECK-NEXT: getelementptr inbounds i8* %{{.*}}, i64 4
> > +  // CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"*
> >   // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"*
> @"\01??0A at constructors@@QAE at XZ"(%"struct.constructors::A"* %{{.*}})
> >   // CHECK-NEXT: br label %[[SKIP_VBASES]]
> >   //
> > @@ -217,7 +221,9 @@ E::E() {
> >   // CHECK-NEXT: %[[offs:.*]] = getelementptr inbounds i8* %[[this_i8]],
> i64 4
> >   // CHECK-NEXT: %[[vbptr_C:.*]] = bitcast i8* %[[offs]] to [2 x i32]**
> >   // CHECK-NEXT: store [2 x i32]* @"\01??_8E at constructors@@7BC at 1@@", [2
> x i32]** %[[vbptr_C]]
> > -  // CHECK-NEXT: bitcast %"struct.constructors::E"* %{{.*}} to
> %"struct.constructors::A"*
> > +  // CHECK-NEXT: bitcast %"struct.constructors::E"* %{{.*}} to i8*
> > +  // CHECK-NEXT: getelementptr inbounds i8* %{{.*}}, i64 4
> > +  // CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"*
> >   // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"*
> @"\01??0A at constructors@@QAE at XZ"(%"struct.constructors::A"* %{{.*}})
> >   // CHECK: call x86_thiscallcc %"struct.constructors::C"*
> @"\01??0C at constructors@@QAE at XZ"(%"struct.constructors::C"* %{{.*}}, i32 0)
> >   // CHECK-NEXT: br label %[[SKIP_VBASES]]
> >
> > Modified: cfe/trunk/test/Coverage/codegen-next.m
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Coverage/codegen-next.m?rev=192494&r1=192493&r2=192494&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/Coverage/codegen-next.m (original)
> > +++ cfe/trunk/test/Coverage/codegen-next.m Fri Oct 11 15:19:00 2013
> > @@ -1,5 +1,5 @@
> > -// RUN: %clang_cc1 -emit-llvm -fobjc-exceptions -o %t %s
> > -// RUN: %clang_cc1 -g -emit-llvm -fobjc-exceptions -o %t %s
> > +// RUN: %clang_cc1 -emit-llvm -fobjc-exceptions -triple
> x86_64-apple-darwin -o %t %s
> > +// RUN: %clang_cc1 -g -emit-llvm -fobjc-exceptions -triple
> x86_64-apple-darwin -o %t %s
> >
> > // An error could be seen for targeting x86_64-win32;
> > //
> >
> > Modified: cfe/trunk/test/PCH/rdar10830559.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/rdar10830559.cpp?rev=192494&r1=192493&r2=192494&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/PCH/rdar10830559.cpp (original)
> > +++ cfe/trunk/test/PCH/rdar10830559.cpp Fri Oct 11 15:19:00 2013
> > @@ -8,7 +8,7 @@
> >
> > // rdar://10830559
> >
> > -#pragma ms_struct on
> > +//#pragma ms_struct on
> >
> > template< typename T >
> > class Templated
> >
> > Modified: cfe/trunk/test/Sema/ms_class_layout.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/ms_class_layout.cpp?rev=192494&r1=192493&r2=192494&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/Sema/ms_class_layout.cpp (original)
> > +++ cfe/trunk/test/Sema/ms_class_layout.cpp Fri Oct 11 15:19:00 2013
> > @@ -164,7 +164,7 @@ int main() {
> > // CHECK-NEXT:  0 |   (D vftable pointer)
> > // CHECK-NEXT:  8 |   double a
> >
> > -// CHECK-NEXT: sizeof=16, dsize=16, align=8
> > +// CHECK-NEXT: sizeof=16, align=8
> > // CHECK-NEXT: nvsize=16, nvalign=8
> >
> > // CHECK: %class.D = type { i32 (...)**, double }
> > @@ -173,7 +173,7 @@ int main() {
> > // CHECK-NEXT:  0 |   (B vftable pointer)
> > // CHECK-NEXT:  4 |   int b_field
> >
> > -// CHECK-NEXT: sizeof=8, dsize=8, align=4
> > +// CHECK-NEXT: sizeof=8, align=4
> > // CHECK-NEXT: nvsize=8, nvalign=4
> >
> > // CHECK: %class.B = type { i32 (...)**, i32 }
> > @@ -185,7 +185,7 @@ int main() {
> > // CHECK-NEXT:  8 |   int a_field
> > // CHECK-NEXT: 12 |   char one
> >
> > -// CHECK-NEXT: sizeof=16, dsize=16, align=4
> > +// CHECK-NEXT: sizeof=16, align=4
> > // CHECK-NEXT: nvsize=16, nvalign=4
> >
> > // CHECK:       0 | class C
> > @@ -207,7 +207,7 @@ int main() {
> > // CHECK-NEXT: 72 |     int a_field
> > // CHECK-NEXT: 76 |     char one
> >
> > -// CHECK-NEXT: sizeof=80, dsize=80, align=8
> > +// CHECK-NEXT: sizeof=80, align=8
> > // CHECK-NEXT: nvsize=64, nvalign=8
> >
> > // CHECK: %class.A = type { %class.B, i32, i8 }
> > @@ -237,10 +237,10 @@ int main() {
> > // CHECK-NEXT: 88 |       int a_field
> > // CHECK-NEXT: 92 |       char one
> >
> > -// CHECK-NEXT: sizeof=80, dsize=80, align=8
> > +// CHECK-NEXT: sizeof=80, align=8
> > // CHECK-NEXT: nvsize=64, nvalign=8
> >
> > -// CHECK: sizeof=96, dsize=96, align=8
> > +// CHECK: sizeof=96, align=8
> > // CHECK-NEXT: nvsize=96, nvalign=8
> >
> > // CHECK: %struct.BaseStruct = type { double, float, %class.C }
> > @@ -267,18 +267,18 @@ int main() {
> > // CHECK-NEXT: 84 |           int b_field
> > // CHECK-NEXT: 88 |         int a_field
> > // CHECK-NEXT: 92 |         char one
> > -// CHECK-NEXT: sizeof=80, dsize=80, align=8
> > +// CHECK-NEXT: sizeof=80, align=8
> > // CHECK-NEXT: nvsize=64, nvalign=8
> >
> > // CHECK: 96 |   int x
> > -// CHECK-NEXT: sizeof=104, dsize=104, align=8
> > +// CHECK-NEXT: sizeof=104, align=8
> > // CHECK-NEXT: nvsize=104, nvalign=8
> >
> > // CHECK: %struct.DerivedStruct = type { %struct.BaseStruct, i32 }
> >
> > // CHECK:      0 | struct G
> > // CHECK-NEXT: 0 |   int g_field
> > -// CHECK-NEXT: sizeof=4, dsize=4, align=4
> > +// CHECK-NEXT: sizeof=4, align=4
> > // CHECK-NEXT: nvsize=4, nvalign=4
> >
> > // CHECK:       0 | struct H
> > @@ -288,7 +288,7 @@ int main() {
> > // CHECK-NEXT:  8 |   class D (virtual base)
> > // CHECK-NEXT:  8 |     (D vftable pointer)
> > // CHECK-NEXT: 16 |     double a
> > -// CHECK-NEXT: sizeof=24, dsize=24, align=8
> > +// CHECK-NEXT: sizeof=24, align=8
> > // CHECK-NEXT: nvsize=8, nvalign=4
> >
> > // CHECK: %struct.H = type { %struct.G, i32*, %class.D }
> > @@ -300,7 +300,7 @@ int main() {
> > // CHECK-NEXT: 24 |   class D (virtual base)
> > // CHECK-NEXT: 24 |     (D vftable pointer)
> > // CHECK-NEXT: 32 |     double a
> > -// CHECK-NEXT: sizeof=40, dsize=40, align=8
> > +// CHECK-NEXT: sizeof=40, align=8
> > // CHECK-NEXT: nvsize=24, nvalign=8
> >
> > // CHECK: %struct.I = type { i32 (...)**, [4 x i8], i32*, double,
> %class.D }
> > @@ -308,12 +308,12 @@ int main() {
> >
> > // CHECK:       0 | struct L
> > // CHECK-NEXT:  0 |   int l
> > -// CHECK-NEXT: sizeof=4, dsize=4, align=4
> > +// CHECK-NEXT: sizeof=4, align=4
> > // CHECK-NEXT: nvsize=4, nvalign=4
> >
> > // CHECK:       0 | struct K
> > // CHECK-NEXT:  0 |   int k
> > -// CHECK-NEXT: sizeof=4, dsize=4, align=4
> > +// CHECK-NEXT: sizeof=4, align=4
> > // CHECK-NEXT: nvsize=4, nvalign=4
> >
> > // CHECK:       0 | struct M
> > @@ -321,42 +321,42 @@ int main() {
> > // CHECK-NEXT:  4 |   int m
> > // CHECK-NEXT:  8 |   struct K (virtual base)
> > // CHECK-NEXT:  8 |     int k
> > -// CHECK-NEXT: sizeof=12, dsize=12, align=4
> > +// CHECK-NEXT: sizeof=12, align=4
> >
> > //CHECK: %struct.M = type { i32*, i32, %struct.K }
> > //CHECK: %struct.M.base = type { i32*, i32 }
> >
> > // CHECK:       0 | struct N
> > +// CHECK-NEXT:  0 |   (N vftable pointer)
> > // CHECK-NEXT:  4 |   struct L (base)
> > // CHECK-NEXT:  4 |     int l
> > // CHECK-NEXT:  8 |   struct M (base)
> > // CHECK-NEXT:  8 |     (M vbtable pointer)
> > // CHECK-NEXT: 12 |     int m
> > -// CHECK-NEXT:  0 |   (N vftable pointer)
> > // CHECK-NEXT: 16 |   struct K (virtual base)
> > // CHECK-NEXT: 16 |     int k
> > -// CHECK-NEXT: sizeof=20, dsize=20, align=4
> > +// CHECK-NEXT: sizeof=20, align=4
> > // CHECK-NEXT: nvsize=16, nvalign=4
> >
> > //CHECK: %struct.N = type { i32 (...)**, %struct.L, %struct.M.base,
> %struct.K }
> >
> > -// FIXME: MSVC place struct H at offset 8.
> > // CHECK:       0 | struct O
> > -// CHECK-NEXT:  4 |   struct H (base)
> > -// CHECK-NEXT:  4 |     struct G (base)
> > -// CHECK-NEXT:  4 |       int g_field
> > -// CHECK-NEXT:  8 |     (H vbtable pointer)
> > -// CHECK-NEXT: 12 |   struct G (base)
> > -// CHECK-NEXT: 12 |     int g_field
> > // CHECK-NEXT:  0 |   (O vftable pointer)
> > -// CHECK-NEXT: 16 |   class D (virtual base)
> > -// CHECK-NEXT: 16 |     (D vftable pointer)
> > -// CHECK-NEXT: 24 |     double a
> > -// CHECK-NEXT: sizeof=32, dsize=32, align=8
> > -// CHECK-NEXT: nvsize=16, nvalign=4
> > +// CHECK-NEXT:  8 |   struct H (base)
> > +// CHECK-NEXT:  8 |     struct G (base)
> > +// CHECK-NEXT:  8 |       int g_field
> > +// CHECK-NEXT: 12 |     (H vbtable pointer)
> > +// CHECK-NEXT: 16 |   struct G (base)
> > +// CHECK-NEXT: 16 |     int g_field
> > +// CHECK-NEXT: 24 |   class D (virtual base)
> > +// CHECK-NEXT: 24 |     (D vftable pointer)
> > +// CHECK-NEXT: 32 |     double a
> > +// CHECK-NEXT:    | [sizeof=40, align=8
> > +// CHECK-NEXT:    |  nvsize=24, nvalign=8]
> > +
> > +// CHECK: struct.O = type { i32 (...)**, [4 x i8], %struct.H.base,
> %struct.G, [4 x i8], %class.D }
> > +// CHECK: struct.O.base = type { i32 (...)**, [4 x i8], %struct.H.base,
> %struct.G, [4 x i8] }
> >
> > -//CHECK: %struct.O = type { i32 (...)**, %struct.H.base, %struct.G,
> %class.D }
> > -//CHECK: %struct.O.base = type { i32 (...)**, %struct.H.base, %struct.G
> }
> >
> > // CHECK:       0 | struct P
> > // CHECK-NEXT:  0 |   struct M (base)
> > @@ -367,20 +367,20 @@ int main() {
> > // CHECK-NEXT: 12 |     int k
> > // CHECK-NEXT: 16 |   struct L (virtual base)
> > // CHECK-NEXT: 16 |     int l
> > -// CHECK-NEXT: sizeof=20, dsize=20, align=4
> > +// CHECK-NEXT: sizeof=20, align=4
> > // CHECK-NEXT: nvsize=12, nvalign=4
> >
> > //CHECK: %struct.P = type { %struct.M.base, i32, %struct.K, %struct.L }
> >
> > // CHECK:       0 | struct R (empty)
> > -// CHECK-NEXT:  sizeof=1, dsize=0, align=1
> > +// CHECK-NEXT:  sizeof=1, align=1
> > // CHECK-NEXT:  nvsize=0, nvalign=1
> >
> > //CHECK: %struct.R = type { i8 }
> >
> > // CHECK:       0 | struct f
> > // CHECK-NEXT:  0 |   (f vftable pointer)
> > -// CHECK-NEXT: sizeof=4, dsize=4, align=4
> > +// CHECK-NEXT: sizeof=4, align=4
> > // CHECK-NEXT: nvsize=4, nvalign=4
> >
> > // CHECK:       0 | struct s
> > @@ -390,12 +390,12 @@ int main() {
> > // CHECK-NEXT: 12 |   (vtordisp for vbase f)
> > // CHECK-NEXT: 16 |   struct f (virtual base)
> > // CHECK-NEXT: 16 |     (f vftable pointer)
> > -// CHECK-NEXT: sizeof=20, dsize=20, align=4
> > +// CHECK-NEXT: sizeof=20, align=4
> > // CHECK-NEXT: nvsize=12, nvalign=4
> >
> > // CHECK:       0 | class IA
> > // CHECK-NEXT:  0 |   (IA vftable pointer)
> > -// CHECK-NEXT:  sizeof=4, dsize=4, align=4
> > +// CHECK-NEXT:  sizeof=4, align=4
> > // CHECK-NEXT:  nvsize=4, nvalign=4
> >
> > // CHECK:       0 | class ICh
> > @@ -404,7 +404,7 @@ int main() {
> > // CHECK-NEXT:  8 |   (vtordisp for vbase IA)
> > // CHECK-NEXT: 12 |   class IA (virtual base)
> > // CHECK-NEXT: 12 |     (IA vftable pointer)
> > -// CHECK-NEXT: sizeof=16, dsize=16, align=4
> > +// CHECK-NEXT: sizeof=16, align=4
> > // CHECK-NEXT: nvsize=8, nvalign=4
> >
> > // CHECK:       0 | struct sd
> > @@ -424,7 +424,7 @@ int main() {
> > // CHECK-NEXT: 40 |   class ICh (virtual base)
> > // CHECK-NEXT: 40 |     (ICh vftable pointer)
> > // CHECK-NEXT: 44 |     (ICh vbtable pointer)
> > -// CHECK-NEXT: sizeof=48, dsize=48, align=4
> > +// CHECK-NEXT: sizeof=48, align=4
> > // CHECK-NEXT: nvsize=12, nvalign=4
> >
> > // CHECK: %struct.f = type { i32 (...)** }
> > @@ -435,14 +435,14 @@ int main() {
> >
> > // CHECK:       0 | struct AV
> > // CHECK-NEXT:  0 |   (AV vftable pointer)
> > -// CHECK-NEXT: sizeof=4, dsize=4, align=4
> > +// CHECK-NEXT: sizeof=4, align=4
> > // CHECK-NEXT: nvsize=4, nvalign=4
> >
> >
> > // CHECK:       0 | struct BV
> > // CHECK-NEXT:  0 |   struct AV (primary base)
> > // CHECK-NEXT:  0 |     (AV vftable pointer)
> > -// CHECK-NEXT: sizeof=4, dsize=4, align=4
> > +// CHECK-NEXT: sizeof=4, align=4
> > // CHECK-NEXT: nvsize=4, nvalign=4
> >
> >
> > @@ -452,7 +452,7 @@ int main() {
> > // CHECK-NEXT:  8 |   struct BV (virtual base)
> > // CHECK-NEXT:  8 |     struct AV (primary base)
> > // CHECK-NEXT:  8 |       (AV vftable pointer)
> > -// CHECK-NEXT: sizeof=12, dsize=12, align=4
> > +// CHECK-NEXT: sizeof=12, align=4
> > // CHECK-NEXT: nvsize=4, nvalign=4
> >
> > // CHECK: %struct.AV = type { i32 (...)** }
> > @@ -464,7 +464,7 @@ int main() {
> > // CHECK-NEXT:  0 |   struct BV (primary base)
> > // CHECK-NEXT:  0 |     struct AV (primary base)
> > // CHECK-NEXT:  0 |       (AV vftable pointer)
> > -// CHECK-NEXT: sizeof=4, dsize=4, align=4
> > +// CHECK-NEXT: sizeof=4, align=4
> > // CHECK-NEXT: nvsize=4, nvalign=4
> >
> > // CHECK: %struct.DV = type { %struct.BV }
> > @@ -480,14 +480,14 @@ int main() {
> > // CHECK-NEXT: 12 |   struct BV (virtual base)
> > // CHECK-NEXT: 12 |     struct AV (primary base)
> > // CHECK-NEXT: 12 |       (AV vftable pointer)
> > -// CHECK-NEXT: sizeof=16, dsize=16, align=4
> > +// CHECK-NEXT: sizeof=16, align=4
> > // CHECK-NEXT: nvsize=8, nvalign=4
> >
> > // CHECK: %struct.EV = type { %struct.DV, %struct.CV.base, [4 x i8],
> %struct.BV }
> > // CHECK: %struct.EV.base = type { %struct.DV, %struct.CV.base }
> >
> > // Overriding a method means that all the vbases containing that
> > -// method need a vtordisp.
> > +// method need a vtordisp.  Note: this code will cause an error in
> cl.exe.
> > namespace test1 {
> >   struct A { virtual void foo(); };
> >   struct B : A {};
> > @@ -503,6 +503,6 @@ namespace test1 {
> > // CHECK-NEXT:  16 |   struct test1::B (virtual base)
> > // CHECK-NEXT:  16 |     struct test1::A (primary base)
> > // CHECK-NEXT:  16 |       (A vftable pointer)
> > -// CHECK-NEXT:  sizeof=20, dsize=20, align=4
> > +// CHECK-NEXT:  sizeof=20, align=4
> > // CHECK-NEXT:  nvsize=4, nvalign=4
> > }
> >
> > Modified: cfe/trunk/test/SemaCXX/ms_struct.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/ms_struct.cpp?rev=192494&r1=192493&r2=192494&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/SemaCXX/ms_struct.cpp (original)
> > +++ cfe/trunk/test/SemaCXX/ms_struct.cpp Fri Oct 11 15:19:00 2013
> > @@ -6,7 +6,6 @@
> > struct A {
> >   unsigned long a:4;
> >   unsigned char b;
> > -  A();
> > };
> >
> > struct B : public A {
> >
> >
> > _______________________________________________
> > cfe-commits mailing list
> > cfe-commits at cs.uiuc.edu
> > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131011/ddf90173/attachment.html>


More information about the cfe-commits mailing list