<div dir="ltr">I'm trying to understand how to fix the ASan/Windows breakage wrt vftables.<div><br></div><div>Here's what David told me on the r212138 thread:<br>2014-07-08 4:39 GMT+04:00 David Majnemer <<a href="mailto:david.majnemer@gmail.com">david.majnemer@gmail.com</a>>:<br>

> ASAN replaces one internal global with another. Because the new symbol<br>> isn't in a Comdat, it's alias isn't either.  This makes the alias a<br>> strong definition.<br></div><div><br></div><div>
After rethinking this a bit, I'm puzzled.</div>
<div>Not only we need to correctly link no-rtti with rtti-enabled TUs but we should also handle asan vs no-asan TUs.</div><div>ASan increases the size of globals by adding redzones.</div><div>It looks like an internal GV for a vftable in a (asan enabled, no-rtti) configuration will be *larger* than the same vftable in a (no-asan,rtti-enabled) configuration and the linking process will cause bad result.</div>

<div>That said, I think we have to disable instrumentation of vftables on Windows as long as we want to support mixing rtti- with no-rtti TUs or asan with no-asan TUs.<br></div><div>Are we on the same page here?</div><div>

<br></div><div>If we agree that we can't add redzones to vftables, we should adjust AddressSanitizerModule::ShouldInstrumentGlobal(GV) to handle this.</div><div>The problem is that those GVs are unnamed.</div><div>Is there a condition that's only true for the internal vftable GVs so I can write an "if()"?</div>

<div>I think "if (G->hasComdat() && G->getLinkage() == InternalLinkage)" is a too wide condition.</div><div>Or can we name these internal GVs somehow to make them easy to filter out?  E.g. "\02?_7blah"?</div>

</div><div class="gmail_extra"><br><br><div class="gmail_quote">2014-07-02 0:30 GMT+04:00 David Majnemer <span dir="ltr"><<a href="mailto:david.majnemer@gmail.com" target="_blank">david.majnemer@gmail.com</a>></span>:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: majnemer<br>
Date: Tue Jul  1 15:30:31 2014<br>
New Revision: 212125<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=212125&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=212125&view=rev</a><br>
Log:<br>
MS ABI: Reference MSVC RTTI from the VFTable<br>
<br>
The pointer for a class's RTTI data comes right before the VFTable but<br>
has no name.  To be properly compatible with this, we do the following:<br>
* Create a single GlobalVariable which holds the contents of the VFTable<br>
  _and_ the pointer to the RTTI data.<br>
* Create a GlobalAlias, with appropriate linkage/visibility, that points<br>
  just after the RTTI data pointer.  This ensures that the VFTable<br>
  symbol will always refer to VFTable data.<br>
* Create a Comdat with a "Largest" SelectionKind and stick the private<br>
  GlobalVariable in it.  By transitivity, the GlobalAlias will be a<br>
  member of the Comdat group.  Using "Largest" ensures that foreign<br>
  definitions without an RTTI data pointer will _not_ be chosen in the<br>
  final linked image.<br>
<br>
Whether or not we emit RTTI data depends on several things:<br>
* The -fno-rtti flag implies that we should never not emit a pointer to<br>
  RTTI data before the VFTable.<br>
* __declspec(dllimport) brings in the VFTable from a remote DLL. Use an<br>
  available_externally GlobalVariable to provide a local definition of<br>
  the VFTable.  This means that we won't have any available_externally<br>
  definitions of things like complete object locators.  This is<br>
  acceptable because they are never directly referenced.<br>
<br>
To my knowledge, this completes the implementation of MSVC RTTI code<br>
generation.<br>
<br>
Further semantic work should be done to properly support /GR-.<br>
<br>
Modified:<br>
    cfe/trunk/lib/AST/VTableBuilder.cpp<br>
    cfe/trunk/lib/CodeGen/CGVTables.cpp<br>
    cfe/trunk/lib/CodeGen/CGVTables.h<br>
    cfe/trunk/lib/CodeGen/CodeGenModule.h<br>
    cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp<br>
    cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp<br>
    cfe/trunk/lib/CodeGen/MicrosoftRTTI.cpp<br>
    cfe/trunk/test/CodeGenCXX/dllexport.cpp<br>
