<div dir="ltr">Should've been fixed in r192495:<div><a href="http://bb.pgr.jp/builders/ninja-clang-i686-msc17-R/builds/5434">http://bb.pgr.jp/builders/ninja-clang-i686-msc17-R/builds/5434</a><br></div><div><br></div><div>
Same failure was reported here:</div><div><a href="http://bb.pgr.jp/builders/ninja-clang-i686-msc17-R/builds/5433">http://bb.pgr.jp/builders/ninja-clang-i686-msc17-R/builds/5433</a><br></div></div><div class="gmail_extra">
<br><br><div class="gmail_quote">On Fri, Oct 11, 2013 at 3:00 PM, jahanian <span dir="ltr"><<a href="mailto:fjahanian@apple.com" target="_blank">fjahanian@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
We are experiencing VS buildbot failures after this patch went in. These three tests are failing.<br>
<br>
Testing Time: 47.63s<br>
  ********************<br>
  Failing Tests (3):<br>
      Clang :: Analysis/inlining/dyn-dispatch-bifurcate.cpp<br>
      Clang :: SemaCXX/primary-base.cpp<br>
      Clang :: SemaCXX/warn-reinterpret-base-class.cpp<br>
<br>
They all give error having to do with what it says is illegal use of reinterpret_cast.<br>
<br>
- Fariborz<br>
<div class="HOEnZb"><div class="h5"><br>
On Oct 11, 2013, at 1:19 PM, Warren Hunt <<a href="mailto:whunt@google.com">whunt@google.com</a>> wrote:<br>
<br>
> Author: whunt<br>
> Date: Fri Oct 11 15:19:00 2013<br>
> New Revision: 192494<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=192494&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=192494&view=rev</a><br>
> Log:<br>
> Adds Microsoft compatiable C++ record layout code to clang.<br>
><br>
><br>
> Modified:<br>
>    cfe/trunk/include/clang/AST/ASTContext.h<br>
>    cfe/trunk/include/clang/AST/RecordLayout.h<br>
>    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
>    cfe/trunk/lib/AST/RecordLayout.cpp<br>
>    cfe/trunk/lib/AST/RecordLayoutBuilder.cpp<br>
>    cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp<br>
>    cfe/trunk/lib/CodeGen/MicrosoftVBTables.cpp<br>
>    cfe/trunk/lib/Sema/SemaDecl.cpp<br>
>    cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>
>    cfe/trunk/test/CodeGen/pr2394.c<br>
>    cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp<br>
>    cfe/trunk/test/Coverage/codegen-next.m<br>
>    cfe/trunk/test/PCH/rdar10830559.cpp<br>
>    cfe/trunk/test/Sema/ms_class_layout.cpp<br>
>    cfe/trunk/test/SemaCXX/ms_struct.cpp<br>
><br>
> Modified: cfe/trunk/include/clang/AST/ASTContext.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=192494&r1=192493&r2=192494&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=192494&r1=192493&r2=192494&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/include/clang/AST/ASTContext.h (original)<br>
> +++ cfe/trunk/include/clang/AST/ASTContext.h Fri Oct 11 15:19:00 2013<br>
> @@ -1660,6 +1660,7 @@ public:<br>
>   /// record (struct/union/class) \p D, which indicates its size and field<br>
>   /// position information.<br>
>   const ASTRecordLayout &getASTRecordLayout(const RecordDecl *D) const;<br>
> +  const ASTRecordLayout *BuildMicrosoftASTRecordLayout(const RecordDecl *D) const;<br>
><br>
>   /// \brief Get or compute information about the layout of the specified<br>
>   /// Objective-C interface.<br>
><br>
> Modified: cfe/trunk/include/clang/AST/RecordLayout.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecordLayout.h?rev=192494&r1=192493&r2=192494&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecordLayout.h?rev=192494&r1=192493&r2=192494&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/include/clang/AST/RecordLayout.h (original)<br>
> +++ cfe/trunk/include/clang/AST/RecordLayout.h Fri Oct 11 15:19:00 2013<br>
> @@ -93,7 +93,20 @@ private:<br>
>     /// HasOwnVFPtr - Does this class provide a virtual function table<br>
>     /// (vtable in Itanium, vftbl in Microsoft) that is independent from<br>
>     /// its base classes?<br>
> -    bool HasOwnVFPtr; // TODO: stash this somewhere more efficient<br>
> +    bool HasOwnVFPtr : 1;<br>
> +<br>
> +    /// HasVFPtr - Does this class have a vftable at all (could be inherited<br>
> +    /// from its primary base.)<br>
> +    bool HasVFPtr : 1;<br>
> +<br>
> +    /// HasOwnVBPtr - Does this class provide a virtual function table<br>
> +    /// (vtable in Itanium, VBtbl in Microsoft) that is independent from<br>
> +    /// its base classes?<br>
> +    bool HasOwnVBPtr : 1;<br>
> +<br>
> +    /// AlignAfterVBases - Force appropriate alignment after virtual bases are<br>
> +    /// laid out in MS-C++-ABI.<br>
> +    bool AlignAfterVBases : 1;<br>
><br>
>     /// PrimaryBase - The primary base info for this record.<br>
>     llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> PrimaryBase;<br>
> @@ -122,13 +135,15 @@ private:<br>
>   typedef CXXRecordLayoutInfo::BaseOffsetsMapTy BaseOffsetsMapTy;<br>
>   ASTRecordLayout(const ASTContext &Ctx,<br>
>                   CharUnits size, CharUnits alignment,<br>
> -                  bool hasOwnVFPtr, CharUnits vbptroffset,<br>
> +                  bool hasOwnVFPtr, bool hasVFPtr, bool hasOwnVBPtr,<br>
> +                  CharUnits vbptroffset,<br>
>                   CharUnits datasize,<br>
>                   const uint64_t *fieldoffsets, unsigned fieldcount,<br>
>                   CharUnits nonvirtualsize, CharUnits nonvirtualalign,<br>
>                   CharUnits SizeOfLargestEmptySubobject,<br>
>                   const CXXRecordDecl *PrimaryBase,<br>
>                   bool IsPrimaryBaseVirtual,<br>
> +                  bool ForceAlign,<br>
>                   const BaseOffsetsMapTy& BaseOffsets,<br>
>                   const VBaseOffsetsMapTy& VBaseOffsets);<br>
><br>
> @@ -226,6 +241,35 @@ public:<br>
>     return CXXInfo->HasOwnVFPtr;<br>
>   }<br>
><br>
> +  /// hasVFPtr - Does this class have a virtual function table pointer.<br>
> +  bool hasVFPtr() const {<br>
> +    assert(CXXInfo && "Record layout does not have C++ specific info!");<br>
> +    return CXXInfo->HasVFPtr;<br>
> +  }<br>
> +<br>
> +  /// hasOwnVBPtr - Does this class provide its own virtual-base<br>
> +  /// table pointer, rather than inheriting one from a primary base<br>
> +  /// class?<br>
> +  ///<br>
> +  /// This implies that the ABI has no primary base class, meaning<br>
> +  /// that it has no base classes that are suitable under the conditions<br>
> +  /// of the ABI.<br>
> +  bool hasOwnVBPtr() const {<br>
> +    assert(CXXInfo && "Record layout does not have C++ specific info!");<br>
> +    return CXXInfo->HasOwnVBPtr;<br>
> +  }<br>
> +<br>
> +  /// hasVBPtr - Does this class have a virtual function table pointer.<br>
> +  bool hasVBPtr() const {<br>
> +    assert(CXXInfo && "Record layout does not have C++ specific info!");<br>
> +    return !CXXInfo->VBPtrOffset.isNegative();<br>
> +  }<br>
> +<br>
> +  bool getAlignAfterVBases() const {<br>
> +    assert(CXXInfo && "Record layout does not have C++ specific info!");<br>
> +    return CXXInfo->AlignAfterVBases;<br>
> +  }<br>
> +<br>
>   /// getVBPtrOffset - Get the offset for virtual base table pointer.<br>
>   /// This is only meaningful with the Microsoft ABI.<br>
>   CharUnits getVBPtrOffset() const {<br>
><br>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=192494&r1=192493&r2=192494&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=192494&r1=192493&r2=192494&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)<br>
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Oct 11 15:19:00 2013<br>
> @@ -463,6 +463,7 @@ def warn_pragma_pack_show : Warning<"val<br>
> def warn_pragma_pack_pop_identifer_and_alignment : Warning<<br>
>   "specifying both a name and alignment to 'pop' is undefined">;<br>
> def warn_pragma_pack_pop_failed : Warning<"#pragma pack(pop, ...) failed: %0">;<br>
> +def warn_pragma_ms_struct_failed : Warning<"#pramga ms_struct can not be used with dynamic classes or structures">, InGroup<IgnoredAttributes>;<br>
><br>
> def warn_pragma_unused_undeclared_var : Warning<<br>
>   "undeclared variable %0 used as an argument for '#pragma unused'">;<br>
><br>
> Modified: cfe/trunk/lib/AST/RecordLayout.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayout.cpp?rev=192494&r1=192493&r2=192494&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayout.cpp?rev=192494&r1=192493&r2=192494&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/AST/RecordLayout.cpp (original)<br>
> +++ cfe/trunk/lib/AST/RecordLayout.cpp Fri Oct 11 15:19:00 2013<br>
> @@ -43,7 +43,9 @@ ASTRecordLayout::ASTRecordLayout(const A<br>
> // Constructor for C++ records.<br>
> ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx,<br>
>                                  CharUnits size, CharUnits alignment,<br>
> -                                 bool hasOwnVFPtr, CharUnits vbptroffset,<br>
> +                                 bool hasOwnVFPtr, bool hasVFPtr,<br>
> +                                 bool hasOwnVBPtr,<br>
> +                                 CharUnits vbptroffset,<br>
>                                  CharUnits datasize,<br>
>                                  const uint64_t *fieldoffsets,<br>
>                                  unsigned fieldcount,<br>
> @@ -52,6 +54,7 @@ ASTRecordLayout::ASTRecordLayout(const A<br>
>                                  CharUnits SizeOfLargestEmptySubobject,<br>
>                                  const CXXRecordDecl *PrimaryBase,<br>
>                                  bool IsPrimaryBaseVirtual,<br>
> +                                 bool AlignAfterVBases,<br>
>                                  const BaseOffsetsMapTy& BaseOffsets,<br>
>                                  const VBaseOffsetsMapTy& VBaseOffsets)<br>
>   : Size(size), DataSize(datasize), Alignment(alignment), FieldOffsets(0),<br>
> @@ -71,6 +74,10 @@ ASTRecordLayout::ASTRecordLayout(const A<br>
>   CXXInfo->VBaseOffsets = VBaseOffsets;<br>
>   CXXInfo->HasOwnVFPtr = hasOwnVFPtr;<br>
>   CXXInfo->VBPtrOffset = vbptroffset;<br>
> +  CXXInfo->HasVFPtr = hasVFPtr;<br>
> +  CXXInfo->HasOwnVBPtr = hasOwnVBPtr;<br>
> +  CXXInfo->AlignAfterVBases = AlignAfterVBases;<br>
> +<br>
><br>
> #ifndef NDEBUG<br>
>     if (const CXXRecordDecl *PrimaryBase = getPrimaryBase()) {<br>
><br>
> Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=192494&r1=192493&r2=192494&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=192494&r1=192493&r2=192494&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)<br>
> +++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Fri Oct 11 15:19:00 2013<br>
> @@ -604,6 +604,10 @@ protected:<br>
>   /// pointer, as opposed to inheriting one from a primary base class.<br>
>   bool HasOwnVFPtr;<br>
><br>
> +  /// HasOwnVBPtr - Whether the class provides its own vbtbl<br>
> +  /// pointer, as opposed to inheriting one from a base class. Only for MS.<br>
> +  bool HasOwnVBPtr;<br>
> +<br>
>   /// VBPtrOffset - Virtual base table offset. Only for MS layout.<br>
>   CharUnits VBPtrOffset;<br>
><br>
> @@ -654,6 +658,7 @@ protected:<br>
>       NonVirtualAlignment(CharUnits::One()),<br>
>       PrimaryBase(0), PrimaryBaseIsVirtual(false),<br>
>       HasOwnVFPtr(false),<br>
> +      HasOwnVBPtr(false),<br>
>       VBPtrOffset(CharUnits::fromQuantity(-1)),<br>
>       FirstNearlyEmptyVBase(0) { }<br>
><br>
> @@ -1074,8 +1079,10 @@ RecordLayoutBuilder::LayoutNonVirtualBas<br>
>       cast<CXXRecordDecl>(I->getType()->castAs<RecordType>()->getDecl());<br>
><br>
>     // Remember if this base has virtual bases itself.<br>
> -    if (BaseDecl->getNumVBases())<br>
> +    if (BaseDecl->getNumVBases()) {<br>
> +      const ASTRecordLayout &Layout = Context.getASTRecordLayout(BaseDecl);<br>
>       HasNonVirtualBaseWithVBTable = true;<br>
> +    }<br>
><br>
>     // Skip the primary base, because we've already laid it out.  The<br>
>     // !PrimaryBaseIsVirtual check is required because we might have a<br>
> @@ -1116,6 +1123,7 @@ RecordLayoutBuilder::LayoutNonVirtualBas<br>
>     PtrAlign = std::max(PtrAlign, Alignment);<br>
><br>
>     EnsureVTablePointerAlignment(PtrAlign);<br>
> +    HasOwnVBPtr = true;<br>
>     VBPtrOffset = getSize();<br>
>     setSize(getSize() + PtrWidth);<br>
>     setDataSize(getSize());<br>
> @@ -2338,6 +2346,704 @@ static bool mustSkipTailPadding(TargetCX<br>
>   llvm_unreachable("bad tail-padding use kind");<br>
> }<br>
><br>
> +static bool isMsLayout(const RecordDecl* D) {<br>
> +  return (D->getASTContext().getTargetInfo().getCXXABI().isMicrosoft() ||<br>
> +          D->getASTContext().getTargetInfo().getTriple().getOS() ==<br>
> +          llvm::Triple::Win32) &&<br>
> +          D->getASTContext().getTargetInfo().getPointerWidth(0) == 32;<br>
> +  // FIXME: we intend to enable 64 bit mode once it's been verified.<br>
> +}<br>
> +<br>
> +// This section contains an implementation of struct layout that is, up to the<br>
> +// included tests, compatible with cl.exe (2012).  The layout produced is<br>
> +// significantly different than those produced by the Itanium ABI.  Here we note<br>
> +// the most important differences.<br>
> +//<br>
> +// * The alignment of bitfields in unions is ignored when computing the<br>
> +//   alignment of the union.<br>
> +// * The existance of zero-width bitfield that occurs after anything other than<br>
> +//   a non-zero length bitfield is ignored.<br>
> +// * The Itanium equivalent vtable pointers are split into a vfptr (virtual<br>
> +//   function pointer) and a vbptr (virtual base pointer).  They can each be<br>
> +//   shared with a, non-virtual bases. These bases need not be the same.  vfptrs always occur at offset 0.  vbptrs can occur at an<br>
> +//   arbitrary offset and are placed after non-virtual bases but before fields.<br>
> +// * Virtual bases sometimes require a 'vtordisp' field that is laid out before<br>
> +//   the virtual base and is used in conjunction with virtual overrides during<br>
> +//   construction and destruction.<br>
> +// * vfptrs are allocated in a block of memory equal to the alignment of the<br>
> +//   fields and non-virtual bases at offset 0.<br>
> +// * vbptrs are allocated in a block of memory equal to the alignment of the<br>
> +//   fields and non-virtual bases.  This block is at a potentially unaligned offset.  If the<br>
> +//   allocation slot is unaligned and the alignment is less than or equal to the<br>
> +//   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<br>
> +//   the code).<br>
> +// * vtordisps are allocated in a block of memory with size and alignment equal<br>
> +//   to the alignment of the completed structure (before applying __declspec(<br>
> +//   align())).  The vtordisp always occur at the end of the allocation block, immediately prior to the virtual base.<br>
> +// * The last zero sized non-virtual base is allocated after the placement of<br>
> +//   vbptr if one exists and can be placed at the end of the struct, potentially<br>
> +//   aliasing either the first member or another struct allocated after this<br>
> +//   one.<br>
> +// * The last zero size virtual base may be placed at the end of the struct.<br>
> +//   and can potentially alias a zero sized type in the next struct.<br>
> +<br>
> +namespace {<br>
> +struct MicrosoftRecordLayoutBuilder {<br>
> +  typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;<br>
> +  MicrosoftRecordLayoutBuilder(const ASTContext &Context) : Context(Context) {}<br>
> +private:<br>
> +  MicrosoftRecordLayoutBuilder(const MicrosoftRecordLayoutBuilder &)<br>
> +  LLVM_DELETED_FUNCTION;<br>
> +  void operator=(const MicrosoftRecordLayoutBuilder &) LLVM_DELETED_FUNCTION;<br>
> +public:<br>
> +<br>
> +  void layout(const RecordDecl *RD);<br>
> +  void cxxLayout(const CXXRecordDecl *RD);<br>
> +  /// \brief Initializes size and alignment and honors some flags.<br>
> +  void initializeLayout(const RecordDecl *RD);<br>
> +  /// \brief Initialized C++ layout, compute alignment and virtual alignment and<br>
> +  /// existance of vfptrs and vbptrs.  Alignment is needed before the vfptr is<br>
> +  /// laid out.<br>
> +  void initializeCXXLayout(const CXXRecordDecl *RD);<br>
> +  void layoutVFPtr(const CXXRecordDecl *RD);<br>
> +  void layoutNonVirtualBases(const CXXRecordDecl *RD);<br>
> +  void layoutNonVirtualBase(const CXXRecordDecl *RD);<br>
> +  void layoutVBPtr(const CXXRecordDecl *RD);<br>
> +  /// \brief Lays out the fields of the record.  Also rounds size up to<br>
> +  /// alignment.<br>
> +  void layoutFields(const RecordDecl *RD);<br>
> +  void layoutField(const FieldDecl *FD);<br>
> +  void layoutBitField(const FieldDecl *FD);<br>
> +  /// \brief Lays out a single zero-width bit-field in the record and handles<br>
> +  /// special cases associated with zero-width bit-fields.<br>
> +  void layoutZeroWidthBitField(const FieldDecl *FD);<br>
> +  void layoutVirtualBases(const CXXRecordDecl *RD);<br>
> +  void layoutVirtualBase(const CXXRecordDecl *RD, bool HasVtordisp);<br>
> +  /// \brief Flushes the lazy virtual base and conditionally rounds up to<br>
> +  /// alignment.<br>
> +  void finalizeCXXLayout(const CXXRecordDecl *RD);<br>
> +  void honorDeclspecAlign(const RecordDecl *RD);<br>
> +<br>
> +  /// \brief Updates the alignment of the type.  This function doesn't take any<br>
> +  /// properties (such as packedness) into account.  getAdjustedFieldInfo()<br>
> +  /// adjustes for packedness.<br>
> +  void updateAlignment(CharUnits NewAlignment) {<br>
> +    Alignment = std::max(Alignment, NewAlignment);<br>
> +  }<br>
> +  /// \brief Gets the size and alignment taking attributes into account.<br>
> +  std::pair<CharUnits, CharUnits> getAdjustedFieldInfo(const FieldDecl *FD);<br>
> +  /// \brief Places a field at offset 0.<br>
> +  void placeFieldAtZero() { FieldOffsets.push_back(0); }<br>
> +  /// \brief Places a field at an offset in CharUnits.<br>
> +  void placeFieldAtOffset(CharUnits FieldOffset) {<br>
> +    FieldOffsets.push_back(Context.toBits(FieldOffset));<br>
> +  }<br>
> +  /// \brief Places a bitfield at a bit offset.<br>
> +  void placeFieldAtBitOffset(uint64_t FieldOffset) {<br>
> +    FieldOffsets.push_back(FieldOffset);<br>
> +  }<br>
> +  /// \brief Compute the set of virtual bases for which vtordisps are required.<br>
> +  llvm::SmallPtrSet<const CXXRecordDecl *, 2><br>
> +  computeVtorDispSet(const CXXRecordDecl *RD);<br>
> +<br>
> +  const ASTContext &Context;<br>
> +  /// \brief The size of the record being laid out.<br>
> +  CharUnits Size;<br>
> +  /// \brief The current alignment of the record layout.<br>
> +  CharUnits Alignment;<br>
> +  /// \brief The collection of field offsets.<br>
> +  SmallVector<uint64_t, 16> FieldOffsets;<br>
> +  /// \brief The maximum allowed field alignment. This is set by #pragma pack.<br>
> +  CharUnits MaxFieldAlignment;<br>
> +  /// \brief Alignment does not occur for virtual bases unless something<br>
> +  /// forces it to by explicitly using __declspec(align())<br>
> +  bool AlignAfterVBases : 1;<br>
> +  bool IsUnion : 1;<br>
> +  /// \brief True if the last field laid out was a bitfield and was not 0<br>
> +  /// width.<br>
> +  bool LastFieldIsNonZeroWidthBitfield : 1;<br>
> +  /// \brief The size of the allocation of the currently active bitfield.<br>
> +  /// This value isn't meaningful unless LastFieldIsNonZeroWidthBitfield<br>
> +  /// is true.<br>
> +  CharUnits CurrentBitfieldSize;<br>
> +  /// \brief The number of remaining bits in our last bitfield allocation.<br>
> +  /// This value isn't meaningful unless LastFieldIsNonZeroWidthBitfield is<br>
> +  /// true.<br>
> +  unsigned RemainingBitsInField;<br>
> +<br>
> +  /// \brief The data alignment of the record layout.<br>
> +  CharUnits DataSize;<br>
> +  /// \brief The alignment of the non-virtual portion of the record layout<br>
> +  /// including. Only used for C++ layouts.<br>
> +  CharUnits NonVirtualAlignment;<br>
> +  /// \brief The additional alignment imposed by the virtual bases.<br>
> +  CharUnits VirtualAlignment;<br>
> +  /// \brief The primary base class (if one exists).<br>
> +  const CXXRecordDecl *PrimaryBase;<br>
> +  /// \brief The class we share our vb-pointer with.<br>
> +  const CXXRecordDecl *SharedVBPtrBase;<br>
> +  /// \brief True if the class has a (not necessarily its own) vftable pointer.<br>
> +  bool HasVFPtr : 1;<br>
> +  /// \brief True if the class has a (not necessarily its own) vbtable pointer.<br>
> +  bool HasVBPtr : 1;<br>
> +  /// \brief Offset to the virtual base table pointer (if one exists).<br>
> +  CharUnits VBPtrOffset;<br>
> +  /// \brief Base classes and their offsets in the record.<br>
> +  BaseOffsetsMapTy Bases;<br>
> +  /// \brief virtual base classes and their offsets in the record.<br>
> +  ASTRecordLayout::VBaseOffsetsMapTy VBases;<br>
> +  /// \brief The size of a pointer.<br>
> +  CharUnits PointerSize;<br>
> +  /// \brief The alignment of a pointer.<br>
> +  CharUnits PointerAlignment;<br>
> +  /// \brief Holds an empty base we haven't yet laid out.<br>
> +  const CXXRecordDecl *LazyEmptyBase;<br>
> +};<br>
> +} // namespace<br>
> +<br>
> +std::pair<CharUnits, CharUnits><br>
> +MicrosoftRecordLayoutBuilder::getAdjustedFieldInfo(const FieldDecl *FD) {<br>
> +  std::pair<CharUnits, CharUnits> FieldInfo;<br>
> +  if (FD->getType()->isIncompleteArrayType()) {<br>
> +    // This is a flexible array member; we can't directly<br>
> +    // query getTypeInfo about these, so we figure it out here.<br>
> +    // Flexible array members don't have any size, but they<br>
> +    // have to be aligned appropriately for their element type.<br>
> +    FieldInfo.first = CharUnits::Zero();<br>
> +    const ArrayType *ATy = Context.getAsArrayType(FD->getType());<br>
> +    FieldInfo.second = Context.getTypeAlignInChars(ATy->getElementType());<br>
> +  } else if (const ReferenceType *RT = FD->getType()->getAs<ReferenceType>()) {<br>
> +    unsigned AS = RT->getPointeeType().getAddressSpace();<br>
> +    FieldInfo.first = Context<br>
> +        .toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(AS));<br>
> +    FieldInfo.second = Context<br>
> +        .toCharUnitsFromBits(Context.getTargetInfo().getPointerAlign(AS));<br>
> +  } else<br>
> +    FieldInfo = Context.getTypeInfoInChars(FD->getType());<br>
> +<br>
> +  // If we're not on win32 and using ms_struct the field alignment will be wrong<br>
> +  // for 64 bit types, so we fix that here.<br>
> +  if (FD->getASTContext().getTargetInfo().getTriple().getOS() !=<br>
> +      llvm::Triple::Win32) {<br>
> +    QualType T = Context.getBaseElementType(FD->getType());<br>
> +    if (const BuiltinType *BTy = T->getAs<BuiltinType>()) {<br>
> +      CharUnits TypeSize = Context.getTypeSizeInChars(BTy);<br>
> +      if (TypeSize > FieldInfo.second)<br>
> +        FieldInfo.second = TypeSize;<br>
> +    }<br>
> +  }<br>
> +<br>
> +  // Respect packed attribute.<br>
> +  if (FD->hasAttr<PackedAttr>())<br>
> +    FieldInfo.second = CharUnits::One();<br>
> +  // Respect pack pragma.<br>
> +  else if (!MaxFieldAlignment.isZero())<br>
> +    FieldInfo.second = std::min(FieldInfo.second, MaxFieldAlignment);<br>
> +  // Respect alignment attributes.<br>
> +  if (unsigned fieldAlign = FD->getMaxAlignment()) {<br>
> +    CharUnits FieldAlign = Context.toCharUnitsFromBits(fieldAlign);<br>
> +    AlignAfterVBases = true;<br>
> +    FieldInfo.second = std::max(FieldInfo.second, FieldAlign);<br>
> +  }<br>
> +  return FieldInfo;<br>
> +}<br>
> +<br>
> +void MicrosoftRecordLayoutBuilder::initializeLayout(const RecordDecl *RD) {<br>
> +  IsUnion = RD->isUnion();<br>
> +<br>
> +  Size = CharUnits::Zero();<br>
> +  Alignment = CharUnits::One();<br>
> +  AlignAfterVBases = false;<br>
> +<br>
> +  // Compute the maximum field alignment.<br>
> +  MaxFieldAlignment = CharUnits::Zero();<br>
> +  // Honor the default struct packing maximum alignment flag.<br>
> +  if (unsigned DefaultMaxFieldAlignment = Context.getLangOpts().PackStruct)<br>
> +    MaxFieldAlignment = CharUnits::fromQuantity(DefaultMaxFieldAlignment);<br>
> +  // Honor the packing attribute.<br>
> +  if (const MaxFieldAlignmentAttr *MFAA = RD->getAttr<MaxFieldAlignmentAttr>())<br>
> +    MaxFieldAlignment = Context.toCharUnitsFromBits(MFAA->getAlignment());<br>
> +  // Packed attribute forces max field alignment to be 1.<br>
> +  if (RD->hasAttr<PackedAttr>())<br>
> +    MaxFieldAlignment = CharUnits::One();<br>
> +}<br>
> +<br>
> +void MicrosoftRecordLayoutBuilder::layout(const RecordDecl *RD) {<br>
> +  initializeLayout(RD);<br>
> +  layoutFields(RD);<br>
> +  honorDeclspecAlign(RD);<br>
> +}<br>
> +<br>
> +void MicrosoftRecordLayoutBuilder::cxxLayout(const CXXRecordDecl *RD) {<br>
> +  initializeLayout(RD);<br>
> +  initializeCXXLayout(RD);<br>
> +  layoutVFPtr(RD);<br>
> +  layoutNonVirtualBases(RD);<br>
> +  layoutVBPtr(RD);<br>
> +  layoutFields(RD);<br>
> +  DataSize = Size;<br>
> +  NonVirtualAlignment = Alignment;<br>
> +  layoutVirtualBases(RD);<br>
> +  finalizeCXXLayout(RD);<br>
> +  honorDeclspecAlign(RD);<br>
> +}<br>
> +<br>
> +void<br>
> +MicrosoftRecordLayoutBuilder::initializeCXXLayout(const CXXRecordDecl *RD) {<br>
> +  // Calculate pointer size and alignment.<br>
> +  PointerSize =<br>
> +      Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));<br>
> +  PointerAlignment = PointerSize;<br>
> +  if (!MaxFieldAlignment.isZero())<br>
> +    PointerAlignment = std::min(PointerAlignment, MaxFieldAlignment);<br>
> +<br>
> +  // Initialize information about the bases.<br>
> +  HasVBPtr = false;<br>
> +  HasVFPtr = false;<br>
> +  SharedVBPtrBase = 0;<br>
> +  PrimaryBase = 0;<br>
> +  VirtualAlignment = CharUnits::One();<br>
> +<br>
> +  // If the record has a dynamic base class, attempt to choose a primary base<br>
> +  // class. It is the first (in direct base class order) non-virtual dynamic<br>
> +  // base class, if one exists.<br>
> +  for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),<br>
> +                                                e = RD->bases_end();<br>
> +       i != e; ++i) {<br>
> +    const CXXRecordDecl *BaseDecl =<br>
> +        cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());<br>
> +    const ASTRecordLayout &Layout = Context.getASTRecordLayout(BaseDecl);<br>
> +    // Handle forced alignment.<br>
> +    if (Layout.getAlignAfterVBases())<br>
> +      AlignAfterVBases = true;<br>
> +    // Handle virtual bases.<br>
> +    if (i->isVirtual()) {<br>
> +      VirtualAlignment = std::max(VirtualAlignment, Layout.getAlignment());<br>
> +      HasVBPtr = true;<br>
> +      continue;<br>
> +    }<br>
> +    // We located a primary base class!<br>
> +    if (!PrimaryBase && Layout.hasVFPtr()) {<br>
> +      PrimaryBase = BaseDecl;<br>
> +      HasVFPtr = true;<br>
> +    }<br>
> +    // We located a base to share a VBPtr with!<br>
> +    if (!SharedVBPtrBase && Layout.hasVBPtr()) {<br>
> +      SharedVBPtrBase = BaseDecl;<br>
> +      HasVBPtr = true;<br>
> +    }<br>
> +    updateAlignment(Layout.getAlignment());<br>
> +  }<br>
> +<br>
> +  // Use LayoutFields to compute the alignment of the fields.  The layout<br>
> +  // is discarded.  This is the simplest way to get all of the bit-field<br>
> +  // behavior correct and is not actually very expensive.<br>
> +  layoutFields(RD);<br>
> +  Size = CharUnits::Zero();<br>
> +  FieldOffsets.clear();<br>
> +}<br>
> +<br>
> +void MicrosoftRecordLayoutBuilder::layoutVFPtr(const CXXRecordDecl *RD) {<br>
> +  // If we have a primary base then our VFPtr was already laid out<br>
> +  if (PrimaryBase)<br>
> +    return;<br>
> +<br>
> +  // Look at all of our methods to determine if we need a VFPtr.  We need a<br>
> +  // vfptr if we define a new virtual function.<br>
> +  if (!HasVFPtr && RD->isDynamicClass())<br>
> +    for (CXXRecordDecl::method_iterator i = RD->method_begin(),<br>
> +                                        e = RD->method_end();<br>
> +         !HasVFPtr && i != e; ++i)<br>
> +      HasVFPtr = i->isVirtual() && i->size_overridden_methods() == 0;<br>
> +  if (!HasVFPtr)<br>
> +    return;<br>
> +<br>
> +  // MSVC potentially over-aligns the vf-table pointer by giving it<br>
> +  // the max alignment of all the non-virtual data in the class.  The resulting<br>
> +  // layout is essentially { vftbl, { nvdata } }.  This is completely<br>
> +  // unnecessary, but we're not here to pass judgment.<br>
> +  Size += Alignment;<br>
> +  updateAlignment(PointerAlignment);<br>
> +}<br>
> +<br>
> +void<br>
> +MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(const CXXRecordDecl *RD) {<br>
> +  LazyEmptyBase = 0;<br>
> +<br>
> +  // Lay out the primary base first.<br>
> +  if (PrimaryBase)<br>
> +    layoutNonVirtualBase(PrimaryBase);<br>
> +<br>
> +  // Iterate through the bases and lay out the non-virtual ones.<br>
> +  for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),<br>
> +                                                e = RD->bases_end();<br>
> +       i != e; ++i) {<br>
> +    if (i->isVirtual())<br>
> +      continue;<br>
> +    const CXXRecordDecl *BaseDecl =<br>
> +        cast<CXXRecordDecl>(i->getType()->castAs<RecordType>()->getDecl());<br>
> +    if (BaseDecl != PrimaryBase)<br>
> +      layoutNonVirtualBase(BaseDecl);<br>
> +  }<br>
> +}<br>
> +<br>
> +void<br>
> +MicrosoftRecordLayoutBuilder::layoutNonVirtualBase(const CXXRecordDecl *RD) {<br>
> +  const ASTRecordLayout *Layout = RD ? &Context.getASTRecordLayout(RD) : 0;<br>
> +<br>
> +  // If we have a lazy empty base we haven't laid out yet, do that now.<br>
> +  if (LazyEmptyBase) {<br>
> +    const ASTRecordLayout &LazyLayout =<br>
> +        Context.getASTRecordLayout(LazyEmptyBase);<br>
> +    Size = Size.RoundUpToAlignment(LazyLayout.getAlignment());<br>
> +    Bases.insert(std::make_pair(LazyEmptyBase, Size));<br>
> +    // Empty bases only consume space when followed by another empty base.<br>
> +    if (RD && Layout->getNonVirtualSize().isZero())<br>
> +      Size++;<br>
> +    LazyEmptyBase = 0;<br>
> +  }<br>
> +<br>
> +  // RD is null when flushing the final lazy base.<br>
> +  if (!RD)<br>
> +    return;<br>
> +<br>
> +  if (Layout->getNonVirtualSize().isZero()) {<br>
> +    LazyEmptyBase = RD;<br>
> +    return;<br>
> +  }<br>
> +<br>
> +  // Insert the base here.<br>
> +  CharUnits BaseOffset = Size.RoundUpToAlignment(Layout->getAlignment());<br>
> +  Bases.insert(std::make_pair(RD, BaseOffset));<br>
> +  Size = BaseOffset + Layout->getDataSize();<br>
> +  // Note: we don't update alignment here because it was accounted<br>
> +  // for during initalization.<br>
> +}<br>
> +<br>
> +void MicrosoftRecordLayoutBuilder::layoutVBPtr(const CXXRecordDecl *RD) {<br>
> +  if (!HasVBPtr)<br>
> +    VBPtrOffset = CharUnits::fromQuantity(-1);<br>
> +  else if (SharedVBPtrBase) {<br>
> +    const ASTRecordLayout &Layout = Context.getASTRecordLayout(SharedVBPtrBase);<br>
> +    VBPtrOffset = Bases[SharedVBPtrBase] + Layout.getVBPtrOffset();<br>
> +  } else {<br>
> +    updateAlignment(PointerAlignment);<br>
> +    VBPtrOffset = Size.RoundUpToAlignment(PointerAlignment);<br>
> +<br>
> +    if (Alignment == PointerAlignment && Size % PointerAlignment) {<br>
> +      CharUnits x = Size + Alignment + Alignment;<br>
> +      Size = VBPtrOffset + Alignment;<br>
> +      // Handle strange padding rules.  I have no explanation for why the<br>
> +      // virtual base is padded in such an odd way.  My guess is that they<br>
> +      // always Add 2 * Alignment and incorrectly round down to the appropriate<br>
> +      // alignment.  It's important to get this case correct because it impacts<br>
> +      // the layout of the first member of the struct.<br>
> +<br>
> +      RecordDecl::field_iterator FieldBegin = RD->field_begin();<br>
> +      if (FieldBegin != RD->field_end())<br>
> +        Size += CharUnits::fromQuantity(<br>
> +            x % getAdjustedFieldInfo(*FieldBegin).second);<br>
> +    } else<br>
> +      Size += Alignment;<br>
> +  }<br>
> +<br>
> +  // Flush the lazy empty base.<br>
> +  layoutNonVirtualBase(0);<br>
> +}<br>
> +<br>
> +void MicrosoftRecordLayoutBuilder::layoutFields(const RecordDecl *RD) {<br>
> +  LastFieldIsNonZeroWidthBitfield = false;<br>
> +  for (RecordDecl::field_iterator Field = RD->field_begin(),<br>
> +                                  FieldEnd = RD->field_end();<br>
> +       Field != FieldEnd; ++Field)<br>
> +    layoutField(*Field);<br>
> +  Size = Size.RoundUpToAlignment(Alignment);<br>
> +}<br>
> +<br>
> +void MicrosoftRecordLayoutBuilder::layoutField(const FieldDecl *FD) {<br>
> +  if (FD->isBitField()) {<br>
> +    layoutBitField(FD);<br>
> +    return;<br>
> +  }<br>
> +  LastFieldIsNonZeroWidthBitfield = false;<br>
> +<br>
> +  std::pair<CharUnits, CharUnits> FieldInfo = getAdjustedFieldInfo(FD);<br>
> +  CharUnits FieldSize = FieldInfo.first;<br>
> +  CharUnits FieldAlign = FieldInfo.second;<br>
> +<br>
> +  updateAlignment(FieldAlign);<br>
> +  if (IsUnion) {<br>
> +    placeFieldAtZero();<br>
> +    Size = std::max(Size, FieldSize);<br>
> +  } else {<br>
> +    // Round up the current record size to the field's alignment boundary.<br>
> +    CharUnits FieldOffset = Size.RoundUpToAlignment(FieldAlign);<br>
> +    placeFieldAtOffset(FieldOffset);<br>
> +    Size = FieldOffset + FieldSize;<br>
> +  }<br>
> +}<br>
> +<br>
> +void MicrosoftRecordLayoutBuilder::layoutBitField(const FieldDecl *FD) {<br>
> +  unsigned Width = FD->getBitWidthValue(Context);<br>
> +  if (Width == 0) {<br>
> +    layoutZeroWidthBitField(FD);<br>
> +    return;<br>
> +  }<br>
> +<br>
> +  std::pair<CharUnits, CharUnits> FieldInfo = getAdjustedFieldInfo(FD);<br>
> +  CharUnits FieldSize = FieldInfo.first;<br>
> +  CharUnits FieldAlign = FieldInfo.second;<br>
> +<br>
> +  // Clamp the bitfield to a containable size for the sake of being able<br>
> +  // to lay them out.  Sema will throw an error.<br>
> +  if (Width > Context.toBits(FieldSize))<br>
> +    Width = Context.toBits(FieldSize);<br>
> +<br>
> +  // Check to see if this bitfield fits into an existing allocation.  Note:<br>
> +  // MSVC refuses to pack bitfields of formal types with different sizes<br>
> +  // into the same allocation.<br>
> +  if (!IsUnion && LastFieldIsNonZeroWidthBitfield &&<br>
> +      CurrentBitfieldSize == FieldSize && Width <= RemainingBitsInField) {<br>
> +    placeFieldAtBitOffset(Context.toBits(Size) - RemainingBitsInField);<br>
> +    RemainingBitsInField -= Width;<br>
> +    return;<br>
> +  }<br>
> +<br>
> +  LastFieldIsNonZeroWidthBitfield = true;<br>
> +  CurrentBitfieldSize = FieldSize;<br>
> +  if (IsUnion) {<br>
> +    placeFieldAtZero();<br>
> +    Size = std::max(Size, FieldSize);<br>
> +    // TODO: Add a Sema warning that MS ignores bitfield alignment in unions.<br>
> +  } else {<br>
> +    // Allocate a new block of memory and place the bitfield in it.<br>
> +    CharUnits FieldOffset = Size.RoundUpToAlignment(FieldAlign);<br>
> +    placeFieldAtOffset(FieldOffset);<br>
> +    Size = FieldOffset + FieldSize;<br>
> +    updateAlignment(FieldAlign);<br>
> +    RemainingBitsInField = Context.toBits(FieldSize) - Width;<br>
> +  }<br>
> +}<br>
> +<br>
> +void<br>
> +MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(const FieldDecl *FD) {<br>
> +  // Zero-width bitfields are ignored unless they follow a non-zero-width<br>
> +  // bitfield.<br>
> +  std::pair<CharUnits, CharUnits> FieldInfo = getAdjustedFieldInfo(FD);<br>
> +  CharUnits FieldSize = FieldInfo.first;<br>
> +  CharUnits FieldAlign = FieldInfo.second;<br>
> +<br>
> +  if (!LastFieldIsNonZeroWidthBitfield) {<br>
> +    placeFieldAtOffset(IsUnion ? CharUnits::Zero() : Size);<br>
> +    // TODO: Add a Sema warning that MS ignores alignment for zero<br>
> +    // sized bitfields that occur after zero-size bitfields or non bitfields.<br>
> +    return;<br>
> +  }<br>
> +<br>
> +  LastFieldIsNonZeroWidthBitfield = false;<br>
> +  if (IsUnion) {<br>
> +    placeFieldAtZero();<br>
> +    Size = std::max(Size, FieldSize);<br>
> +  } else {<br>
> +    // Round up the current record size to the field's alignment boundary.<br>
> +    CharUnits FieldOffset = Size.RoundUpToAlignment(FieldAlign);<br>
> +    placeFieldAtOffset(FieldOffset);<br>
> +    Size = FieldOffset;<br>
> +    updateAlignment(FieldAlign);<br>
> +  }<br>
> +}<br>
> +<br>
> +void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const CXXRecordDecl *RD) {<br>
> +  if (!HasVBPtr)<br>
> +    return;<br>
> +<br>
> +  updateAlignment(VirtualAlignment);<br>
> +<br>
> +  // Zero-sized v-bases obey the alignment attribute so apply it here.  The<br>
> +  // alignment attribute is normally accounted for in FinalizeLayout.<br>
> +  if (unsigned MaxAlign = RD->getMaxAlignment())<br>
> +    updateAlignment(Context.toCharUnitsFromBits(MaxAlign));<br>
> +<br>
> +  llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtordisp =<br>
> +      computeVtorDispSet(RD);<br>
> +<br>
> +  // Iterate through the virtual bases and lay them out.<br>
> +  for (CXXRecordDecl::base_class_const_iterator i = RD->vbases_begin(),<br>
> +                                                e = RD->vbases_end();<br>
> +       i != e; ++i) {<br>
> +    const CXXRecordDecl *BaseDecl =<br>
> +        cast<CXXRecordDecl>(i->getType()->castAs<RecordType>()->getDecl());<br>
> +    layoutVirtualBase(BaseDecl, HasVtordisp.count(BaseDecl));<br>
> +  }<br>
> +}<br>
> +<br>
> +void MicrosoftRecordLayoutBuilder::layoutVirtualBase(const CXXRecordDecl *RD,<br>
> +                                                     bool HasVtordisp) {<br>
> +  if (LazyEmptyBase) {<br>
> +    const ASTRecordLayout &LazyLayout =<br>
> +        Context.getASTRecordLayout(LazyEmptyBase);<br>
> +    Size = Size.RoundUpToAlignment(LazyLayout.getAlignment());<br>
> +    VBases.insert(<br>
> +        std::make_pair(LazyEmptyBase, ASTRecordLayout::VBaseInfo(Size, false)));<br>
> +    // Empty bases only consume space when followed by another empty base.<br>
> +    // The space consumed is in an Alignment sized/aligned block and the v-base<br>
> +    // is placed at its alignment offset into the chunk, unless its alignment<br>
> +    // is less than the size of a pointer, at which it is placed at pointer<br>
> +    // width offset in the chunck.  We have no idea why.<br>
> +    if (RD && Context.getASTRecordLayout(RD).getNonVirtualSize().isZero())<br>
> +      Size = Size.RoundUpToAlignment(Alignment) + PointerSize;<br>
> +    LazyEmptyBase = 0;<br>
> +  }<br>
> +<br>
> +  // RD is null when flushing the final lazy virtual base.<br>
> +  if (!RD)<br>
> +    return;<br>
> +<br>
> +  const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);<br>
> +  if (Layout.getNonVirtualSize().isZero() && !HasVtordisp) {<br>
> +    LazyEmptyBase = RD;<br>
> +    return;<br>
> +  }<br>
> +<br>
> +  CharUnits BaseNVSize = Layout.getNonVirtualSize();<br>
> +  CharUnits BaseAlign = Layout.getAlignment();<br>
> +<br>
> +  if (HasVtordisp)<br>
> +    Size = Size.RoundUpToAlignment(Alignment) + PointerSize;<br>
> +  Size = Size.RoundUpToAlignment(BaseAlign);<br>
> +<br>
> +  // Insert the base here.<br>
> +  CharUnits BaseOffset = Size.RoundUpToAlignment(BaseAlign);<br>
> +  VBases.insert(<br>
> +      std::make_pair(RD, ASTRecordLayout::VBaseInfo(BaseOffset, HasVtordisp)));<br>
> +  Size = BaseOffset + BaseNVSize;<br>
> +  // Note: we don't update alignment here because it was accounted for in<br>
> +  // InitializeLayout.<br>
> +}<br>
> +<br>
> +void MicrosoftRecordLayoutBuilder::finalizeCXXLayout(const CXXRecordDecl *RD) {<br>
> +  // Flush the lazy virtual base.<br>
> +  layoutVirtualBase(0, false);<br>
> +<br>
> +  if (RD->vbases_begin() == RD->vbases_end() || AlignAfterVBases)<br>
> +    Size = Size.RoundUpToAlignment(Alignment);<br>
> +<br>
> +  if (Size.isZero())<br>
> +    Size = Alignment;<br>
> +}<br>
> +<br>
> +void MicrosoftRecordLayoutBuilder::honorDeclspecAlign(const RecordDecl *RD) {<br>
> +  if (unsigned MaxAlign = RD->getMaxAlignment()) {<br>
> +    AlignAfterVBases = true;<br>
> +    updateAlignment(Context.toCharUnitsFromBits(MaxAlign));<br>
> +    Size = Size.RoundUpToAlignment(Alignment);<br>
> +  }<br>
> +}<br>
> +<br>
> +static bool<br>
> +RequiresVtordisp(const llvm::SmallPtrSet<const CXXRecordDecl *, 2> &HasVtordisp,<br>
> +                 const CXXRecordDecl *RD) {<br>
> +  if (HasVtordisp.count(RD))<br>
> +    return true;<br>
> +  // If any of a virtual bases non-virtual bases (recursively) requires a<br>
> +  // vtordisp than so does this virtual base.<br>
> +  for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),<br>
> +                                                e = RD->bases_end();<br>
> +       i != e; ++i)<br>
> +    if (!i->isVirtual() &&<br>
> +        RequiresVtordisp(<br>
> +            HasVtordisp,<br>
> +            cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl())))<br>
> +      return true;<br>
> +  return false;<br>
> +}<br>
> +<br>
> +llvm::SmallPtrSet<const CXXRecordDecl *, 2><br>
> +MicrosoftRecordLayoutBuilder::computeVtorDispSet(const CXXRecordDecl *RD) {<br>
> +  llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtordisp;<br>
> +<br>
> +  // If any of our bases need a vtordisp for this type, so do we.  Check our<br>
> +  // direct bases for vtordisp requirements.<br>
> +  for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),<br>
> +                                                e = RD->bases_end();<br>
> +       i != e; ++i) {<br>
> +    const CXXRecordDecl *BaseDecl =<br>
> +        cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());<br>
> +    const ASTRecordLayout &Layout = Context.getASTRecordLayout(BaseDecl);<br>
> +    for (ASTRecordLayout::VBaseOffsetsMapTy::const_iterator<br>
> +             bi = Layout.getVBaseOffsetsMap().begin(),<br>
> +             be = Layout.getVBaseOffsetsMap().end();<br>
> +         bi != be; ++bi)<br>
> +      if (bi->second.hasVtorDisp())<br>
> +        HasVtordisp.insert(bi->first);<br>
> +  }<br>
> +<br>
> +  // If we define a constructor or destructor and override a function that is<br>
> +  // defined in a virtual base's vtable, that virtual bases need a vtordisp.<br>
> +  // Here we collect a list of classes with vtables for which our virtual bases<br>
> +  // actually live.  The virtual bases with this property will require<br>
> +  // vtordisps.  In addition, virtual bases that contain non-virtual bases that<br>
> +  // define functions we override also require vtordisps, this case is checked<br>
> +  // explicitly below.<br>
> +  if (RD->hasUserDeclaredConstructor() || RD->hasUserDeclaredDestructor()) {<br>
> +    llvm::SmallPtrSet<const CXXMethodDecl *, 8> Work;<br>
> +    // Seed the working set with our non-destructor virtual methods.<br>
> +    for (CXXRecordDecl::method_iterator i = RD->method_begin(),<br>
> +                                        e = RD->method_end();<br>
> +         i != e; ++i)<br>
> +      if ((*i)->isVirtual() && (*i) != RD->getDestructor())<br>
> +        Work.insert(*i);<br>
> +    while (!Work.empty()) {<br>
> +      const CXXMethodDecl *MD = *Work.begin();<br>
> +      CXXMethodDecl::method_iterator i = MD->begin_overridden_methods(),<br>
> +                                     e = MD->end_overridden_methods();<br>
> +      if (i == e)<br>
> +        // If a virtual method has no-overrides it lives in its parent's vtable.<br>
> +        HasVtordisp.insert(MD->getParent());<br>
> +      else<br>
> +        Work.insert(i, e);<br>
> +      // We've finished processing this element, remove it from the working set.<br>
> +      Work.erase(MD);<br>
> +    }<br>
> +  }<br>
> +<br>
> +  // Re-check all of our vbases for vtordisp requirements (in case their<br>
> +  // non-virtual bases have vtordisp requirements).<br>
> +  for (CXXRecordDecl::base_class_const_iterator i = RD->vbases_begin(),<br>
> +                                                e = RD->vbases_end();<br>
> +       i != e; ++i) {<br>
> +    const CXXRecordDecl *BaseDecl =  i->getType()->getAsCXXRecordDecl();<br>
> +    if (!HasVtordisp.count(BaseDecl) && RequiresVtordisp(HasVtordisp, BaseDecl))<br>
> +      HasVtordisp.insert(BaseDecl);<br>
> +  }<br>
> +<br>
> +  return HasVtordisp;<br>
> +}<br>
> +<br>
> +/// \brief Get or compute information about the layout of the specified record<br>
> +/// (struct/union/class), which indicates its size and field position<br>
> +/// information.<br>
> +const ASTRecordLayout *<br>
> +ASTContext::BuildMicrosoftASTRecordLayout(const RecordDecl *D) const {<br>
> +  MicrosoftRecordLayoutBuilder Builder(*this);<br>
> +  if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {<br>
> +    Builder.cxxLayout(RD);<br>
> +    return new (*this) ASTRecordLayout(<br>
> +        *this, Builder.Size, Builder.Alignment,<br>
> +        Builder.HasVFPtr && !Builder.PrimaryBase, Builder.HasVFPtr,<br>
> +        Builder.HasVBPtr && !Builder.SharedVBPtrBase, Builder.VBPtrOffset,<br>
> +        Builder.DataSize, Builder.FieldOffsets.data(),<br>
> +        Builder.FieldOffsets.size(), Builder.DataSize,<br>
> +        Builder.NonVirtualAlignment, CharUnits::Zero(), Builder.PrimaryBase,<br>
> +        false, Builder.AlignAfterVBases, Builder.Bases, Builder.VBases);<br>
> +  } else {<br>
> +    Builder.layout(D);<br>
> +    return new (*this) ASTRecordLayout(<br>
> +        *this, Builder.Size, Builder.Alignment, Builder.Size,<br>
> +        Builder.FieldOffsets.data(), Builder.FieldOffsets.size());<br>
> +  }<br>
> +}<br>
> +<br>
> /// getASTRecordLayout - Get or compute information about the layout of the<br>
> /// specified record (struct/union/class), which indicates its size and field<br>
> /// position information.<br>
> @@ -2362,27 +3068,15 @@ ASTContext::getASTRecordLayout(const Rec<br>
>   const ASTRecordLayout *Entry = ASTRecordLayouts[D];<br>
>   if (Entry) return *Entry;<br>
><br>
> -  const ASTRecordLayout *NewEntry;<br>
> +  const ASTRecordLayout *NewEntry = 0;<br>
><br>
> -  if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {<br>
> +  if (isMsLayout(D) && !D->getASTContext().getExternalSource()) {<br>
> +    NewEntry = BuildMicrosoftASTRecordLayout(D);<br>
> +  } else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {<br>
>     EmptySubobjectMap EmptySubobjects(*this, RD);<br>
>     RecordLayoutBuilder Builder(*this, &EmptySubobjects);<br>
>     Builder.Layout(RD);<br>
><br>
> -    // MSVC gives the vb-table pointer an alignment equal to that of<br>
> -    // the non-virtual part of the structure.  That's an inherently<br>
> -    // multi-pass operation.  If our first pass doesn't give us<br>
> -    // adequate alignment, try again with the specified minimum<br>
> -    // alignment.  This is *much* more maintainable than computing the<br>
> -    // alignment in advance in a separately-coded pass; it's also<br>
> -    // significantly more efficient in the common case where the<br>
> -    // vb-table doesn't need extra padding.<br>
> -    if (Builder.VBPtrOffset != CharUnits::fromQuantity(-1) &&<br>
> -        (Builder.VBPtrOffset % Builder.NonVirtualAlignment) != 0) {<br>
> -      Builder.resetWithTargetAlignment(Builder.NonVirtualAlignment);<br>
> -      Builder.Layout(RD);<br>
> -    }<br>
> -<br>
>     // In certain situations, we are allowed to lay out objects in the<br>
>     // tail-padding of base classes.  This is ABI-dependent.<br>
>     // FIXME: this should be stored in the record layout.<br>
> @@ -2394,11 +3088,12 @@ ASTContext::getASTRecordLayout(const Rec<br>
>       skipTailPadding ? Builder.getSize() : Builder.getDataSize();<br>
>     CharUnits NonVirtualSize =<br>
>       skipTailPadding ? DataSize : Builder.NonVirtualSize;<br>
> -<br>
>     NewEntry =<br>
>       new (*this) ASTRecordLayout(*this, Builder.getSize(),<br>
>                                   Builder.Alignment,<br>
>                                   Builder.HasOwnVFPtr,<br>
> +                                  RD->isDynamicClass(),<br>
> +                                  Builder.HasOwnVBPtr,<br>
>                                   Builder.VBPtrOffset,<br>
>                                   DataSize,<br>
>                                   Builder.FieldOffsets.data(),<br>
> @@ -2408,6 +3103,7 @@ ASTContext::getASTRecordLayout(const Rec<br>
>                                   EmptySubobjects.SizeOfLargestEmptySubobject,<br>
>                                   Builder.PrimaryBase,<br>
>                                   Builder.PrimaryBaseIsVirtual,<br>
> +                                  true,<br>
>                                   Builder.Bases, Builder.VBases);<br>
>   } else {<br>
>     RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0);<br>
> @@ -2564,16 +3260,19 @@ static void DumpCXXRecordLayout(raw_ostr<br>
>   IndentLevel++;<br>
><br>
>   const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();<br>
> -  bool HasVfptr = Layout.hasOwnVFPtr();<br>
> -  bool HasVbptr = Layout.getVBPtrOffset() != CharUnits::fromQuantity(-1);<br>
> +  bool HasOwnVFPtr = Layout.hasOwnVFPtr();<br>
> +  bool HasOwnVBPtr = Layout.hasOwnVBPtr();<br>
><br>
>   // Vtable pointer.<br>
> -  if (RD->isDynamicClass() && !PrimaryBase &&<br>
> -      !C.getTargetInfo().getCXXABI().isMicrosoft()) {<br>
> +  if (RD->isDynamicClass() && !PrimaryBase && !isMsLayout(RD)) {<br>
>     PrintOffset(OS, Offset, IndentLevel);<br>
>     OS << '(' << *RD << " vtable pointer)\n";<br>
> +  } else if (HasOwnVFPtr) {<br>
> +    PrintOffset(OS, Offset, IndentLevel);<br>
> +    // vfptr (for Microsoft C++ ABI)<br>
> +    OS << '(' << *RD << " vftable pointer)\n";<br>
>   }<br>
> -<br>
> +<br>
>   // Dump (non-virtual) bases<br>
>   for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),<br>
>          E = RD->bases_end(); I != E; ++I) {<br>
> @@ -2592,12 +3291,8 @@ static void DumpCXXRecordLayout(raw_ostr<br>
>                         /*IncludeVirtualBases=*/false);<br>
>   }<br>
><br>
> -  // vfptr and vbptr (for Microsoft C++ ABI)<br>
> -  if (HasVfptr) {<br>
> -    PrintOffset(OS, Offset, IndentLevel);<br>
> -    OS << '(' << *RD << " vftable pointer)\n";<br>
> -  }<br>
> -  if (HasVbptr) {<br>
> +  // vbptr (for Microsoft C++ ABI)<br>
> +  if (HasOwnVBPtr) {<br>
>     PrintOffset(OS, Offset + Layout.getVBPtrOffset(), IndentLevel);<br>
>     OS << '(' << *RD << " vbtable pointer)\n";<br>
>   }<br>
> @@ -2650,7 +3345,8 @@ static void DumpCXXRecordLayout(raw_ostr<br>
><br>
>   PrintIndentNoOffset(OS, IndentLevel - 1);<br>
>   OS << "[sizeof=" << Layout.getSize().getQuantity();<br>
> -  OS << ", dsize=" << Layout.getDataSize().getQuantity();<br>
> +  if (!isMsLayout(RD))<br>
> +    OS << ", dsize=" << Layout.getDataSize().getQuantity();<br>
>   OS << ", align=" << Layout.getAlignment().getQuantity() << '\n';<br>
><br>
>   PrintIndentNoOffset(OS, IndentLevel - 1);<br>
> @@ -2677,7 +3373,8 @@ void ASTContext::DumpRecordLayout(const<br>
>   OS << "\nLayout: ";<br>
>   OS << "<ASTRecordLayout\n";<br>
>   OS << "  Size:" << toBits(Info.getSize()) << "\n";<br>
> -  OS << "  DataSize:" << toBits(Info.getDataSize()) << "\n";<br>
> +  if (!isMsLayout(RD))<br>
> +    OS << "  DataSize:" << toBits(Info.getDataSize()) << "\n";<br>
>   OS << "  Alignment:" << toBits(Info.getAlignment()) << "\n";<br>
>   OS << "  FieldOffsets: [";<br>
>   for (unsigned i = 0, e = Info.getFieldCount(); i != e; ++i) {<br>
><br>
> Modified: cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp?rev=192494&r1=192493&r2=192494&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp?rev=192494&r1=192493&r2=192494&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp (original)<br>
> +++ cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp Fri Oct 11 15:19:00 2013<br>
> @@ -696,7 +696,7 @@ CGRecordLayoutBuilder::LayoutNonVirtualB<br>
>   }<br>
><br>
>   // Add a vb-table pointer if the layout insists.<br>
> -  if (Layout.getVBPtrOffset() != CharUnits::fromQuantity(-1)) {<br>
> +    if (Layout.hasOwnVBPtr()) {<br>
>     CharUnits VBPtrOffset = Layout.getVBPtrOffset();<br>
>     llvm::Type *Vbptr = llvm::Type::getInt32PtrTy(Types.getLLVMContext());<br>
>     AppendPadding(VBPtrOffset, getTypeAlignment(Vbptr));<br>
><br>
> Modified: cfe/trunk/lib/CodeGen/MicrosoftVBTables.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftVBTables.cpp?rev=192494&r1=192493&r2=192494&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftVBTables.cpp?rev=192494&r1=192493&r2=192494&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/CodeGen/MicrosoftVBTables.cpp (original)<br>
> +++ cfe/trunk/lib/CodeGen/MicrosoftVBTables.cpp Fri Oct 11 15:19:00 2013<br>
> @@ -54,10 +54,6 @@ void VBTableBuilder::enumerateVBTables(V<br>
>   }<br>
> }<br>
><br>
> -bool VBTableBuilder::hasVBPtr(const CXXRecordDecl *RD) {<br>
> -  const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);<br>
> -  return Layout.getVBPtrOffset().getQuantity() != -1;<br>
> -}<br>
><br>
> void VBTableBuilder::findUnambiguousPaths(const CXXRecordDecl *ReusingBase,<br>
>                                           BaseSubobject CurSubobject,<br>
> @@ -65,10 +61,11 @@ void VBTableBuilder::findUnambiguousPath<br>
>   size_t PathsStart = Paths.size();<br>
>   bool ReuseVBPtrFromBase = true;<br>
>   const CXXRecordDecl *CurBase = CurSubobject.getBase();<br>
> +  const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(CurBase);<br>
><br>
>   // If this base has a vbptr, then we've found a path.  These are not full<br>
>   // paths, so we don't use CXXBasePath.<br>
> -  if (hasVBPtr(CurBase)) {<br>
> +  if (Layout.hasOwnVBPtr()) {<br>
>     ReuseVBPtrFromBase = false;<br>
>     VBTablePath *Info = new VBTablePath(<br>
>       VBTableInfo(ReusingBase, CurSubobject, /*GV=*/0));<br>
> @@ -76,7 +73,6 @@ void VBTableBuilder::findUnambiguousPath<br>
>   }<br>
><br>
>   // Recurse onto any bases which themselves have virtual bases.<br>
> -  const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(CurBase);<br>
>   for (CXXRecordDecl::base_class_const_iterator I = CurBase->bases_begin(),<br>
>        E = CurBase->bases_end(); I != E; ++I) {<br>
>     const CXXRecordDecl *Base = I->getType()->getAsCXXRecordDecl();<br>
><br>
> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=192494&r1=192493&r2=192494&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=192494&r1=192493&r2=192494&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Oct 11 15:19:00 2013<br>
> @@ -11503,8 +11503,7 @@ Decl *Sema::ActOnIvar(Scope *S,<br>
><br>
>   if (BitWidth) {<br>
>     // 6.7.2.1p3, 6.7.2.1p4<br>
> -    BitWidth =<br>
> -        VerifyBitField(Loc, II, T, /*IsMsStruct=*/false, BitWidth).take();<br>
> +    BitWidth = VerifyBitField(Loc, II, T, /*IsMsStruct*/false, BitWidth).take();<br>
>     if (!BitWidth)<br>
>       D.setInvalidType();<br>
>   } else {<br>
><br>
> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=192494&r1=192493&r2=192494&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=192494&r1=192493&r2=192494&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Oct 11 15:19:00 2013<br>
> @@ -4451,6 +4451,13 @@ void Sema::CheckCompletedCXXClass(CXXRec<br>
>     }<br>
>   }<br>
><br>
> +  // Check to see if we're trying to lay out a struct using the ms_struct<br>
> +  // attribute that is dynamic.<br>
> +  if (Record->isMsStruct(Context) && Record->isDynamicClass()) {<br>
> +    Diag(Record->getLocation(), diag::warn_pragma_ms_struct_failed);<br>
> +    Record->dropAttr<MsStructAttr>();<br>
> +  }<br>
> +<br>
>   // Declare inheriting constructors. We do this eagerly here because:<br>
>   // - The standard requires an eager diagnostic for conflicting inheriting<br>
>   //   constructors from different classes.<br>
><br>
> Modified: cfe/trunk/test/CodeGen/pr2394.c<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/pr2394.c?rev=192494&r1=192493&r2=192494&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/pr2394.c?rev=192494&r1=192493&r2=192494&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/CodeGen/pr2394.c (original)<br>
> +++ cfe/trunk/test/CodeGen/pr2394.c Fri Oct 11 15:19:00 2013<br>
> @@ -1,4 +1,4 @@<br>
> -// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s<br>
> +// RUN: %clang_cc1 %s -triple i386-apple-darwin10 -emit-llvm -o - | FileCheck %s<br>
> struct __attribute((packed)) x {int a : 24;};<br>
> int a(struct x* g) {<br>
>   // CHECK: load i24<br>
><br>
> Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp?rev=192494&r1=192493&r2=192494&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp?rev=192494&r1=192493&r2=192494&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp (original)<br>
> +++ cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp Fri Oct 11 15:19:00 2013<br>
> @@ -156,7 +156,9 @@ C::C() {<br>
>   // CHECK-NEXT: %[[vbptr_off:.*]] = getelementptr inbounds i8* %[[this_i8]], i64 0<br>
>   // CHECK-NEXT: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to [2 x i32]**<br>
>   // CHECK-NEXT: store [2 x i32]* @"\01??_8C@constructors@@7B@", [2 x i32]** %[[vbptr]]<br>
> -  // CHECK-NEXT: bitcast %"struct.constructors::C"* %{{.*}} to %"struct.constructors::A"*<br>
> +  // CHECK-NEXT: bitcast %"struct.constructors::C"* %{{.*}} to i8*<br>
> +  // CHECK-NEXT: getelementptr inbounds i8* %{{.*}}, i64 4<br>
> +  // CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"*<br>
>   // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})<br>
>   // CHECK-NEXT: br label %[[SKIP_VBASES]]<br>
>   //<br>
> @@ -189,7 +191,9 @@ D::D() {<br>
>   // CHECK-NEXT: %[[vbptr_off:.*]] = getelementptr inbounds i8* %[[this_i8]], i64 0<br>
>   // CHECK-NEXT: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to [2 x i32]**<br>
>   // CHECK-NEXT: store [2 x i32]* @"\01??_8D@constructors@@7B@", [2 x i32]** %[[vbptr]]<br>
> -  // CHECK-NEXT: bitcast %"struct.constructors::D"* %{{.*}} to %"struct.constructors::A"*<br>
> +  // CHECK-NEXT: bitcast %"struct.constructors::D"* %{{.*}} to i8*<br>
> +  // CHECK-NEXT: getelementptr inbounds i8* %{{.*}}, i64 4<br>
> +  // CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"*<br>
>   // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})<br>
>   // CHECK-NEXT: br label %[[SKIP_VBASES]]<br>
>   //<br>
> @@ -217,7 +221,9 @@ E::E() {<br>
>   // CHECK-NEXT: %[[offs:.*]] = getelementptr inbounds i8* %[[this_i8]], i64 4<br>
>   // CHECK-NEXT: %[[vbptr_C:.*]] = bitcast i8* %[[offs]] to [2 x i32]**<br>
>   // CHECK-NEXT: store [2 x i32]* @"\01??_8E@constructors@@7BC@1@@", [2 x i32]** %[[vbptr_C]]<br>
> -  // CHECK-NEXT: bitcast %"struct.constructors::E"* %{{.*}} to %"struct.constructors::A"*<br>
> +  // CHECK-NEXT: bitcast %"struct.constructors::E"* %{{.*}} to i8*<br>
> +  // CHECK-NEXT: getelementptr inbounds i8* %{{.*}}, i64 4<br>
> +  // CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"*<br>
>   // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})<br>
>   // CHECK: call x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %{{.*}}, i32 0)<br>
>   // CHECK-NEXT: br label %[[SKIP_VBASES]]<br>
><br>
> Modified: cfe/trunk/test/Coverage/codegen-next.m<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Coverage/codegen-next.m?rev=192494&r1=192493&r2=192494&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Coverage/codegen-next.m?rev=192494&r1=192493&r2=192494&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/Coverage/codegen-next.m (original)<br>
> +++ cfe/trunk/test/Coverage/codegen-next.m Fri Oct 11 15:19:00 2013<br>
> @@ -1,5 +1,5 @@<br>
> -// RUN: %clang_cc1 -emit-llvm -fobjc-exceptions -o %t %s<br>
> -// RUN: %clang_cc1 -g -emit-llvm -fobjc-exceptions -o %t %s<br>
> +// RUN: %clang_cc1 -emit-llvm -fobjc-exceptions -triple x86_64-apple-darwin -o %t %s<br>
> +// RUN: %clang_cc1 -g -emit-llvm -fobjc-exceptions -triple x86_64-apple-darwin -o %t %s<br>
><br>
> // An error could be seen for targeting x86_64-win32;<br>
> //<br>
><br>
> Modified: cfe/trunk/test/PCH/rdar10830559.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/rdar10830559.cpp?rev=192494&r1=192493&r2=192494&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/rdar10830559.cpp?rev=192494&r1=192493&r2=192494&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/PCH/rdar10830559.cpp (original)<br>
> +++ cfe/trunk/test/PCH/rdar10830559.cpp Fri Oct 11 15:19:00 2013<br>
> @@ -8,7 +8,7 @@<br>
><br>
> // rdar://10830559<br>
><br>
> -#pragma ms_struct on<br>
> +//#pragma ms_struct on<br>
><br>
> template< typename T ><br>
> class Templated<br>
><br>
> Modified: cfe/trunk/test/Sema/ms_class_layout.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/ms_class_layout.cpp?rev=192494&r1=192493&r2=192494&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/ms_class_layout.cpp?rev=192494&r1=192493&r2=192494&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/Sema/ms_class_layout.cpp (original)<br>
> +++ cfe/trunk/test/Sema/ms_class_layout.cpp Fri Oct 11 15:19:00 2013<br>
> @@ -164,7 +164,7 @@ int main() {<br>
> // CHECK-NEXT:  0 |   (D vftable pointer)<br>
> // CHECK-NEXT:  8 |   double a<br>
><br>
> -// CHECK-NEXT: sizeof=16, dsize=16, align=8<br>
> +// CHECK-NEXT: sizeof=16, align=8<br>
> // CHECK-NEXT: nvsize=16, nvalign=8<br>
><br>
> // CHECK: %class.D = type { i32 (...)**, double }<br>
> @@ -173,7 +173,7 @@ int main() {<br>
> // CHECK-NEXT:  0 |   (B vftable pointer)<br>
> // CHECK-NEXT:  4 |   int b_field<br>
><br>
> -// CHECK-NEXT: sizeof=8, dsize=8, align=4<br>
> +// CHECK-NEXT: sizeof=8, align=4<br>
> // CHECK-NEXT: nvsize=8, nvalign=4<br>
><br>
> // CHECK: %class.B = type { i32 (...)**, i32 }<br>
> @@ -185,7 +185,7 @@ int main() {<br>
> // CHECK-NEXT:  8 |   int a_field<br>
> // CHECK-NEXT: 12 |   char one<br>
><br>
> -// CHECK-NEXT: sizeof=16, dsize=16, align=4<br>
> +// CHECK-NEXT: sizeof=16, align=4<br>
> // CHECK-NEXT: nvsize=16, nvalign=4<br>
><br>
> // CHECK:       0 | class C<br>
> @@ -207,7 +207,7 @@ int main() {<br>
> // CHECK-NEXT: 72 |     int a_field<br>
> // CHECK-NEXT: 76 |     char one<br>
><br>
> -// CHECK-NEXT: sizeof=80, dsize=80, align=8<br>
> +// CHECK-NEXT: sizeof=80, align=8<br>
> // CHECK-NEXT: nvsize=64, nvalign=8<br>
><br>
> // CHECK: %class.A = type { %class.B, i32, i8 }<br>
> @@ -237,10 +237,10 @@ int main() {<br>
> // CHECK-NEXT: 88 |       int a_field<br>
> // CHECK-NEXT: 92 |       char one<br>
><br>
> -// CHECK-NEXT: sizeof=80, dsize=80, align=8<br>
> +// CHECK-NEXT: sizeof=80, align=8<br>
> // CHECK-NEXT: nvsize=64, nvalign=8<br>
><br>
> -// CHECK: sizeof=96, dsize=96, align=8<br>
> +// CHECK: sizeof=96, align=8<br>
> // CHECK-NEXT: nvsize=96, nvalign=8<br>
><br>
> // CHECK: %struct.BaseStruct = type { double, float, %class.C }<br>
> @@ -267,18 +267,18 @@ int main() {<br>
> // CHECK-NEXT: 84 |           int b_field<br>
> // CHECK-NEXT: 88 |         int a_field<br>
> // CHECK-NEXT: 92 |         char one<br>
> -// CHECK-NEXT: sizeof=80, dsize=80, align=8<br>
> +// CHECK-NEXT: sizeof=80, align=8<br>
> // CHECK-NEXT: nvsize=64, nvalign=8<br>
><br>
> // CHECK: 96 |   int x<br>
> -// CHECK-NEXT: sizeof=104, dsize=104, align=8<br>
> +// CHECK-NEXT: sizeof=104, align=8<br>
> // CHECK-NEXT: nvsize=104, nvalign=8<br>
><br>
> // CHECK: %struct.DerivedStruct = type { %struct.BaseStruct, i32 }<br>
><br>
> // CHECK:      0 | struct G<br>
> // CHECK-NEXT: 0 |   int g_field<br>
> -// CHECK-NEXT: sizeof=4, dsize=4, align=4<br>
> +// CHECK-NEXT: sizeof=4, align=4<br>
> // CHECK-NEXT: nvsize=4, nvalign=4<br>
><br>
> // CHECK:       0 | struct H<br>
> @@ -288,7 +288,7 @@ int main() {<br>
> // CHECK-NEXT:  8 |   class D (virtual base)<br>
> // CHECK-NEXT:  8 |     (D vftable pointer)<br>
> // CHECK-NEXT: 16 |     double a<br>
> -// CHECK-NEXT: sizeof=24, dsize=24, align=8<br>
> +// CHECK-NEXT: sizeof=24, align=8<br>
> // CHECK-NEXT: nvsize=8, nvalign=4<br>
><br>
> // CHECK: %struct.H = type { %struct.G, i32*, %class.D }<br>
> @@ -300,7 +300,7 @@ int main() {<br>
> // CHECK-NEXT: 24 |   class D (virtual base)<br>
> // CHECK-NEXT: 24 |     (D vftable pointer)<br>
> // CHECK-NEXT: 32 |     double a<br>
> -// CHECK-NEXT: sizeof=40, dsize=40, align=8<br>
> +// CHECK-NEXT: sizeof=40, align=8<br>
> // CHECK-NEXT: nvsize=24, nvalign=8<br>
><br>
> // CHECK: %struct.I = type { i32 (...)**, [4 x i8], i32*, double, %class.D }<br>
> @@ -308,12 +308,12 @@ int main() {<br>
><br>
> // CHECK:       0 | struct L<br>
> // CHECK-NEXT:  0 |   int l<br>
> -// CHECK-NEXT: sizeof=4, dsize=4, align=4<br>
> +// CHECK-NEXT: sizeof=4, align=4<br>
> // CHECK-NEXT: nvsize=4, nvalign=4<br>
><br>
> // CHECK:       0 | struct K<br>
> // CHECK-NEXT:  0 |   int k<br>
> -// CHECK-NEXT: sizeof=4, dsize=4, align=4<br>
> +// CHECK-NEXT: sizeof=4, align=4<br>
> // CHECK-NEXT: nvsize=4, nvalign=4<br>
><br>
> // CHECK:       0 | struct M<br>
> @@ -321,42 +321,42 @@ int main() {<br>
> // CHECK-NEXT:  4 |   int m<br>
> // CHECK-NEXT:  8 |   struct K (virtual base)<br>
> // CHECK-NEXT:  8 |     int k<br>
> -// CHECK-NEXT: sizeof=12, dsize=12, align=4<br>
> +// CHECK-NEXT: sizeof=12, align=4<br>
><br>
> //CHECK: %struct.M = type { i32*, i32, %struct.K }<br>
> //CHECK: %struct.M.base = type { i32*, i32 }<br>
><br>
> // CHECK:       0 | struct N<br>
> +// CHECK-NEXT:  0 |   (N vftable pointer)<br>
> // CHECK-NEXT:  4 |   struct L (base)<br>
> // CHECK-NEXT:  4 |     int l<br>
> // CHECK-NEXT:  8 |   struct M (base)<br>
> // CHECK-NEXT:  8 |     (M vbtable pointer)<br>
> // CHECK-NEXT: 12 |     int m<br>
> -// CHECK-NEXT:  0 |   (N vftable pointer)<br>
> // CHECK-NEXT: 16 |   struct K (virtual base)<br>
> // CHECK-NEXT: 16 |     int k<br>
> -// CHECK-NEXT: sizeof=20, dsize=20, align=4<br>
> +// CHECK-NEXT: sizeof=20, align=4<br>
> // CHECK-NEXT: nvsize=16, nvalign=4<br>
><br>
> //CHECK: %struct.N = type { i32 (...)**, %struct.L, %struct.M.base, %struct.K }<br>
><br>
> -// FIXME: MSVC place struct H at offset 8.<br>
> // CHECK:       0 | struct O<br>
> -// CHECK-NEXT:  4 |   struct H (base)<br>
> -// CHECK-NEXT:  4 |     struct G (base)<br>
> -// CHECK-NEXT:  4 |       int g_field<br>
> -// CHECK-NEXT:  8 |     (H vbtable pointer)<br>
> -// CHECK-NEXT: 12 |   struct G (base)<br>
> -// CHECK-NEXT: 12 |     int g_field<br>
> // CHECK-NEXT:  0 |   (O vftable pointer)<br>
> -// CHECK-NEXT: 16 |   class D (virtual base)<br>
> -// CHECK-NEXT: 16 |     (D vftable pointer)<br>
> -// CHECK-NEXT: 24 |     double a<br>
> -// CHECK-NEXT: sizeof=32, dsize=32, align=8<br>
> -// CHECK-NEXT: nvsize=16, nvalign=4<br>
> +// CHECK-NEXT:  8 |   struct H (base)<br>
> +// CHECK-NEXT:  8 |     struct G (base)<br>
> +// CHECK-NEXT:  8 |       int g_field<br>
> +// CHECK-NEXT: 12 |     (H vbtable pointer)<br>
> +// CHECK-NEXT: 16 |   struct G (base)<br>
> +// CHECK-NEXT: 16 |     int g_field<br>
> +// CHECK-NEXT: 24 |   class D (virtual base)<br>
> +// CHECK-NEXT: 24 |     (D vftable pointer)<br>
> +// CHECK-NEXT: 32 |     double a<br>
> +// CHECK-NEXT:    | [sizeof=40, align=8<br>
> +// CHECK-NEXT:    |  nvsize=24, nvalign=8]<br>
> +<br>
> +// CHECK: struct.O = type { i32 (...)**, [4 x i8], %struct.H.base, %struct.G, [4 x i8], %class.D }<br>
> +// CHECK: struct.O.base = type { i32 (...)**, [4 x i8], %struct.H.base, %struct.G, [4 x i8] }<br>
><br>
> -//CHECK: %struct.O = type { i32 (...)**, %struct.H.base, %struct.G, %class.D }<br>
> -//CHECK: %struct.O.base = type { i32 (...)**, %struct.H.base, %struct.G }<br>
><br>
> // CHECK:       0 | struct P<br>
> // CHECK-NEXT:  0 |   struct M (base)<br>
> @@ -367,20 +367,20 @@ int main() {<br>
> // CHECK-NEXT: 12 |     int k<br>
> // CHECK-NEXT: 16 |   struct L (virtual base)<br>
> // CHECK-NEXT: 16 |     int l<br>
> -// CHECK-NEXT: sizeof=20, dsize=20, align=4<br>
> +// CHECK-NEXT: sizeof=20, align=4<br>
> // CHECK-NEXT: nvsize=12, nvalign=4<br>
><br>
> //CHECK: %struct.P = type { %struct.M.base, i32, %struct.K, %struct.L }<br>
><br>
> // CHECK:       0 | struct R (empty)<br>
> -// CHECK-NEXT:  sizeof=1, dsize=0, align=1<br>
> +// CHECK-NEXT:  sizeof=1, align=1<br>
> // CHECK-NEXT:  nvsize=0, nvalign=1<br>
><br>
> //CHECK: %struct.R = type { i8 }<br>
><br>
> // CHECK:       0 | struct f<br>
> // CHECK-NEXT:  0 |   (f vftable pointer)<br>
> -// CHECK-NEXT: sizeof=4, dsize=4, align=4<br>
> +// CHECK-NEXT: sizeof=4, align=4<br>
> // CHECK-NEXT: nvsize=4, nvalign=4<br>
><br>
> // CHECK:       0 | struct s<br>
> @@ -390,12 +390,12 @@ int main() {<br>
> // CHECK-NEXT: 12 |   (vtordisp for vbase f)<br>
> // CHECK-NEXT: 16 |   struct f (virtual base)<br>
> // CHECK-NEXT: 16 |     (f vftable pointer)<br>
> -// CHECK-NEXT: sizeof=20, dsize=20, align=4<br>
> +// CHECK-NEXT: sizeof=20, align=4<br>
> // CHECK-NEXT: nvsize=12, nvalign=4<br>
><br>
> // CHECK:       0 | class IA<br>
> // CHECK-NEXT:  0 |   (IA vftable pointer)<br>
> -// CHECK-NEXT:  sizeof=4, dsize=4, align=4<br>
> +// CHECK-NEXT:  sizeof=4, align=4<br>
> // CHECK-NEXT:  nvsize=4, nvalign=4<br>
><br>
> // CHECK:       0 | class ICh<br>
> @@ -404,7 +404,7 @@ int main() {<br>
> // CHECK-NEXT:  8 |   (vtordisp for vbase IA)<br>
> // CHECK-NEXT: 12 |   class IA (virtual base)<br>
> // CHECK-NEXT: 12 |     (IA vftable pointer)<br>
> -// CHECK-NEXT: sizeof=16, dsize=16, align=4<br>
> +// CHECK-NEXT: sizeof=16, align=4<br>
> // CHECK-NEXT: nvsize=8, nvalign=4<br>
><br>
> // CHECK:       0 | struct sd<br>
> @@ -424,7 +424,7 @@ int main() {<br>
> // CHECK-NEXT: 40 |   class ICh (virtual base)<br>
> // CHECK-NEXT: 40 |     (ICh vftable pointer)<br>
> // CHECK-NEXT: 44 |     (ICh vbtable pointer)<br>
> -// CHECK-NEXT: sizeof=48, dsize=48, align=4<br>
> +// CHECK-NEXT: sizeof=48, align=4<br>
> // CHECK-NEXT: nvsize=12, nvalign=4<br>
><br>
> // CHECK: %struct.f = type { i32 (...)** }<br>
> @@ -435,14 +435,14 @@ int main() {<br>
><br>
> // CHECK:       0 | struct AV<br>
> // CHECK-NEXT:  0 |   (AV vftable pointer)<br>
> -// CHECK-NEXT: sizeof=4, dsize=4, align=4<br>
> +// CHECK-NEXT: sizeof=4, align=4<br>
> // CHECK-NEXT: nvsize=4, nvalign=4<br>
><br>
><br>
> // CHECK:       0 | struct BV<br>
> // CHECK-NEXT:  0 |   struct AV (primary base)<br>
> // CHECK-NEXT:  0 |     (AV vftable pointer)<br>
> -// CHECK-NEXT: sizeof=4, dsize=4, align=4<br>
> +// CHECK-NEXT: sizeof=4, align=4<br>
> // CHECK-NEXT: nvsize=4, nvalign=4<br>
><br>
><br>
> @@ -452,7 +452,7 @@ int main() {<br>
> // CHECK-NEXT:  8 |   struct BV (virtual base)<br>
> // CHECK-NEXT:  8 |     struct AV (primary base)<br>
> // CHECK-NEXT:  8 |       (AV vftable pointer)<br>
> -// CHECK-NEXT: sizeof=12, dsize=12, align=4<br>
> +// CHECK-NEXT: sizeof=12, align=4<br>
> // CHECK-NEXT: nvsize=4, nvalign=4<br>
><br>
> // CHECK: %struct.AV = type { i32 (...)** }<br>
> @@ -464,7 +464,7 @@ int main() {<br>
> // CHECK-NEXT:  0 |   struct BV (primary base)<br>
> // CHECK-NEXT:  0 |     struct AV (primary base)<br>
> // CHECK-NEXT:  0 |       (AV vftable pointer)<br>
> -// CHECK-NEXT: sizeof=4, dsize=4, align=4<br>
> +// CHECK-NEXT: sizeof=4, align=4<br>
> // CHECK-NEXT: nvsize=4, nvalign=4<br>
><br>
> // CHECK: %struct.DV = type { %struct.BV }<br>
> @@ -480,14 +480,14 @@ int main() {<br>
> // CHECK-NEXT: 12 |   struct BV (virtual base)<br>
> // CHECK-NEXT: 12 |     struct AV (primary base)<br>
> // CHECK-NEXT: 12 |       (AV vftable pointer)<br>
> -// CHECK-NEXT: sizeof=16, dsize=16, align=4<br>
> +// CHECK-NEXT: sizeof=16, align=4<br>
> // CHECK-NEXT: nvsize=8, nvalign=4<br>
><br>
> // CHECK: %struct.EV = type { %struct.DV, %struct.CV.base, [4 x i8], %struct.BV }<br>
> // CHECK: %struct.EV.base = type { %struct.DV, %struct.CV.base }<br>
><br>
> // Overriding a method means that all the vbases containing that<br>
> -// method need a vtordisp.<br>
> +// method need a vtordisp.  Note: this code will cause an error in cl.exe.<br>
> namespace test1 {<br>
>   struct A { virtual void foo(); };<br>
>   struct B : A {};<br>
> @@ -503,6 +503,6 @@ namespace test1 {<br>
> // CHECK-NEXT:  16 |   struct test1::B (virtual base)<br>
> // CHECK-NEXT:  16 |     struct test1::A (primary base)<br>
> // CHECK-NEXT:  16 |       (A vftable pointer)<br>
> -// CHECK-NEXT:  sizeof=20, dsize=20, align=4<br>
> +// CHECK-NEXT:  sizeof=20, align=4<br>
> // CHECK-NEXT:  nvsize=4, nvalign=4<br>
> }<br>
><br>
> Modified: cfe/trunk/test/SemaCXX/ms_struct.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/ms_struct.cpp?rev=192494&r1=192493&r2=192494&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/ms_struct.cpp?rev=192494&r1=192493&r2=192494&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/SemaCXX/ms_struct.cpp (original)<br>
> +++ cfe/trunk/test/SemaCXX/ms_struct.cpp Fri Oct 11 15:19:00 2013<br>
> @@ -6,7 +6,6 @@<br>
> struct A {<br>
>   unsigned long a:4;<br>
>   unsigned char b;<br>
> -  A();<br>
> };<br>
><br>
> struct B : public A {<br>
><br>
><br>
> _______________________________________________<br>
> cfe-commits mailing list<br>
> <a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</div></div></blockquote></div><br></div>