Index: include/clang/AST/RecordLayout.h
===================================================================
--- include/clang/AST/RecordLayout.h	(revision 154089)
+++ include/clang/AST/RecordLayout.h	(working copy)
@@ -16,6 +16,7 @@
 
 #include "llvm/Support/DataTypes.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
 #include "clang/AST/CharUnits.h"
 #include "clang/AST/DeclCXX.h"
 
@@ -33,6 +34,22 @@
 /// ObjCInterfaceDecl. FIXME - Find appropriate name.
 /// These objects are managed by ASTContext.
 class ASTRecordLayout {
+public:
+  struct VBaseInfo {
+    CharUnits VBaseOffset;
+    bool IsVtordispPresent;
+
+    VBaseInfo() :
+     IsVtordispPresent(false) {}
+
+    VBaseInfo(CharUnits VBaseOffset, bool IsVtordispNeed) :
+     VBaseOffset(VBaseOffset), IsVtordispPresent(IsVtordispNeed) {}
+  };
+
+  typedef llvm::DenseMap<const CXXRecordDecl *, VBaseInfo>
+    VBaseOffsetsMapTy;
+
+private:
   /// Size - Size of record in characters.
   CharUnits Size;
 
@@ -79,7 +96,7 @@
     BaseOffsetsMapTy BaseOffsets;
 
     /// VBaseOffsets - Contains a map from vbase classes to their offset.
-    BaseOffsetsMapTy VBaseOffsets;
+    VBaseOffsetsMapTy VBaseOffsets;
   };
 
   /// CXXInfo - If the record layout is for a C++ record, this will have
@@ -104,7 +121,7 @@
                   const CXXRecordDecl *PrimaryBase,
                   bool IsPrimaryBaseVirtual,
                   const BaseOffsetsMapTy& BaseOffsets,
-                  const BaseOffsetsMapTy& VBaseOffsets);
+                  const VBaseOffsetsMapTy& VBaseOffsets);
 
   ~ASTRecordLayout() {}
 
@@ -180,7 +197,7 @@
     assert(CXXInfo && "Record layout does not have C++ specific info!");
     assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!");
 
-    return CXXInfo->VBaseOffsets[VBase];
+    return CXXInfo->VBaseOffsets[VBase].VBaseOffset;
   }
 
   /// getBaseClassOffsetInBits - Get the offset, in bits, for the given
@@ -221,6 +238,11 @@
     assert(CXXInfo && "Record layout does not have C++ specific info!");
     return CXXInfo->VBPtrOffset;
   }
+
+  const VBaseOffsetsMapTy &getVBaseOffsetsMap() const {
+    assert(CXXInfo && "Record layout does not have C++ specific info!");
+    return CXXInfo->VBaseOffsets;
+  }
 };
 
 }  // end namespace clang
Index: lib/AST/RecordLayout.cpp
===================================================================
--- lib/AST/RecordLayout.cpp	(revision 154089)
+++ lib/AST/RecordLayout.cpp	(working copy)
@@ -53,7 +53,7 @@
                                  const CXXRecordDecl *PrimaryBase,
                                  bool IsPrimaryBaseVirtual,
                                  const BaseOffsetsMapTy& BaseOffsets,
-                                 const BaseOffsetsMapTy& VBaseOffsets)
+                                 const VBaseOffsetsMapTy& VBaseOffsets)
   : Size(size), DataSize(datasize), FieldOffsets(0), Alignment(alignment),
     FieldCount(fieldcount), CXXInfo(new (Ctx) CXXRecordLayoutInfo)
 {
Index: lib/AST/RecordLayoutBuilder.cpp
===================================================================
--- lib/AST/RecordLayoutBuilder.cpp	(revision 154089)
+++ lib/AST/RecordLayoutBuilder.cpp	(working copy)
@@ -612,7 +612,7 @@
   BaseOffsetsMapTy Bases;
 
   // VBases - virtual base classes and their offsets in the record.
-  BaseOffsetsMapTy VBases;
+  ASTRecordLayout::VBaseOffsetsMapTy VBases;
 
   /// IndirectPrimaryBases - Virtual base classes, direct or indirect, that are
   /// primary base classes for some other direct or indirect base class.
@@ -725,15 +725,26 @@
                                     CharUnits Offset);
 
   bool needsVFTable(const CXXRecordDecl *RD) const;