<br>
Modified: cfe/trunk/lib/AST/VTableBuilder.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/VTableBuilder.cpp?rev=212125&r1=212124&r2=212125&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/VTableBuilder.cpp?rev=212125&r1=212124&r2=212125&view=diff</a><br>


==============================================================================<br>
--- cfe/trunk/lib/AST/VTableBuilder.cpp (original)<br>
+++ cfe/trunk/lib/AST/VTableBuilder.cpp Tue Jul  1 15:30:31 2014<br>
@@ -2574,6 +2574,12 @@ public:<br>
         MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)),<br>
         WhichVFPtr(*Which),<br>
         Overriders(MostDerivedClass, CharUnits(), MostDerivedClass) {<br>
+    // Only include the RTTI component if we know that we will provide a<br>
+    // definition of the vftable.<br>
+    if (Context.getLangOpts().RTTI &&<br>
+        !MostDerivedClass->hasAttr<DLLImportAttr>())<br>
+      Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass));<br>
+<br>
     LayoutVFTable();<br>
<br>
     if (Context.getLangOpts().DumpVTableLayouts)<br>
@@ -2915,7 +2921,8 @@ void VFTableBuilder::AddMethods(BaseSubo<br>
     // it requires return adjustment. Insert the method info for this method.<br>
     unsigned VBIndex =<br>
         LastVBase ? VTables.getVBTableIndex(MostDerivedClass, LastVBase) : 0;<br>
-    MethodInfo MI(VBIndex, Components.size());<br>
+    MethodInfo MI(VBIndex, Context.getLangOpts().RTTI ? Components.size() - 1<br>
+                                                      : Components.size());<br>
<br>
     assert(!MethodInfoMap.count(MD) &&<br>
            "Should not have method info for this method yet!");<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGVTables.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.cpp?rev=212125&r1=212124&r2=212125&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.cpp?rev=212125&r1=212124&r2=212125&view=diff</a><br>


==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGVTables.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGVTables.cpp Tue Jul  1 15:30:31 2014<br>
@@ -431,12 +431,10 @@ void CodeGenVTables::EmitThunks(GlobalDe<br>
     emitThunk(GD, (*ThunkInfoVector)[I], /*ForVTable=*/false);<br>
 }<br>
<br>
-llvm::Constant *<br>
-CodeGenVTables::CreateVTableInitializer(const CXXRecordDecl *RD,<br>
-                                        const VTableComponent *Components,<br>
-                                        unsigned NumComponents,<br>
-                                const VTableLayout::VTableThunkTy *VTableThunks,<br>
-                                        unsigned NumVTableThunks) {<br>
+llvm::Constant *CodeGenVTables::CreateVTableInitializer(<br>
+    const CXXRecordDecl *RD, const VTableComponent *Components,<br>
+    unsigned NumComponents, const VTableLayout::VTableThunkTy *VTableThunks,<br>
+    unsigned NumVTableThunks, llvm::Constant *RTTI) {<br>
   SmallVector<llvm::Constant *, 64> Inits;<br>
<br>
   llvm::Type *Int8PtrTy = CGM.Int8PtrTy;<br>
@@ -444,9 +442,6 @@ CodeGenVTables::CreateVTableInitializer(<br>
   llvm::Type *PtrDiffTy =<br>
     CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());<br>
<br>
-  QualType ClassType = CGM.getContext().getTagDeclType(RD);<br>
-  llvm::Constant *RTTI = CGM.GetAddrOfRTTIDescriptor(ClassType);<br>
-<br>
   unsigned NextVTableThunkIndex = 0;<br>
<br>
   llvm::Constant *PureVirtualFn = nullptr, *DeletedVirtualFn = nullptr;<br>
@@ -594,13 +589,14 @@ CodeGenVTables::GenerateConstructionVTab<br>
   // V-tables are always unnamed_addr.<br>
   VTable->setUnnamedAddr(true);<br>
<br>
+  llvm::Constant *RTTI = CGM.GetAddrOfRTTIDescriptor(<br>
+      CGM.getContext().getTagDeclType(Base.getBase()));<br>
+<br>
   // Create and set the initializer.<br>
-  llvm::Constant *Init =<br>
-    CreateVTableInitializer(Base.getBase(),<br>
-                            VTLayout->vtable_component_begin(),<br>
-                            VTLayout->getNumVTableComponents(),<br>
-                            VTLayout->vtable_thunk_begin(),<br>
-                            VTLayout->getNumVTableThunks());<br>
+  llvm::Constant *Init = CreateVTableInitializer(<br>
+      Base.getBase(), VTLayout->vtable_component_begin(),<br>
+      VTLayout->getNumVTableComponents(), VTLayout->vtable_thunk_begin(),<br>
+      VTLayout->getNumVTableThunks(), RTTI);<br>
   VTable->setInitializer(Init);<br>
<br>
   return VTable;<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGVTables.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.h?rev=212125&r1=212124&r2=212125&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.h?rev=212125&r1=212124&r2=212125&view=diff</a><br>


==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGVTables.h (original)<br>
+++ cfe/trunk/lib/CodeGen/CGVTables.h Tue Jul  1 15:30:31 2014<br>
@@ -61,11 +61,10 @@ public:<br>
   /// decl.<br>
   /// \param Components - The vtable components; this is really an array of<br>
   /// VTableComponents.<br>
-  llvm::Constant *CreateVTableInitializer(const CXXRecordDecl *RD,<br>
-                                          const VTableComponent *Components,<br>
-                                          unsigned NumComponents,<br>
-                                const VTableLayout::VTableThunkTy *VTableThunks,<br>
-                                          unsigned NumVTableThunks);<br>
+  llvm::Constant *CreateVTableInitializer(<br>
+      const CXXRecordDecl *RD, const VTableComponent *Components,<br>
+      unsigned NumComponents, const VTableLayout::VTableThunkTy *VTableThunks,<br>
+      unsigned NumVTableThunks, llvm::Constant *RTTI);<br>
<br>
   CodeGenVTables(CodeGenModule &CGM);<br>
<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=212125&r1=212124&r2=212125&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=212125&r1=212124&r2=212125&view=diff</a><br>


==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)<br>
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Tue Jul  1 15:30:31 2014<br>
@@ -750,8 +750,8 @@ public:<br>
   /// \brief Gets or a creats a Microsoft TypeDescriptor.<br>
   llvm::Constant *getMSTypeDescriptor(QualType Ty);<br>
   /// \brief Gets or a creats a Microsoft CompleteObjectLocator.<br>
-  llvm::GlobalVariable *getMSCompleteObjectLocator(const CXXRecordDecl *RD,<br>
-                                                   const VPtrInfo *Info);<br>
+  llvm::Constant *getMSCompleteObjectLocator(const CXXRecordDecl *RD,<br>
+                                             const VPtrInfo *Info);<br>
<br>
   /// Gets the address of a block which requires no captures.<br>
   llvm::Constant *GetAddrOfGlobalBlock(const BlockExpr *BE, const char *);<br>
<br>
Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=212125&r1=212124&r2=212125&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=212125&r1=212124&r2=212125&view=diff</a><br>


==============================================================================<br>
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Tue Jul  1 15:30:31 2014<br>
@@ -1182,11 +1182,13 @@ void ItaniumCXXABI::emitVTableDefinition<br>
   ItaniumVTableContext &VTContext = CGM.getItaniumVTableContext();<br>
   const VTableLayout &VTLayout = VTContext.getVTableLayout(RD);<br>
   llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);<br>
+  llvm::Constant *RTTI =<br>
+      CGM.GetAddrOfRTTIDescriptor(CGM.getContext().getTagDeclType(RD));<br>
<br>
   // Create and set the initializer.<br>
   llvm::Constant *Init = CGVT.CreateVTableInitializer(<br>
       RD, VTLayout.vtable_component_begin(), VTLayout.getNumVTableComponents(),<br>
-      VTLayout.vtable_thunk_begin(), VTLayout.getNumVTableThunks());<br>
+      VTLayout.vtable_thunk_begin(), VTLayout.getNumVTableThunks(), RTTI);<br>
   VTable->setInitializer(Init);<br>
