<div dir="ltr">Rather than doing a full -Asserts build, I strip the LLVM IR like so for faster iteration:<div><br><div>// RUN: %clang_cc1 ... | opt -S -o - -strip | FileCheck %s ...</div></div></div><div class="gmail_extra">
<br><br><div class="gmail_quote">On Fri, Sep 27, 2013 at 9:57 AM, Timur Iskhodzhanov <span dir="ltr"><<a href="mailto:timurrrr@google.com" target="_blank">timurrrr@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Yep, already launched a build without asserts enabled.<br>
Will update the expectations soon.<br>
<br>
Thanks anyways!<br>
<br>
2013/9/27 Charles Davis <<a href="mailto:cdavis5x@gmail.com">cdavis5x@gmail.com</a>>:<br>
<div><div class="h5">><br>
> On Sep 27, 2013, at 10:40 AM, jahanian wrote:<br>
><br>
><br>
> On Sep 27, 2013, at 8:53 AM, jahanian <<a href="mailto:fjahanian@apple.com">fjahanian@apple.com</a>> wrote:<br>
><br>
> This patch causes a test failure in a win64 buildbot.<br>
><br>
> C:\public\win64\src\tools\clang\test\CodeGenCXX\microsoft-abi-multiple-nonvirtual-inheritance.cpp:165:12:<br>
> error: expected string not found in input<br>
>    // CHECK: %[[VFPTR:.*]] = bitcast %struct.ChildOverride* %this1 to [1 x<br>
> i8*]**<br>
><br>
><br>
> [[THIS]]<br>
><br>
> He's trying to tell you that it won't have that name outside of a +Asserts<br>
> build, so you need to use a FileCheck variable to match the name of the this<br>
> pointer value.<br>
><br>
> Chip<br>
><br>
><br>
> - Fariborz<br>
><br>
><br>
> +  // Don't pass the PathToMangle as it should be calculated later.<br>
>   VFPtrInfo(CharUnits VFPtrOffset, const BasePath &PathToBaseWithVFPtr)<br>
>       : VBTableIndex(0), LastVBase(0), VFPtrOffset(VFPtrOffset),<br>
>         PathToBaseWithVFPtr(PathToBaseWithVFPtr),<br>
> VFPtrFullOffset(VFPtrOffset) {<br>
>   }<br>
><br>
> +  // Don't pass the PathToMangle as it should be calculated later.<br>
>   VFPtrInfo(uint64_t VBTableIndex, const CXXRecordDecl *LastVBase,<br>
>             CharUnits VFPtrOffset, const BasePath &PathToBaseWithVFPtr,<br>
>             CharUnits VFPtrFullOffset)<br>
> @@ -404,9 +399,13 @@ struct VFPtrInfo {<br>
>   CharUnits VFPtrOffset;<br>
><br>
>   /// This holds the base classes path from the complete type to the first<br>
> base<br>
> -  /// with the given vfptr offset.<br>
> +  /// with the given vfptr offset, in the base-to-derived order.<br>
>   BasePath PathToBaseWithVFPtr;<br>
><br>
> +  /// This holds the subset of records that need to be mangled into the<br>
> vftable<br>
> +  /// symbol name in order to get a unique name, in the derived-to-base<br>
> order.<br>
> +  BasePath PathToMangle;<br>
> +<br>
>   /// This is the full offset of the vfptr from the start of the complete<br>
> type.<br>
>   CharUnits VFPtrFullOffset;<br>
> };<br>
><br>
> Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp<br>
> URL:<br>
> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=191523&r1=191522&r2=191523&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=191523&r1=191522&r2=191523&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)<br>
> +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Fri Sep 27 09:48:01 2013<br>
> @@ -137,6 +137,9 @@ public:<br>
>                                 raw_ostream &);<br>
>   void mangleCXXVTable(const CXXRecordDecl *RD,<br>
>                        raw_ostream &);<br>
> +  void mangleCXXVFTable(const CXXRecordDecl *Derived,<br>
> +                        ArrayRef<const CXXRecordDecl *> BasePath,<br>
> +                        raw_ostream &Out);<br>
>   void mangleCXXVTT(const CXXRecordDecl *RD,<br>
>                     raw_ostream &);<br>
>   void mangleCXXVBTable(const CXXRecordDecl *Derived,<br>
> @@ -3772,6 +3775,14 @@ void ItaniumMangleContext::mangleCXXVTab<br>
>   Mangler.mangleNameOrStandardSubstitution(RD);<br>
> }<br>
><br>
> +void<br>
> +ItaniumMangleContext::mangleCXXVFTable(const CXXRecordDecl *Derived,<br>
> +                                       ArrayRef<const CXXRecordDecl *><br>
> BasePath,<br>
> +                                       raw_ostream &Out) {<br>
> +  llvm_unreachable(<br>
> +      "The Itanium C++ ABI does not have vftables (use vtables instead)!");<br>
> +}<br>
> +<br>
> void ItaniumMangleContext::mangleCXXVTT(const CXXRecordDecl *RD,<br>
>                                         raw_ostream &Out) {<br>
>   // <special-name> ::= TT <type>  # VTT structure<br>
><br>
> Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp<br>
> URL:<br>
> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftMangle.cpp?rev=191523&r1=191522&r2=191523&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftMangle.cpp?rev=191523&r1=191522&r2=191523&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original)<br>
> +++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Fri Sep 27 09:48:01 2013<br>
> @@ -188,6 +188,9 @@ public:<br>
>                                   raw_ostream &);<br>
>   virtual void mangleCXXVTable(const CXXRecordDecl *RD,<br>
>                                raw_ostream &);<br>
> +  virtual void mangleCXXVFTable(const CXXRecordDecl *Derived,<br>
> +                                ArrayRef<const CXXRecordDecl *> BasePath,<br>
> +                                raw_ostream &Out);<br>
>   virtual void mangleCXXVTT(const CXXRecordDecl *RD,<br>
>                             raw_ostream &);<br>
>   virtual void mangleCXXVBTable(const CXXRecordDecl *Derived,<br>
> @@ -1900,16 +1903,26 @@ void MicrosoftMangleContext::mangleCXXDt<br>
><br>
> void MicrosoftMangleContext::mangleCXXVTable(const CXXRecordDecl *RD,<br>
>                                              raw_ostream &Out) {<br>
> +  llvm_unreachable(<br>
> +      "The Microsoft C++ ABI does not have vtables (use vftables<br>
> instead)!");<br>
> +}<br>
> +<br>
> +void MicrosoftMangleContext::mangleCXXVFTable(<br>
> +    const CXXRecordDecl *Derived, ArrayRef<const CXXRecordDecl *> BasePath,<br>
> +    raw_ostream &Out) {<br>
>   // <mangled-name> ::= ?_7 <class-name> <storage-class><br>
>   //                    <cvr-qualifiers> [<name>] @<br>
>   // NOTE: <cvr-qualifiers> here is always 'B' (const). <storage-class><br>
>   // is always '6' for vftables.<br>
>   MicrosoftCXXNameMangler Mangler(*this, Out);<br>
>   Mangler.getStream() << "\01??_7";<br>
> -  Mangler.mangleName(RD);<br>
> -  Mangler.getStream() << "6B";  // '6' for vftable, 'B' for const.<br>
> -  // TODO: If the class has more than one vtable, mangle in the class it<br>
> came<br>
> -  // from.<br>
> +  Mangler.mangleName(Derived);<br>
> +  Mangler.getStream() << "6B"; // '6' for vftable, 'B' for const.<br>
> +  for (ArrayRef<const CXXRecordDecl *>::iterator I = BasePath.begin(),<br>
> +                                                 E = BasePath.end();<br>
> +       I != E; ++I) {<br>
> +    Mangler.mangleName(*I);<br>
> +  }<br>
>   Mangler.getStream() << '@';<br>
> }<br>
><br>
><br>
> Modified: cfe/trunk/lib/AST/VTableBuilder.cpp<br>
> URL:<br>
> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/VTableBuilder.cpp?rev=191523&r1=191522&r2=191523&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/VTableBuilder.cpp?rev=191523&r1=191522&r2=191523&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/AST/VTableBuilder.cpp (original)<br>
> +++ cfe/trunk/lib/AST/VTableBuilder.cpp Fri Sep 27 09:48:01 2013<br>
> @@ -999,10 +999,6 @@ public:<br>
>       dumpLayout(llvm::errs());<br>
>   }<br>
><br>
> -  bool isMicrosoftABI() const {<br>
> -    return VTables.isMicrosoftABI();<br>
> -  }<br>
> -<br>
>   uint64_t getNumThunks() const {<br>
>     return Thunks.size();<br>
>   }<br>
> @@ -1157,7 +1153,7 @@ void VTableBuilder::ComputeThisAdjustmen<br>
>     // Add it.<br>
>     VTableThunks[VTableIndex].This = ThisAdjustment;<br>
><br>
> -    if (isa<CXXDestructorDecl>(MD) && !isMicrosoftABI()) {<br>
> +    if (isa<CXXDestructorDecl>(MD)) {<br>
>       // Add an adjustment for the deleting destructor as well.<br>
>       VTableThunks[VTableIndex + 1].This = ThisAdjustment;<br>
>     }<br>
> @@ -1188,8 +1184,6 @@ void VTableBuilder::ComputeThisAdjustmen<br>
>       break;<br>
>     case VTableComponent::CK_DeletingDtorPointer:<br>
>       // We've already added the thunk when we saw the complete dtor<br>
> pointer.<br>
> -      // FIXME: check how this works in the Microsoft ABI<br>
> -      // while working on the multiple inheritance patch.<br>
>       continue;<br>
>     }<br>
><br>
> @@ -1326,15 +1320,9 @@ VTableBuilder::AddMethod(const CXXMethod<br>
>     assert(ReturnAdjustment.isEmpty() &&<br>
>            "Destructor can't have return adjustment!");<br>
><br>
> -    // FIXME: Should probably add a layer of abstraction for vtable<br>
> generation.<br>
> -    if (!isMicrosoftABI()) {<br>
> -      // Add both the complete destructor and the deleting destructor.<br>
> -      Components.push_back(VTableComponent::MakeCompleteDtor(DD));<br>
> -      Components.push_back(VTableComponent::MakeDeletingDtor(DD));<br>
> -    } else {<br>
> -      // Add the scalar deleting destructor.<br>
> -      Components.push_back(VTableComponent::MakeDeletingDtor(DD));<br>
> -    }<br>
> +    // Add both the complete destructor and the deleting destructor.<br>
> +    Components.push_back(VTableComponent::MakeCompleteDtor(DD));<br>
> +    Components.push_back(VTableComponent::MakeDeletingDtor(DD));<br>
>   } else {<br>
>     // Add the return adjustment if necessary.<br>
>     if (!ReturnAdjustment.isEmpty())<br>
> @@ -1693,18 +1681,12 @@ VTableBuilder::LayoutPrimaryAndSecondary<br>
>   if (Base.getBase() == MostDerivedClass)<br>
>     VBaseOffsetOffsets = Builder.getVBaseOffsetOffsets();<br>
><br>
> -  // FIXME: Should probably add a layer of abstraction for vtable<br>
> generation.<br>
> -  if (!isMicrosoftABI()) {<br>
> -    // Add the offset to top.<br>
> -    CharUnits OffsetToTop = MostDerivedClassOffset - OffsetInLayoutClass;<br>
> -    Components.push_back(VTableComponent::MakeOffsetToTop(OffsetToTop));<br>
> +  // Add the offset to top.<br>
> +  CharUnits OffsetToTop = MostDerivedClassOffset - OffsetInLayoutClass;<br>
> +  Components.push_back(VTableComponent::MakeOffsetToTop(OffsetToTop));<br>
><br>
> -    // Next, add the RTTI.<br>
> -    Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass));<br>
> -  } else {<br>
> -    // FIXME: unclear what to do with RTTI in MS ABI as emitting it<br>
> anywhere<br>
> -    // breaks the vftable layout. Just skip RTTI for now, can't mangle<br>
> anyway.<br>
> -  }<br>
> +  // Next, add the RTTI.<br>
> +  Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass));<br>
><br>
>   uint64_t AddressPoint = Components.size();<br>
><br>
> @@ -1722,16 +1704,10 @@ VTableBuilder::LayoutPrimaryAndSecondary<br>
>       const CXXMethodDecl *MD = I->first;<br>
>       const MethodInfo &MI = I->second;<br>
>       if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {<br>
> -        // FIXME: Should probably add a layer of abstraction for vtable<br>
> generation.<br>
> -        if (!isMicrosoftABI()) {<br>
> -          MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)]<br>
> -              = MI.VTableIndex - AddressPoint;<br>
> -          MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)]<br>
> -              = MI.VTableIndex + 1 - AddressPoint;<br>
> -        } else {<br>
> -          MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)]<br>
> -              = MI.VTableIndex - AddressPoint;<br>
> -        }<br>
> +        MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)]<br>
> +            = MI.VTableIndex - AddressPoint;<br>
> +        MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)]<br>
> +            = MI.VTableIndex + 1 - AddressPoint;<br>
>       } else {<br>
>         MethodVTableIndices[MD] = MI.VTableIndex - AddressPoint;<br>
>       }<br>
> @@ -2044,8 +2020,6 @@ void VTableBuilder::dumpLayout(raw_ostre<br>
>       Out << DD->getQualifiedNameAsString();<br>
>       if (IsComplete)<br>
>         Out << "() [complete]";<br>
> -      else if (isMicrosoftABI())<br>
> -        Out << "() [scalar deleting]";<br>
>       else<br>
>         Out << "() [deleting]";<br>
><br>
> @@ -2230,18 +2204,11 @@ void VTableBuilder::dumpLayout(raw_ostre<br>
>                                   MD);<br>
><br>
>     if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {<br>
> -      // FIXME: Should add a layer of abstraction for vtable generation.<br>
> -      if (!isMicrosoftABI()) {<br>
> -        GlobalDecl GD(DD, Dtor_Complete);<br>
> -        assert(MethodVTableIndices.count(GD));<br>
> -        uint64_t VTableIndex = MethodVTableIndices[GD];<br>
> -        IndicesMap[VTableIndex] = MethodName + " [complete]";<br>
> -        IndicesMap[VTableIndex + 1] = MethodName + " [deleting]";<br>
> -      } else {<br>
> -        GlobalDecl GD(DD, Dtor_Deleting);<br>
> -        assert(MethodVTableIndices.count(GD));<br>
> -        IndicesMap[MethodVTableIndices[GD]] = MethodName + " [scalar<br>
> deleting]";<br>
> -      }<br>
> +      GlobalDecl GD(DD, Dtor_Complete);<br>
> +      assert(MethodVTableIndices.count(GD));<br>
> +      uint64_t VTableIndex = MethodVTableIndices[GD];<br>
> +      IndicesMap[VTableIndex] = MethodName + " [complete]";<br>
> +      IndicesMap[VTableIndex + 1] = MethodName + " [deleting]";<br>
>     } else {<br>
>       assert(MethodVTableIndices.count(MD));<br>
>       IndicesMap[MethodVTableIndices[MD]] = MethodName;<br>
> @@ -2352,10 +2319,12 @@ static VTableLayout *CreateVTableLayout(<br>
>                           VTableThunks.size(),<br>
>                           VTableThunks.data(),<br>
>                           Builder.getAddressPoints(),<br>
> -                          Builder.isMicrosoftABI());<br>
> +                          /*IsMicrosoftABI=*/false);<br>
> }<br>
><br>
> void VTableContext::computeVTableRelatedInformation(const CXXRecordDecl *RD)<br>
> {<br>
> +  assert(!IsMicrosoftABI && "Shouldn't be called in this ABI!");<br>
> +<br>
>   const VTableLayout *&Entry = VTableLayouts[RD];<br>
><br>
>   // Check if we've computed this information before.<br>
> @@ -3132,6 +3101,55 @@ static void EnumerateVFPtrs(<br>
>   }<br>
> }<br>
><br>
> +/// CalculatePathToMangle - Calculate the subset of records that should be<br>
> used<br>
> +/// to mangle the vftable for the given vfptr.<br>
> +/// Should only be called if a class has multiple vftables.<br>
> +static void<br>
> +CalculatePathToMangle(const CXXRecordDecl *RD, VFPtrInfo &VFPtr) {<br>
> +  // FIXME: In some rare cases this code produces a slightly incorrect<br>
> mangling.<br>
> +  // It's very likely that the vbtable mangling code can be adjusted to<br>
> mangle<br>
> +  // both vftables and vbtables correctly.<br>
> +<br>
> +  VFPtrInfo::BasePath &FullPath = VFPtr.PathToBaseWithVFPtr;<br>
> +  if (FullPath.empty()) {<br>
> +    // Mangle the class's own vftable.<br>
> +    assert(RD->getNumVBases() &&<br>
> +           "Something's wrong: if the most derived "<br>
> +           "class has more than one vftable, it can only have its own "<br>
> +           "vftable if it has vbases");<br>
> +    VFPtr.PathToMangle.push_back(RD);<br>
> +    return;<br>
> +  }<br>
> +<br>
> +  unsigned Begin = 0;<br>
> +<br>
> +  // First, skip all the bases before the vbase.<br>
> +  if (VFPtr.LastVBase) {<br>
> +    while (FullPath[Begin] != VFPtr.LastVBase) {<br>
> +      Begin++;<br>
> +      assert(Begin < FullPath.size());<br>
> +    }<br>
> +  }<br>
> +<br>
> +  // Then, put the rest of the base path in the reverse order.<br>
> +  for (unsigned I = FullPath.size(); I != Begin; --I) {<br>
> +    const CXXRecordDecl *CurBase = FullPath[I - 1],<br>
> +                        *ItsBase = (I == 1) ? RD : FullPath[I - 2];<br>
> +    bool BaseIsVirtual = false;<br>
> +    for (CXXRecordDecl::base_class_const_iterator J =<br>
> ItsBase->bases_begin(),<br>
> +         F = ItsBase->bases_end(); J != F; ++J) {<br>
> +      if (J->getType()->getAsCXXRecordDecl() == CurBase) {<br>
> +        BaseIsVirtual = J->isVirtual();<br>
> +        break;<br>
> +      }<br>
> +    }<br>
> +<br>
> +    // Should skip the current base if it is a non-virtual base with no<br>
> siblings.<br>
> +    if (BaseIsVirtual || ItsBase->getNumBases() != 1)<br>
> +      VFPtr.PathToMangle.push_back(CurBase);<br>
> +  }<br>
> +}<br>
> +<br>
> static void EnumerateVFPtrs(ASTContext &Context, const CXXRecordDecl<br>
> *ForClass,<br>
>                             MicrosoftVFTableContext::VFPtrListTy &Result) {<br>
>   Result.clear();<br>
> @@ -3140,6 +3158,10 @@ static void EnumerateVFPtrs(ASTContext &<br>
>   EnumerateVFPtrs(Context, ForClass, ClassLayout,<br>
>                   BaseSubobject(ForClass, CharUnits::Zero()), 0,<br>
>                   VFPtrInfo::BasePath(), VisitedVBases, Result);<br>
> +  if (Result.size() > 1) {<br>
> +    for (unsigned I = 0, E = Result.size(); I != E; ++I)<br>
> +      CalculatePathToMangle(ForClass, Result[I]);<br>
> +  }<br>
> }<br>
><br>
> void MicrosoftVFTableContext::computeVTableRelatedInformation(<br>
><br>
> Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp<br>
> URL:<br>
> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=191523&r1=191522&r2=191523&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=191523&r1=191522&r2=191523&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)<br>
> +++ cfe/trunk/lib/CodeGen/CGCXX.cpp Fri Sep 27 09:48:01 2013<br>
> @@ -280,7 +280,7 @@ static llvm::Value *BuildAppleKextVirtua<br>
>          "No kext in Microsoft ABI");<br>
>   GD = GD.getCanonicalDecl();<br>
>   CodeGenModule &CGM = CGF.CGM;<br>
> -  llvm::Value *VTable = CGM.getVTables().GetAddrOfVTable(RD);<br>
> +  llvm::Value *VTable = CGM.getCXXABI().getAddrOfVTable(RD, CharUnits());<br>
>   Ty = Ty->getPointerTo()->getPointerTo();<br>
>   VTable = CGF.Builder.CreateBitCast(VTable, Ty);<br>
>   assert(VTable && "BuildVirtualCall = kext vtbl pointer is null");<br>
><br>
> Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h<br>
> URL:<br>
> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=191523&r1=191522&r2=191523&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=191523&r1=191522&r2=191523&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)<br>
> +++ cfe/trunk/lib/CodeGen/CGCXXABI.h Fri Sep 27 09:48:01 2013<br>
> @@ -303,6 +303,29 @@ public:<br>
>                                    CallExpr::const_arg_iterator ArgBeg,<br>
>                                    CallExpr::const_arg_iterator ArgEnd) = 0;<br>
><br>
> +  /// Emits the VTable definitions required for the given record type.<br>
> +  virtual void emitVTableDefinitions(CodeGenVTables &CGVT,<br>
> +                                     const CXXRecordDecl *RD) = 0;<br>
> +<br>
> +  /// Get the address point of the vtable for the given base subobject<br>
> while<br>
> +  /// building a constructor or a destructor. On return, NeedsVirtualOffset<br>
> +  /// tells if a virtual base adjustment is needed in order to get the<br>
> offset<br>
> +  /// of the base subobject.<br>
> +  virtual llvm::Value *getVTableAddressPointInStructor(<br>
> +      CodeGenFunction &CGF, const CXXRecordDecl *RD, BaseSubobject Base,<br>
> +      const CXXRecordDecl *NearestVBase, bool &NeedsVirtualOffset) = 0;<br>
> +<br>
> +  /// Get the address point of the vtable for the given base subobject<br>
> while<br>
> +  /// building a constexpr.<br>
> +  virtual llvm::Constant *<br>
> +  getVTableAddressPointForConstExpr(BaseSubobject Base,<br>
> +                                    const CXXRecordDecl *VTableClass) = 0;<br>
> +<br>
> +  /// Get the address of the vtable for the given record decl which should<br>
> be<br>
> +  /// used for the vptr at the given offset in RD.<br>
> +  virtual llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD,<br>
> +                                                CharUnits VPtrOffset) = 0;<br>
> +<br>
>   /// Build a virtual function pointer in the ABI-specific way.<br>
>   virtual llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF,<br>
>                                                  GlobalDecl GD,<br>
> @@ -319,9 +342,7 @@ public:<br>
>   /// Emit any tables needed to implement virtual inheritance.  For Itanium,<br>
>   /// this emits virtual table tables.  For the MSVC++ ABI, this emits<br>
> virtual<br>
>   /// base tables.<br>
> -  virtual void<br>
> -      EmitVirtualInheritanceTables(llvm::GlobalVariable::LinkageTypes<br>
> Linkage,<br>
> -                                   const CXXRecordDecl *RD) = 0;<br>
> +  virtual void emitVirtualInheritanceTables(const CXXRecordDecl *RD) = 0;<br>
><br>
>   virtual void EmitReturnFromThunk(CodeGenFunction &CGF,<br>
>                                    RValue RV, QualType ResultType);<br>
><br>
> Modified: cfe/trunk/lib/CodeGen/CGClass.cpp<br>
> URL:<br>
> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=191523&r1=191522&r2=191523&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=191523&r1=191522&r2=191523&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/CodeGen/CGClass.cpp (original)<br>
> +++ cfe/trunk/lib/CodeGen/CGClass.cpp Fri Sep 27 09:48:01 2013<br>
> @@ -1878,39 +1878,19 @@ CodeGenFunction::InitializeVTablePointer<br>
>                                          const CXXRecordDecl *NearestVBase,<br>
>                                          CharUnits OffsetFromNearestVBase,<br>
>                                          const CXXRecordDecl *VTableClass) {<br>
> -  const CXXRecordDecl *RD = Base.getBase();<br>
> -<br>
>   // Compute the address point.<br>
> -  llvm::Value *VTableAddressPoint;<br>
> -<br>
> -  bool NeedsVTTParam = CGM.getCXXABI().NeedsVTTParameter(CurGD);<br>
> -<br>
> -  // Check if we need to use a vtable from the VTT.<br>
> -  if (NeedsVTTParam && (RD->getNumVBases() || NearestVBase)) {<br>
> -    // Get the secondary vpointer index.<br>
> -    uint64_t VirtualPointerIndex =<br>
> -     CGM.getVTables().getSecondaryVirtualPointerIndex(VTableClass, Base);<br>
> -<br>
> -    /// Load the VTT.<br>
> -    llvm::Value *VTT = LoadCXXVTT();<br>
> -    if (VirtualPointerIndex)<br>
> -      VTT = Builder.CreateConstInBoundsGEP1_64(VTT, VirtualPointerIndex);<br>
> -<br>
> -    // And load the address point from the VTT.<br>
> -    VTableAddressPoint = Builder.CreateLoad(VTT);<br>
> -  } else {<br>
> -    llvm::Constant *VTable = CGM.getVTables().GetAddrOfVTable(VTableClass);<br>
> -    uint64_t AddressPoint =<br>
> -<br>
> CGM.getVTableContext().getVTableLayout(VTableClass).getAddressPoint(Base);<br>
> -    VTableAddressPoint =<br>
> -      Builder.CreateConstInBoundsGEP2_64(VTable, 0, AddressPoint);<br>
> -  }<br>
> +  bool NeedsVirtualOffset;<br>
> +  llvm::Value *VTableAddressPoint =<br>
> +      CGM.getCXXABI().getVTableAddressPointInStructor(<br>
> +          *this, VTableClass, Base, NearestVBase, NeedsVirtualOffset);<br>
> +  if (!VTableAddressPoint)<br>
> +    return;<br>
><br>
>   // Compute where to store the address point.<br>
>   llvm::Value *VirtualOffset = 0;<br>
>   CharUnits NonVirtualOffset = CharUnits::Zero();<br>
><br>
> -  if (NeedsVTTParam && NearestVBase) {<br>
> +  if (NeedsVirtualOffset) {<br>
>     // We need to use the virtual base offset offset because the virtual<br>
> base<br>
>     // might have a different offset in the most derived class.<br>
>     VirtualOffset = CGM.getCXXABI().GetVirtualBaseClassOffset(*this,<br>
><br>
> Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp<br>
> URL:<br>
> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=191523&r1=191522&r2=191523&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=191523&r1=191522&r2=191523&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)<br>
> +++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Fri Sep 27 09:48:01 2013<br>
> @@ -1053,7 +1053,11 @@ CGDebugInfo::CreateCXXMemberFunction(con<br>
><br>
>     // It doesn't make sense to give a virtual destructor a vtable index,<br>
>     // since a single destructor has two entries in the vtable.<br>
> -    if (!isa<CXXDestructorDecl>(Method))<br>
> +    // FIXME: Add proper support for debug info for virtual calls in<br>
> +    // the Microsoft ABI, where we may use multiple vptrs to make a vftable<br>
> +    // lookup if we have multiple or virtual inheritance.<br>
> +    if (!isa<CXXDestructorDecl>(Method) &&<br>
> +        !CGM.getTarget().getCXXABI().isMicrosoft())<br>
>       VIndex = CGM.getVTableContext().getMethodVTableIndex(Method);<br>
>     ContainingType = RecordTy;<br>
>   }<br>
><br>
> Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp<br>
> URL:<br>
> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=191523&r1=191522&r2=191523&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=191523&r1=191522&r2=191523&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)<br>
> +++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Fri Sep 27 09:48:01 2013<br>
> @@ -53,9 +53,6 @@ private:<br>
>     NextFieldOffsetInChars(CharUnits::Zero()),<br>
>     LLVMStructAlignment(CharUnits::One()) { }<br>
><br>
> -  void AppendVTablePointer(BaseSubobject Base, llvm::Constant *VTable,<br>
> -                           const CXXRecordDecl *VTableClass);<br>
> -<br>
>   void AppendField(const FieldDecl *Field, uint64_t FieldOffset,<br>
>                    llvm::Constant *InitExpr);<br>
><br>
> @@ -72,8 +69,7 @@ private:<br>
><br>
>   bool Build(InitListExpr *ILE);<br>
>   void Build(const APValue &Val, const RecordDecl *RD, bool IsPrimaryBase,<br>
> -             llvm::Constant *VTable, const CXXRecordDecl *VTableClass,<br>
> -             CharUnits BaseOffset);<br>
> +             const CXXRecordDecl *VTableClass, CharUnits BaseOffset);<br>
>   llvm::Constant *Finalize(QualType Ty);<br>
><br>
>   CharUnits getAlignment(const llvm::Constant *C) const {<br>
> @@ -88,23 +84,6 @@ private:<br>
>   }<br>
> };<br>
><br>
> -void ConstStructBuilder::AppendVTablePointer(BaseSubobject Base,<br>
> -                                             llvm::Constant *VTable,<br>
> -                                             const CXXRecordDecl<br>
> *VTableClass) {<br>
> -  // Find the appropriate vtable within the vtable group.<br>
> -  uint64_t AddressPoint =<br>
> -<br>
> CGM.getVTableContext().getVTableLayout(VTableClass).getAddressPoint(Base);<br>
> -  llvm::Value *Indices[] = {<br>
> -    llvm::ConstantInt::get(CGM.Int64Ty, 0),<br>
> -    llvm::ConstantInt::get(CGM.Int64Ty, AddressPoint)<br>
> -  };<br>
> -  llvm::Constant *VTableAddressPoint =<br>
> -    llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Indices);<br>
> -<br>
> -  // Add the vtable at the start of the object.<br>
> -  AppendBytes(Base.getBaseOffset(), VTableAddressPoint);<br>
> -}<br>
> -<br>
> void ConstStructBuilder::<br>
> AppendField(const FieldDecl *Field, uint64_t FieldOffset,<br>
>             llvm::Constant *InitCst) {<br>
> @@ -424,15 +403,19 @@ struct BaseInfo {<br>
> }<br>
><br>
> void ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,<br>
> -                               bool IsPrimaryBase, llvm::Constant *VTable,<br>
> +                               bool IsPrimaryBase,<br>
>                                const CXXRecordDecl *VTableClass,<br>
>                                CharUnits Offset) {<br>
>   const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);<br>
><br>
>   if (const CXXRecordDecl *CD = dyn_cast<CXXRecordDecl>(RD)) {<br>
>     // Add a vtable pointer, if we need one and it hasn't already been<br>
> added.<br>
> -    if (CD->isDynamicClass() && !IsPrimaryBase)<br>
> -      AppendVTablePointer(BaseSubobject(CD, Offset), VTable, VTableClass);<br>
> +    if (CD->isDynamicClass() && !IsPrimaryBase) {<br>
> +      llvm::Constant *VTableAddressPoint =<br>
> +          CGM.getCXXABI().getVTableAddressPointForConstExpr(<br>
> +              BaseSubobject(CD, Offset), VTableClass);<br>
> +      AppendBytes(Offset, VTableAddressPoint);<br>
> +    }<br>
><br>
>     // Accumulate and sort bases, in order to visit them in address order,<br>
> which<br>
>     // may not be the same as declaration order.<br>
> @@ -453,7 +436,7 @@ void ConstStructBuilder::Build(const APV<br>
><br>
>       bool IsPrimaryBase = Layout.getPrimaryBase() == Base.Decl;<br>
>       Build(Val.getStructBase(Base.Index), Base.Decl, IsPrimaryBase,<br>
> -            VTable, VTableClass, Offset + Base.Offset);<br>
> +            VTableClass, Offset + Base.Offset);<br>
>     }<br>
>   }<br>
><br>
> @@ -560,11 +543,7 @@ llvm::Constant *ConstStructBuilder::Buil<br>
><br>
>   const RecordDecl *RD = ValTy->castAs<RecordType>()->getDecl();<br>
>   const CXXRecordDecl *CD = dyn_cast<CXXRecordDecl>(RD);<br>
> -  llvm::Constant *VTable = 0;<br>
> -  if (CD && CD->isDynamicClass())<br>
> -    VTable = CGM.getVTables().GetAddrOfVTable(CD);<br>
> -<br>
> -  Builder.Build(Val, RD, false, VTable, CD, CharUnits::Zero());<br>
> +  Builder.Build(Val, RD, false, CD, CharUnits::Zero());<br>
><br>
>   return Builder.Finalize(ValTy);<br>
> }<br>
><br>
> Modified: cfe/trunk/lib/CodeGen/CGVTT.cpp<br>
> URL:<br>
> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTT.cpp?rev=191523&r1=191522&r2=191523&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTT.cpp?rev=191523&r1=191522&r2=191523&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/CodeGen/CGVTT.cpp (original)<br>
> +++ cfe/trunk/lib/CodeGen/CGVTT.cpp Fri Sep 27 09:48:01 2013<br>
> @@ -19,7 +19,8 @@ using namespace clang;<br>
> using namespace CodeGen;<br>
><br>
> static llvm::Constant *<br>
> -GetAddrOfVTTVTable(CodeGenVTables &CGVT, const CXXRecordDecl<br>
> *MostDerivedClass,<br>
> +GetAddrOfVTTVTable(CodeGenVTables &CGVT, CodeGenModule &CGM,<br>
> +                   const CXXRecordDecl *MostDerivedClass,<br>
>                    const VTTVTable &VTable,<br>
>                    llvm::GlobalVariable::LinkageTypes Linkage,<br>
>                    llvm::DenseMap<BaseSubobject, uint64_t> &AddressPoints) {<br>
> @@ -27,7 +28,7 @@ GetAddrOfVTTVTable(CodeGenVTables &CGVT,<br>
>     assert(VTable.getBaseOffset().isZero() &&<br>
>            "Most derived class vtable must have a zero offset!");<br>
>     // This is a regular vtable.<br>
> -    return CGVT.GetAddrOfVTable(MostDerivedClass);<br>
> +    return CGM.getCXXABI().getAddrOfVTable(MostDerivedClass, CharUnits());<br>
>   }<br>
><br>
>   return CGVT.GenerateConstructionVTable(MostDerivedClass,<br>
> @@ -52,7 +53,7 @@ CodeGenVTables::EmitVTTDefinition(llvm::<br>
>   for (const VTTVTable *i = Builder.getVTTVTables().begin(),<br>
>                        *e = Builder.getVTTVTables().end(); i != e; ++i) {<br>
>     VTableAddressPoints.push_back(VTableAddressPointsMapTy());<br>
> -    VTables.push_back(GetAddrOfVTTVTable(*this, RD, *i, Linkage,<br>
> +    VTables.push_back(GetAddrOfVTTVTable(*this, CGM, RD, *i, Linkage,<br>
>                                          VTableAddressPoints.back()));<br>
>   }<br>
><br>
> @@ -106,7 +107,7 @@ llvm::GlobalVariable *CodeGenVTables::Ge<br>
>   StringRef Name = OutName.str();<br>
><br>
>   // This will also defer the definition of the VTT.<br>
> -  (void) GetAddrOfVTable(RD);<br>
> +  (void) CGM.getCXXABI().getAddrOfVTable(RD, CharUnits());<br>
><br>
>   VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false);<br>
><br>
><br>
> Modified: cfe/trunk/lib/CodeGen/CGVTables.cpp<br>
> URL:<br>
> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.cpp?rev=191523&r1=191522&r2=191523&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.cpp?rev=191523&r1=191522&r2=191523&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/CodeGen/CGVTables.cpp (original)<br>
> +++ cfe/trunk/lib/CodeGen/CGVTables.cpp Fri Sep 27 09:48:01 2013<br>
> @@ -498,6 +498,7 @@ void CodeGenVTables::EmitThunks(GlobalDe<br>
>     // FIXME: This is a temporary solution to force generation of vftables<br>
> in<br>
>     // Microsoft ABI. Remove when we thread VFTableContext through CodeGen.<br>
>     VFTContext->getVFPtrOffsets(MD->getParent());<br>
> +    return;<br>
>   }<br>
><br>
>   const VTableContext::ThunkInfoVectorTy *ThunkInfoVector =<br>
> @@ -629,53 +630,6 @@ CodeGenVTables::CreateVTableInitializer(<br>
>   return llvm::ConstantArray::get(ArrayType, Inits);<br>
> }<br>
><br>
> -llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTable(const CXXRecordDecl<br>
> *RD) {<br>
> -  llvm::GlobalVariable *&VTable = VTables[RD];<br>
> -  if (VTable)<br>
> -    return VTable;<br>
> -<br>
> -  // Queue up this v-table for possible deferred emission.<br>
> -  CGM.addDeferredVTable(RD);<br>
> -<br>
> -  SmallString<256> OutName;<br>
> -  llvm::raw_svector_ostream Out(OutName);<br>
> -  CGM.getCXXABI().getMangleContext().mangleCXXVTable(RD, Out);<br>
> -  Out.flush();<br>
> -  StringRef Name = OutName.str();<br>
> -<br>
> -  llvm::ArrayType *ArrayType =<br>
> -    llvm::ArrayType::get(CGM.Int8PtrTy,<br>
> -<br>
> VTContext.getVTableLayout(RD).getNumVTableComponents());<br>
> -<br>
> -  VTable =<br>
> -    CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType,<br>
> -<br>
> llvm::GlobalValue::ExternalLinkage);<br>
> -  VTable->setUnnamedAddr(true);<br>
> -  return VTable;<br>
> -}<br>
> -<br>
> -void<br>
> -CodeGenVTables::EmitVTableDefinition(llvm::GlobalVariable *VTable,<br>
> -                                     llvm::GlobalVariable::LinkageTypes<br>
> Linkage,<br>
> -                                     const CXXRecordDecl *RD) {<br>
> -  const VTableLayout &VTLayout = VTContext.getVTableLayout(RD);<br>
> -<br>
> -  // Create and set the initializer.<br>
> -  llvm::Constant *Init =<br>
> -    CreateVTableInitializer(RD,<br>
> -                            VTLayout.vtable_component_begin(),<br>
> -                            VTLayout.getNumVTableComponents(),<br>
> -                            VTLayout.vtable_thunk_begin(),<br>
> -                            VTLayout.getNumVTableThunks());<br>
> -  VTable->setInitializer(Init);<br>
> -<br>
> -  // Set the correct linkage.<br>
> -  VTable->setLinkage(Linkage);<br>
> -<br>
> -  // Set the right visibility.<br>
> -  CGM.setTypeVisibility(VTable, RD, CodeGenModule::TVK_ForVTable);<br>
> -}<br>
> -<br>
> llvm::GlobalVariable *<br>
> CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,<br>
>                                       const BaseSubobject &Base,<br>
> @@ -818,35 +772,10 @@ CodeGenVTables::GenerateClassData(const<br>
>   if (CGDebugInfo *DI = CGM.getModuleDebugInfo())<br>
>     DI->completeClassData(RD);<br>
><br>
> -  if (VFTContext.isValid()) {<br>
> -    // FIXME: This is a temporary solution to force generation of vftables<br>
> in<br>
> -    // Microsoft ABI. Remove when we thread VFTableContext through CodeGen.<br>
> -    VFTContext->getVFPtrOffsets(RD);<br>
> -  }<br>
> -<br>
> -  // First off, check whether we've already emitted the v-table and<br>
> -  // associated stuff.<br>
> -  llvm::GlobalVariable *VTable = GetAddrOfVTable(RD);<br>
> -  if (VTable->hasInitializer())<br>
> -    return;<br>
> -<br>
> -  llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);<br>
> -  EmitVTableDefinition(VTable, Linkage, RD);<br>
> -<br>
>   if (RD->getNumVBases())<br>
> -    CGM.getCXXABI().EmitVirtualInheritanceTables(Linkage, RD);<br>
> +    CGM.getCXXABI().emitVirtualInheritanceTables(RD);<br>
><br>
> -  // If this is the magic class __cxxabiv1::__fundamental_type_info,<br>
> -  // we will emit the typeinfo for the fundamental types. This is the<br>
> -  // same behaviour as GCC.<br>
> -  const DeclContext *DC = RD->getDeclContext();<br>
> -  if (RD->getIdentifier() &&<br>
> -      RD->getIdentifier()->isStr("__fundamental_type_info") &&<br>
> -      isa<NamespaceDecl>(DC) &&<br>
> -      cast<NamespaceDecl>(DC)->getIdentifier() &&<br>
> -      cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__cxxabiv1") &&<br>
> -      DC->getParent()->isTranslationUnit())<br>
> -    CGM.EmitFundamentalRTTIDescriptors();<br>
> +  CGM.getCXXABI().emitVTableDefinitions(*this, RD);<br>
> }<br>
><br>
> /// At this point in the translation unit, does it appear that can we<br>
><br>
> Modified: cfe/trunk/lib/CodeGen/CGVTables.h<br>
> URL:<br>
> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.h?rev=191523&r1=191522&r2=191523&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.h?rev=191523&r1=191522&r2=191523&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/CodeGen/CGVTables.h (original)<br>
> +++ cfe/trunk/lib/CodeGen/CGVTables.h Fri Sep 27 09:48:01 2013<br>
> @@ -35,9 +35,6 @@ class CodeGenVTables {<br>
>   // classes?<br>
>   VTableContext VTContext;<br>
>   OwningPtr<MicrosoftVFTableContext> VFTContext;<br>
> -<br>
> -  /// VTables - All the vtables which have been defined.<br>
> -  llvm::DenseMap<const CXXRecordDecl *, llvm::GlobalVariable *> VTables;<br>
><br>
>   /// VTableAddressPointsMapTy - Address points for a single vtable.<br>
>   typedef llvm::DenseMap<BaseSubobject, uint64_t> VTableAddressPointsMapTy;<br>
> @@ -65,6 +62,7 @@ class CodeGenVTables {<br>
>   /// doesn't contain any incomplete types.<br>
>   void MaybeEmitThunkAvailableExternally(GlobalDecl GD, const ThunkInfo<br>
> &Thunk);<br>
><br>
> +public:<br>
>   /// CreateVTableInitializer - Create a vtable initializer for the given<br>
> record<br>
>   /// decl.<br>
>   /// \param Components - The vtable components; this is really an array of<br>
> @@ -75,7 +73,6 @@ class CodeGenVTables {<br>
>                                 const VTableLayout::VTableThunkTy<br>
> *VTableThunks,<br>
>                                           unsigned NumVTableThunks);<br>
><br>
> -public:<br>
>   CodeGenVTables(CodeGenModule &CGM);<br>
><br>
>   VTableContext &getVTableContext() { return VTContext; }<br>
> @@ -95,14 +92,6 @@ public:<br>
>   /// class decl.<br>
>   uint64_t getAddressPoint(BaseSubobject Base, const CXXRecordDecl *RD);<br>
><br>
> -  /// GetAddrOfVTable - Get the address of the vtable for the given record<br>
> decl.<br>
> -  llvm::GlobalVariable *GetAddrOfVTable(const CXXRecordDecl *RD);<br>
> -<br>
> -  /// EmitVTableDefinition - Emit the definition of the given vtable.<br>
> -  void EmitVTableDefinition(llvm::GlobalVariable *VTable,<br>
> -                            llvm::GlobalVariable::LinkageTypes Linkage,<br>
> -                            const CXXRecordDecl *RD);<br>
> -<br>
>   /// GenerateConstructionVTable - Generate a construction vtable for the<br>
> given<br>
>   /// base subobject.<br>
>   llvm::GlobalVariable *<br>
><br>
> Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h<br>
> URL:<br>
> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=191523&r1=191522&r2=191523&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=191523&r1=191522&r2=191523&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)<br>
> +++ cfe/trunk/lib/CodeGen/CodeGenModule.h Fri Sep 27 09:48:01 2013<br>
> @@ -250,7 +250,6 @@ class CodeGenModule : public CodeGenType<br>
><br>
>   /// VTables - Holds information about C++ vtables.<br>
>   CodeGenVTables VTables;<br>
> -  friend class CodeGenVTables;<br>
><br>
>   CGObjCRuntime* ObjCRuntime;<br>
>   CGOpenCLRuntime* OpenCLRuntime;<br>
> @@ -915,6 +914,10 @@ public:<br>
><br>
>   void EmitVTable(CXXRecordDecl *Class, bool DefinitionRequired);<br>
><br>
> +  /// EmitFundamentalRTTIDescriptors - Emit the RTTI descriptors for the<br>
> +  /// builtin types.<br>
> +  void EmitFundamentalRTTIDescriptors();<br>
> +<br>
>   /// \brief Appends Opts to the "Linker Options" metadata value.<br>
>   void AppendLinkerOptions(StringRef Opts);<br>
><br>
> @@ -1068,10 +1071,6 @@ private:<br>
>   /// given type.<br>
>   void EmitFundamentalRTTIDescriptor(QualType Type);<br>
><br>
> -  /// EmitFundamentalRTTIDescriptors - Emit the RTTI descriptors for the<br>
> -  /// builtin types.<br>
> -  void EmitFundamentalRTTIDescriptors();<br>
> -<br>
>   /// EmitDeferred - Emit any needed decls for which code generation<br>
>   /// was deferred.<br>
>   void EmitDeferred();<br>
><br>
> Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp<br>
> URL:<br>
> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=191523&r1=191522&r2=191523&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=191523&r1=191522&r2=191523&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)<br>
> +++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Fri Sep 27 09:48:01 2013<br>
> @@ -34,6 +34,9 @@ using namespace CodeGen;<br>
><br>
> namespace {<br>
> class ItaniumCXXABI : public CodeGen::CGCXXABI {<br>
> +  /// VTables - All the vtables which have been defined.<br>
> +  llvm::DenseMap<const CXXRecordDecl *, llvm::GlobalVariable *> VTables;<br>
> +<br>
> protected:<br>
>   bool UseARMMethodPtrABI;<br>
>   bool UseARMGuardVarABI;<br>
> @@ -142,6 +145,20 @@ public:<br>
>                            CallExpr::const_arg_iterator ArgBeg,<br>
>                            CallExpr::const_arg_iterator ArgEnd);<br>
><br>
> +  void emitVTableDefinitions(CodeGenVTables &CGVT, const CXXRecordDecl<br>
> *RD);<br>
> +<br>
> +  llvm::Value *getVTableAddressPointInStructor(<br>
> +      CodeGenFunction &CGF, const CXXRecordDecl *VTableClass,<br>
> +      BaseSubobject Base, const CXXRecordDecl *NearestVBase,<br>
> +      bool &NeedsVirtualOffset);<br>
> +<br>
> +  llvm::Constant *<br>
> +  getVTableAddressPointForConstExpr(BaseSubobject Base,<br>
> +                                    const CXXRecordDecl *VTableClass);<br>
> +<br>
> +  llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD,<br>
> +                                        CharUnits VPtrOffset);<br>
> +<br>
>   llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl<br>
> GD,<br>
>                                          llvm::Value *This, llvm::Type *Ty);<br>
><br>
> @@ -150,8 +167,7 @@ public:<br>
>                                  CXXDtorType DtorType, SourceLocation<br>
> CallLoc,<br>
>                                  llvm::Value *This);<br>
><br>
> -  void EmitVirtualInheritanceTables(llvm::GlobalVariable::LinkageTypes<br>
> Linkage,<br>
> -                                    const CXXRecordDecl *RD);<br>
> +  void emitVirtualInheritanceTables(const CXXRecordDecl *RD);<br>
><br>
>   StringRef GetPureVirtualCallName() { return "__cxa_pure_virtual"; }<br>
>   StringRef GetDeletedVirtualCallName() { return "__cxa_deleted_virtual"; }<br>
> @@ -888,6 +904,113 @@ void ItaniumCXXABI::EmitConstructorCall(<br>
>                         This, VTT, VTTTy, ArgBeg, ArgEnd);<br>
> }<br>
><br>
> +void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,<br>
> +                                          const CXXRecordDecl *RD) {<br>
> +  llvm::GlobalVariable *VTable = getAddrOfVTable(RD, CharUnits());<br>
> +  if (VTable->hasInitializer())<br>
> +    return;<br>
> +<br>
> +  VTableContext &VTContext = CGM.getVTableContext();<br>
> +  const VTableLayout &VTLayout = VTContext.getVTableLayout(RD);<br>
> +  llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);<br>
> +<br>
> +  // Create and set the initializer.<br>
> +  llvm::Constant *Init = CGVT.CreateVTableInitializer(<br>
> +      RD, VTLayout.vtable_component_begin(),<br>
> VTLayout.getNumVTableComponents(),<br>
> +      VTLayout.vtable_thunk_begin(), VTLayout.getNumVTableThunks());<br>
> +  VTable->setInitializer(Init);<br>
> +<br>
> +  // Set the correct linkage.<br>
> +  VTable->setLinkage(Linkage);<br>
> +<br>
> +  // Set the right visibility.<br>
> +  CGM.setTypeVisibility(VTable, RD, CodeGenModule::TVK_ForVTable);<br>
> +<br>
> +  // If this is the magic class __cxxabiv1::__fundamental_type_info,<br>
> +  // we will emit the typeinfo for the fundamental types. This is the<br>
> +  // same behaviour as GCC.<br>
> +  const DeclContext *DC = RD->getDeclContext();<br>
> +  if (RD->getIdentifier() &&<br>
> +      RD->getIdentifier()->isStr("__fundamental_type_info") &&<br>
> +      isa<NamespaceDecl>(DC) && cast<NamespaceDecl>(DC)->getIdentifier() &&<br>
> +      cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__cxxabiv1") &&<br>
> +      DC->getParent()->isTranslationUnit())<br>
> +    CGM.EmitFundamentalRTTIDescriptors();<br>
> +}<br>
> +<br>
> +llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructor(<br>
> +    CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject<br>
> Base,<br>
> +    const CXXRecordDecl *NearestVBase, bool &NeedsVirtualOffset) {<br>
> +  bool NeedsVTTParam = CGM.getCXXABI().NeedsVTTParameter(CGF.CurGD);<br>
> +  NeedsVirtualOffset = (NeedsVTTParam && NearestVBase);<br>
> +<br>
> +  llvm::Value *VTableAddressPoint;<br>
> +  if (NeedsVTTParam && (Base.getBase()->getNumVBases() || NearestVBase)) {<br>
> +    // Get the secondary vpointer index.<br>
> +    uint64_t VirtualPointerIndex =<br>
> +        CGM.getVTables().getSecondaryVirtualPointerIndex(VTableClass,<br>
> Base);<br>
> +<br>
> +    /// Load the VTT.<br>
> +    llvm::Value *VTT = CGF.LoadCXXVTT();<br>
> +    if (VirtualPointerIndex)<br>
> +      VTT = CGF.Builder.CreateConstInBoundsGEP1_64(VTT,<br>
> VirtualPointerIndex);<br>
> +<br>
> +    // And load the address point from the VTT.<br>
> +    VTableAddressPoint = CGF.Builder.CreateLoad(VTT);<br>
> +  } else {<br>
> +    llvm::Constant *VTable =<br>
> +        CGM.getCXXABI().getAddrOfVTable(VTableClass, CharUnits());<br>
> +    uint64_t AddressPoint =<br>
> CGM.getVTableContext().getVTableLayout(VTableClass)<br>
> +        .getAddressPoint(Base);<br>
> +    VTableAddressPoint =<br>
> +        CGF.Builder.CreateConstInBoundsGEP2_64(VTable, 0, AddressPoint);<br>
> +  }<br>
> +<br>
> +  return VTableAddressPoint;<br>
> +}<br>
> +<br>
> +llvm::Constant *ItaniumCXXABI::getVTableAddressPointForConstExpr(<br>
> +    BaseSubobject Base, const CXXRecordDecl *VTableClass) {<br>
> +  llvm::Constant *VTable = getAddrOfVTable(VTableClass, CharUnits());<br>
> +<br>
> +  // Find the appropriate vtable within the vtable group.<br>
> +  uint64_t AddressPoint =<br>
> +<br>
> CGM.getVTableContext().getVTableLayout(VTableClass).getAddressPoint(Base);<br>
> +  llvm::Value *Indices[] = {<br>
> +    llvm::ConstantInt::get(CGM.Int64Ty, 0),<br>
> +    llvm::ConstantInt::get(CGM.Int64Ty, AddressPoint)<br>
> +  };<br>
> +<br>
> +  return llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Indices);<br>
> +}<br>
> +<br>
> +llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl<br>
> *RD,<br>
> +                                                     CharUnits VPtrOffset)<br>
> {<br>
> +  assert(VPtrOffset.isZero() && "Itanium ABI only supports zero vptr<br>
> offsets");<br>
> +<br>
> +  llvm::GlobalVariable *&VTable = VTables[RD];<br>
> +  if (VTable)<br>
> +    return VTable;<br>
> +<br>
> +  // Queue up this v-table for possible deferred emission.<br>
> +  CGM.addDeferredVTable(RD);<br>
> +<br>
> +  SmallString<256> OutName;<br>
> +  llvm::raw_svector_ostream Out(OutName);<br>
> +  CGM.getCXXABI().getMangleContext().mangleCXXVTable(RD, Out);<br>
> +  Out.flush();<br>
> +  StringRef Name = OutName.str();<br>
> +<br>
> +  VTableContext &VTContext = CGM.getVTableContext();<br>
> +  llvm::ArrayType *ArrayType = llvm::ArrayType::get(<br>
> +      CGM.Int8PtrTy,<br>
> VTContext.getVTableLayout(RD).getNumVTableComponents());<br>
> +<br>
> +  VTable = CGM.CreateOrReplaceCXXRuntimeVariable(<br>
> +      Name, ArrayType, llvm::GlobalValue::ExternalLinkage);<br>
> +  VTable->setUnnamedAddr(true);<br>
> +  return VTable;<br>
> +}<br>
> +<br>
> llvm::Value *ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,<br>
>                                                       GlobalDecl GD,<br>
>                                                       llvm::Value *This,<br>
> @@ -919,11 +1042,10 @@ void ItaniumCXXABI::EmitVirtualDestructo<br>
>                         /*ImplicitParam=*/0, QualType(), 0, 0);<br>
> }<br>
><br>
> -void ItaniumCXXABI::EmitVirtualInheritanceTables(<br>
> -    llvm::GlobalVariable::LinkageTypes Linkage, const CXXRecordDecl *RD) {<br>
> +void ItaniumCXXABI::emitVirtualInheritanceTables(const CXXRecordDecl *RD) {<br>
>   CodeGenVTables &VTables = CGM.getVTables();<br>
>   llvm::GlobalVariable *VTT = VTables.GetAddrOfVTT(RD);<br>
> -  VTables.EmitVTTDefinition(VTT, Linkage, RD);<br>
> +  VTables.EmitVTTDefinition(VTT, CGM.getVTableLinkage(RD), RD);<br>
> }<br>
><br>
> void ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,<br>
><br>
> Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp<br>
> URL:<br>
> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=191523&r1=191522&r2=191523&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=191523&r1=191522&r2=191523&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)<br>
> +++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Fri Sep 27 09:48:01 2013<br>
> @@ -21,6 +21,7 @@<br>
> #include "clang/AST/Decl.h"<br>
> #include "clang/AST/DeclCXX.h"<br>
> #include "clang/AST/VTableBuilder.h"<br>
> +#include "llvm/ADT/StringSet.h"<br>
><br>
> using namespace clang;<br>
> using namespace CodeGen;<br>
> @@ -150,6 +151,20 @@ public:<br>
>                            CallExpr::const_arg_iterator ArgBeg,<br>
>                            CallExpr::const_arg_iterator ArgEnd);<br>
><br>
> +  void emitVTableDefinitions(CodeGenVTables &CGVT, const CXXRecordDecl<br>
> *RD);<br>
> +<br>
> +  llvm::Value *getVTableAddressPointInStructor(<br>
> +      CodeGenFunction &CGF, const CXXRecordDecl *VTableClass,<br>
> +      BaseSubobject Base, const CXXRecordDecl *NearestVBase,<br>
> +      bool &NeedsVirtualOffset);<br>
> +<br>
> +  llvm::Constant *<br>
> +  getVTableAddressPointForConstExpr(BaseSubobject Base,<br>
> +                                    const CXXRecordDecl *VTableClass);<br>
> +<br>
> +  llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD,<br>
> +                                        CharUnits VPtrOffset);<br>
> +<br>
>   llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl<br>
> GD,<br>
>                                          llvm::Value *This, llvm::Type *Ty);<br>
><br>
> @@ -158,8 +173,7 @@ public:<br>
>                                  CXXDtorType DtorType, SourceLocation<br>
> CallLoc,<br>
>                                  llvm::Value *This);<br>
><br>
> -  void EmitVirtualInheritanceTables(llvm::GlobalVariable::LinkageTypes<br>
> Linkage,<br>
> -                                    const CXXRecordDecl *RD);<br>
> +  void emitVirtualInheritanceTables(const CXXRecordDecl *RD);<br>
><br>
>   void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,<br>
>                        llvm::GlobalVariable *DeclPtr,<br>
> @@ -303,7 +317,16 @@ public:<br>
>                                   const MemberPointerType *MPT);<br>
><br>
> private:<br>
> -  /// VBTables - All the vbtables which have been referenced.<br>
> +  typedef std::pair<const CXXRecordDecl *, CharUnits> VFTableIdTy;<br>
> +  typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalVariable *><br>
> VFTablesMapTy;<br>
> +  /// \brief All the vftables that have been referenced.<br>
> +  VFTablesMapTy VFTablesMap;<br>
> +<br>
> +  /// \brief This set holds the record decls we've deferred vtable emission<br>
> for.<br>
> +  llvm::SmallPtrSet<const CXXRecordDecl *, 4> DeferredVFTables;<br>
> +<br>
> +<br>
> +  /// \brief All the vbtables which have been referenced.<br>
>   llvm::DenseMap<const CXXRecordDecl *, VBTableVector> VBTablesMap;<br>
><br>
>   /// Info on the global variable used to guard initialization of static<br>
> locals.<br>
> @@ -616,6 +639,116 @@ void MicrosoftCXXABI::EmitConstructorCal<br>
>                         ImplicitParam, ImplicitParamTy, ArgBeg, ArgEnd);<br>
> }<br>
><br>
> +void MicrosoftCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,<br>
> +                                            const CXXRecordDecl *RD) {<br>
> +  MicrosoftVFTableContext &VFTContext = CGM.getVFTableContext();<br>
> +  MicrosoftVFTableContext::VFPtrListTy VFPtrs =<br>
> VFTContext.getVFPtrOffsets(RD);<br>
> +  llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);<br>
> +<br>
> +  for (MicrosoftVFTableContext::VFPtrListTy::iterator I = VFPtrs.begin(),<br>
> +       E = VFPtrs.end(); I != E; ++I) {<br>
> +    llvm::GlobalVariable *VTable = getAddrOfVTable(RD, I->VFPtrFullOffset);<br>
> +    if (VTable->hasInitializer())<br>
> +      continue;<br>
> +<br>
> +    const VTableLayout &VTLayout =<br>
> +        VFTContext.getVFTableLayout(RD, I->VFPtrFullOffset);<br>
> +    llvm::Constant *Init = CGVT.CreateVTableInitializer(<br>
> +        RD, VTLayout.vtable_component_begin(),<br>
> +        VTLayout.getNumVTableComponents(), VTLayout.vtable_thunk_begin(),<br>
> +        VTLayout.getNumVTableThunks());<br>
> +    VTable->setInitializer(Init);<br>
> +<br>
> +    VTable->setLinkage(Linkage);<br>
> +    CGM.setTypeVisibility(VTable, RD, CodeGenModule::TVK_ForVTable);<br>
> +  }<br>
> +}<br>
> +<br>
> +llvm::Value *MicrosoftCXXABI::getVTableAddressPointInStructor(<br>
> +    CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject<br>
> Base,<br>
> +    const CXXRecordDecl *NearestVBase, bool &NeedsVirtualOffset) {<br>
> +  NeedsVirtualOffset = (NearestVBase != 0);<br>
> +<br>
> +  llvm::Value *VTableAddressPoint =<br>
> +      getAddrOfVTable(VTableClass, Base.getBaseOffset());<br>
> +  if (!VTableAddressPoint) {<br>
> +    assert(Base.getBase()->getNumVBases() &&<br>
> +<br>
> !CGM.getContext().getASTRecordLayout(Base.getBase()).hasOwnVFPtr());<br>
> +  }<br>
> +  return VTableAddressPoint;<br>
> +}<br>
> +<br>
> +static void mangleVFTableName(CodeGenModule &CGM, const CXXRecordDecl *RD,<br>
> +                              const VFPtrInfo &VFPtr, SmallString<256><br>
> &Name) {<br>
> +  llvm::raw_svector_ostream Out(Name);<br>
> +  CGM.getCXXABI().getMangleContext().mangleCXXVFTable(<br>
> +      RD, VFPtr.PathToMangle, Out);<br>
> +}<br>
> +<br>
> +llvm::Constant *MicrosoftCXXABI::getVTableAddressPointForConstExpr(<br>
> +    BaseSubobject Base, const CXXRecordDecl *VTableClass) {<br>
> +  llvm::Constant *VTable = getAddrOfVTable(VTableClass,<br>
> Base.getBaseOffset());<br>
> +  assert(VTable && "Couldn't find a vftable for the given base?");<br>
> +  return VTable;<br>
> +}<br>
> +<br>
> +llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl<br>
> *RD,<br>
> +                                                       CharUnits<br>
> VPtrOffset) {<br>
> +  // getAddrOfVTable may return 0 if asked to get an address of a vtable<br>
> which<br>
> +  // shouldn't be used in the given record type. We want to cache this<br>
> result in<br>
> +  // VFTablesMap, thus a simple zero check is not sufficient.<br>
> +  VFTableIdTy ID(RD, VPtrOffset);<br>
> +  VFTablesMapTy::iterator I;<br>
> +  bool Inserted;<br>
> +  llvm::tie(I, Inserted) = VFTablesMap.insert(<br>
> +      std::make_pair(ID, static_cast<llvm::GlobalVariable *>(0)));<br>
> +  if (!Inserted)<br>
> +    return I->second;<br>
> +<br>
> +  llvm::GlobalVariable *&VTable = I->second;<br>
> +<br>
> +  MicrosoftVFTableContext &VFTContext = CGM.getVFTableContext();<br>
> +  const MicrosoftVFTableContext::VFPtrListTy &VFPtrs =<br>
> +      VFTContext.getVFPtrOffsets(RD);<br>
> +<br>
> +  if (DeferredVFTables.insert(RD)) {<br>
> +    // We haven't processed this record type before.<br>
> +    // Queue up this v-table for possible deferred emission.<br>
> +    CGM.addDeferredVTable(RD);<br>
> +<br>
> +#ifndef NDEBUG<br>
> +    // Create all the vftables at once in order to make sure each vftable<br>
> has<br>
> +    // a unique mangled name.<br>
> +    llvm::StringSet<> ObservedMangledNames;<br>
> +    for (size_t J = 0, F = VFPtrs.size(); J != F; ++J) {<br>
> +      SmallString<256> Name;<br>
> +      mangleVFTableName(CGM, RD, VFPtrs[J], Name);<br>
> +      if (!ObservedMangledNames.insert(Name.str()))<br>
> +        llvm_unreachable("Already saw this mangling before?");<br>
> +    }<br>
> +#endif<br>
> +  }<br>
> +<br>
> +  for (size_t J = 0, F = VFPtrs.size(); J != F; ++J) {<br>
> +    if (VFPtrs[J].VFPtrFullOffset != VPtrOffset)<br>
> +      continue;<br>
> +<br>
> +    llvm::ArrayType *ArrayType = llvm::ArrayType::get(<br>
> +        CGM.Int8PtrTy,<br>
> +        VFTContext.getVFTableLayout(RD, VFPtrs[J].VFPtrFullOffset)<br>
> +            .getNumVTableComponents());<br>
> +<br>
> +    SmallString<256> Name;<br>
> +    mangleVFTableName(CGM, RD, VFPtrs[J], Name);<br>
> +    VTable = CGM.CreateOrReplaceCXXRuntimeVariable(<br>
> +        Name.str(), ArrayType, llvm::GlobalValue::ExternalLinkage);<br>
> +    VTable->setUnnamedAddr(true);<br>
> +    break;<br>
> +  }<br>
> +<br>
> +  return VTable;<br>
> +}<br>
> +<br>
> llvm::Value *MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction<br>
> &CGF,<br>
>                                                         GlobalDecl GD,<br>
>                                                         llvm::Value *This,<br>
> @@ -674,9 +807,10 @@ MicrosoftCXXABI::EnumerateVBTables(const<br>
>   return VBTables;<br>
> }<br>
><br>
> -void MicrosoftCXXABI::EmitVirtualInheritanceTables(<br>
> -    llvm::GlobalVariable::LinkageTypes Linkage, const CXXRecordDecl *RD) {<br>
> +void MicrosoftCXXABI::emitVirtualInheritanceTables(const CXXRecordDecl *RD)<br>
> {<br>
>   const VBTableVector &VBTables = EnumerateVBTables(RD);<br>
> +  llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);<br>
> +<br>
>   for (VBTableVector::const_iterator I = VBTables.begin(), E =<br>
> VBTables.end();<br>
>        I != E; ++I) {<br>
>     I->EmitVBTableDefinition(CGM, RD, Linkage);<br>
><br>
> Added: cfe/trunk/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp<br>
> URL:<br>
> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp?rev=191523&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp?rev=191523&view=auto</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp<br>
> (added)<br>
> +++ cfe/trunk/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp Fri<br>
> Sep 27 09:48:01 2013<br>
> @@ -0,0 +1,23 @@<br>
> +// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm %s -o - -cxx-abi<br>
> microsoft -triple=i386-pc-win32 | FileCheck %s<br>
> +<br>
> +struct A {<br>
> +  constexpr A(int x) : x(x) {}<br>
> +  virtual void f();<br>
> +  int x;<br>
> +};<br>
> +<br>
> +A a(42);<br>
> +// CHECK: @"\01?a@@3UA@@A" = global { [1 x i8*]*, i32 } { [1 x i8*]*<br>
> @"\01??_7A@@6B@", i32 42 }, align 4<br>
> +<br>
> +struct B {<br>
> +  constexpr B(int y) : y(y) {}<br>
> +  virtual void g();<br>
> +  int y;<br>
> +};<br>
> +<br>
> +struct C : A, B {<br>
> +  constexpr C() : A(777), B(13) {}<br>
> +};<br>
> +<br>
> +C c;<br>
> +// CHECK: @"\01?c@@3UC@@A" = global { [1 x i8*]*, i32, [1 x i8*]*, i32 } {<br>
> [1 x i8*]* @"\01??_7C@@6BA@@@", i32 777, [1 x i8*]* @"\01??_7C@@6BB@@@", i32<br>
> 13 }<br>
><br>
> Modified:<br>
> cfe/trunk/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp<br>
> URL:<br>
> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp?rev=191523&r1=191522&r2=191523&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp?rev=191523&r1=191522&r2=191523&view=diff</a><br>