-  bool hasNewVirtualFunction(const CXXRecordDecl *RD) const;
+  bool hasNewVirtualFunction(const CXXRecordDecl *RD,
+                             bool IgnoreDestructor = false) const;
   bool isPossiblePrimaryBase(const CXXRecordDecl *Base) const;
 
+  typedef llvm::SmallPtrSet<const CXXRecordDecl*, 4> ClassSetTy;
+
+  bool hasAnyNonVirtualBase(const CXXRecordDecl *RD, 
+                            const ClassSetTy &Overridden,
+                            const ClassSetTy &Vtordisps);
+
+  void fillVtordisps(const CXXRecordDecl *RD, 
+                     ClassSetTy &VtordispVBases);
+
   /// LayoutVirtualBases - Lays out all the virtual bases.
   void LayoutVirtualBases(const CXXRecordDecl *RD,
                           const CXXRecordDecl *MostDerivedClass);
 
   /// LayoutVirtualBase - Lays out a single virtual base.
-  void LayoutVirtualBase(const BaseSubobjectInfo *Base);
+  void LayoutVirtualBase(const BaseSubobjectInfo *Base, 
+                         bool IsVtordispNeed = false);
 
   /// LayoutBase - Will lay out a base and return the offset where it was
   /// placed, in chars.
@@ -1142,7 +1153,7 @@
       assert(!VBases.count(Info->PrimaryVirtualBaseInfo->Class) && 
              "primary vbase offset already exists!");
       VBases.insert(std::make_pair(Info->PrimaryVirtualBaseInfo->Class,
-                                   Offset));
+                                   ASTRecordLayout::VBaseInfo(Offset, false)));
 
       // Traverse the primary virtual base.
       AddPrimaryVirtualBaseOffsets(Info->PrimaryVirtualBaseInfo, Offset);
@@ -1193,19 +1204,117 @@
   return hasNewVirtualFunction(RD);
 }
 
+bool 
+RecordLayoutBuilder::hasAnyNonVirtualBase(const CXXRecordDecl *RD, 
+                                          const ClassSetTy &Overridden,
+                                          const ClassSetTy &Vtordisps) {
+  for (ClassSetTy::const_iterator I = Overridden.begin(),
+       E = Overridden.end(); I != E; ++I) {
+    const CXXRecordDecl *OV = *I;
+    if (RD->isDerivedFrom(OV) && 
+        !RD->isVirtuallyDerivedFrom(const_cast<CXXRecordDecl *>(OV)))
+      return true;
+  }
+
+  return false;
+}
+
+void RecordLayoutBuilder::fillVtordisps(const CXXRecordDecl *RD,
+                                        ClassSetTy &VtordispVBases) {
+  if (!RD->getNumVBases())
+    return;
+
+  // As an optimization, remember the set of
+  // virtual bases that we haven't decided yet.
+  ClassSetTy UndecidedVBases;
+  for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
+       E = RD->vbases_end(); I != E; ++I) {
+    const CXXRecordDecl *VBase = I->getType()->getAsCXXRecordDecl();
+
+    UndecidedVBases.insert(VBase);
+  }
+
+  for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+       E = RD->bases_end(); I != E; ++I) {
+    const CXXRecordDecl *BaseDecl = I->getType()->getAsCXXRecordDecl();
+    const ASTRecordLayout &BaseLayout = Context.getASTRecordLayout(BaseDecl);
+
+    for (ASTRecordLayout::VBaseOffsetsMapTy::const_iterator
+         VI = BaseLayout.getVBaseOffsetsMap().begin(), 
+         VE = BaseLayout.getVBaseOffsetsMap().end(); VI != VE; ++VI) {
+      if (!VI->second.IsVtordispPresent)
+        continue;
+      if (!UndecidedVBases.erase(VI->first)) 
+        continue;
+
+      VtordispVBases.insert(VI->first);
+
+      if (UndecidedVBases.empty()) 
+        return;
+    }
+  }
+
+  // Otherwise, a virtual base requires a vtor disp if any the non-destructor
+  // virtual methods declared in this class directly override a method provided
+  // by that virtual base.
+
+  // Collect the set of bases directly overridden by any method in this class.
+  // It's possible that some of these classes won't be virtual bases, or won't be
+  // provided by virtual bases, or won't be virtual bases in the overridden
+  // instance but are virtual bases elsewhere.  Only the last matters for what
+  // we're doing, and we can ignore those:  if we don't directly override
+  // a method provided by a virtual copy of a base class, but we do directly
+  // override a method provided by a non-virtual copy of that base class,
+  // then we must indirectly override the method provided by the virtual base,
+  // and so we should already have collected it in the loop above.
+  ClassSetTy OverriddenBases;
+  for (CXXRecordDecl::method_iterator M = RD->method_begin(),
+       E = RD->method_end(); M != E; ++M) {
+    if (!M->isVirtual() || isa<CXXDestructorDecl>(*M)) 
+      continue;
+    
+    for (CXXMethodDecl::method_iterator I = M->begin_overridden_methods(),
+          E = M->end_overridden_methods(); I != E; ++I) {
+      const CXXRecordDecl *OverriddenBase = (*I)->getParent();
+      const CXXMethodDecl *OverriddenMD = *I;
+
+      // As an optimization, check immediately whether we're overriding
+      // something from the undecided set.
+      if (!OverriddenMD->size_overridden_methods()) {
+        if (UndecidedVBases.erase(OverriddenBase)) {
+          VtordispVBases.insert(OverriddenBase);
+          if (UndecidedVBases.empty()) return;
+          continue;
+        }
+      }
+      // Otherwise, just collect it.
+      OverriddenBases.insert(OverriddenBase);
+    }
+  }
+
+  // Walk the undecided v-bases and check whether they (non-virtually)
+  // provide any of the overridden bases.
+  for (ClassSetTy::const_iterator I = UndecidedVBases.begin(),
+       E = UndecidedVBases.end(); I != E; ++I) {
+    if (hasAnyNonVirtualBase(*I, OverriddenBases, VtordispVBases))
+      VtordispVBases.insert(*I);
+  }
+}
+
 /// hasNewVirtualFunction - Does the given polymorphic class declare a
 /// virtual function that does not override a method from any of its
 /// base classes?
 bool 