<br>
   // Set the correct linkage.<br>
<br>
Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=212125&r1=212124&r2=212125&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=212125&r1=212124&r2=212125&view=diff</a><br>


==============================================================================<br>
--- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Tue Jul  1 15:30:31 2014<br>
@@ -403,9 +403,11 @@ public:<br>
<br>
 private:<br>
   typedef std::pair<const CXXRecordDecl *, CharUnits> VFTableIdTy;<br>
-  typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalVariable *> VFTablesMapTy;<br>
+  typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalVariable *> VTablesMapTy;<br>
+  typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalValue *> VFTablesMapTy;<br>
   /// \brief All the vftables that have been referenced.<br>
   VFTablesMapTy VFTablesMap;<br>
+  VTablesMapTy VTablesMap;<br>
<br>
   /// \brief This set holds the record decls we've deferred vtable emission for.<br>
   llvm::SmallPtrSet<const CXXRecordDecl *, 4> DeferredVFTables;<br>
@@ -1051,26 +1053,22 @@ void MicrosoftCXXABI::emitVTableDefiniti<br>
                                             const CXXRecordDecl *RD) {<br>
   MicrosoftVTableContext &VFTContext = CGM.getMicrosoftVTableContext();<br>
   VPtrInfoVector VFPtrs = VFTContext.getVFPtrOffsets(RD);<br>
-  llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);<br>
<br>
   for (VPtrInfo *Info : VFPtrs) {<br>
     llvm::GlobalVariable *VTable = getAddrOfVTable(RD, Info->FullOffsetInMDC);<br>
     if (VTable->hasInitializer())<br>
       continue;<br>
-    if (getContext().getLangOpts().RTTI)<br>
-      CGM.getMSCompleteObjectLocator(RD, Info);<br>
+<br>
+    llvm::Constant *RTTI = CGM.getMSCompleteObjectLocator(RD, Info);<br>
<br>
     const VTableLayout &VTLayout =<br>
       VFTContext.getVFTableLayout(RD, Info->FullOffsetInMDC);<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>
+        VTLayout.getNumVTableThunks(), RTTI);<br>
<br>
-    CGM.setGlobalVisibility(VTable, RD);<br>
+    VTable->setInitializer(Init);<br>
   }<br>
 }<br>