> ==============================================================================<br>
> ---<br>
> cfe/trunk/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp<br>
> (original)<br>
> +++<br>
> cfe/trunk/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp<br>
> Fri Sep 27 09:48:01 2013<br>
> @@ -145,3 +145,39 @@ void call_grandchild_right(GrandchildOve<br>
>   // Just make sure we don't crash.<br>
>   obj->right();<br>
> }<br>
> +<br>
> +void emit_ctors() {<br>
> +  Left l;<br>
> +  // CHECK: define {{.*}} @"\01??0Left@@QAE@XZ"<br>
> +  // CHECK-NOT: getelementptr<br>
> +  // CHECK:   store [1 x i8*]* @"\01??_7Left@@6B@"<br>
> +  // CHECK: ret<br>
> +<br>
> +  Right r;<br>
> +  // CHECK: define {{.*}} @"\01??0Right@@QAE@XZ"<br>
> +  // CHECK-NOT: getelementptr<br>
> +  // CHECK:   store [1 x i8*]* @"\01??_7Right@@6B@"<br>
> +  // CHECK: ret<br>
> +<br>
> +  ChildOverride co;<br>
> +  // CHECK: define {{.*}} @"\01??0ChildOverride@@QAE@XZ"<br>
> +  // CHECK:   %[[THIS:.*]] = load %struct.ChildOverride**<br>
> +  // CHECK:   %[[VFPTR:.*]] = bitcast %struct.ChildOverride* %this1 to [1 x<br>
> i8*]**<br>
> +  // CHECK:   store [1 x i8*]* @"\01??_7ChildOverride@@6BLeft@@@", [1 x<br>
> i8*]** %[[VFPTR]]<br>
> +  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.ChildOverride* %[[THIS]] to<br>
> i8*<br>
> +  // CHECK:   %[[VFPTR_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]],<br>
> i32 4<br>
> +  // CHECK:   %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [1 x i8*]**<br>
> +  // CHECK:   store [1 x i8*]* @"\01??_7ChildOverride@@6BRight@@@", [1 x<br>
> i8*]** %[[VFPTR]]<br>
> +  // CHECK: ret<br>
> +<br>
> +  GrandchildOverride gc;<br>
> +  // CHECK: define {{.*}} @"\01??0GrandchildOverride@@QAE@XZ"<br>
> +  // CHECK:   %[[THIS:.*]] = load %struct.GrandchildOverride**<br>
> +  // CHECK:   %[[VFPTR:.*]] = bitcast %struct.GrandchildOverride* %this1 to<br>
> [1 x i8*]**<br>
> +  // CHECK:   store [1 x i8*]* @"\01??_7GrandchildOverride@@6BLeft@@@", [1<br>
> x i8*]** %[[VFPTR]]<br>
> +  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.GrandchildOverride*<br>
> %[[THIS]] to i8*<br>
> +  // CHECK:   %[[VFPTR_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]],<br>
> i32 4<br>
> +  // CHECK:   %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [1 x i8*]**<br>
> +  // CHECK:   store [1 x i8*]* @"\01??_7GrandchildOverride@@6BRight@@@", [1<br>
> x i8*]** %[[VFPTR]]<br>
> +  // CHECK: ret<br>
> +}<br>
><br>
> Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp<br>
> URL:<br>
> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp?rev=191523&r1=191522&r2=191523&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp?rev=191523&r1=191522&r2=191523&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp (original)<br>
> +++ cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp Fri Sep 27<br>
> 09:48:01 2013<br>
> @@ -71,8 +71,8 @@ void C::foo() {}<br>
> void check_vftable_offset() {<br>
>   C c;<br>
> // The vftable pointer should point at the beginning of the vftable.<br>
> -// CHECK: [[THIS_PTR:%[0-9]+]] = bitcast %"struct.basic::C"* {{.*}} to<br>
> i8***<br>
> -// CHECK: store i8** getelementptr inbounds ([2 x i8*]*<br>
> @"\01??_7C@basic@@6B@", i64 0, i64 0), i8*** [[THIS_PTR]]<br>
> +// CHECK: [[THIS_PTR:%[0-9]+]] = bitcast %"struct.basic::C"* {{.*}} to [2 x<br>
> i8*]**<br>
> +// CHECK: store [2 x i8*]* @"\01??_7C@basic@@6B@", [2 x i8*]** [[THIS_PTR]]<br>
> }<br>
><br>
> void call_complete_dtor(C *obj_ptr) {<br>
> @@ -161,7 +161,8 @@ C::C() {<br>
>   // CHECK-NEXT: br label %[[SKIP_VBASES]]<br>
>   //<br>
>   // CHECK: [[SKIP_VBASES]]<br>
> -  // CHECK: @"\01??_7C@constructors@@6B@"<br>
> +  // Class C does not define or override methods, so shouldn't change the<br>
> vfptr.<br>
> +  // CHECK-NOT: @"\01??_7C@constructors@@6B@"<br>
>   // CHECK: ret<br>
> }<br>
><br>
><br>
> Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp<br>
> URL:<br>
> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp?rev=191523&r1=191522&r2=191523&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp?rev=191523&r1=191522&r2=191523&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp<br>
> (original)<br>
> +++ cfe/trunk/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp Fri Sep<br>
> 27 09:48:01 2013<br>
> @@ -7,10 +7,26 @@ struct VBase {<br>
> };<br>
><br>
> struct B : virtual VBase {<br>
> +  B();<br>
>   virtual void foo();<br>
>   virtual void bar();<br>
> };<br>
><br>
> +B::B() {<br>
> +  // CHECK: @"\01??0B@@QAE@XZ"<br>
> +  // CHECK:   %[[THIS:.*]] = load %struct.B**<br>
> +  // CHECK:   br i1 %{{.*}}, label %[[INIT_VBASES:.*]], label<br>
> %[[SKIP_VBASES:.*]]<br>
> +  // CHECK: %[[SKIP_VBASES]]<br>
> +  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*<br>
> +  // CHECK:   %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32<br>
> 0<br>
> +  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*<br>
> +  // CHECK:   %[[VFPTR_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]],<br>
> i32 %{{.*}}<br>
> +  // CHECK:   %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [2 x i8*]**<br>
> +  // CHECK:   store [2 x i8*]* @"\01??_7B@@6B@", [2 x i8*]** %[[VFPTR]]<br>
> +  // FIXME: Should initialize the vtorDisp here.<br>
> +  // CHECK: ret<br>
> +}<br>
> +<br>
> void B::foo() {<br>
> // CHECK: define x86_thiscallcc void @"\01?foo@B@@UAEXXZ"(i8*<br>
> //<br>
><br>
> Modified:<br>
> cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp<br>
> URL:<br>
> <a href="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" target="_blank">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</a><br>

> ==============================================================================<br>
> ---<br>
> cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp<br>
> (original)<br>
> +++<br>
> cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp<br>
> Fri Sep 27 09:48:01 2013<br>
> @@ -19,6 +19,8 @@<br>
> // RUN: FileCheck --check-prefix=RET-THUNKS-Test4 %s < %t<br>
> // RUN: FileCheck --check-prefix=RET-THUNKS-Test5 %s < %t<br>
><br>
> +// RUN: FileCheck --check-prefix=MANGLING %s < %t<br>
> +<br>
> struct Empty {<br>
>   // Doesn't have a vftable!<br>
> };<br>
> @@ -51,6 +53,9 @@ struct Test1: A, B {<br>
>   // NO-THUNKS-Test1: VFTable indices for 'no_thunks::Test1' (1 entries)<br>
>   // NO-THUNKS-Test1-NEXT: 0 | void no_thunks::Test1::f()<br>
><br>
> +  // MANGLING-DAG: @"\01??_7Test1@no_thunks@@6BA@@@"<br>
> +  // MANGLING-DAG: @"\01??_7Test1@no_thunks@@6BB@@@"<br>
> +<br>
>   // Overrides only the left child's method (A::f), needs no thunks.<br>
>   virtual void f();<br>
> };<br>
> @@ -102,6 +107,8 @@ struct Test4 : Empty, A {<br>
>   // NO-THUNKS-Test4: VFTable indices for 'no_thunks::Test4' (1 entries).<br>
>   // NO-THUNKS-Test4-NEXT: 0 | void no_thunks::Test4::f()<br>
><br>
> +  // MANGLING-DAG: @"\01??_7Test4@no_thunks@@6B@"<br>
> +<br>
>   virtual void f();<br>
> };<br>
><br>
> @@ -127,6 +134,11 @@ struct Test5: Test1, Test2 {<br>
>   // NO-THUNKS-Test5: VFTable indices for 'no_thunks::Test5' (1 entries).<br>
>   // NO-THUNKS-Test5-NEXT: 1 | void no_thunks::Test5::z()<br>
><br>
> +  // MANGLING-DAG: @"\01??_7Test5@no_thunks@@6BA@@Test1@1@@"<br>
> +  // MANGLING-DAG: @"\01??_7Test5@no_thunks@@6BA@@Test2@1@@"<br>
> +  // MANGLING-DAG: @"\01??_7Test5@no_thunks@@6BB@@Test1@1@@"<br>
> +  // MANGLING-DAG: @"\01??_7Test5@no_thunks@@6BB@@Test2@1@@"<br>
> +<br>
>   virtual void z();<br>
> };<br>
><br>
> @@ -143,6 +155,9 @@ struct Test6: Test1 {<br>
>   // NO-THUNKS-Test6: VFTable indices for 'no_thunks::Test6' (1 entries).<br>
>   // NO-THUNKS-Test6-NEXT: 0 | void no_thunks::Test6::f()<br>
><br>
> +  // MANGLING-DAG: @"\01??_7Test6@no_thunks@@6BA@@@"<br>
> +  // MANGLING-DAG: @"\01??_7Test6@no_thunks@@6BB@@@"<br>
> +<br>
>   // Overrides both no_thunks::Test1::f and A::f.<br>
>   virtual void f();<br>
> };<br>
> @@ -203,6 +218,9 @@ struct Test9: A, D {<br>
>   // NO-THUNKS-Test9: VFTable indices for 'no_thunks::Test9' (1 entries).<br>
>   // NO-THUNKS-Test9-NEXT: 1 | void no_thunks::Test9::h()<br>
><br>
> +  // MANGLING-DAG: @"\01??_7Test9@no_thunks@@6BA@@@"<br>
> +  // MANGLING-DAG: @"\01??_7Test9@no_thunks@@6BD@1@@"<br>
> +<br>
>   virtual void h();<br>
> };<br>
><br>
> @@ -228,6 +246,9 @@ struct Test1: A, D {<br>
>   // PURE-VIRTUAL-Test1-NEXT: via vfptr at offset 4<br>
>   // PURE-VIRTUAL-Test1-NEXT: 0 | void pure_virtual::Test1::g()<br>
><br>
> +  // MANGLING-DAG: @"\01??_7Test1@pure_virtual@@6BA@@@"<br>
> +  // MANGLING-DAG: @"\01??_7Test1@pure_virtual@@6BD@1@@"<br>
> +<br>
>   // Overrides only the right child's method (pure_virtual::D::g), needs<br>
> this adjustment but<br>
>   // not thunks.<br>
>   virtual void g();<br>
> @@ -254,6 +275,9 @@ struct Test1 : B, C {<br>
>   // THIS-THUNKS-Test1: VFTable indices for 'this_adjustment::Test1' (1<br>
> entries).<br>
>   // THIS-THUNKS-Test1-NEXT: 0 | void this_adjustment::Test1::g()<br>
><br>
> +  // MANGLING-DAG: @"\01??_7Test1@this_adjustment@@6BB@@@"<br>
> +  // MANGLING-DAG: @"\01??_7Test1@this_adjustment@@6BC@@@"<br>
> +<br>
>   virtual void g();<br>
> };<br>
><br>
> @@ -278,6 +302,10 @@ struct Test2 : A, B, C {<br>
>   // THIS-THUNKS-Test2-NEXT: via vfptr at offset 4<br>
>   // THIS-THUNKS-Test2-NEXT: 0 | void this_adjustment::Test2::g()<br>
><br>
> +  // MANGLING-DAG: @"\01??_7Test2@this_adjustment@@6BA@@@"<br>
> +  // MANGLING-DAG: @"\01??_7Test2@this_adjustment@@6BB@@@"<br>
> +  // MANGLING-DAG: @"\01??_7Test2@this_adjustment@@6BC@@@"<br>
> +<br>
>   virtual void g();<br>
> };<br>
><br>
> @@ -337,6 +365,8 @@ struct Test1 : Ret1 {<br>
>   // RET-THUNKS-Test1: VFTable indices for 'return_adjustment::Test1' (1<br>
> entries).<br>
>   // RET-THUNKS-Test1-NEXT: 2 | this_adjustment::Test1<br>
> *return_adjustment::Test1::foo()<br>
><br>
> +  // MANGLING-DAG: @"\01??_7Test1@return_adjustment@@6B@"<br>
> +<br>
>   virtual this_adjustment::Test1* foo();<br>
> };<br>
><br>
><br>
> Modified:<br>
> cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp<br>
> URL:<br>
> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp?rev=191523&r1=191522&r2=191523&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp?rev=191523&r1=191522&r2=191523&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp<br>
> (original)<br>
> +++ cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp<br>
> Fri Sep 27 09:48:01 2013<br>
> @@ -1,6 +1,6 @@<br>
> // RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=i386-pc-win32<br>
> -emit-llvm -fdump-vtable-layouts -o - > %t 2>&1<br>
> -// RUN: FileCheck --check-prefix=EMITS-VTABLE %s < %t<br>
> -// RUN: FileCheck --check-prefix=NO-VTABLE %s < %t<br>
> +// RUN: FileCheck --check-prefix=EMITS-VFTABLE %s < %t<br>
> +// RUN: FileCheck --check-prefix=NO-VFTABLE %s < %t<br>
> // RUN: FileCheck --check-prefix=CHECK-A %s < %t<br>
> // RUN: FileCheck --check-prefix=CHECK-B %s < %t<br>
> // RUN: FileCheck --check-prefix=CHECK-C %s < %t<br>
> @@ -10,19 +10,12 @@<br>
> // RUN: FileCheck --check-prefix=CHECK-G %s < %t<br>
> // RUN: FileCheck --check-prefix=CHECK-I %s < %t<br>
><br>
> -// FIXME: Currently, we only test VFTableContext in the AST, but still use<br>
> -// VTableContext for CodeGen. We should remove the "Vtable" checks below<br>
> when we<br>
> -// completely switch from VTableContext to VFTableContext.<br>
> -// Currently, the order of Vtable vs VFTable output depends on whether the<br>
> -// v*table info was required by a constructor or a method definition.<br>
> -<br>
> struct A {<br>
>   // CHECK-A: VFTable for 'A' (3 entries)<br>
>   // CHECK-A-NEXT: 0 | void A::f()<br>
>   // CHECK-A-NEXT: 1 | void A::g()<br>
>   // CHECK-A-NEXT: 2 | void A::h()<br>
> -<br>
> -  // CHECK-A: Vtable for 'A' (3 entries)<br>
> +  // CHECK-A: VFTable indices for 'A' (3 entries)<br>
>   // CHECK-A-NEXT: 0 | void A::f()<br>
>   // CHECK-A-NEXT: 1 | void A::g()<br>
>   // CHECK-A-NEXT: 2 | void A::h()<br>
> @@ -33,20 +26,17 @@ struct A {<br>
>   int ia;<br>
> };<br>
> A a;<br>
> -// EMITS-VTABLE-DAG: @"\01??_7A@@6B@" = linkonce_odr unnamed_addr constant<br>
> [3 x i8*]<br>
> +// EMITS-VFTABLE-DAG: @"\01??_7A@@6B@" = linkonce_odr unnamed_addr constant<br>
> [3 x i8*]<br>
><br>
> struct B : A {<br>
> -  // CHECK-B: Vtable for 'B' (5 entries)<br>
> +  // CHECK-B: VFTable for 'A' in 'B' (5 entries)<br>
>   // CHECK-B-NEXT: 0 | void B::f()<br>
>   // CHECK-B-NEXT: 1 | void A::g()<br>
>   // CHECK-B-NEXT: 2 | void A::h()<br>
>   // CHECK-B-NEXT: 3 | void B::i()<br>
>   // CHECK-B-NEXT: 4 | void B::j()<br>
> -<br>
> -  // CHECK-B: VFTable for 'A' in 'B' (5 entries)<br>
> +  // CHECK-B: VFTable indices for 'B' (3 entries)<br>
>   // CHECK-B-NEXT: 0 | void B::f()<br>
> -  // CHECK-B-NEXT: 1 | void A::g()<br>
> -  // CHECK-B-NEXT: 2 | void A::h()<br>
>   // CHECK-B-NEXT: 3 | void B::i()<br>
>   // CHECK-B-NEXT: 4 | void B::j()<br>
><br>
> @@ -55,7 +45,7 @@ struct B : A {<br>
>   virtual void j();<br>
> };<br>
> B b;<br>
> -// EMITS-VTABLE-DAG: @"\01??_7B@@6B@" = linkonce_odr unnamed_addr constant<br>
> [5 x i8*]<br>
> +// EMITS-VFTABLE-DAG: @"\01??_7B@@6B@" = linkonce_odr unnamed_addr constant<br>
> [5 x i8*]<br>
><br>
> struct C {<br>
>   // CHECK-C: VFTable for 'C' (2 entries)<br>
> @@ -65,25 +55,17 @@ struct C {<br>
>   // CHECK-C-NEXT: 0 | C::~C() [scalar deleting]<br>
>   // CHECK-C-NEXT: 1 | void C::f()<br>
><br>
> -  // CHECK-C: Vtable for 'C' (2 entries)<br>
> -  // CHECK-C-NEXT: 0 | C::~C() [scalar deleting]<br>
> -  // CHECK-C-NEXT: 1 | void C::f()<br>
> -  // CHECK-C: VTable indices for 'C' (2 entries).<br>
> -  // CHECK-C-NEXT: 0 | C::~C() [scalar deleting]<br>
> -  // CHECK-C-NEXT: 1 | void C::f()<br>
> -<br>
>   virtual ~C();<br>
>   virtual void f();<br>
> };<br>
> void C::f() {}<br>
> -// NO-VTABLE-NOT: @"\01??_7C@@6B@"<br>
> +// NO-VFTABLE-NOT: @"\01??_7C@@6B@"<br>
><br>
> struct D {<br>
> -  // CHECK-D: Vtable for 'D' (2 entries)<br>
> +  // CHECK-D: VFTable for 'D' (2 entries)<br>
>   // CHECK-D-NEXT: 0 | void D::f()<br>
>   // CHECK-D-NEXT: 1 | D::~D() [scalar deleting]<br>
> -<br>
> -  // CHECK-D: VFTable for 'D' (2 entries)<br>
> +  // CHECK-D: VFTable indices for 'D' (2 entries)<br>
>   // CHECK-D-NEXT: 0 | void D::f()<br>
>   // CHECK-D-NEXT: 1 | D::~D() [scalar deleting]<br>
><br>
> @@ -91,7 +73,7 @@ struct D {<br>
>   virtual ~D();<br>
> };<br>
> D d;<br>
> -// EMITS-VTABLE-DAG: @"\01??_7D@@6B@" = linkonce_odr unnamed_addr constant<br>
> [2 x i8*]<br>
> +// EMITS-VFTABLE-DAG: @"\01??_7D@@6B@" = linkonce_odr unnamed_addr constant<br>
> [2 x i8*]<br>
><br>
> struct E : A {<br>
>   // CHECK-E: VFTable for 'A' in 'E' (5 entries)<br>
> @@ -104,35 +86,15 @@ struct E : A {<br>
>   // CHECK-E-NEXT: 3 | E::~E() [scalar deleting]<br>
>   // CHECK-E-NEXT: 4 | void E::i()<br>
><br>
> -  // CHECK-E: Vtable for 'E' (5 entries)<br>
> -  // CHECK-E-NEXT: 0 | void A::f()<br>
> -  // CHECK-E-NEXT: 1 | void A::g()<br>
> -  // CHECK-E-NEXT: 2 | void A::h()<br>
> -  // CHECK-E-NEXT: 3 | E::~E() [scalar deleting]<br>
> -  // CHECK-E-NEXT: 4 | void E::i()<br>
> -  // CHECK-E: VTable indices for 'E' (2 entries).<br>
> -  // CHECK-E-NEXT: 3 | E::~E() [scalar deleting]<br>
> -  // CHECK-E-NEXT: 4 | void E::i()<br>
> -<br>
>   // ~E would be the key method, but it isn't used, and MS ABI has no key<br>
>   // methods.<br>
>   virtual ~E();<br>
>   virtual void i();<br>
> };<br>
> void E::i() {}<br>
> -// NO-VTABLE-NOT: @"\01??_7E@@6B@"<br>
> +// NO-VFTABLE-NOT: @"\01??_7E@@6B@"<br>
><br>
> struct F : A {<br>
> -  // CHECK-F: Vtable for 'F' (5 entries)<br>
</div></div><div class="im">> -  // CHECK-F-NEXT: 0 | void A::f()<br>
> -  // CHECK-F-NEXT: 1 | void A::g()<br>
> -  // CHECK-F-NEXT: 2 | void A::h()<br>
> -  // CHECK-F-NEXT: 3 | void F::i()<br>
> -  // CHECK-F-NEXT: 4 | F::~F() [scalar deleting]<br>
> -  // CHECK-F: VTable indices for 'F' (2 entries).<br>
> -  // CHECK-F-NEXT: 3 | void F::i()<br>
> -  // CHECK-F-NEXT: 4 | F::~F() [scalar deleting]<br>
> -<br>
>   // CHECK-F: VFTable for 'A' in 'F' (5 entries)<br>
>   // CHECK-F-NEXT: 0 | void A::f()<br>
>   // CHECK-F-NEXT: 1 | void A::g()<br>
> @@ -147,7 +109,7 @@ struct F : A {<br>
</div>>   virtual ~F();<br>
> };<br>
> F f;<br>
> -// EMITS-VTABLE-DAG: @"\01??_7F@@6B@" = linkonce_odr unnamed_addr constant<br>
> [5 x i8*]<br>
> +// EMITS-VFTABLE-DAG: @"\01??_7F@@6B@" = linkonce_odr unnamed_addr constant<br>
> [5 x i8*]<br>
><br>
<div><div class="h5">> struct G : E {<br>
>   // CHECK-G: VFTable for 'A' in 'E' in 'G' (6 entries)<br>
> @@ -162,31 +124,19 @@ struct G : E {<br>
>   // CHECK-G-NEXT: 3 | G::~G() [scalar deleting]<br>
>   // CHECK-G-NEXT: 5 | void G::j()<br>
><br>
> -  // CHECK-G: Vtable for 'G' (6 entries)<br>
> -  // CHECK-G-NEXT: 0 | void G::f()<br>
> -  // CHECK-G-NEXT: 1 | void A::g()<br>
> -  // CHECK-G-NEXT: 2 | void A::h()<br>
> -  // CHECK-G-NEXT: 3 | G::~G() [scalar deleting]<br>
> -  // CHECK-G-NEXT: 4 | void E::i()<br>
> -  // CHECK-G-NEXT: 5 | void G::j()<br>
> -  // CHECK-G: VTable indices for 'G' (3 entries).<br>
> -  // CHECK-G-NEXT: 0 | void G::f()<br>
> -  // CHECK-G-NEXT: 3 | G::~G() [scalar deleting]<br>
> -  // CHECK-G-NEXT: 5 | void G::j()<br>
> -<br>
>   virtual void f();  // overrides A::f()<br>
>   virtual ~G();<br>
>   virtual void j();<br>
> };<br>
> void G::j() {}<br>
> -// NO-VTABLE-NOT: @"\01??_7G@@6B@"<br>
> +// NO-VFTABLE-NOT: @"\01??_7G@@6B@"<br>
><br>
> // Test that the usual Itanium-style key method does not emit a vtable.<br>
> struct H {<br>
>   virtual void f();<br>
> };<br>
> void H::f() {}<br>
> -// NO-VTABLE-NOT: @"\01??_7H@@6B@"<br>
> +// NO-VFTABLE-NOT: @"\01??_7H@@6B@"<br>
><br>
> struct Empty { };<br>
><br>
><br>
> Modified:<br>
> cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp<br>
> URL:<br>
> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp?rev=191523&r1=191522&r2=191523&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp?rev=191523&r1=191522&r2=191523&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp<br>
> (original)<br>
> +++ cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp<br>
</div></div><div class="im">> Fri Sep 27 09:48:01 2013<br>
</div>> @@ -18,6 +18,8 @@<br>
> // RUN: FileCheck --check-prefix=RET-W %s < %t<br>
> // RUN: FileCheck --check-prefix=RET-T %s < %t<br>
<div class="im">><br>
> +// RUN: FileCheck --check-prefix=MANGLING %s < %t<br>
> +<br>
</div><div><div class="h5">> struct Empty { };<br>
><br>
> struct A {<br>
> @@ -38,6 +40,8 @@ struct C: virtual A {<br>
>   // VTABLE-C-NEXT: vbtable index 1, vfptr at offset 0<br>
>   // VTABLE-C-NEXT: 0 | void C::f()<br>
><br>
> +  // MANGLING-DAG: @"\01??_7C@@6B@"<br>
> +<br>
>   ~C();  // Currently required to have correct record layout, see PR16406<br>
>   virtual void f();<br>
> };<br>
> @@ -58,6 +62,9 @@ struct D: virtual A {<br>
>   // VTABLE-D-NEXT: via vbtable index 1, vfptr at offset 0<br>
>   // VTABLE-D-NEXT: 0 | void D::f()<br>
><br>
> +  // MANGLING-DAG: @"\01??_7D@@6B0@@"<br>
> +  // MANGLING-DAG: @"\01??_7D@@6BA@@@"<br>
> +<br>
>   virtual void f();<br>
>   virtual void h();<br>
> };<br>
> @@ -71,6 +78,7 @@ struct X { int x; };<br>
><br>
> // X and A get reordered in the layout since X doesn't have a vfptr while A<br>
> has.<br>
> struct Y : X, A { };<br>
> +// MANGLING-DAG: @"\01??_7Y@Test1@@6B@"<br>
><br>
> struct Z : virtual Y {<br>
>   // TEST1: VFTable for 'A' in 'Test1::Y' in 'Test1::Z' (2 entries).<br>
> @@ -78,6 +86,8 @@ struct Z : virtual Y {<br>
>   // TEST1-NEXT: 1 | void A::z()<br>
><br>
>   // TEST1-NOT: VFTable indices for 'Test1::Z'<br>
> +<br>
> +  // MANGLING-DAG: @"\01??_7Z@Test1@@6B@"<br>
> };<br>
><br>
> Z z;<br>
> @@ -99,6 +109,10 @@ struct X: virtual A, virtual B {<br>
>   // TEST2: VFTable indices for 'Test2::X' (1 entries).<br>
>   // TEST2-NEXT: 0 | void Test2::X::h()<br>
><br>
> +  // MANGLING-DAG: @"\01??_7X@Test2@@6B01@@"<br>
> +  // MANGLING-DAG: @"\01??_7X@Test2@@6BA@@@"<br>
> +  // MANGLING-DAG: @"\01??_7X@Test2@@6BB@@@"<br>
</div></div>> +<br>
>   virtual void h();<br>
> };<br>
><br>
<div><div class="h5">> @@ -107,7 +121,9 @@ X x;<br>
><br>
> namespace Test3 {<br>
><br>
> -struct X : virtual A { };<br>
> +struct X : virtual A {<br>
> +  // MANGLING-DAG: @"\01??_7X@Test3@@6B@"<br>
> +};<br>
><br>
> struct Y: virtual X {<br>
>   // TEST3: VFTable for 'A' in 'Test3::X' in 'Test3::Y' (2 entries).<br>
> @@ -115,6 +131,8 @@ struct Y: virtual X {<br>
>   // TEST3-NEXT: 1 | void A::z()<br>
><br>
>   // TEST3-NOT: VFTable indices for 'Test3::Y'<br>
> +<br>
> +  // MANGLING-DAG: @"\01??_7Y@Test3@@6B@"<br>
> };<br>
><br>
> Y y;<br>
> @@ -134,6 +152,8 @@ struct X: virtual C {<br>
>   // TEST4-NEXT: 1 | void A::z()<br>
><br>
>   // TEST4-NOT: VFTable indices for 'Test4::X'<br>
> +<br>
> +  // MANGLING-DAG: @"\01??_7X@Test4@@6B@"<br>
> };<br>
><br>
> X x;<br>
> @@ -143,6 +163,7 @@ namespace Test5 {<br>
><br>
> // New methods are added to the base's vftable.<br>
> struct X : A {<br>
> +  // MANGLING-DAG: @"\01??_7X@Test5@@6B@"<br>
>   virtual void g();<br>
> };<br>
><br>
> @@ -158,6 +179,9 @@ struct Y : virtual X {<br>
>   // TEST5: VFTable indices for 'Test5::Y' (1 entries).<br>
>   // TEST5-NEXT: 0 | void Test5::Y::h()<br>
><br>
> +  // MANGLING-DAG: @"\01??_7Y@Test5@@6B01@@"<br>
> +  // MANGLING-DAG: @"\01??_7Y@Test5@@6BX@1@@"<br>
</div></div>> +<br>
>   virtual void h();<br>
> };<br>
><br>
<div><div class="h5">> @@ -172,6 +196,8 @@ struct X : A, virtual Empty {<br>
>   // TEST6-NEXT: 1 | void A::z()<br>
><br>
>   // TEST6-NOT: VFTable indices for 'Test6::X'<br>
> +<br>
> +  // MANGLING-DAG: @"\01??_7X@Test6@@6B@"<br>
> };<br>
><br>
> X x;<br>
> @@ -179,7 +205,9 @@ X x;<br>
><br>
> namespace Test7 {<br>
><br>
> -struct X : C { };<br>
> +struct X : C {<br>
> +  // MANGLING-DAG: @"\01??_7X@Test7@@6B@"<br>
> +};<br>
><br>
> struct Y : virtual X {<br>
>   // TEST7: VFTable for 'A' in 'C' in 'Test7::X' in 'Test7::Y' (2 entries).<br>
> @@ -191,6 +219,8 @@ struct Y : virtual X {<br>
>   // TEST7-NEXT: 0 | this adjustment: 12 non-virtual<br>
><br>
>   // TEST7-NOT: VFTable indices for 'Test7::Y'<br>
> +<br>
> +  // MANGLING-DAG: @"\01??_7Y@Test7@@6B@"<br>
> };<br>
><br>
> Y y;<br>
> @@ -210,6 +240,9 @@ struct X : D, C {<br>
>   // TEST8: VFTable indices for 'Test8::X' (1 entries).<br>
>   // TEST8-NEXT: via vbtable index 1, vfptr at offset 0<br>
><br>
> +  // MANGLING-DAG: @"\01??_7X@Test8@@6BA@@@"<br>
> +  // MANGLING-DAG: @"\01??_7X@Test8@@6BD@@@"<br>
</div></div>> +<br>
>   virtual void f();<br>
> };<br>
><br>
<div class="im">> @@ -231,6 +264,9 @@ struct Y : virtual X {<br>
>   // TEST9-Y: VFTable indices for 'Test9::Y' (1 entries).<br>
>   // TEST9-Y-NEXT: 0 | void Test9::Y::h()<br>
><br>
> +  // MANGLING-DAG: @"\01??_7Y@Test9@@6B01@@"<br>
> +  // MANGLING-DAG: @"\01??_7Y@Test9@@6BX@1@@"<br>
</div>> +<br>
>   virtual void h();<br>
> };<br>
><br>
<div><div class="h5">> @@ -248,6 +284,13 @@ struct Z : Y, virtual B {<br>
>   // TEST9-Z-NEXT: 0 | void B::g()<br>
><br>
>   // TEST9-Z-NOT: VFTable indices for 'Test9::Z'<br>
> +<br>
> +  // MANGLING-DAG: @"\01??_7Z@Test9@@6BX@1@@"<br>
> +  // MANGLING-DAG: @"\01??_7Z@Test9@@6BY@1@@"<br>
> +<br>
> +  // FIXME this one is wrong:<br>
> +  // INCORRECT MANGLING-DAG: @"\01??_7Z@Test9@@6BB@@@"<br>
> +  // MANGLING-DAG-SHOULD-BE: @"\01??_7Z@Test9@@6B@"<br>
> };<br>
><br>
> Z z;<br>
> @@ -275,6 +318,16 @@ struct W : Z, D, virtual A, virtual B {<br>
>   // TEST9-W-NEXT: 0 | this adjustment: -8 non-virtual<br>
><br>
>   // TEST9-W-NOT: VFTable indices for 'Test9::W'<br>
> +<br>
> +  // MANGLING-DAG: @"\01??_7W@Test9@@6BA@@@"<br>
> +  // MANGLING-DAG: @"\01??_7W@Test9@@6BD@@@"<br>
> +  // MANGLING-DAG: @"\01??_7W@Test9@@6BX@1@@"<br>
> +<br>
> +  // FIXME: these two are wrong:<br>
> +  // INCORRECT MANGLING-DAG: @"\01??_7W@Test9@@6BB@@@"<br>
> +  // MANGLING-DAG-SHOULD-BE: @"\01??_7W@Test9@@6B@"<br>
> +  // INCORRECT MANGLING-DAG: @"\01??_7W@Test9@@6BY@1@Z@1@@"<br>
> +  // MANGLING-DAG-SHOULD-BE: @"\01??_7W@Test9@@6BY@1@@"<br>
> };<br>
><br>
> W w;<br>
> @@ -320,6 +373,16 @@ struct T : Z, D, virtual A, virtual B {<br>
>   // TEST9-T-NEXT: via vbtable index 2, vfptr at offset 0<br>
>   // TEST9-T-NEXT: 0 | void Test9::T::g()<br>
><br>
> +  // MANGLING-DAG: @"\01??_7T@Test9@@6BA@@@"<br>
> +  // MANGLING-DAG: @"\01??_7T@Test9@@6BD@@@"<br>
> +  // MANGLING-DAG: @"\01??_7T@Test9@@6BX@1@@"<br>
> +<br>
> +  // FIXME: these two are wrong:<br>
> +  // INCORRECT MANGLING-DAG: @"\01??_7T@Test9@@6BB@@@"<br>
> +  // MANGLING-DAG-SHOULD-BE: @"\01??_7T@Test9@@6B@"<br>
> +  // INCORRECT MANGLING-DAG: @"\01??_7T@Test9@@6BY@1@Z@1@@"<br>
> +  // MANGLING-DAG-SHOULD-BE: @"\01??_7T@Test9@@6BY@1@@"<br>
> +<br>
>   virtual void f();<br>
>   virtual void g();<br>
>   virtual void h();<br>
><br>
> Modified: cfe/trunk/test/CodeGenCXX/virtual-base-destructor-call.cpp<br>
> URL:<br>
> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/virtual-base-destructor-call.cpp?rev=191523&r1=191522&r2=191523&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/virtual-base-destructor-call.cpp?rev=191523&r1=191522&r2=191523&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/CodeGenCXX/virtual-base-destructor-call.cpp (original)<br>
</div></div>> +++ cfe/trunk/test/CodeGenCXX/virtual-base-destructor-call.cpp Fri Sep 27<br>
> 09:48:01 2013<br>
<div class="HOEnZb"><div class="h5">> @@ -27,12 +27,6 @@ int main() {<br>
> //  CHECK: call {{.*}} @_ZN13basic_istreamIcED2Ev<br>
> //  CHECK: }<br>
><br>
> -// basic_iostream's deleting dtor calls its complete dtor, then<br>
> -// operator delete().<br>
> -//  CHECK: define linkonce_odr {{.*}}<br>
> @_ZN14basic_iostreamIcED0Ev(%struct.basic_iostream* {{.*}}%this)<br>
> unnamed_addr<br>
> -//  CHECK: call {{.*}} @_ZN14basic_iostreamIcED1Ev<br>
> -//  CHECK: call {{.*}} @_ZdlPv<br>
> -<br>
> // basic_istream's complete dtor calls the base dtor,<br>
> // then its virtual base's base dtor.<br>
> //  CHECK: define linkonce_odr {{.*}}<br>
> @_ZN13basic_istreamIcED1Ev(%struct.basic_istream* {{.*}}%this) unnamed_addr<br>
> @@ -45,6 +39,12 @@ int main() {<br>
> //  CHECK: call {{.*}} @_ZN13basic_istreamIcED1Ev<br>
> //  CHECK: call {{.*}} @_ZdlPv<br>
><br>
> +// basic_iostream's deleting dtor calls its complete dtor, then<br>
> +// operator delete().<br>
> +//  CHECK: define linkonce_odr {{.*}}<br>
> @_ZN14basic_iostreamIcED0Ev(%struct.basic_iostream* {{.*}}%this)<br>
> unnamed_addr<br>
> +//  CHECK: call {{.*}} @_ZN14basic_iostreamIcED1Ev<br>
> +//  CHECK: call {{.*}} @_ZdlPv<br>
> +<br>
> // basic_istream's base dtor is a no-op.<br>
> //  CHECK: define linkonce_odr {{.*}}<br>
> @_ZN13basic_istreamIcED2Ev(%struct.basic_istream* {{.*}}%this, i8** %vtt)<br>
> unnamed_addr<br>
> //  CHECK-NOT: call<br>
><br>
><br>
> _______________________________________________<br>
> cfe-commits mailing list<br>
> <a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
><br>
><br>
> _______________________________________________<br>
> cfe-commits mailing list<br>
> <a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
><br>
><br>
> _______________________________________________<br>
> cfe-commits mailing list<br>
> <a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
><br>
><br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</div></div></blockquote></div><br></div>