-RecordLayoutBuilder::hasNewVirtualFunction(const CXXRecordDecl *RD) const {
-  assert(RD->isPolymorphic());
+RecordLayoutBuilder::hasNewVirtualFunction(const CXXRecordDecl *RD, 
+                                           bool IgnoreDestructor) const {
   if (!RD->getNumBases()) 
     return true;
 
   for (CXXRecordDecl::method_iterator method = RD->method_begin();
        method != RD->method_end();
        ++method) {
-    if (method->isVirtual() && !method->size_overridden_methods()) {
+    if (method->isVirtual() && !method->size_overridden_methods() &&
+        !(IgnoreDestructor && method->getKind() == Decl::CXXDestructor)) {
       return true;
     }
   }
@@ -1232,9 +1341,14 @@
 
   // If it has no virtual bases, then everything is at a static offset.
   if (!Base->getNumVBases()) return true;
+  
+  const ASTRecordLayout &Layout = Context.getASTRecordLayout(Base);
 
+  // If class has primary, then it can be primary base.
+  if (Layout.getPrimaryBase()) return true;
+
   // Okay, just ask the base class's layout.
-  return (Context.getASTRecordLayout(Base).getVFPtrOffset()
+  return (Layout.getVFPtrOffset()
             != CharUnits::fromQuantity(-1));
 }
 
@@ -1288,23 +1402,36 @@
 }
 
 void RecordLayoutBuilder::MSLayoutVirtualBases(const CXXRecordDecl *RD) {
-
   if (!RD->getNumVBases())
     return;
 
+  ClassSetTy VtordispVBases;
+  fillVtordisps(RD, VtordispVBases);
+  
   // This is substantially simplified because there are no virtual
   // primary bases.
   for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
        E = RD->vbases_end(); I != E; ++I) {
     const CXXRecordDecl *BaseDecl = I->getType()->getAsCXXRecordDecl();
     const BaseSubobjectInfo *BaseInfo = VirtualBaseInfo.lookup(BaseDecl);
+    bool VtordispIsNeed = false;
     assert(BaseInfo && "Did not find virtual base info!");
     
-    LayoutVirtualBase(BaseInfo);
+    if (VtordispVBases.count(BaseDecl)) {
+      CharUnits IntSize = 
+        CharUnits::fromQuantity(Context.getTargetInfo().getIntWidth() / 8);
+
+      setSize(getSize() + IntSize);
+      setDataSize(getSize());
+      VtordispIsNeed = true;
+    }
+
+    LayoutVirtualBase(BaseInfo, VtordispIsNeed);
   }
 }
 
-void RecordLayoutBuilder::LayoutVirtualBase(const BaseSubobjectInfo *Base) {
+void RecordLayoutBuilder::LayoutVirtualBase(const BaseSubobjectInfo *Base,
+                                            bool IsVtordispNeed) {
   assert(!Base->Derived && "Trying to lay out a primary virtual base!");
   
   // Layout the base.
@@ -1312,9 +1439,11 @@
 
   // Add its base class offset.
   assert(!VBases.count(Base->Class) && "vbase offset already exists!");
-  VBases.insert(std::make_pair(Base->Class, Offset));
-  
-  AddPrimaryVirtualBaseOffsets(Base, Offset);
+  VBases.insert(std::make_pair(Base->Class, 
+                       ASTRecordLayout::VBaseInfo(Offset, IsVtordispNeed)));
+
+  if (!isMicrosoftCXXABI())
+    AddPrimaryVirtualBaseOffsets(Base, Offset);
 }
 
 CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
@@ -1461,8 +1590,8 @@
                                  Context.getTargetInfo().getCharAlign()));
   NonVirtualAlignment = Alignment;
 