<br>
@@ -1079,8 +1077,9 @@ llvm::Value *MicrosoftCXXABI::getVTableA<br>
     const CXXRecordDecl *NearestVBase, bool &NeedsVirtualOffset) {<br>
   NeedsVirtualOffset = (NearestVBase != nullptr);<br>
<br>
-  llvm::Value *VTableAddressPoint =<br>
-      getAddrOfVTable(VTableClass, Base.getBaseOffset());<br>
+  (void)getAddrOfVTable(VTableClass, Base.getBaseOffset());<br>
+  VFTableIdTy ID(VTableClass, Base.getBaseOffset());<br>
+  llvm::GlobalValue *VTableAddressPoint = VFTablesMap[ID];<br>
   if (!VTableAddressPoint) {<br>
     assert(Base.getBase()->getNumVBases() &&<br>
            !CGM.getContext().getASTRecordLayout(Base.getBase()).hasOwnVFPtr());<br>
@@ -1097,9 +1096,11 @@ static void mangleVFTableName(MicrosoftM<br>
<br>
 llvm::Constant *MicrosoftCXXABI::getVTableAddressPointForConstExpr(<br>
     BaseSubobject Base, const CXXRecordDecl *VTableClass) {<br>
-  llvm::Constant *VTable = getAddrOfVTable(VTableClass, Base.getBaseOffset());<br>
-  assert(VTable && "Couldn't find a vftable for the given base?");<br>
-  return VTable;<br>
+  (void)getAddrOfVTable(VTableClass, Base.getBaseOffset());<br>
+  VFTableIdTy ID(VTableClass, Base.getBaseOffset());<br>
+  llvm::GlobalValue *VFTable = VFTablesMap[ID];<br>
+  assert(VFTable && "Couldn't find a vftable for the given base?");<br>
+  return VFTable;<br>
 }<br>
<br>
 llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,<br>
@@ -1108,9 +1109,9 @@ llvm::GlobalVariable *MicrosoftCXXABI::g<br>
   // shouldn't be used in the given record type. We want to cache this result in<br>
   // VFTablesMap, thus a simple zero check is not sufficient.<br>
   VFTableIdTy ID(RD, VPtrOffset);<br>
-  VFTablesMapTy::iterator I;<br>
+  VTablesMapTy::iterator I;<br>
   bool Inserted;<br>
-  std::tie(I, Inserted) = VFTablesMap.insert(std::make_pair(ID, nullptr));<br>
+  std::tie(I, Inserted) = VTablesMap.insert(std::make_pair(ID, nullptr));<br>
   if (!Inserted)<br>
     return I->second;<br>
<br>
@@ -1140,21 +1141,73 @@ llvm::GlobalVariable *MicrosoftCXXABI::g<br>
   for (size_t J = 0, F = VFPtrs.size(); J != F; ++J) {<br>
     if (VFPtrs[J]->FullOffsetInMDC != VPtrOffset)<br>
       continue;<br>
+    SmallString<256> VFTableName;<br>
+    mangleVFTableName(getMangleContext(), RD, VFPtrs[J], VFTableName);<br>
+    StringRef VTableName = VFTableName;<br>
<br>
-    llvm::ArrayType *ArrayType = llvm::ArrayType::get(<br>
-        CGM.Int8PtrTy,<br>
+    uint64_t NumVTableSlots =<br>
         VTContext.getVFTableLayout(RD, VFPtrs[J]->FullOffsetInMDC)<br>
-            .getNumVTableComponents());<br>
+            .getNumVTableComponents();<br>
+    llvm::GlobalValue::LinkageTypes VTableLinkage =<br>
+        llvm::GlobalValue::ExternalLinkage;<br>
+    llvm::ArrayType *VTableType =<br>
+        llvm::ArrayType::get(CGM.Int8PtrTy, NumVTableSlots);<br>
+    if (getContext().getLangOpts().RTTI) {<br>
+      VTableLinkage = llvm::GlobalValue::PrivateLinkage;<br>
+      VTableName = "";<br>
+    }<br>
<br>
-    SmallString<256> Name;<br>
-    mangleVFTableName(getMangleContext(), RD, VFPtrs[J], Name);<br>
-    VTable = CGM.CreateOrReplaceCXXRuntimeVariable(<br>
-        Name.str(), ArrayType, llvm::GlobalValue::ExternalLinkage);<br>
-    VTable->setUnnamedAddr(true);<br>
-    if (RD->hasAttr<DLLImportAttr>())<br>
-      VTable->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);<br>
-    else if (RD->hasAttr<DLLExportAttr>())<br>
-      VTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);<br>
+    VTable = CGM.getModule().getNamedGlobal(VFTableName);<br>
+    if (!VTable) {<br>
+      llvm::GlobalValue *VFTable = VTable = new llvm::GlobalVariable(<br>
+          CGM.getModule(), VTableType, /*isConstant=*/true, VTableLinkage,<br>
+          /*Initializer=*/nullptr, VTableName);<br>
+      VTable->setUnnamedAddr(true);<br>
+      if (getContext().getLangOpts().RTTI && !RD->hasAttr<DLLImportAttr>()) {<br>
+        llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.IntTy, 0),<br>
+                                     llvm::ConstantInt::get(CGM.IntTy, 1)};<br>
+        llvm::Constant *VTableGEP =<br>
+            llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, GEPIndices);<br>
+        VFTable = llvm::GlobalAlias::create(<br>
+            cast<llvm::SequentialType>(VTableGEP->getType())->getElementType(),<br>
+            /*AddressSpace=*/0, llvm::GlobalValue::ExternalLinkage,<br>
+            VFTableName.str(), VTableGEP, &CGM.getModule());<br>
+      } else {<br>
+        VTable->setName(VFTableName.str());<br>
+      }<br>
+<br>
+      VFTable->setUnnamedAddr(true);<br>
+      if (RD->hasAttr<DLLImportAttr>())<br>
+        VFTable->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);<br>
+      else if (RD->hasAttr<DLLExportAttr>())<br>
+        VFTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);<br>
+<br>
+      llvm::GlobalValue::LinkageTypes VFTableLinkage = CGM.getVTableLinkage(RD);<br>
+      if (VFTable != VTable) {<br>
+        if (llvm::GlobalValue::isAvailableExternallyLinkage(VFTableLinkage)) {<br>
+          // AvailableExternally implies that we grabbed the data from another<br>
+          // executable.  No need to stick the alias in a Comdat.<br>
+        } else if (llvm::GlobalValue::isLocalLinkage(VFTableLinkage)) {<br>
+          // If it's local, it means that the virtual function table can't be<br>
+          // referenced in another translation unit. No need to stick the alias<br>
+          // in a Comdat.<br>
+        } else if (llvm::GlobalValue::isWeakODRLinkage(VFTableLinkage) ||<br>
+                   llvm::GlobalValue::isLinkOnceODRLinkage(VFTableLinkage)) {<br>
+          // The alias is going to be dropped into a Comdat, no need to make it<br>
+          // weak.<br>
+          VFTableLinkage = llvm::GlobalValue::ExternalLinkage;<br>
+          llvm::Comdat *C =<br>
+              CGM.getModule().getOrInsertComdat(VFTable->getName());<br>
+          C->setSelectionKind(llvm::Comdat::Largest);<br>
+          VTable->setComdat(C);<br>
+        } else {<br>
+          llvm_unreachable("unexpected linkage for vftable!");<br>
+        }<br>
+      }<br>
+      VFTable->setLinkage(VFTableLinkage);<br>
+      CGM.setGlobalVisibility(VFTable, RD);<br>
+      VFTablesMap[ID] = VFTable;<br>
+    }<br>
     break;<br>
   }<br>
