r191523 - Abstract out the emission of vtables, add basic support for vtable emission when using -cxx-abi microsoft

Reid Kleckner rnk at google.com
Fri Sep 27 10:12:49 PDT 2013


Rather than doing a full -Asserts build, I strip the LLVM IR like so for
faster iteration:

// RUN: %clang_cc1 ... | opt -S -o - -strip | FileCheck %s ...


On Fri, Sep 27, 2013 at 9:57 AM, Timur Iskhodzhanov <timurrrr at google.com>wrote:

> Yep, already launched a build without asserts enabled.
> Will update the expectations soon.
>
> Thanks anyways!
>
> 2013/9/27 Charles Davis <cdavis5x at gmail.com>:
> >
> > On Sep 27, 2013, at 10:40 AM, jahanian wrote:
> >
> >
> > On Sep 27, 2013, at 8:53 AM, jahanian <fjahanian at apple.com> wrote:
> >
> > This patch causes a test failure in a win64 buildbot.
> >
> >
> C:\public\win64\src\tools\clang\test\CodeGenCXX\microsoft-abi-multiple-nonvirtual-inheritance.cpp:165:12:
> > error: expected string not found in input
> >    // CHECK: %[[VFPTR:.*]] = bitcast %struct.ChildOverride* %this1 to [1
> x
> > i8*]**
> >
> >
> > [[THIS]]
> >
> > He's trying to tell you that it won't have that name outside of a
> +Asserts
> > build, so you need to use a FileCheck variable to match the name of the
> this
> > pointer value.
> >
> > Chip
> >
> >
> > - Fariborz
> >
> >
> > +  // Don't pass the PathToMangle as it should be calculated later.
> >   VFPtrInfo(CharUnits VFPtrOffset, const BasePath &PathToBaseWithVFPtr)
> >       : VBTableIndex(0), LastVBase(0), VFPtrOffset(VFPtrOffset),
> >         PathToBaseWithVFPtr(PathToBaseWithVFPtr),
> > VFPtrFullOffset(VFPtrOffset) {
> >   }
> >
> > +  // Don't pass the PathToMangle as it should be calculated later.
> >   VFPtrInfo(uint64_t VBTableIndex, const CXXRecordDecl *LastVBase,
> >             CharUnits VFPtrOffset, const BasePath &PathToBaseWithVFPtr,
> >             CharUnits VFPtrFullOffset)
> > @@ -404,9 +399,13 @@ struct VFPtrInfo {
> >   CharUnits VFPtrOffset;
> >
> >   /// This holds the base classes path from the complete type to the
> first
> > base
> > -  /// with the given vfptr offset.
> > +  /// with the given vfptr offset, in the base-to-derived order.
> >   BasePath PathToBaseWithVFPtr;
> >
> > +  /// This holds the subset of records that need to be mangled into the
> > vftable
> > +  /// symbol name in order to get a unique name, in the derived-to-base
> > order.
> > +  BasePath PathToMangle;
> > +
> >   /// This is the full offset of the vfptr from the start of the complete
> > type.
> >   CharUnits VFPtrFullOffset;
> > };
> >
> > Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
> > URL:
> >
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=191523&r1=191522&r2=191523&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
> > +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Fri Sep 27 09:48:01 2013
> > @@ -137,6 +137,9 @@ public:
> >                                 raw_ostream &);
> >   void mangleCXXVTable(const CXXRecordDecl *RD,
> >                        raw_ostream &);
> > +  void mangleCXXVFTable(const CXXRecordDecl *Derived,
> > +                        ArrayRef<const CXXRecordDecl *> BasePath,
> > +                        raw_ostream &Out);
> >   void mangleCXXVTT(const CXXRecordDecl *RD,
> >                     raw_ostream &);
> >   void mangleCXXVBTable(const CXXRecordDecl *Derived,
> > @@ -3772,6 +3775,14 @@ void ItaniumMangleContext::mangleCXXVTab
> >   Mangler.mangleNameOrStandardSubstitution(RD);
> > }
> >
> > +void
> > +ItaniumMangleContext::mangleCXXVFTable(const CXXRecordDecl *Derived,
> > +                                       ArrayRef<const CXXRecordDecl *>
> > BasePath,
> > +                                       raw_ostream &Out) {
> > +  llvm_unreachable(
> > +      "The Itanium C++ ABI does not have vftables (use vtables
> instead)!");
> > +}
> > +
> > void ItaniumMangleContext::mangleCXXVTT(const CXXRecordDecl *RD,
> >                                         raw_ostream &Out) {
> >   // <special-name> ::= TT <type>  # VTT structure
> >
> > Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp
> > URL:
> >
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftMangle.cpp?rev=191523&r1=191522&r2=191523&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original)
> > +++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Fri Sep 27 09:48:01 2013
> > @@ -188,6 +188,9 @@ public:
> >                                   raw_ostream &);
> >   virtual void mangleCXXVTable(const CXXRecordDecl *RD,
> >                                raw_ostream &);
> > +  virtual void mangleCXXVFTable(const CXXRecordDecl *Derived,
> > +                                ArrayRef<const CXXRecordDecl *>
> BasePath,
> > +                                raw_ostream &Out);
> >   virtual void mangleCXXVTT(const CXXRecordDecl *RD,
> >                             raw_ostream &);
> >   virtual void mangleCXXVBTable(const CXXRecordDecl *Derived,
> > @@ -1900,16 +1903,26 @@ void MicrosoftMangleContext::mangleCXXDt
> >
> > void MicrosoftMangleContext::mangleCXXVTable(const CXXRecordDecl *RD,
> >                                              raw_ostream &Out) {
> > +  llvm_unreachable(
> > +      "The Microsoft C++ ABI does not have vtables (use vftables
> > instead)!");
> > +}
> > +
> > +void MicrosoftMangleContext::mangleCXXVFTable(
> > +    const CXXRecordDecl *Derived, ArrayRef<const CXXRecordDecl *>
> BasePath,
> > +    raw_ostream &Out) {
> >   // <mangled-name> ::= ?_7 <class-name> <storage-class>
> >   //                    <cvr-qualifiers> [<name>] @
> >   // NOTE: <cvr-qualifiers> here is always 'B' (const). <storage-class>
> >   // is always '6' for vftables.
> >   MicrosoftCXXNameMangler Mangler(*this, Out);
> >   Mangler.getStream() << "\01??_7";
> > -  Mangler.mangleName(RD);
> > -  Mangler.getStream() << "6B";  // '6' for vftable, 'B' for const.
> > -  // TODO: If the class has more than one vtable, mangle in the class it
> > came
> > -  // from.
> > +  Mangler.mangleName(Derived);
> > +  Mangler.getStream() << "6B"; // '6' for vftable, 'B' for const.
> > +  for (ArrayRef<const CXXRecordDecl *>::iterator I = BasePath.begin(),
> > +                                                 E = BasePath.end();
> > +       I != E; ++I) {
> > +    Mangler.mangleName(*I);
> > +  }
> >   Mangler.getStream() << '@';
> > }
> >
> >
> > Modified: cfe/trunk/lib/AST/VTableBuilder.cpp
> > URL:
> >
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/VTableBuilder.cpp?rev=191523&r1=191522&r2=191523&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/AST/VTableBuilder.cpp (original)
> > +++ cfe/trunk/lib/AST/VTableBuilder.cpp Fri Sep 27 09:48:01 2013
> > @@ -999,10 +999,6 @@ public:
> >       dumpLayout(llvm::errs());
> >   }
> >
> > -  bool isMicrosoftABI() const {
> > -    return VTables.isMicrosoftABI();
> > -  }
> > -
> >   uint64_t getNumThunks() const {
> >     return Thunks.size();
> >   }
> > @@ -1157,7 +1153,7 @@ void VTableBuilder::ComputeThisAdjustmen
> >     // Add it.
> >     VTableThunks[VTableIndex].This = ThisAdjustment;
> >
> > -    if (isa<CXXDestructorDecl>(MD) && !isMicrosoftABI()) {
> > +    if (isa<CXXDestructorDecl>(MD)) {
> >       // Add an adjustment for the deleting destructor as well.
> >       VTableThunks[VTableIndex + 1].This = ThisAdjustment;
> >     }
> > @@ -1188,8 +1184,6 @@ void VTableBuilder::ComputeThisAdjustmen
> >       break;
> >     case VTableComponent::CK_DeletingDtorPointer:
> >       // We've already added the thunk when we saw the complete dtor
> > pointer.
> > -      // FIXME: check how this works in the Microsoft ABI
> > -      // while working on the multiple inheritance patch.
> >       continue;
> >     }
> >
> > @@ -1326,15 +1320,9 @@ VTableBuilder::AddMethod(const CXXMethod
> >     assert(ReturnAdjustment.isEmpty() &&
> >            "Destructor can't have return adjustment!");
> >
> > -    // FIXME: Should probably add a layer of abstraction for vtable
> > generation.
> > -    if (!isMicrosoftABI()) {
> > -      // Add both the complete destructor and the deleting destructor.
> > -      Components.push_back(VTableComponent::MakeCompleteDtor(DD));
> > -      Components.push_back(VTableComponent::MakeDeletingDtor(DD));
> > -    } else {
> > -      // Add the scalar deleting destructor.
> > -      Components.push_back(VTableComponent::MakeDeletingDtor(DD));
> > -    }
> > +    // Add both the complete destructor and the deleting destructor.
> > +    Components.push_back(VTableComponent::MakeCompleteDtor(DD));
> > +    Components.push_back(VTableComponent::MakeDeletingDtor(DD));
> >   } else {
> >     // Add the return adjustment if necessary.
> >     if (!ReturnAdjustment.isEmpty())
> > @@ -1693,18 +1681,12 @@ VTableBuilder::LayoutPrimaryAndSecondary
> >   if (Base.getBase() == MostDerivedClass)
> >     VBaseOffsetOffsets = Builder.getVBaseOffsetOffsets();
> >
> > -  // FIXME: Should probably add a layer of abstraction for vtable
> > generation.
> > -  if (!isMicrosoftABI()) {
> > -    // Add the offset to top.
> > -    CharUnits OffsetToTop = MostDerivedClassOffset -
> OffsetInLayoutClass;
> > -    Components.push_back(VTableComponent::MakeOffsetToTop(OffsetToTop));
> > +  // Add the offset to top.
> > +  CharUnits OffsetToTop = MostDerivedClassOffset - OffsetInLayoutClass;
> > +  Components.push_back(VTableComponent::MakeOffsetToTop(OffsetToTop));
> >
> > -    // Next, add the RTTI.
> > -    Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass));
> > -  } else {
> > -    // FIXME: unclear what to do with RTTI in MS ABI as emitting it
> > anywhere
> > -    // breaks the vftable layout. Just skip RTTI for now, can't mangle
> > anyway.
> > -  }
> > +  // Next, add the RTTI.
> > +  Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass));
> >
> >   uint64_t AddressPoint = Components.size();
> >
> > @@ -1722,16 +1704,10 @@ VTableBuilder::LayoutPrimaryAndSecondary
> >       const CXXMethodDecl *MD = I->first;
> >       const MethodInfo &MI = I->second;
> >       if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD))
> {
> > -        // FIXME: Should probably add a layer of abstraction for vtable
> > generation.
> > -        if (!isMicrosoftABI()) {
> > -          MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)]
> > -              = MI.VTableIndex - AddressPoint;
> > -          MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)]
> > -              = MI.VTableIndex + 1 - AddressPoint;
> > -        } else {
> > -          MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)]
> > -              = MI.VTableIndex - AddressPoint;
> > -        }
> > +        MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)]
> > +            = MI.VTableIndex - AddressPoint;
> > +        MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)]
> > +            = MI.VTableIndex + 1 - AddressPoint;
> >       } else {
> >         MethodVTableIndices[MD] = MI.VTableIndex - AddressPoint;
> >       }
> > @@ -2044,8 +2020,6 @@ void VTableBuilder::dumpLayout(raw_ostre
> >       Out << DD->getQualifiedNameAsString();
> >       if (IsComplete)
> >         Out << "() [complete]";
> > -      else if (isMicrosoftABI())
> > -        Out << "() [scalar deleting]";
> >       else
> >         Out << "() [deleting]";
> >
> > @@ -2230,18 +2204,11 @@ void VTableBuilder::dumpLayout(raw_ostre
> >                                   MD);
> >
> >     if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
> > -      // FIXME: Should add a layer of abstraction for vtable generation.
> > -      if (!isMicrosoftABI()) {
> > -        GlobalDecl GD(DD, Dtor_Complete);
> > -        assert(MethodVTableIndices.count(GD));
> > -        uint64_t VTableIndex = MethodVTableIndices[GD];
> > -        IndicesMap[VTableIndex] = MethodName + " [complete]";
> > -        IndicesMap[VTableIndex + 1] = MethodName + " [deleting]";
> > -      } else {
> > -        GlobalDecl GD(DD, Dtor_Deleting);
> > -        assert(MethodVTableIndices.count(GD));
> > -        IndicesMap[MethodVTableIndices[GD]] = MethodName + " [scalar
> > deleting]";
> > -      }
> > +      GlobalDecl GD(DD, Dtor_Complete);
> > +      assert(MethodVTableIndices.count(GD));
> > +      uint64_t VTableIndex = MethodVTableIndices[GD];
> > +      IndicesMap[VTableIndex] = MethodName + " [complete]";
> > +      IndicesMap[VTableIndex + 1] = MethodName + " [deleting]";
> >     } else {
> >       assert(MethodVTableIndices.count(MD));
> >       IndicesMap[MethodVTableIndices[MD]] = MethodName;
> > @@ -2352,10 +2319,12 @@ static VTableLayout *CreateVTableLayout(
> >                           VTableThunks.size(),
> >                           VTableThunks.data(),
> >                           Builder.getAddressPoints(),
> > -                          Builder.isMicrosoftABI());
> > +                          /*IsMicrosoftABI=*/false);
> > }
> >
> > void VTableContext::computeVTableRelatedInformation(const CXXRecordDecl
> *RD)
> > {
> > +  assert(!IsMicrosoftABI && "Shouldn't be called in this ABI!");
> > +
> >   const VTableLayout *&Entry = VTableLayouts[RD];
> >
> >   // Check if we've computed this information before.
> > @@ -3132,6 +3101,55 @@ static void EnumerateVFPtrs(
> >   }
> > }
> >
> > +/// CalculatePathToMangle - Calculate the subset of records that should
> be
> > used
> > +/// to mangle the vftable for the given vfptr.
> > +/// Should only be called if a class has multiple vftables.
> > +static void
> > +CalculatePathToMangle(const CXXRecordDecl *RD, VFPtrInfo &VFPtr) {
> > +  // FIXME: In some rare cases this code produces a slightly incorrect
> > mangling.
> > +  // It's very likely that the vbtable mangling code can be adjusted to
> > mangle
> > +  // both vftables and vbtables correctly.
> > +
> > +  VFPtrInfo::BasePath &FullPath = VFPtr.PathToBaseWithVFPtr;
> > +  if (FullPath.empty()) {
> > +    // Mangle the class's own vftable.
> > +    assert(RD->getNumVBases() &&
> > +           "Something's wrong: if the most derived "
> > +           "class has more than one vftable, it can only have its own "
> > +           "vftable if it has vbases");
> > +    VFPtr.PathToMangle.push_back(RD);
> > +    return;
> > +  }
> > +
> > +  unsigned Begin = 0;
> > +
> > +  // First, skip all the bases before the vbase.
> > +  if (VFPtr.LastVBase) {
> > +    while (FullPath[Begin] != VFPtr.LastVBase) {
> > +      Begin++;
> > +      assert(Begin < FullPath.size());
> > +    }
> > +  }
> > +
> > +  // Then, put the rest of the base path in the reverse order.
> > +  for (unsigned I = FullPath.size(); I != Begin; --I) {
> > +    const CXXRecordDecl *CurBase = FullPath[I - 1],
> > +                        *ItsBase = (I == 1) ? RD : FullPath[I - 2];
> > +    bool BaseIsVirtual = false;
> > +    for (CXXRecordDecl::base_class_const_iterator J =
> > ItsBase->bases_begin(),
> > +         F = ItsBase->bases_end(); J != F; ++J) {
> > +      if (J->getType()->getAsCXXRecordDecl() == CurBase) {
> > +        BaseIsVirtual = J->isVirtual();
> > +        break;
> > +      }
> > +    }
> > +
> > +    // Should skip the current base if it is a non-virtual base with no
> > siblings.
> > +    if (BaseIsVirtual || ItsBase->getNumBases() != 1)
> > +      VFPtr.PathToMangle.push_back(CurBase);
> > +  }
> > +}
> > +
> > static void EnumerateVFPtrs(ASTContext &Context, const CXXRecordDecl
> > *ForClass,
> >                             MicrosoftVFTableContext::VFPtrListTy
> &Result) {
> >   Result.clear();
> > @@ -3140,6 +3158,10 @@ static void EnumerateVFPtrs(ASTContext &
> >   EnumerateVFPtrs(Context, ForClass, ClassLayout,
> >                   BaseSubobject(ForClass, CharUnits::Zero()), 0,
> >                   VFPtrInfo::BasePath(), VisitedVBases, Result);
> > +  if (Result.size() > 1) {
> > +    for (unsigned I = 0, E = Result.size(); I != E; ++I)
> > +      CalculatePathToMangle(ForClass, Result[I]);
> > +  }
> > }
> >
> > void MicrosoftVFTableContext::computeVTableRelatedInformation(
> >
> > Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
> > URL:
> >
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=191523&r1=191522&r2=191523&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
> > +++ cfe/trunk/lib/CodeGen/CGCXX.cpp Fri Sep 27 09:48:01 2013
> > @@ -280,7 +280,7 @@ static llvm::Value *BuildAppleKextVirtua
> >          "No kext in Microsoft ABI");
> >   GD = GD.getCanonicalDecl();
> >   CodeGenModule &CGM = CGF.CGM;
> > -  llvm::Value *VTable = CGM.getVTables().GetAddrOfVTable(RD);
> > +  llvm::Value *VTable = CGM.getCXXABI().getAddrOfVTable(RD,
> CharUnits());
> >   Ty = Ty->getPointerTo()->getPointerTo();
> >   VTable = CGF.Builder.CreateBitCast(VTable, Ty);
> >   assert(VTable && "BuildVirtualCall = kext vtbl pointer is null");
> >
> > Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h
> > URL:
> >
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=191523&r1=191522&r2=191523&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)
> > +++ cfe/trunk/lib/CodeGen/CGCXXABI.h Fri Sep 27 09:48:01 2013
> > @@ -303,6 +303,29 @@ public:
> >                                    CallExpr::const_arg_iterator ArgBeg,
> >                                    CallExpr::const_arg_iterator ArgEnd)
> = 0;
> >
> > +  /// Emits the VTable definitions required for the given record type.
> > +  virtual void emitVTableDefinitions(CodeGenVTables &CGVT,
> > +                                     const CXXRecordDecl *RD) = 0;
> > +
> > +  /// Get the address point of the vtable for the given base subobject
> > while
> > +  /// building a constructor or a destructor. On return,
> NeedsVirtualOffset
> > +  /// tells if a virtual base adjustment is needed in order to get the
> > offset
> > +  /// of the base subobject.
> > +  virtual llvm::Value *getVTableAddressPointInStructor(
> > +      CodeGenFunction &CGF, const CXXRecordDecl *RD, BaseSubobject Base,
> > +      const CXXRecordDecl *NearestVBase, bool &NeedsVirtualOffset) = 0;
> > +
> > +  /// Get the address point of the vtable for the given base subobject
> > while
> > +  /// building a constexpr.
> > +  virtual llvm::Constant *
> > +  getVTableAddressPointForConstExpr(BaseSubobject Base,
> > +                                    const CXXRecordDecl *VTableClass) =
> 0;
> > +
> > +  /// Get the address of the vtable for the given record decl which
> should
> > be
> > +  /// used for the vptr at the given offset in RD.
> > +  virtual llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD,
> > +                                                CharUnits VPtrOffset) =
> 0;
> > +
> >   /// Build a virtual function pointer in the ABI-specific way.
> >   virtual llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF,
> >                                                  GlobalDecl GD,
> > @@ -319,9 +342,7 @@ public:
> >   /// Emit any tables needed to implement virtual inheritance.  For
> Itanium,
> >   /// this emits virtual table tables.  For the MSVC++ ABI, this emits
> > virtual
> >   /// base tables.
> > -  virtual void
> > -      EmitVirtualInheritanceTables(llvm::GlobalVariable::LinkageTypes
> > Linkage,
> > -                                   const CXXRecordDecl *RD) = 0;
> > +  virtual void emitVirtualInheritanceTables(const CXXRecordDecl *RD) =
> 0;
> >
> >   virtual void EmitReturnFromThunk(CodeGenFunction &CGF,
> >                                    RValue RV, QualType ResultType);
> >
> > Modified: cfe/trunk/lib/CodeGen/CGClass.cpp
> > URL:
> >
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=191523&r1=191522&r2=191523&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/CodeGen/CGClass.cpp (original)
> > +++ cfe/trunk/lib/CodeGen/CGClass.cpp Fri Sep 27 09:48:01 2013
> > @@ -1878,39 +1878,19 @@ CodeGenFunction::InitializeVTablePointer
> >                                          const CXXRecordDecl
> *NearestVBase,
> >                                          CharUnits
> OffsetFromNearestVBase,
> >                                          const CXXRecordDecl
> *VTableClass) {
> > -  const CXXRecordDecl *RD = Base.getBase();
> > -
> >   // Compute the address point.
> > -  llvm::Value *VTableAddressPoint;
> > -
> > -  bool NeedsVTTParam = CGM.getCXXABI().NeedsVTTParameter(CurGD);
> > -
> > -  // Check if we need to use a vtable from the VTT.
> > -  if (NeedsVTTParam && (RD->getNumVBases() || NearestVBase)) {
> > -    // Get the secondary vpointer index.
> > -    uint64_t VirtualPointerIndex =
> > -     CGM.getVTables().getSecondaryVirtualPointerIndex(VTableClass,
> Base);
> > -
> > -    /// Load the VTT.
> > -    llvm::Value *VTT = LoadCXXVTT();
> > -    if (VirtualPointerIndex)
> > -      VTT = Builder.CreateConstInBoundsGEP1_64(VTT,
> VirtualPointerIndex);
> > -
> > -    // And load the address point from the VTT.
> > -    VTableAddressPoint = Builder.CreateLoad(VTT);
> > -  } else {
> > -    llvm::Constant *VTable =
> CGM.getVTables().GetAddrOfVTable(VTableClass);
> > -    uint64_t AddressPoint =
> > -
> >
> CGM.getVTableContext().getVTableLayout(VTableClass).getAddressPoint(Base);
> > -    VTableAddressPoint =
> > -      Builder.CreateConstInBoundsGEP2_64(VTable, 0, AddressPoint);
> > -  }
> > +  bool NeedsVirtualOffset;
> > +  llvm::Value *VTableAddressPoint =
> > +      CGM.getCXXABI().getVTableAddressPointInStructor(
> > +          *this, VTableClass, Base, NearestVBase, NeedsVirtualOffset);
> > +  if (!VTableAddressPoint)
> > +    return;
> >
> >   // Compute where to store the address point.
> >   llvm::Value *VirtualOffset = 0;
> >   CharUnits NonVirtualOffset = CharUnits::Zero();
> >
> > -  if (NeedsVTTParam && NearestVBase) {
> > +  if (NeedsVirtualOffset) {
> >     // We need to use the virtual base offset offset because the virtual
> > base
> >     // might have a different offset in the most derived class.
> >     VirtualOffset = CGM.getCXXABI().GetVirtualBaseClassOffset(*this,
> >
> > Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
> > URL:
> >
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=191523&r1=191522&r2=191523&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
> > +++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Fri Sep 27 09:48:01 2013
> > @@ -1053,7 +1053,11 @@ CGDebugInfo::CreateCXXMemberFunction(con
> >
> >     // It doesn't make sense to give a virtual destructor a vtable index,
> >     // since a single destructor has two entries in the vtable.
> > -    if (!isa<CXXDestructorDecl>(Method))
> > +    // FIXME: Add proper support for debug info for virtual calls in
> > +    // the Microsoft ABI, where we may use multiple vptrs to make a
> vftable
> > +    // lookup if we have multiple or virtual inheritance.
> > +    if (!isa<CXXDestructorDecl>(Method) &&
> > +        !CGM.getTarget().getCXXABI().isMicrosoft())
> >       VIndex = CGM.getVTableContext().getMethodVTableIndex(Method);
> >     ContainingType = RecordTy;
> >   }
> >
> > Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
> > URL:
> >
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=191523&r1=191522&r2=191523&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
> > +++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Fri Sep 27 09:48:01 2013
> > @@ -53,9 +53,6 @@ private:
> >     NextFieldOffsetInChars(CharUnits::Zero()),
> >     LLVMStructAlignment(CharUnits::One()) { }
> >
> > -  void AppendVTablePointer(BaseSubobject Base, llvm::Constant *VTable,
> > -                           const CXXRecordDecl *VTableClass);
> > -
> >   void AppendField(const FieldDecl *Field, uint64_t FieldOffset,
> >                    llvm::Constant *InitExpr);
> >
> > @@ -72,8 +69,7 @@ private:
> >
> >   bool Build(InitListExpr *ILE);
> >   void Build(const APValue &Val, const RecordDecl *RD, bool
> IsPrimaryBase,
> > -             llvm::Constant *VTable, const CXXRecordDecl *VTableClass,
> > -             CharUnits BaseOffset);
> > +             const CXXRecordDecl *VTableClass, CharUnits BaseOffset);
> >   llvm::Constant *Finalize(QualType Ty);
> >
> >   CharUnits getAlignment(const llvm::Constant *C) const {
> > @@ -88,23 +84,6 @@ private:
> >   }
> > };
> >
> > -void ConstStructBuilder::AppendVTablePointer(BaseSubobject Base,
> > -                                             llvm::Constant *VTable,
> > -                                             const CXXRecordDecl
> > *VTableClass) {
> > -  // Find the appropriate vtable within the vtable group.
> > -  uint64_t AddressPoint =
> > -
> >
> CGM.getVTableContext().getVTableLayout(VTableClass).getAddressPoint(Base);
> > -  llvm::Value *Indices[] = {
> > -    llvm::ConstantInt::get(CGM.Int64Ty, 0),
> > -    llvm::ConstantInt::get(CGM.Int64Ty, AddressPoint)
> > -  };
> > -  llvm::Constant *VTableAddressPoint =
> > -    llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Indices);
> > -
> > -  // Add the vtable at the start of the object.
> > -  AppendBytes(Base.getBaseOffset(), VTableAddressPoint);
> > -}
> > -
> > void ConstStructBuilder::
> > AppendField(const FieldDecl *Field, uint64_t FieldOffset,
> >             llvm::Constant *InitCst) {
> > @@ -424,15 +403,19 @@ struct BaseInfo {
> > }
> >
> > void ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,
> > -                               bool IsPrimaryBase, llvm::Constant
> *VTable,
> > +                               bool IsPrimaryBase,
> >                                const CXXRecordDecl *VTableClass,
> >                                CharUnits Offset) {
> >   const ASTRecordLayout &Layout =
> CGM.getContext().getASTRecordLayout(RD);
> >
> >   if (const CXXRecordDecl *CD = dyn_cast<CXXRecordDecl>(RD)) {
> >     // Add a vtable pointer, if we need one and it hasn't already been
> > added.
> > -    if (CD->isDynamicClass() && !IsPrimaryBase)
> > -      AppendVTablePointer(BaseSubobject(CD, Offset), VTable,
> VTableClass);
> > +    if (CD->isDynamicClass() && !IsPrimaryBase) {
> > +      llvm::Constant *VTableAddressPoint =
> > +          CGM.getCXXABI().getVTableAddressPointForConstExpr(
> > +              BaseSubobject(CD, Offset), VTableClass);
> > +      AppendBytes(Offset, VTableAddressPoint);
> > +    }
> >
> >     // Accumulate and sort bases, in order to visit them in address
> order,
> > which
> >     // may not be the same as declaration order.
> > @@ -453,7 +436,7 @@ void ConstStructBuilder::Build(const APV
> >
> >       bool IsPrimaryBase = Layout.getPrimaryBase() == Base.Decl;
> >       Build(Val.getStructBase(Base.Index), Base.Decl, IsPrimaryBase,
> > -            VTable, VTableClass, Offset + Base.Offset);
> > +            VTableClass, Offset + Base.Offset);
> >     }
> >   }
> >
> > @@ -560,11 +543,7 @@ llvm::Constant *ConstStructBuilder::Buil
> >
> >   const RecordDecl *RD = ValTy->castAs<RecordType>()->getDecl();
> >   const CXXRecordDecl *CD = dyn_cast<CXXRecordDecl>(RD);
> > -  llvm::Constant *VTable = 0;
> > -  if (CD && CD->isDynamicClass())
> > -    VTable = CGM.getVTables().GetAddrOfVTable(CD);
> > -
> > -  Builder.Build(Val, RD, false, VTable, CD, CharUnits::Zero());
> > +  Builder.Build(Val, RD, false, CD, CharUnits::Zero());
> >
> >   return Builder.Finalize(ValTy);
> > }
> >
> > Modified: cfe/trunk/lib/CodeGen/CGVTT.cpp
> > URL:
> >
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTT.cpp?rev=191523&r1=191522&r2=191523&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/CodeGen/CGVTT.cpp (original)
> > +++ cfe/trunk/lib/CodeGen/CGVTT.cpp Fri Sep 27 09:48:01 2013
> > @@ -19,7 +19,8 @@ using namespace clang;
> > using namespace CodeGen;
> >
> > static llvm::Constant *
> > -GetAddrOfVTTVTable(CodeGenVTables &CGVT, const CXXRecordDecl
> > *MostDerivedClass,
> > +GetAddrOfVTTVTable(CodeGenVTables &CGVT, CodeGenModule &CGM,
> > +                   const CXXRecordDecl *MostDerivedClass,
> >                    const VTTVTable &VTable,
> >                    llvm::GlobalVariable::LinkageTypes Linkage,
> >                    llvm::DenseMap<BaseSubobject, uint64_t>
> &AddressPoints) {
> > @@ -27,7 +28,7 @@ GetAddrOfVTTVTable(CodeGenVTables &CGVT,
> >     assert(VTable.getBaseOffset().isZero() &&
> >            "Most derived class vtable must have a zero offset!");
> >     // This is a regular vtable.
> > -    return CGVT.GetAddrOfVTable(MostDerivedClass);
> > +    return CGM.getCXXABI().getAddrOfVTable(MostDerivedClass,
> CharUnits());
> >   }
> >
> >   return CGVT.GenerateConstructionVTable(MostDerivedClass,
> > @@ -52,7 +53,7 @@ CodeGenVTables::EmitVTTDefinition(llvm::
> >   for (const VTTVTable *i = Builder.getVTTVTables().begin(),
> >                        *e = Builder.getVTTVTables().end(); i != e; ++i) {
> >     VTableAddressPoints.push_back(VTableAddressPointsMapTy());
> > -    VTables.push_back(GetAddrOfVTTVTable(*this, RD, *i, Linkage,
> > +    VTables.push_back(GetAddrOfVTTVTable(*this, CGM, RD, *i, Linkage,
> >                                          VTableAddressPoints.back()));
> >   }
> >
> > @@ -106,7 +107,7 @@ llvm::GlobalVariable *CodeGenVTables::Ge
> >   StringRef Name = OutName.str();
> >
> >   // This will also defer the definition of the VTT.
> > -  (void) GetAddrOfVTable(RD);
> > +  (void) CGM.getCXXABI().getAddrOfVTable(RD, CharUnits());
> >
> >   VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false);
> >
> >
> > Modified: cfe/trunk/lib/CodeGen/CGVTables.cpp
> > URL:
> >
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.cpp?rev=191523&r1=191522&r2=191523&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/CodeGen/CGVTables.cpp (original)
> > +++ cfe/trunk/lib/CodeGen/CGVTables.cpp Fri Sep 27 09:48:01 2013
> > @@ -498,6 +498,7 @@ void CodeGenVTables::EmitThunks(GlobalDe
> >     // FIXME: This is a temporary solution to force generation of
> vftables
> > in
> >     // Microsoft ABI. Remove when we thread VFTableContext through
> CodeGen.
> >     VFTContext->getVFPtrOffsets(MD->getParent());
> > +    return;
> >   }
> >
> >   const VTableContext::ThunkInfoVectorTy *ThunkInfoVector =
> > @@ -629,53 +630,6 @@ CodeGenVTables::CreateVTableInitializer(
> >   return llvm::ConstantArray::get(ArrayType, Inits);
> > }
> >
> > -llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTable(const
> CXXRecordDecl
> > *RD) {
> > -  llvm::GlobalVariable *&VTable = VTables[RD];
> > -  if (VTable)
> > -    return VTable;
> > -
> > -  // Queue up this v-table for possible deferred emission.
> > -  CGM.addDeferredVTable(RD);
> > -
> > -  SmallString<256> OutName;
> > -  llvm::raw_svector_ostream Out(OutName);
> > -  CGM.getCXXABI().getMangleContext().mangleCXXVTable(RD, Out);
> > -  Out.flush();
> > -  StringRef Name = OutName.str();
> > -
> > -  llvm::ArrayType *ArrayType =
> > -    llvm::ArrayType::get(CGM.Int8PtrTy,
> > -
> > VTContext.getVTableLayout(RD).getNumVTableComponents());
> > -
> > -  VTable =
> > -    CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType,
> > -
> > llvm::GlobalValue::ExternalLinkage);
> > -  VTable->setUnnamedAddr(true);
> > -  return VTable;
> > -}
> > -
> > -void
> > -CodeGenVTables::EmitVTableDefinition(llvm::GlobalVariable *VTable,
> > -                                     llvm::GlobalVariable::LinkageTypes
> > Linkage,
> > -                                     const CXXRecordDecl *RD) {
> > -  const VTableLayout &VTLayout = VTContext.getVTableLayout(RD);
> > -
> > -  // Create and set the initializer.
> > -  llvm::Constant *Init =
> > -    CreateVTableInitializer(RD,
> > -                            VTLayout.vtable_component_begin(),
> > -                            VTLayout.getNumVTableComponents(),
> > -                            VTLayout.vtable_thunk_begin(),
> > -                            VTLayout.getNumVTableThunks());
> > -  VTable->setInitializer(Init);
> > -
> > -  // Set the correct linkage.
> > -  VTable->setLinkage(Linkage);
> > -
> > -  // Set the right visibility.
> > -  CGM.setTypeVisibility(VTable, RD, CodeGenModule::TVK_ForVTable);
> > -}
> > -
> > llvm::GlobalVariable *
> > CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
> >                                       const BaseSubobject &Base,
> > @@ -818,35 +772,10 @@ CodeGenVTables::GenerateClassData(const
> >   if (CGDebugInfo *DI = CGM.getModuleDebugInfo())
> >     DI->completeClassData(RD);
> >
> > -  if (VFTContext.isValid()) {
> > -    // FIXME: This is a temporary solution to force generation of
> vftables
> > in
> > -    // Microsoft ABI. Remove when we thread VFTableContext through
> CodeGen.
> > -    VFTContext->getVFPtrOffsets(RD);
> > -  }
> > -
> > -  // First off, check whether we've already emitted the v-table and
> > -  // associated stuff.
> > -  llvm::GlobalVariable *VTable = GetAddrOfVTable(RD);
> > -  if (VTable->hasInitializer())
> > -    return;
> > -
> > -  llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);
> > -  EmitVTableDefinition(VTable, Linkage, RD);
> > -
> >   if (RD->getNumVBases())
> > -    CGM.getCXXABI().EmitVirtualInheritanceTables(Linkage, RD);
> > +    CGM.getCXXABI().emitVirtualInheritanceTables(RD);
> >
> > -  // If this is the magic class __cxxabiv1::__fundamental_type_info,
> > -  // we will emit the typeinfo for the fundamental types. This is the
> > -  // same behaviour as GCC.
> > -  const DeclContext *DC = RD->getDeclContext();
> > -  if (RD->getIdentifier() &&
> > -      RD->getIdentifier()->isStr("__fundamental_type_info") &&
> > -      isa<NamespaceDecl>(DC) &&
> > -      cast<NamespaceDecl>(DC)->getIdentifier() &&
> > -      cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__cxxabiv1") &&
> > -      DC->getParent()->isTranslationUnit())
> > -    CGM.EmitFundamentalRTTIDescriptors();
> > +  CGM.getCXXABI().emitVTableDefinitions(*this, RD);
> > }
> >
> > /// At this point in the translation unit, does it appear that can we
> >
> > Modified: cfe/trunk/lib/CodeGen/CGVTables.h
> > URL:
> >
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.h?rev=191523&r1=191522&r2=191523&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/CodeGen/CGVTables.h (original)
> > +++ cfe/trunk/lib/CodeGen/CGVTables.h Fri Sep 27 09:48:01 2013
> > @@ -35,9 +35,6 @@ class CodeGenVTables {
> >   // classes?
> >   VTableContext VTContext;
> >   OwningPtr<MicrosoftVFTableContext> VFTContext;
> > -
> > -  /// VTables - All the vtables which have been defined.
> > -  llvm::DenseMap<const CXXRecordDecl *, llvm::GlobalVariable *> VTables;
> >
> >   /// VTableAddressPointsMapTy - Address points for a single vtable.
> >   typedef llvm::DenseMap<BaseSubobject, uint64_t>
> VTableAddressPointsMapTy;
> > @@ -65,6 +62,7 @@ class CodeGenVTables {
> >   /// doesn't contain any incomplete types.
> >   void MaybeEmitThunkAvailableExternally(GlobalDecl GD, const ThunkInfo
> > &Thunk);
> >
> > +public:
> >   /// CreateVTableInitializer - Create a vtable initializer for the given
> > record
> >   /// decl.
> >   /// \param Components - The vtable components; this is really an array
> of
> > @@ -75,7 +73,6 @@ class CodeGenVTables {
> >                                 const VTableLayout::VTableThunkTy
> > *VTableThunks,
> >                                           unsigned NumVTableThunks);
> >
> > -public:
> >   CodeGenVTables(CodeGenModule &CGM);
> >
> >   VTableContext &getVTableContext() { return VTContext; }
> > @@ -95,14 +92,6 @@ public:
> >   /// class decl.
> >   uint64_t getAddressPoint(BaseSubobject Base, const CXXRecordDecl *RD);
> >
> > -  /// GetAddrOfVTable - Get the address of the vtable for the given
> record
> > decl.
> > -  llvm::GlobalVariable *GetAddrOfVTable(const CXXRecordDecl *RD);
> > -
> > -  /// EmitVTableDefinition - Emit the definition of the given vtable.
> > -  void EmitVTableDefinition(llvm::GlobalVariable *VTable,
> > -                            llvm::GlobalVariable::LinkageTypes Linkage,
> > -                            const CXXRecordDecl *RD);
> > -
> >   /// GenerateConstructionVTable - Generate a construction vtable for the
> > given
> >   /// base subobject.
> >   llvm::GlobalVariable *
> >
> > Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
> > URL:
> >
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=191523&r1=191522&r2=191523&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
> > +++ cfe/trunk/lib/CodeGen/CodeGenModule.h Fri Sep 27 09:48:01 2013
> > @@ -250,7 +250,6 @@ class CodeGenModule : public CodeGenType
> >
> >   /// VTables - Holds information about C++ vtables.
> >   CodeGenVTables VTables;
> > -  friend class CodeGenVTables;
> >
> >   CGObjCRuntime* ObjCRuntime;
> >   CGOpenCLRuntime* OpenCLRuntime;
> > @@ -915,6 +914,10 @@ public:
> >
> >   void EmitVTable(CXXRecordDecl *Class, bool DefinitionRequired);
> >
> > +  /// EmitFundamentalRTTIDescriptors - Emit the RTTI descriptors for the
> > +  /// builtin types.
> > +  void EmitFundamentalRTTIDescriptors();
> > +
> >   /// \brief Appends Opts to the "Linker Options" metadata value.
> >   void AppendLinkerOptions(StringRef Opts);
> >
> > @@ -1068,10 +1071,6 @@ private:
> >   /// given type.
> >   void EmitFundamentalRTTIDescriptor(QualType Type);
> >
> > -  /// EmitFundamentalRTTIDescriptors - Emit the RTTI descriptors for the
> > -  /// builtin types.
> > -  void EmitFundamentalRTTIDescriptors();
> > -
> >   /// EmitDeferred - Emit any needed decls for which code generation
> >   /// was deferred.
> >   void EmitDeferred();
> >
> > Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
> > URL:
> >
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=191523&r1=191522&r2=191523&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
> > +++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Fri Sep 27 09:48:01 2013
> > @@ -34,6 +34,9 @@ using namespace CodeGen;
> >
> > namespace {
> > class ItaniumCXXABI : public CodeGen::CGCXXABI {
> > +  /// VTables - All the vtables which have been defined.
> > +  llvm::DenseMap<const CXXRecordDecl *, llvm::GlobalVariable *> VTables;
> > +
> > protected:
> >   bool UseARMMethodPtrABI;
> >   bool UseARMGuardVarABI;
> > @@ -142,6 +145,20 @@ public:
> >                            CallExpr::const_arg_iterator ArgBeg,
> >                            CallExpr::const_arg_iterator ArgEnd);
> >
> > +  void emitVTableDefinitions(CodeGenVTables &CGVT, const CXXRecordDecl
> > *RD);
> > +
> > +  llvm::Value *getVTableAddressPointInStructor(
> > +      CodeGenFunction &CGF, const CXXRecordDecl *VTableClass,
> > +      BaseSubobject Base, const CXXRecordDecl *NearestVBase,
> > +      bool &NeedsVirtualOffset);
> > +
> > +  llvm::Constant *
> > +  getVTableAddressPointForConstExpr(BaseSubobject Base,
> > +                                    const CXXRecordDecl *VTableClass);
> > +
> > +  llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD,
> > +                                        CharUnits VPtrOffset);
> > +
> >   llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl
> > GD,
> >                                          llvm::Value *This, llvm::Type
> *Ty);
> >
> > @@ -150,8 +167,7 @@ public:
> >                                  CXXDtorType DtorType, SourceLocation
> > CallLoc,
> >                                  llvm::Value *This);
> >
> > -  void EmitVirtualInheritanceTables(llvm::GlobalVariable::LinkageTypes
> > Linkage,
> > -                                    const CXXRecordDecl *RD);
> > +  void emitVirtualInheritanceTables(const CXXRecordDecl *RD);
> >
> >   StringRef GetPureVirtualCallName() { return "__cxa_pure_virtual"; }
> >   StringRef GetDeletedVirtualCallName() { return
> "__cxa_deleted_virtual"; }
> > @@ -888,6 +904,113 @@ void ItaniumCXXABI::EmitConstructorCall(
> >                         This, VTT, VTTTy, ArgBeg, ArgEnd);
> > }
> >
> > +void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
> > +                                          const CXXRecordDecl *RD) {
> > +  llvm::GlobalVariable *VTable = getAddrOfVTable(RD, CharUnits());
> > +  if (VTable->hasInitializer())
> > +    return;
> > +
> > +  VTableContext &VTContext = CGM.getVTableContext();
> > +  const VTableLayout &VTLayout = VTContext.getVTableLayout(RD);
> > +  llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);
> > +
> > +  // Create and set the initializer.
> > +  llvm::Constant *Init = CGVT.CreateVTableInitializer(
> > +      RD, VTLayout.vtable_component_begin(),
> > VTLayout.getNumVTableComponents(),
> > +      VTLayout.vtable_thunk_begin(), VTLayout.getNumVTableThunks());
> > +  VTable->setInitializer(Init);
> > +
> > +  // Set the correct linkage.
> > +  VTable->setLinkage(Linkage);
> > +
> > +  // Set the right visibility.
> > +  CGM.setTypeVisibility(VTable, RD, CodeGenModule::TVK_ForVTable);
> > +
> > +  // If this is the magic class __cxxabiv1::__fundamental_type_info,
> > +  // we will emit the typeinfo for the fundamental types. This is the
> > +  // same behaviour as GCC.
> > +  const DeclContext *DC = RD->getDeclContext();
> > +  if (RD->getIdentifier() &&
> > +      RD->getIdentifier()->isStr("__fundamental_type_info") &&
> > +      isa<NamespaceDecl>(DC) &&
> cast<NamespaceDecl>(DC)->getIdentifier() &&
> > +      cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__cxxabiv1") &&
> > +      DC->getParent()->isTranslationUnit())
> > +    CGM.EmitFundamentalRTTIDescriptors();
> > +}
> > +
> > +llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructor(
> > +    CodeGenFunction &CGF, const CXXRecordDecl *VTableClass,
> BaseSubobject
> > Base,
> > +    const CXXRecordDecl *NearestVBase, bool &NeedsVirtualOffset) {
> > +  bool NeedsVTTParam = CGM.getCXXABI().NeedsVTTParameter(CGF.CurGD);
> > +  NeedsVirtualOffset = (NeedsVTTParam && NearestVBase);
> > +
> > +  llvm::Value *VTableAddressPoint;
> > +  if (NeedsVTTParam && (Base.getBase()->getNumVBases() ||
> NearestVBase)) {
> > +    // Get the secondary vpointer index.
> > +    uint64_t VirtualPointerIndex =
> > +        CGM.getVTables().getSecondaryVirtualPointerIndex(VTableClass,
> > Base);
> > +
> > +    /// Load the VTT.
> > +    llvm::Value *VTT = CGF.LoadCXXVTT();
> > +    if (VirtualPointerIndex)
> > +      VTT = CGF.Builder.CreateConstInBoundsGEP1_64(VTT,
> > VirtualPointerIndex);
> > +
> > +    // And load the address point from the VTT.
> > +    VTableAddressPoint = CGF.Builder.CreateLoad(VTT);
> > +  } else {
> > +    llvm::Constant *VTable =
> > +        CGM.getCXXABI().getAddrOfVTable(VTableClass, CharUnits());
> > +    uint64_t AddressPoint =
> > CGM.getVTableContext().getVTableLayout(VTableClass)
> > +        .getAddressPoint(Base);
> > +    VTableAddressPoint =
> > +        CGF.Builder.CreateConstInBoundsGEP2_64(VTable, 0, AddressPoint);
> > +  }
> > +
> > +  return VTableAddressPoint;
> > +}
> > +
> > +llvm::Constant *ItaniumCXXABI::getVTableAddressPointForConstExpr(
> > +    BaseSubobject Base, const CXXRecordDecl *VTableClass) {
> > +  llvm::Constant *VTable = getAddrOfVTable(VTableClass, CharUnits());
> > +
> > +  // Find the appropriate vtable within the vtable group.
> > +  uint64_t AddressPoint =
> > +
> >
> CGM.getVTableContext().getVTableLayout(VTableClass).getAddressPoint(Base);
> > +  llvm::Value *Indices[] = {
> > +    llvm::ConstantInt::get(CGM.Int64Ty, 0),
> > +    llvm::ConstantInt::get(CGM.Int64Ty, AddressPoint)
> > +  };
> > +
> > +  return llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Indices);
> > +}
> > +
> > +llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl
> > *RD,
> > +                                                     CharUnits
> VPtrOffset)
> > {
> > +  assert(VPtrOffset.isZero() && "Itanium ABI only supports zero vptr
> > offsets");
> > +
> > +  llvm::GlobalVariable *&VTable = VTables[RD];
> > +  if (VTable)
> > +    return VTable;
> > +
> > +  // Queue up this v-table for possible deferred emission.
> > +  CGM.addDeferredVTable(RD);
> > +
> > +  SmallString<256> OutName;
> > +  llvm::raw_svector_ostream Out(OutName);
> > +  CGM.getCXXABI().getMangleContext().mangleCXXVTable(RD, Out);
> > +  Out.flush();
> > +  StringRef Name = OutName.str();
> > +
> > +  VTableContext &VTContext = CGM.getVTableContext();
> > +  llvm::ArrayType *ArrayType = llvm::ArrayType::get(
> > +      CGM.Int8PtrTy,
> > VTContext.getVTableLayout(RD).getNumVTableComponents());
> > +
> > +  VTable = CGM.CreateOrReplaceCXXRuntimeVariable(
> > +      Name, ArrayType, llvm::GlobalValue::ExternalLinkage);
> > +  VTable->setUnnamedAddr(true);
> > +  return VTable;
> > +}
> > +
> > llvm::Value *ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction
> &CGF,
> >                                                       GlobalDecl GD,
> >                                                       llvm::Value *This,
> > @@ -919,11 +1042,10 @@ void ItaniumCXXABI::EmitVirtualDestructo
> >                         /*ImplicitParam=*/0, QualType(), 0, 0);
> > }
> >
> > -void ItaniumCXXABI::EmitVirtualInheritanceTables(
> > -    llvm::GlobalVariable::LinkageTypes Linkage, const CXXRecordDecl
> *RD) {
> > +void ItaniumCXXABI::emitVirtualInheritanceTables(const CXXRecordDecl
> *RD) {
> >   CodeGenVTables &VTables = CGM.getVTables();
> >   llvm::GlobalVariable *VTT = VTables.GetAddrOfVTT(RD);
> > -  VTables.EmitVTTDefinition(VTT, Linkage, RD);
> > +  VTables.EmitVTTDefinition(VTT, CGM.getVTableLinkage(RD), RD);
> > }
> >
> > void ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,
> >
> > Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
> > URL:
> >
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=191523&r1=191522&r2=191523&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
> > +++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Fri Sep 27 09:48:01 2013
> > @@ -21,6 +21,7 @@
> > #include "clang/AST/Decl.h"
> > #include "clang/AST/DeclCXX.h"
> > #include "clang/AST/VTableBuilder.h"
> > +#include "llvm/ADT/StringSet.h"
> >
> > using namespace clang;
> > using namespace CodeGen;
> > @@ -150,6 +151,20 @@ public:
> >                            CallExpr::const_arg_iterator ArgBeg,
> >                            CallExpr::const_arg_iterator ArgEnd);
> >
> > +  void emitVTableDefinitions(CodeGenVTables &CGVT, const CXXRecordDecl
> > *RD);
> > +
> > +  llvm::Value *getVTableAddressPointInStructor(
> > +      CodeGenFunction &CGF, const CXXRecordDecl *VTableClass,
> > +      BaseSubobject Base, const CXXRecordDecl *NearestVBase,
> > +      bool &NeedsVirtualOffset);
> > +
> > +  llvm::Constant *
> > +  getVTableAddressPointForConstExpr(BaseSubobject Base,
> > +                                    const CXXRecordDecl *VTableClass);
> > +
> > +  llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD,
> > +                                        CharUnits VPtrOffset);
> > +
> >   llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl
> > GD,
> >                                          llvm::Value *This, llvm::Type
> *Ty);
> >
> > @@ -158,8 +173,7 @@ public:
> >                                  CXXDtorType DtorType, SourceLocation
> > CallLoc,
> >                                  llvm::Value *This);
> >
> > -  void EmitVirtualInheritanceTables(llvm::GlobalVariable::LinkageTypes
> > Linkage,
> > -                                    const CXXRecordDecl *RD);
> > +  void emitVirtualInheritanceTables(const CXXRecordDecl *RD);
> >
> >   void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
> >                        llvm::GlobalVariable *DeclPtr,
> > @@ -303,7 +317,16 @@ public:
> >                                   const MemberPointerType *MPT);
> >
> > private:
> > -  /// VBTables - All the vbtables which have been referenced.
> > +  typedef std::pair<const CXXRecordDecl *, CharUnits> VFTableIdTy;
> > +  typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalVariable *>
> > VFTablesMapTy;
> > +  /// \brief All the vftables that have been referenced.
> > +  VFTablesMapTy VFTablesMap;
> > +
> > +  /// \brief This set holds the record decls we've deferred vtable
> emission
> > for.
> > +  llvm::SmallPtrSet<const CXXRecordDecl *, 4> DeferredVFTables;
> > +
> > +
> > +  /// \brief All the vbtables which have been referenced.
> >   llvm::DenseMap<const CXXRecordDecl *, VBTableVector> VBTablesMap;
> >
> >   /// Info on the global variable used to guard initialization of static
> > locals.
> > @@ -616,6 +639,116 @@ void MicrosoftCXXABI::EmitConstructorCal
> >                         ImplicitParam, ImplicitParamTy, ArgBeg, ArgEnd);
> > }
> >
> > +void MicrosoftCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
> > +                                            const CXXRecordDecl *RD) {
> > +  MicrosoftVFTableContext &VFTContext = CGM.getVFTableContext();
> > +  MicrosoftVFTableContext::VFPtrListTy VFPtrs =
> > VFTContext.getVFPtrOffsets(RD);
> > +  llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);
> > +
> > +  for (MicrosoftVFTableContext::VFPtrListTy::iterator I =
> VFPtrs.begin(),
> > +       E = VFPtrs.end(); I != E; ++I) {
> > +    llvm::GlobalVariable *VTable = getAddrOfVTable(RD,
> I->VFPtrFullOffset);
> > +    if (VTable->hasInitializer())
> > +      continue;
> > +
> > +    const VTableLayout &VTLayout =
> > +        VFTContext.getVFTableLayout(RD, I->VFPtrFullOffset);
> > +    llvm::Constant *Init = CGVT.CreateVTableInitializer(
> > +        RD, VTLayout.vtable_component_begin(),
> > +        VTLayout.getNumVTableComponents(),
> VTLayout.vtable_thunk_begin(),
> > +        VTLayout.getNumVTableThunks());
> > +    VTable->setInitializer(Init);
> > +
> > +    VTable->setLinkage(Linkage);
> > +    CGM.setTypeVisibility(VTable, RD, CodeGenModule::TVK_ForVTable);
> > +  }
> > +}
> > +
> > +llvm::Value *MicrosoftCXXABI::getVTableAddressPointInStructor(
> > +    CodeGenFunction &CGF, const CXXRecordDecl *VTableClass,
> BaseSubobject
> > Base,
> > +    const CXXRecordDecl *NearestVBase, bool &NeedsVirtualOffset) {
> > +  NeedsVirtualOffset = (NearestVBase != 0);
> > +
> > +  llvm::Value *VTableAddressPoint =
> > +      getAddrOfVTable(VTableClass, Base.getBaseOffset());
> > +  if (!VTableAddressPoint) {
> > +    assert(Base.getBase()->getNumVBases() &&
> > +
> > !CGM.getContext().getASTRecordLayout(Base.getBase()).hasOwnVFPtr());
> > +  }
> > +  return VTableAddressPoint;
> > +}
> > +
> > +static void mangleVFTableName(CodeGenModule &CGM, const CXXRecordDecl
> *RD,
> > +                              const VFPtrInfo &VFPtr, SmallString<256>
> > &Name) {
> > +  llvm::raw_svector_ostream Out(Name);
> > +  CGM.getCXXABI().getMangleContext().mangleCXXVFTable(
> > +      RD, VFPtr.PathToMangle, Out);
> > +}
> > +
> > +llvm::Constant *MicrosoftCXXABI::getVTableAddressPointForConstExpr(
> > +    BaseSubobject Base, const CXXRecordDecl *VTableClass) {
> > +  llvm::Constant *VTable = getAddrOfVTable(VTableClass,
> > Base.getBaseOffset());
> > +  assert(VTable && "Couldn't find a vftable for the given base?");
> > +  return VTable;
> > +}
> > +
> > +llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const
> CXXRecordDecl
> > *RD,
> > +                                                       CharUnits
> > VPtrOffset) {
> > +  // getAddrOfVTable may return 0 if asked to get an address of a vtable
> > which
> > +  // shouldn't be used in the given record type. We want to cache this
> > result in
> > +  // VFTablesMap, thus a simple zero check is not sufficient.
> > +  VFTableIdTy ID(RD, VPtrOffset);
> > +  VFTablesMapTy::iterator I;
> > +  bool Inserted;
> > +  llvm::tie(I, Inserted) = VFTablesMap.insert(
> > +      std::make_pair(ID, static_cast<llvm::GlobalVariable *>(0)));
> > +  if (!Inserted)
> > +    return I->second;
> > +
> > +  llvm::GlobalVariable *&VTable = I->second;
> > +
> > +  MicrosoftVFTableContext &VFTContext = CGM.getVFTableContext();
> > +  const MicrosoftVFTableContext::VFPtrListTy &VFPtrs =
> > +      VFTContext.getVFPtrOffsets(RD);
> > +
> > +  if (DeferredVFTables.insert(RD)) {
> > +    // We haven't processed this record type before.
> > +    // Queue up this v-table for possible deferred emission.
> > +    CGM.addDeferredVTable(RD);
> > +
> > +#ifndef NDEBUG
> > +    // Create all the vftables at once in order to make sure each
> vftable
> > has
> > +    // a unique mangled name.
> > +    llvm::StringSet<> ObservedMangledNames;
> > +    for (size_t J = 0, F = VFPtrs.size(); J != F; ++J) {
> > +      SmallString<256> Name;
> > +      mangleVFTableName(CGM, RD, VFPtrs[J], Name);
> > +      if (!ObservedMangledNames.insert(Name.str()))
> > +        llvm_unreachable("Already saw this mangling before?");
> > +    }
> > +#endif
> > +  }
> > +
> > +  for (size_t J = 0, F = VFPtrs.size(); J != F; ++J) {
> > +    if (VFPtrs[J].VFPtrFullOffset != VPtrOffset)
> > +      continue;
> > +
> > +    llvm::ArrayType *ArrayType = llvm::ArrayType::get(
> > +        CGM.Int8PtrTy,
> > +        VFTContext.getVFTableLayout(RD, VFPtrs[J].VFPtrFullOffset)
> > +            .getNumVTableComponents());
> > +
> > +    SmallString<256> Name;
> > +    mangleVFTableName(CGM, RD, VFPtrs[J], Name);
> > +    VTable = CGM.CreateOrReplaceCXXRuntimeVariable(
> > +        Name.str(), ArrayType, llvm::GlobalValue::ExternalLinkage);
> > +    VTable->setUnnamedAddr(true);
> > +    break;
> > +  }
> > +
> > +  return VTable;
> > +}
> > +
> > llvm::Value *MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction
> > &CGF,
> >                                                         GlobalDecl GD,
> >                                                         llvm::Value
> *This,
> > @@ -674,9 +807,10 @@ MicrosoftCXXABI::EnumerateVBTables(const
> >   return VBTables;
> > }
> >
> > -void MicrosoftCXXABI::EmitVirtualInheritanceTables(
> > -    llvm::GlobalVariable::LinkageTypes Linkage, const CXXRecordDecl
> *RD) {
> > +void MicrosoftCXXABI::emitVirtualInheritanceTables(const CXXRecordDecl
> *RD)
> > {
> >   const VBTableVector &VBTables = EnumerateVBTables(RD);
> > +  llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);
> > +
> >   for (VBTableVector::const_iterator I = VBTables.begin(), E =
> > VBTables.end();
> >        I != E; ++I) {
> >     I->EmitVBTableDefinition(CGM, RD, Linkage);
> >
> > Added:
> cfe/trunk/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp
> > URL:
> >
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp?rev=191523&view=auto
> >
> ==============================================================================
> > --- cfe/trunk/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp
> > (added)
> > +++ cfe/trunk/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp
> Fri
> > Sep 27 09:48:01 2013
> > @@ -0,0 +1,23 @@
> > +// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm %s -o - -cxx-abi
> > microsoft -triple=i386-pc-win32 | FileCheck %s
> > +
> > +struct A {
> > +  constexpr A(int x) : x(x) {}
> > +  virtual void f();
> > +  int x;
> > +};
> > +
> > +A a(42);
> > +// CHECK: @"\01?a@@3UA@@A" = global { [1 x i8*]*, i32 } { [1 x i8*]*
> > @"\01??_7A@@6B@", i32 42 }, align 4
> > +
> > +struct B {
> > +  constexpr B(int y) : y(y) {}
> > +  virtual void g();
> > +  int y;
> > +};
> > +
> > +struct C : A, B {
> > +  constexpr C() : A(777), B(13) {}
> > +};
> > +
> > +C c;
> > +// CHECK: @"\01?c@@3UC@@A" = global { [1 x i8*]*, i32, [1 x i8*]*, i32
> } {
> > [1 x i8*]* @"\01??_7C@@6BA@@@", i32 777, [1 x i8*]* @"\01??_7C@@6BB@@@",
> i32
> > 13 }
> >
> > Modified:
> >
> cfe/trunk/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp
> > URL:
> >
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp?rev=191523&r1=191522&r2=191523&view=diff
> >
> ==============================================================================
> > ---
> >
> cfe/trunk/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp
> > (original)
> > +++
> >
> cfe/trunk/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp
> > Fri Sep 27 09:48:01 2013
> > @@ -145,3 +145,39 @@ void call_grandchild_right(GrandchildOve
> >   // Just make sure we don't crash.
> >   obj->right();
> > }
> > +
> > +void emit_ctors() {
> > +  Left l;
> > +  // CHECK: define {{.*}} @"\01??0Left@@QAE at XZ"
> > +  // CHECK-NOT: getelementptr
> > +  // CHECK:   store [1 x i8*]* @"\01??_7Left@@6B@"
> > +  // CHECK: ret
> > +
> > +  Right r;
> > +  // CHECK: define {{.*}} @"\01??0Right@@QAE at XZ"
> > +  // CHECK-NOT: getelementptr
> > +  // CHECK:   store [1 x i8*]* @"\01??_7Right@@6B@"
> > +  // CHECK: ret
> > +
> > +  ChildOverride co;
> > +  // CHECK: define {{.*}} @"\01??0ChildOverride@@QAE at XZ"
> > +  // CHECK:   %[[THIS:.*]] = load %struct.ChildOverride**
> > +  // CHECK:   %[[VFPTR:.*]] = bitcast %struct.ChildOverride* %this1 to
> [1 x
> > i8*]**
> > +  // CHECK:   store [1 x i8*]* @"\01??_7ChildOverride@@6BLeft@@@", [1 x
> > i8*]** %[[VFPTR]]
> > +  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.ChildOverride*
> %[[THIS]] to
> > i8*
> > +  // CHECK:   %[[VFPTR_i8:.*]] = getelementptr inbounds i8*
> %[[THIS_i8]],
> > i32 4
> > +  // CHECK:   %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [1 x i8*]**
> > +  // CHECK:   store [1 x i8*]* @"\01??_7ChildOverride@@6BRight@@@", [1
> x
> > i8*]** %[[VFPTR]]
> > +  // CHECK: ret
> > +
> > +  GrandchildOverride gc;
> > +  // CHECK: define {{.*}} @"\01??0GrandchildOverride@@QAE at XZ"
> > +  // CHECK:   %[[THIS:.*]] = load %struct.GrandchildOverride**
> > +  // CHECK:   %[[VFPTR:.*]] = bitcast %struct.GrandchildOverride*
> %this1 to
> > [1 x i8*]**
> > +  // CHECK:   store [1 x i8*]* @"\01??_7GrandchildOverride@@6BLeft@@@",
> [1
> > x i8*]** %[[VFPTR]]
> > +  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.GrandchildOverride*
> > %[[THIS]] to i8*
> > +  // CHECK:   %[[VFPTR_i8:.*]] = getelementptr inbounds i8*
> %[[THIS_i8]],
> > i32 4
> > +  // CHECK:   %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [1 x i8*]**
> > +  // CHECK:   store [1 x i8*]* @"\01??_7GrandchildOverride@@6BRight@@@",
> [1
> > x i8*]** %[[VFPTR]]
> > +  // CHECK: ret
> > +}
> >
> > Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp
> > URL:
> >
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp?rev=191523&r1=191522&r2=191523&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp (original)
> > +++ cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp Fri Sep 27
> > 09:48:01 2013
> > @@ -71,8 +71,8 @@ void C::foo() {}
> > void check_vftable_offset() {
> >   C c;
> > // The vftable pointer should point at the beginning of the vftable.
> > -// CHECK: [[THIS_PTR:%[0-9]+]] = bitcast %"struct.basic::C"* {{.*}} to
> > i8***
> > -// CHECK: store i8** getelementptr inbounds ([2 x i8*]*
> > @"\01??_7C at basic@@6B@", i64 0, i64 0), i8*** [[THIS_PTR]]
> > +// CHECK: [[THIS_PTR:%[0-9]+]] = bitcast %"struct.basic::C"* {{.*}} to
> [2 x
> > i8*]**
> > +// CHECK: store [2 x i8*]* @"\01??_7C at basic@@6B@", [2 x i8*]**
> [[THIS_PTR]]
> > }
> >
> > void call_complete_dtor(C *obj_ptr) {
> > @@ -161,7 +161,8 @@ C::C() {
> >   // CHECK-NEXT: br label %[[SKIP_VBASES]]
> >   //
> >   // CHECK: [[SKIP_VBASES]]
> > -  // CHECK: @"\01??_7C at constructors@@6B@"
> > +  // Class C does not define or override methods, so shouldn't change
> the
> > vfptr.
> > +  // CHECK-NOT: @"\01??_7C at constructors@@6B@"
> >   // CHECK: ret
> > }
> >
> >
> > Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
> > URL:
> >
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp?rev=191523&r1=191522&r2=191523&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
> > (original)
> > +++ cfe/trunk/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp Fri
> Sep
> > 27 09:48:01 2013
> > @@ -7,10 +7,26 @@ struct VBase {
> > };
> >
> > struct B : virtual VBase {
> > +  B();
> >   virtual void foo();
> >   virtual void bar();
> > };
> >
> > +B::B() {
> > +  // CHECK: @"\01??0B@@QAE at XZ"
> > +  // CHECK:   %[[THIS:.*]] = load %struct.B**
> > +  // CHECK:   br i1 %{{.*}}, label %[[INIT_VBASES:.*]], label
> > %[[SKIP_VBASES:.*]]
> > +  // CHECK: %[[SKIP_VBASES]]
> > +  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
> > +  // CHECK:   %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS_i8]],
> i32
> > 0
> > +  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
> > +  // CHECK:   %[[VFPTR_i8:.*]] = getelementptr inbounds i8*
> %[[THIS_i8]],
> > i32 %{{.*}}
> > +  // CHECK:   %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [2 x i8*]**
> > +  // CHECK:   store [2 x i8*]* @"\01??_7B@@6B@", [2 x i8*]** %[[VFPTR]]
> > +  // FIXME: Should initialize the vtorDisp here.
> > +  // CHECK: ret
> > +}
> > +
> > void B::foo() {
> > // CHECK: define x86_thiscallcc void @"\01?foo at B@@UAEXXZ"(i8*
> > //
> >
> > Modified:
> >
> cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp
> > URL:
> >
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp?rev=191523&r1=191522&r2=191523&view=diff
> >
> ==============================================================================
> > ---
> >
> cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp
> > (original)
> > +++
> >
> cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp
> > Fri Sep 27 09:48:01 2013
> > @@ -19,6 +19,8 @@
> > // RUN: FileCheck --check-prefix=RET-THUNKS-Test4 %s < %t
> > // RUN: FileCheck --check-prefix=RET-THUNKS-Test5 %s < %t
> >
> > +// RUN: FileCheck --check-prefix=MANGLING %s < %t
> > +
> > struct Empty {
> >   // Doesn't have a vftable!
> > };
> > @@ -51,6 +53,9 @@ struct Test1: A, B {
> >   // NO-THUNKS-Test1: VFTable indices for 'no_thunks::Test1' (1 entries)
> >   // NO-THUNKS-Test1-NEXT: 0 | void no_thunks::Test1::f()
> >
> > +  // MANGLING-DAG: @"\01??_7Test1 at no_thunks@@6BA@@@"
> > +  // MANGLING-DAG: @"\01??_7Test1 at no_thunks@@6BB@@@"
> > +
> >   // Overrides only the left child's method (A::f), needs no thunks.
> >   virtual void f();
> > };
> > @@ -102,6 +107,8 @@ struct Test4 : Empty, A {
> >   // NO-THUNKS-Test4: VFTable indices for 'no_thunks::Test4' (1 entries).
> >   // NO-THUNKS-Test4-NEXT: 0 | void no_thunks::Test4::f()
> >
> > +  // MANGLING-DAG: @"\01??_7Test4 at no_thunks@@6B@"
> > +
> >   virtual void f();
> > };
> >
> > @@ -127,6 +134,11 @@ struct Test5: Test1, Test2 {
> >   // NO-THUNKS-Test5: VFTable indices for 'no_thunks::Test5' (1 entries).
> >   // NO-THUNKS-Test5-NEXT: 1 | void no_thunks::Test5::z()
> >
> > +  // MANGLING-DAG: @"\01??_7Test5 at no_thunks@@6BA@@Test1 at 1@@"
> > +  // MANGLING-DAG: @"\01??_7Test5 at no_thunks@@6BA@@Test2 at 1@@"
> > +  // MANGLING-DAG: @"\01??_7Test5 at no_thunks@@6BB@@Test1 at 1@@"
> > +  // MANGLING-DAG: @"\01??_7Test5 at no_thunks@@6BB@@Test2 at 1@@"
> > +
> >   virtual void z();
> > };
> >
> > @@ -143,6 +155,9 @@ struct Test6: Test1 {
> >   // NO-THUNKS-Test6: VFTable indices for 'no_thunks::Test6' (1 entries).
> >   // NO-THUNKS-Test6-NEXT: 0 | void no_thunks::Test6::f()
> >
> > +  // MANGLING-DAG: @"\01??_7Test6 at no_thunks@@6BA@@@"
> > +  // MANGLING-DAG: @"\01??_7Test6 at no_thunks@@6BB@@@"
> > +
> >   // Overrides both no_thunks::Test1::f and A::f.
> >   virtual void f();
> > };
> > @@ -203,6 +218,9 @@ struct Test9: A, D {
> >   // NO-THUNKS-Test9: VFTable indices for 'no_thunks::Test9' (1 entries).
> >   // NO-THUNKS-Test9-NEXT: 1 | void no_thunks::Test9::h()
> >
> > +  // MANGLING-DAG: @"\01??_7Test9 at no_thunks@@6BA@@@"
> > +  // MANGLING-DAG: @"\01??_7Test9 at no_thunks@@6BD at 1@@"
> > +
> >   virtual void h();
> > };
> >
> > @@ -228,6 +246,9 @@ struct Test1: A, D {
> >   // PURE-VIRTUAL-Test1-NEXT: via vfptr at offset 4
> >   // PURE-VIRTUAL-Test1-NEXT: 0 | void pure_virtual::Test1::g()
> >
> > +  // MANGLING-DAG: @"\01??_7Test1 at pure_virtual@@6BA@@@"
> > +  // MANGLING-DAG: @"\01??_7Test1 at pure_virtual@@6BD at 1@@"
> > +
> >   // Overrides only the right child's method (pure_virtual::D::g), needs
> > this adjustment but
> >   // not thunks.
> >   virtual void g();
> > @@ -254,6 +275,9 @@ struct Test1 : B, C {
> >   // THIS-THUNKS-Test1: VFTable indices for 'this_adjustment::Test1' (1
> > entries).
> >   // THIS-THUNKS-Test1-NEXT: 0 | void this_adjustment::Test1::g()
> >
> > +  // MANGLING-DAG: @"\01??_7Test1 at this_adjustment@@6BB@@@"
> > +  // MANGLING-DAG: @"\01??_7Test1 at this_adjustment@@6BC@@@"
> > +
> >   virtual void g();
> > };
> >
> > @@ -278,6 +302,10 @@ struct Test2 : A, B, C {
> >   // THIS-THUNKS-Test2-NEXT: via vfptr at offset 4
> >   // THIS-THUNKS-Test2-NEXT: 0 | void this_adjustment::Test2::g()
> >
> > +  // MANGLING-DAG: @"\01??_7Test2 at this_adjustment@@6BA@@@"
> > +  // MANGLING-DAG: @"\01??_7Test2 at this_adjustment@@6BB@@@"
> > +  // MANGLING-DAG: @"\01??_7Test2 at this_adjustment@@6BC@@@"
> > +
> >   virtual void g();
> > };
> >
> > @@ -337,6 +365,8 @@ struct Test1 : Ret1 {
> >   // RET-THUNKS-Test1: VFTable indices for 'return_adjustment::Test1' (1
> > entries).
> >   // RET-THUNKS-Test1-NEXT: 2 | this_adjustment::Test1
> > *return_adjustment::Test1::foo()
> >
> > +  // MANGLING-DAG: @"\01??_7Test1 at return_adjustment@@6B@"
> > +
> >   virtual this_adjustment::Test1* foo();
> > };
> >
> >
> > Modified:
> > cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
> > URL:
> >
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp?rev=191523&r1=191522&r2=191523&view=diff
> >
> ==============================================================================
> > ---
> cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
> > (original)
> > +++
> cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
> > Fri Sep 27 09:48:01 2013
> > @@ -1,6 +1,6 @@
> > // RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=i386-pc-win32
> > -emit-llvm -fdump-vtable-layouts -o - > %t 2>&1
> > -// RUN: FileCheck --check-prefix=EMITS-VTABLE %s < %t
> > -// RUN: FileCheck --check-prefix=NO-VTABLE %s < %t
> > +// RUN: FileCheck --check-prefix=EMITS-VFTABLE %s < %t
> > +// RUN: FileCheck --check-prefix=NO-VFTABLE %s < %t
> > // RUN: FileCheck --check-prefix=CHECK-A %s < %t
> > // RUN: FileCheck --check-prefix=CHECK-B %s < %t
> > // RUN: FileCheck --check-prefix=CHECK-C %s < %t
> > @@ -10,19 +10,12 @@
> > // RUN: FileCheck --check-prefix=CHECK-G %s < %t
> > // RUN: FileCheck --check-prefix=CHECK-I %s < %t
> >
> > -// FIXME: Currently, we only test VFTableContext in the AST, but still
> use
> > -// VTableContext for CodeGen. We should remove the "Vtable" checks below
> > when we
> > -// completely switch from VTableContext to VFTableContext.
> > -// Currently, the order of Vtable vs VFTable output depends on whether
> the
> > -// v*table info was required by a constructor or a method definition.
> > -
> > struct A {
> >   // CHECK-A: VFTable for 'A' (3 entries)
> >   // CHECK-A-NEXT: 0 | void A::f()
> >   // CHECK-A-NEXT: 1 | void A::g()
> >   // CHECK-A-NEXT: 2 | void A::h()
> > -
> > -  // CHECK-A: Vtable for 'A' (3 entries)
> > +  // CHECK-A: VFTable indices for 'A' (3 entries)
> >   // CHECK-A-NEXT: 0 | void A::f()
> >   // CHECK-A-NEXT: 1 | void A::g()
> >   // CHECK-A-NEXT: 2 | void A::h()
> > @@ -33,20 +26,17 @@ struct A {
> >   int ia;
> > };
> > A a;
> > -// EMITS-VTABLE-DAG: @"\01??_7A@@6B@" = linkonce_odr unnamed_addr
> constant
> > [3 x i8*]
> > +// EMITS-VFTABLE-DAG: @"\01??_7A@@6B@" = linkonce_odr unnamed_addr
> constant
> > [3 x i8*]
> >
> > struct B : A {
> > -  // CHECK-B: Vtable for 'B' (5 entries)
> > +  // CHECK-B: VFTable for 'A' in 'B' (5 entries)
> >   // CHECK-B-NEXT: 0 | void B::f()
> >   // CHECK-B-NEXT: 1 | void A::g()
> >   // CHECK-B-NEXT: 2 | void A::h()
> >   // CHECK-B-NEXT: 3 | void B::i()
> >   // CHECK-B-NEXT: 4 | void B::j()
> > -
> > -  // CHECK-B: VFTable for 'A' in 'B' (5 entries)
> > +  // CHECK-B: VFTable indices for 'B' (3 entries)
> >   // CHECK-B-NEXT: 0 | void B::f()
> > -  // CHECK-B-NEXT: 1 | void A::g()
> > -  // CHECK-B-NEXT: 2 | void A::h()
> >   // CHECK-B-NEXT: 3 | void B::i()
> >   // CHECK-B-NEXT: 4 | void B::j()
> >
> > @@ -55,7 +45,7 @@ struct B : A {
> >   virtual void j();
> > };
> > B b;
> > -// EMITS-VTABLE-DAG: @"\01??_7B@@6B@" = linkonce_odr unnamed_addr
> constant
> > [5 x i8*]
> > +// EMITS-VFTABLE-DAG: @"\01??_7B@@6B@" = linkonce_odr unnamed_addr
> constant
> > [5 x i8*]
> >
> > struct C {
> >   // CHECK-C: VFTable for 'C' (2 entries)
> > @@ -65,25 +55,17 @@ struct C {
> >   // CHECK-C-NEXT: 0 | C::~C() [scalar deleting]
> >   // CHECK-C-NEXT: 1 | void C::f()
> >
> > -  // CHECK-C: Vtable for 'C' (2 entries)
> > -  // CHECK-C-NEXT: 0 | C::~C() [scalar deleting]
> > -  // CHECK-C-NEXT: 1 | void C::f()
> > -  // CHECK-C: VTable indices for 'C' (2 entries).
> > -  // CHECK-C-NEXT: 0 | C::~C() [scalar deleting]
> > -  // CHECK-C-NEXT: 1 | void C::f()
> > -
> >   virtual ~C();
> >   virtual void f();
> > };
> > void C::f() {}
> > -// NO-VTABLE-NOT: @"\01??_7C@@6B@"
> > +// NO-VFTABLE-NOT: @"\01??_7C@@6B@"
> >
> > struct D {
> > -  // CHECK-D: Vtable for 'D' (2 entries)
> > +  // CHECK-D: VFTable for 'D' (2 entries)
> >   // CHECK-D-NEXT: 0 | void D::f()
> >   // CHECK-D-NEXT: 1 | D::~D() [scalar deleting]
> > -
> > -  // CHECK-D: VFTable for 'D' (2 entries)
> > +  // CHECK-D: VFTable indices for 'D' (2 entries)
> >   // CHECK-D-NEXT: 0 | void D::f()
> >   // CHECK-D-NEXT: 1 | D::~D() [scalar deleting]
> >
> > @@ -91,7 +73,7 @@ struct D {
> >   virtual ~D();
> > };
> > D d;
> > -// EMITS-VTABLE-DAG: @"\01??_7D@@6B@" = linkonce_odr unnamed_addr
> constant
> > [2 x i8*]
> > +// EMITS-VFTABLE-DAG: @"\01??_7D@@6B@" = linkonce_odr unnamed_addr
> constant
> > [2 x i8*]
> >
> > struct E : A {
> >   // CHECK-E: VFTable for 'A' in 'E' (5 entries)
> > @@ -104,35 +86,15 @@ struct E : A {
> >   // CHECK-E-NEXT: 3 | E::~E() [scalar deleting]
> >   // CHECK-E-NEXT: 4 | void E::i()
> >
> > -  // CHECK-E: Vtable for 'E' (5 entries)
> > -  // CHECK-E-NEXT: 0 | void A::f()
> > -  // CHECK-E-NEXT: 1 | void A::g()
> > -  // CHECK-E-NEXT: 2 | void A::h()
> > -  // CHECK-E-NEXT: 3 | E::~E() [scalar deleting]
> > -  // CHECK-E-NEXT: 4 | void E::i()
> > -  // CHECK-E: VTable indices for 'E' (2 entries).
> > -  // CHECK-E-NEXT: 3 | E::~E() [scalar deleting]
> > -  // CHECK-E-NEXT: 4 | void E::i()
> > -
> >   // ~E would be the key method, but it isn't used, and MS ABI has no key
> >   // methods.
> >   virtual ~E();
> >   virtual void i();
> > };
> > void E::i() {}
> > -// NO-VTABLE-NOT: @"\01??_7E@@6B@"
> > +// NO-VFTABLE-NOT: @"\01??_7E@@6B@"
> >
> > struct F : A {
> > -  // CHECK-F: Vtable for 'F' (5 entries)
> > -  // CHECK-F-NEXT: 0 | void A::f()
> > -  // CHECK-F-NEXT: 1 | void A::g()
> > -  // CHECK-F-NEXT: 2 | void A::h()
> > -  // CHECK-F-NEXT: 3 | void F::i()
> > -  // CHECK-F-NEXT: 4 | F::~F() [scalar deleting]
> > -  // CHECK-F: VTable indices for 'F' (2 entries).
> > -  // CHECK-F-NEXT: 3 | void F::i()
> > -  // CHECK-F-NEXT: 4 | F::~F() [scalar deleting]
> > -
> >   // CHECK-F: VFTable for 'A' in 'F' (5 entries)
> >   // CHECK-F-NEXT: 0 | void A::f()
> >   // CHECK-F-NEXT: 1 | void A::g()
> > @@ -147,7 +109,7 @@ struct F : A {
> >   virtual ~F();
> > };
> > F f;
> > -// EMITS-VTABLE-DAG: @"\01??_7F@@6B@" = linkonce_odr unnamed_addr
> constant
> > [5 x i8*]
> > +// EMITS-VFTABLE-DAG: @"\01??_7F@@6B@" = linkonce_odr unnamed_addr
> constant
> > [5 x i8*]
> >
> > struct G : E {
> >   // CHECK-G: VFTable for 'A' in 'E' in 'G' (6 entries)
> > @@ -162,31 +124,19 @@ struct G : E {
> >   // CHECK-G-NEXT: 3 | G::~G() [scalar deleting]
> >   // CHECK-G-NEXT: 5 | void G::j()
> >
> > -  // CHECK-G: Vtable for 'G' (6 entries)
> > -  // CHECK-G-NEXT: 0 | void G::f()
> > -  // CHECK-G-NEXT: 1 | void A::g()
> > -  // CHECK-G-NEXT: 2 | void A::h()
> > -  // CHECK-G-NEXT: 3 | G::~G() [scalar deleting]
> > -  // CHECK-G-NEXT: 4 | void E::i()
> > -  // CHECK-G-NEXT: 5 | void G::j()
> > -  // CHECK-G: VTable indices for 'G' (3 entries).
> > -  // CHECK-G-NEXT: 0 | void G::f()
> > -  // CHECK-G-NEXT: 3 | G::~G() [scalar deleting]
> > -  // CHECK-G-NEXT: 5 | void G::j()
> > -
> >   virtual void f();  // overrides A::f()
> >   virtual ~G();
> >   virtual void j();
> > };
> > void G::j() {}
> > -// NO-VTABLE-NOT: @"\01??_7G@@6B@"
> > +// NO-VFTABLE-NOT: @"\01??_7G@@6B@"
> >
> > // Test that the usual Itanium-style key method does not emit a vtable.
> > struct H {
> >   virtual void f();
> > };
> > void H::f() {}
> > -// NO-VTABLE-NOT: @"\01??_7H@@6B@"
> > +// NO-VFTABLE-NOT: @"\01??_7H@@6B@"
> >
> > struct Empty { };
> >
> >
> > Modified:
> > cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
> > URL:
> >
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp?rev=191523&r1=191522&r2=191523&view=diff
> >
> ==============================================================================
> > ---
> cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
> > (original)
> > +++
> cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
> > Fri Sep 27 09:48:01 2013
> > @@ -18,6 +18,8 @@
> > // RUN: FileCheck --check-prefix=RET-W %s < %t
> > // RUN: FileCheck --check-prefix=RET-T %s < %t
> >
> > +// RUN: FileCheck --check-prefix=MANGLING %s < %t
> > +
> > struct Empty { };
> >
> > struct A {
> > @@ -38,6 +40,8 @@ struct C: virtual A {
> >   // VTABLE-C-NEXT: vbtable index 1, vfptr at offset 0
> >   // VTABLE-C-NEXT: 0 | void C::f()
> >
> > +  // MANGLING-DAG: @"\01??_7C@@6B@"
> > +
> >   ~C();  // Currently required to have correct record layout, see PR16406
> >   virtual void f();
> > };
> > @@ -58,6 +62,9 @@ struct D: virtual A {
> >   // VTABLE-D-NEXT: via vbtable index 1, vfptr at offset 0
> >   // VTABLE-D-NEXT: 0 | void D::f()
> >
> > +  // MANGLING-DAG: @"\01??_7D@@6B0@@"
> > +  // MANGLING-DAG: @"\01??_7D@@6BA@@@"
> > +
> >   virtual void f();
> >   virtual void h();
> > };
> > @@ -71,6 +78,7 @@ struct X { int x; };
> >
> > // X and A get reordered in the layout since X doesn't have a vfptr
> while A
> > has.
> > struct Y : X, A { };
> > +// MANGLING-DAG: @"\01??_7Y at Test1@@6B@"
> >
> > struct Z : virtual Y {
> >   // TEST1: VFTable for 'A' in 'Test1::Y' in 'Test1::Z' (2 entries).
> > @@ -78,6 +86,8 @@ struct Z : virtual Y {
> >   // TEST1-NEXT: 1 | void A::z()
> >
> >   // TEST1-NOT: VFTable indices for 'Test1::Z'
> > +
> > +  // MANGLING-DAG: @"\01??_7Z at Test1@@6B@"
> > };
> >
> > Z z;
> > @@ -99,6 +109,10 @@ struct X: virtual A, virtual B {
> >   // TEST2: VFTable indices for 'Test2::X' (1 entries).
> >   // TEST2-NEXT: 0 | void Test2::X::h()
> >
> > +  // MANGLING-DAG: @"\01??_7X at Test2@@6B01@@"
> > +  // MANGLING-DAG: @"\01??_7X at Test2@@6BA@@@"
> > +  // MANGLING-DAG: @"\01??_7X at Test2@@6BB@@@"
> > +
> >   virtual void h();
> > };
> >
> > @@ -107,7 +121,9 @@ X x;
> >
> > namespace Test3 {
> >
> > -struct X : virtual A { };
> > +struct X : virtual A {
> > +  // MANGLING-DAG: @"\01??_7X at Test3@@6B@"
> > +};
> >
> > struct Y: virtual X {
> >   // TEST3: VFTable for 'A' in 'Test3::X' in 'Test3::Y' (2 entries).
> > @@ -115,6 +131,8 @@ struct Y: virtual X {
> >   // TEST3-NEXT: 1 | void A::z()
> >
> >   // TEST3-NOT: VFTable indices for 'Test3::Y'
> > +
> > +  // MANGLING-DAG: @"\01??_7Y at Test3@@6B@"
> > };
> >
> > Y y;
> > @@ -134,6 +152,8 @@ struct X: virtual C {
> >   // TEST4-NEXT: 1 | void A::z()
> >
> >   // TEST4-NOT: VFTable indices for 'Test4::X'
> > +
> > +  // MANGLING-DAG: @"\01??_7X at Test4@@6B@"
> > };
> >
> > X x;
> > @@ -143,6 +163,7 @@ namespace Test5 {
> >
> > // New methods are added to the base's vftable.
> > struct X : A {
> > +  // MANGLING-DAG: @"\01??_7X at Test5@@6B@"
> >   virtual void g();
> > };
> >
> > @@ -158,6 +179,9 @@ struct Y : virtual X {
> >   // TEST5: VFTable indices for 'Test5::Y' (1 entries).
> >   // TEST5-NEXT: 0 | void Test5::Y::h()
> >
> > +  // MANGLING-DAG: @"\01??_7Y at Test5@@6B01@@"
> > +  // MANGLING-DAG: @"\01??_7Y at Test5@@6BX at 1@@"
> > +
> >   virtual void h();
> > };
> >
> > @@ -172,6 +196,8 @@ struct X : A, virtual Empty {
> >   // TEST6-NEXT: 1 | void A::z()
> >
> >   // TEST6-NOT: VFTable indices for 'Test6::X'
> > +
> > +  // MANGLING-DAG: @"\01??_7X at Test6@@6B@"
> > };
> >
> > X x;
> > @@ -179,7 +205,9 @@ X x;
> >
> > namespace Test7 {
> >
> > -struct X : C { };
> > +struct X : C {
> > +  // MANGLING-DAG: @"\01??_7X at Test7@@6B@"
> > +};
> >
> > struct Y : virtual X {
> >   // TEST7: VFTable for 'A' in 'C' in 'Test7::X' in 'Test7::Y' (2
> entries).
> > @@ -191,6 +219,8 @@ struct Y : virtual X {
> >   // TEST7-NEXT: 0 | this adjustment: 12 non-virtual
> >
> >   // TEST7-NOT: VFTable indices for 'Test7::Y'
> > +
> > +  // MANGLING-DAG: @"\01??_7Y at Test7@@6B@"
> > };
> >
> > Y y;
> > @@ -210,6 +240,9 @@ struct X : D, C {
> >   // TEST8: VFTable indices for 'Test8::X' (1 entries).
> >   // TEST8-NEXT: via vbtable index 1, vfptr at offset 0
> >
> > +  // MANGLING-DAG: @"\01??_7X at Test8@@6BA@@@"
> > +  // MANGLING-DAG: @"\01??_7X at Test8@@6BD@@@"
> > +
> >   virtual void f();
> > };
> >
> > @@ -231,6 +264,9 @@ struct Y : virtual X {
> >   // TEST9-Y: VFTable indices for 'Test9::Y' (1 entries).
> >   // TEST9-Y-NEXT: 0 | void Test9::Y::h()
> >
> > +  // MANGLING-DAG: @"\01??_7Y at Test9@@6B01@@"
> > +  // MANGLING-DAG: @"\01??_7Y at Test9@@6BX at 1@@"
> > +
> >   virtual void h();
> > };
> >
> > @@ -248,6 +284,13 @@ struct Z : Y, virtual B {
> >   // TEST9-Z-NEXT: 0 | void B::g()
> >
> >   // TEST9-Z-NOT: VFTable indices for 'Test9::Z'
> > +
> > +  // MANGLING-DAG: @"\01??_7Z at Test9@@6BX at 1@@"
> > +  // MANGLING-DAG: @"\01??_7Z at Test9@@6BY at 1@@"
> > +
> > +  // FIXME this one is wrong:
> > +  // INCORRECT MANGLING-DAG: @"\01??_7Z at Test9@@6BB@@@"
> > +  // MANGLING-DAG-SHOULD-BE: @"\01??_7Z at Test9@@6B@"
> > };
> >
> > Z z;
> > @@ -275,6 +318,16 @@ struct W : Z, D, virtual A, virtual B {
> >   // TEST9-W-NEXT: 0 | this adjustment: -8 non-virtual
> >
> >   // TEST9-W-NOT: VFTable indices for 'Test9::W'
> > +
> > +  // MANGLING-DAG: @"\01??_7W at Test9@@6BA@@@"
> > +  // MANGLING-DAG: @"\01??_7W at Test9@@6BD@@@"
> > +  // MANGLING-DAG: @"\01??_7W at Test9@@6BX at 1@@"
> > +
> > +  // FIXME: these two are wrong:
> > +  // INCORRECT MANGLING-DAG: @"\01??_7W at Test9@@6BB@@@"
> > +  // MANGLING-DAG-SHOULD-BE: @"\01??_7W at Test9@@6B@"
> > +  // INCORRECT MANGLING-DAG: @"\01??_7W at Test9@@6BY at 1@Z at 1@@"
> > +  // MANGLING-DAG-SHOULD-BE: @"\01??_7W at Test9@@6BY at 1@@"
> > };
> >
> > W w;
> > @@ -320,6 +373,16 @@ struct T : Z, D, virtual A, virtual B {
> >   // TEST9-T-NEXT: via vbtable index 2, vfptr at offset 0
> >   // TEST9-T-NEXT: 0 | void Test9::T::g()
> >
> > +  // MANGLING-DAG: @"\01??_7T at Test9@@6BA@@@"
> > +  // MANGLING-DAG: @"\01??_7T at Test9@@6BD@@@"
> > +  // MANGLING-DAG: @"\01??_7T at Test9@@6BX at 1@@"
> > +
> > +  // FIXME: these two are wrong:
> > +  // INCORRECT MANGLING-DAG: @"\01??_7T at Test9@@6BB@@@"
> > +  // MANGLING-DAG-SHOULD-BE: @"\01??_7T at Test9@@6B@"
> > +  // INCORRECT MANGLING-DAG: @"\01??_7T at Test9@@6BY at 1@Z at 1@@"
> > +  // MANGLING-DAG-SHOULD-BE: @"\01??_7T at Test9@@6BY at 1@@"
> > +
> >   virtual void f();
> >   virtual void g();
> >   virtual void h();
> >
> > Modified: cfe/trunk/test/CodeGenCXX/virtual-base-destructor-call.cpp
> > URL:
> >
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/virtual-base-destructor-call.cpp?rev=191523&r1=191522&r2=191523&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/CodeGenCXX/virtual-base-destructor-call.cpp (original)
> > +++ cfe/trunk/test/CodeGenCXX/virtual-base-destructor-call.cpp Fri Sep 27
> > 09:48:01 2013
> > @@ -27,12 +27,6 @@ int main() {
> > //  CHECK: call {{.*}} @_ZN13basic_istreamIcED2Ev
> > //  CHECK: }
> >
> > -// basic_iostream's deleting dtor calls its complete dtor, then
> > -// operator delete().
> > -//  CHECK: define linkonce_odr {{.*}}
> > @_ZN14basic_iostreamIcED0Ev(%struct.basic_iostream* {{.*}}%this)
> > unnamed_addr
> > -//  CHECK: call {{.*}} @_ZN14basic_iostreamIcED1Ev
> > -//  CHECK: call {{.*}} @_ZdlPv
> > -
> > // basic_istream's complete dtor calls the base dtor,
> > // then its virtual base's base dtor.
> > //  CHECK: define linkonce_odr {{.*}}
> > @_ZN13basic_istreamIcED1Ev(%struct.basic_istream* {{.*}}%this)
> unnamed_addr
> > @@ -45,6 +39,12 @@ int main() {
> > //  CHECK: call {{.*}} @_ZN13basic_istreamIcED1Ev
> > //  CHECK: call {{.*}} @_ZdlPv
> >
> > +// basic_iostream's deleting dtor calls its complete dtor, then
> > +// operator delete().
> > +//  CHECK: define linkonce_odr {{.*}}
> > @_ZN14basic_iostreamIcED0Ev(%struct.basic_iostream* {{.*}}%this)
> > unnamed_addr
> > +//  CHECK: call {{.*}} @_ZN14basic_iostreamIcED1Ev
> > +//  CHECK: call {{.*}} @_ZdlPv
> > +
> > // basic_istream's base dtor is a no-op.
> > //  CHECK: define linkonce_odr {{.*}}
> > @_ZN13basic_istreamIcED2Ev(%struct.basic_istream* {{.*}}%this, i8** %vtt)
> > unnamed_addr
> > //  CHECK-NOT: call
> >
> >
> > _______________________________________________
> > cfe-commits mailing list
> > cfe-commits at cs.uiuc.edu
> > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
> >
> >
> > _______________________________________________
> > cfe-commits mailing list
> > cfe-commits at cs.uiuc.edu
> > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
> >
> >
> > _______________________________________________
> > cfe-commits mailing list
> > cfe-commits at cs.uiuc.edu
> > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
> >
> >
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130927/caf3f6f7/attachment.html>


More information about the cfe-commits mailing list