-  if (isMicrosoftCXXABI() &&
-      NonVirtualSize != NonVirtualSize.RoundUpToAlignment(Alignment)) {
+  if (isMicrosoftCXXABI()) {
+    if (NonVirtualSize != NonVirtualSize.RoundUpToAlignment(Alignment)) {
     CharUnits AlignMember = 
       NonVirtualSize.RoundUpToAlignment(Alignment) - NonVirtualSize;
 
@@ -1472,9 +1601,9 @@
     NonVirtualSize = Context.toCharUnitsFromBits(
                              llvm::RoundUpToAlignment(getSizeInBits(),
                              Context.getTargetInfo().getCharAlign()));
+    }
 
     MSLayoutVirtualBases(RD);
-
   } else {
     // Lay out the virtual bases and add the primary virtual base offsets.
     LayoutVirtualBases(RD, RD);
@@ -2438,6 +2567,8 @@
     return;
 
   // Dump virtual bases.
+  const ASTRecordLayout::VBaseOffsetsMapTy &vtordisps = 
+    Layout.getVBaseOffsetsMap();
   for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
          E = RD->vbases_end(); I != E; ++I) {
     assert(I->isVirtual() && "Found non-virtual class!");
@@ -2445,6 +2576,12 @@
       cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
 
     CharUnits VBaseOffset = Offset + Layout.getVBaseClassOffset(VBase);
+
+    if (vtordisps.find(VBase)->second.IsVtordispPresent) {
+      PrintOffset(OS, VBaseOffset - CharUnits::fromQuantity(4), IndentLevel);
+      OS << "(vtordisp for vbase " << *VBase << ")\n";
+    }
+
     DumpCXXRecordLayout(OS, VBase, C, VBaseOffset, IndentLevel,
                         VBase == PrimaryBase ?
                         "(primary virtual base)" : "(virtual base)",
Index: test/Sema/ms_class_layout.cpp
===================================================================
--- test/Sema/ms_class_layout.cpp	(revision 154089)
+++ test/Sema/ms_class_layout.cpp	(working copy)
@@ -97,6 +97,48 @@
 
 struct R {};
 
+class IA {
+public:
+  virtual ~IA(){}
+  virtual void ia() = 0;
+};
+
+class ICh : public virtual IA {
+public:
+  virtual ~ICh(){}
+  virtual void ia(){}
+  virtual void iCh(){}
+};
+
+struct f {
+  virtual int asd() {return -90;}
+};
+
+struct s : public virtual f {
+  virtual ~s(){}
+  int r;
+  virtual int asd() {return -9;}
+};
+
+struct sd : virtual s, virtual ICh {
+  virtual ~sd(){}
+  int q;
+  char y;
+  virtual int asd() {return -1;}
+};
+struct AV { 
+  virtual void foo(); 
+};
+struct BV : AV { 
+};
+struct CV : virtual BV { 
+  CV(); 
+  virtual void foo(); 
+};
+struct DV : BV {
+};
+struct EV : CV, DV {
+};
 #pragma pack(pop)
 
 // This needs only for building layouts. 
@@ -113,6 +155,8 @@
   O* o;
   P* p;
   R* r;
+  sd *h;
+  EV *j;
   return 0;
 }
 
@@ -333,3 +377,111 @@
 // 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: nvsize=4, nvalign=4
+
+// CHECK:       0 | struct s
+// CHECK-NEXT:  0 |   (s vftable pointer)
+// CHECK-NEXT:  4 |   (s vbtable pointer)
+// CHECK-NEXT:  8 |   int r
+// 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: nvsize=12, nvalign=4
+
+// CHECK:       0 | class IA
+// CHECK-NEXT:  0 |   (IA vftable pointer)
+// CHECK-NEXT:  sizeof=4, dsize=4, align=4
+// CHECK-NEXT:  nvsize=4, nvalign=4
+	
+// CHECK:       0 | class ICh
+// CHECK-NEXT:  0 |   (ICh vftable pointer)
+// CHECK-NEXT:  4 |   (ICh vbtable pointer)
+// 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: nvsize=8, nvalign=4
+
+// CHECK:       0 | struct sd
+// CHECK-NEXT:  0 |   (sd vbtable pointer)
+// CHECK-NEXT:  4 |   int q
+// CHECK-NEXT:  8 |   char y
+// CHECK-NEXT: 12 |   (vtordisp for vbase f)
+// CHECK-NEXT: 16 |   struct f (virtual base)
+// CHECK-NEXT: 16 |     (f vftable pointer)
+// CHECK-NEXT: 20 |   struct s (virtual base)
+// CHECK-NEXT: 20 |     (s vftable pointer)
+// CHECK-NEXT: 24 |     (s vbtable pointer)
+// CHECK-NEXT: 28 |     int r
+// CHECK-NEXT: 32 |   (vtordisp for vbase IA)
+// CHECK-NEXT: 36 |   class IA (virtual base)
+// CHECK-NEXT: 36 |     (IA vftable pointer)
+// 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: nvsize=12, nvalign=4
+
+// CHECK: %struct.f = type { i32 (...)** }
+// CHECK: %struct.s = type { i32 (...)**, i32*, i32, [4 x i8], %struct.f }
+// CHECK: %class.IA = type { i32 (...)** }
+// CHECK: %class.ICh = type { i32 (...)**, i32*, [4 x i8], %class.IA }
+// CHECK: %struct.sd = type { i32*, i32, i8, [7 x i8], %struct.f, %struct.s.base, [4 x i8], %class.IA, %class.ICh.base }
+
+// CHECK:       0 | struct AV
+// CHECK-NEXT:  0 |   (AV vftable pointer)
+// CHECK-NEXT: sizeof=4, dsize=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: nvsize=4, nvalign=4
+
+
+// CHECK:       0 | struct CV
+// CHECK-NEXT:  0 |   (CV vbtable pointer)
+// CHECK-NEXT:  4 |   (vtordisp for vbase BV)
+// 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: nvsize=4, nvalign=4
+
+// CHECK: %struct.AV = type { i32 (...)** }
+// CHECK: %struct.BV = type { %struct.AV }
+// CHECK: %struct.CV = type { i32*, [4 x i8], %struct.BV }
+// CHECK: %struct.CV.base = type { i32* }
+
+// CHECK:       0 | struct DV
+// 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: nvsize=4, nvalign=4
+
+// CHECK: %struct.DV = type { %struct.BV }
+
+// CHECK:       0 | struct EV
+// CHECK-NEXT:  4 |   struct CV (base)
+// CHECK-NEXT:  4 |     (CV vbtable pointer)
+// CHECK-NEXT:  0 |   struct DV (primary base)
+// CHECK-NEXT:  0 |     struct BV (primary base)
+// CHECK-NEXT:  0 |       struct AV (primary base)
+// CHECK-NEXT:  0 |         (AV vftable pointer)
+// CHECK-NEXT:  8 |   (vtordisp for vbase BV)
+// 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: 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 }