<br>
<br>
Modified: cfe/trunk/lib/CodeGen/MicrosoftRTTI.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftRTTI.cpp?rev=212125&r1=212124&r2=212125&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftRTTI.cpp?rev=212125&r1=212124&r2=212125&view=diff</a><br>


==============================================================================<br>
--- cfe/trunk/lib/CodeGen/MicrosoftRTTI.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/MicrosoftRTTI.cpp Tue Jul  1 15:30:31 2014<br>
@@ -505,8 +505,10 @@ llvm::Constant *CodeGenModule::getMSType<br>
       Int8PtrTy);<br>
 }<br>
<br>
-llvm::GlobalVariable *<br>
+llvm::Constant *<br>
 CodeGenModule::getMSCompleteObjectLocator(const CXXRecordDecl *RD,<br>
                                           const VPtrInfo *Info) {<br>
+  if (!getLangOpts().RTTI)<br>
+    return llvm::Constant::getNullValue(Int8PtrTy);<br>
   return MSRTTIBuilder(*this, RD).getCompleteObjectLocator(Info);<br>
 }<br>
<br>
Modified: cfe/trunk/test/CodeGenCXX/dllexport.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/dllexport.cpp?rev=212125&r1=212124&r2=212125&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/dllexport.cpp?rev=212125&r1=212124&r2=212125&view=diff</a><br>


==============================================================================<br>
--- cfe/trunk/test/CodeGenCXX/dllexport.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/dllexport.cpp Tue Jul  1 15:30:31 2014<br>
@@ -24,6 +24,9 @@ struct External { int v; };<br>
 #define INSTVAR(var) template int var;<br>
 #define INST(func) template void func();<br>
<br>
+// The vftable for struct W is comdat largest because we have RTTI.<br>
+// M32-DAG: $"\01??_7W@@6B@" = comdat largest<br>
+<br>
<br>
 //===----------------------------------------------------------------------===//<br>
 // Globals<br>
@@ -518,7 +521,8 @@ struct __declspec(dllexport) W { virtual<br>
 // Copy ctor:<br>
 // M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.W* @"\01??0W@@QAE@ABU0@@Z"<br>
 // vftable:<br>
-// M32-DAG: @"\01??_7W@@6B@" = weak_odr dllexport unnamed_addr constant [1 x i8*] [i8* bitcast (void (%struct.W*)* @"\01?foo@W@@UAEXXZ" to i8*)]<br>
+// M32-DAG: [[W_VTABLE:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast (%MSRTTICompleteObjectLocator* @"\01??_R4W@@6B@" to i8*), i8* bitcast (void (%struct.W*)* @"\01?foo@W@@UAEXXZ" to i8*)], comdat $"\01??_7W@@6B@"<br>


+// M32-DAG: @"\01??_7W@@6B@" = dllexport unnamed_addr alias getelementptr inbounds ([2 x i8*]* [[W_VTABLE]], i32 0, i32 1), comdat $"\01??_7W@@6B@"<br>
 // G32-DAG: @_ZTV1W = weak_odr dllexport unnamed_addr constant [3 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI1W to i8*), i8* bitcast (void (%struct.W*)* @_ZN1W3fooEv to i8*)]<br>
<br>
 struct __declspec(dllexport) X : public virtual W {};<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>
</blockquote></div><br></div>