19063302a82423cb83f002257a416741850739a70Reid Kleckner//===--- MicrosoftVBTables.cpp - Virtual Base Table Emission --------------===// 29063302a82423cb83f002257a416741850739a70Reid Kleckner// 39063302a82423cb83f002257a416741850739a70Reid Kleckner// The LLVM Compiler Infrastructure 49063302a82423cb83f002257a416741850739a70Reid Kleckner// 59063302a82423cb83f002257a416741850739a70Reid Kleckner// This file is distributed under the University of Illinois Open Source 69063302a82423cb83f002257a416741850739a70Reid Kleckner// License. See LICENSE.TXT for details. 79063302a82423cb83f002257a416741850739a70Reid Kleckner// 89063302a82423cb83f002257a416741850739a70Reid Kleckner//===----------------------------------------------------------------------===// 99063302a82423cb83f002257a416741850739a70Reid Kleckner// 109063302a82423cb83f002257a416741850739a70Reid Kleckner// This class generates data about MSVC virtual base tables. 119063302a82423cb83f002257a416741850739a70Reid Kleckner// 129063302a82423cb83f002257a416741850739a70Reid Kleckner//===----------------------------------------------------------------------===// 139063302a82423cb83f002257a416741850739a70Reid Kleckner 149063302a82423cb83f002257a416741850739a70Reid Kleckner#include "MicrosoftVBTables.h" 159063302a82423cb83f002257a416741850739a70Reid Kleckner#include "CodeGenModule.h" 169063302a82423cb83f002257a416741850739a70Reid Kleckner#include "CGCXXABI.h" 179063302a82423cb83f002257a416741850739a70Reid Kleckner 189063302a82423cb83f002257a416741850739a70Reid Klecknernamespace clang { 199063302a82423cb83f002257a416741850739a70Reid Klecknernamespace CodeGen { 209063302a82423cb83f002257a416741850739a70Reid Kleckner 219063302a82423cb83f002257a416741850739a70Reid Kleckner/// Holds intermediate data about a path to a vbptr inside a base subobject. 229063302a82423cb83f002257a416741850739a70Reid Klecknerstruct VBTablePath { 239063302a82423cb83f002257a416741850739a70Reid Kleckner VBTablePath(const VBTableInfo &VBInfo) 249063302a82423cb83f002257a416741850739a70Reid Kleckner : VBInfo(VBInfo), NextBase(VBInfo.VBPtrSubobject.getBase()) { } 259063302a82423cb83f002257a416741850739a70Reid Kleckner 269063302a82423cb83f002257a416741850739a70Reid Kleckner /// All the data needed to build a vbtable, minus the GlobalVariable whose 279063302a82423cb83f002257a416741850739a70Reid Kleckner /// name we haven't computed yet. 289063302a82423cb83f002257a416741850739a70Reid Kleckner VBTableInfo VBInfo; 299063302a82423cb83f002257a416741850739a70Reid Kleckner 309063302a82423cb83f002257a416741850739a70Reid Kleckner /// Next base to use for disambiguation. Can be null if we've already 319063302a82423cb83f002257a416741850739a70Reid Kleckner /// disambiguated this path once. 329063302a82423cb83f002257a416741850739a70Reid Kleckner const CXXRecordDecl *NextBase; 339063302a82423cb83f002257a416741850739a70Reid Kleckner 349063302a82423cb83f002257a416741850739a70Reid Kleckner /// Path is not really a full path like a CXXBasePath. It holds the subset of 359063302a82423cb83f002257a416741850739a70Reid Kleckner /// records that need to be mangled into the vbtable symbol name in order to get 369063302a82423cb83f002257a416741850739a70Reid Kleckner /// a unique name. 379063302a82423cb83f002257a416741850739a70Reid Kleckner llvm::SmallVector<const CXXRecordDecl *, 1> Path; 389063302a82423cb83f002257a416741850739a70Reid Kleckner}; 399063302a82423cb83f002257a416741850739a70Reid Kleckner 409063302a82423cb83f002257a416741850739a70Reid KlecknerVBTableBuilder::VBTableBuilder(CodeGenModule &CGM, 419063302a82423cb83f002257a416741850739a70Reid Kleckner const CXXRecordDecl *MostDerived) 429063302a82423cb83f002257a416741850739a70Reid Kleckner : CGM(CGM), MostDerived(MostDerived), 439063302a82423cb83f002257a416741850739a70Reid Kleckner DerivedLayout(CGM.getContext().getASTRecordLayout(MostDerived)) {} 449063302a82423cb83f002257a416741850739a70Reid Kleckner 459063302a82423cb83f002257a416741850739a70Reid Klecknervoid VBTableBuilder::enumerateVBTables(VBTableVector &VBTables) { 469063302a82423cb83f002257a416741850739a70Reid Kleckner VBTablePathVector Paths; 479063302a82423cb83f002257a416741850739a70Reid Kleckner findUnambiguousPaths(MostDerived, BaseSubobject(MostDerived, 489063302a82423cb83f002257a416741850739a70Reid Kleckner CharUnits::Zero()), Paths); 499063302a82423cb83f002257a416741850739a70Reid Kleckner for (VBTablePathVector::iterator I = Paths.begin(), E = Paths.end(); 509063302a82423cb83f002257a416741850739a70Reid Kleckner I != E; ++I) { 519063302a82423cb83f002257a416741850739a70Reid Kleckner VBTablePath *P = *I; 529063302a82423cb83f002257a416741850739a70Reid Kleckner P->VBInfo.GV = getAddrOfVBTable(P->VBInfo.ReusingBase, P->Path); 539063302a82423cb83f002257a416741850739a70Reid Kleckner VBTables.push_back(P->VBInfo); 549063302a82423cb83f002257a416741850739a70Reid Kleckner } 559063302a82423cb83f002257a416741850739a70Reid Kleckner} 569063302a82423cb83f002257a416741850739a70Reid Kleckner 579063302a82423cb83f002257a416741850739a70Reid Klecknerbool VBTableBuilder::hasVBPtr(const CXXRecordDecl *RD) { 589063302a82423cb83f002257a416741850739a70Reid Kleckner const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); 599063302a82423cb83f002257a416741850739a70Reid Kleckner return Layout.getVBPtrOffset().getQuantity() != -1; 609063302a82423cb83f002257a416741850739a70Reid Kleckner} 619063302a82423cb83f002257a416741850739a70Reid Kleckner 629063302a82423cb83f002257a416741850739a70Reid Klecknervoid VBTableBuilder::findUnambiguousPaths(const CXXRecordDecl *ReusingBase, 639063302a82423cb83f002257a416741850739a70Reid Kleckner BaseSubobject CurSubobject, 649063302a82423cb83f002257a416741850739a70Reid Kleckner VBTablePathVector &Paths) { 659063302a82423cb83f002257a416741850739a70Reid Kleckner size_t PathsStart = Paths.size(); 669063302a82423cb83f002257a416741850739a70Reid Kleckner bool ReuseVBPtrFromBase = true; 679063302a82423cb83f002257a416741850739a70Reid Kleckner const CXXRecordDecl *CurBase = CurSubobject.getBase(); 689063302a82423cb83f002257a416741850739a70Reid Kleckner 699063302a82423cb83f002257a416741850739a70Reid Kleckner // If this base has a vbptr, then we've found a path. These are not full 709063302a82423cb83f002257a416741850739a70Reid Kleckner // paths, so we don't use CXXBasePath. 719063302a82423cb83f002257a416741850739a70Reid Kleckner if (hasVBPtr(CurBase)) { 729063302a82423cb83f002257a416741850739a70Reid Kleckner ReuseVBPtrFromBase = false; 739063302a82423cb83f002257a416741850739a70Reid Kleckner VBTablePath *Info = new VBTablePath( 749063302a82423cb83f002257a416741850739a70Reid Kleckner VBTableInfo(ReusingBase, CurSubobject, /*GV=*/0)); 759063302a82423cb83f002257a416741850739a70Reid Kleckner Paths.push_back(Info); 769063302a82423cb83f002257a416741850739a70Reid Kleckner } 779063302a82423cb83f002257a416741850739a70Reid Kleckner 789063302a82423cb83f002257a416741850739a70Reid Kleckner // Recurse onto any bases which themselves have virtual bases. 799063302a82423cb83f002257a416741850739a70Reid Kleckner const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(CurBase); 809063302a82423cb83f002257a416741850739a70Reid Kleckner for (CXXRecordDecl::base_class_const_iterator I = CurBase->bases_begin(), 819063302a82423cb83f002257a416741850739a70Reid Kleckner E = CurBase->bases_end(); I != E; ++I) { 829063302a82423cb83f002257a416741850739a70Reid Kleckner const CXXRecordDecl *Base = I->getType()->getAsCXXRecordDecl(); 839063302a82423cb83f002257a416741850739a70Reid Kleckner if (!Base->getNumVBases()) 849063302a82423cb83f002257a416741850739a70Reid Kleckner continue; // Bases without virtual bases have no vbptrs. 859063302a82423cb83f002257a416741850739a70Reid Kleckner CharUnits NextOffset; 869063302a82423cb83f002257a416741850739a70Reid Kleckner const CXXRecordDecl *NextReusingBase = Base; 879063302a82423cb83f002257a416741850739a70Reid Kleckner if (I->isVirtual()) { 889063302a82423cb83f002257a416741850739a70Reid Kleckner if (!VBasesSeen.insert(Base)) 899063302a82423cb83f002257a416741850739a70Reid Kleckner continue; // Don't visit virtual bases twice. 909063302a82423cb83f002257a416741850739a70Reid Kleckner NextOffset = DerivedLayout.getVBaseClassOffset(Base); 919063302a82423cb83f002257a416741850739a70Reid Kleckner } else { 929063302a82423cb83f002257a416741850739a70Reid Kleckner NextOffset = (CurSubobject.getBaseOffset() + 939063302a82423cb83f002257a416741850739a70Reid Kleckner Layout.getBaseClassOffset(Base)); 949063302a82423cb83f002257a416741850739a70Reid Kleckner 959063302a82423cb83f002257a416741850739a70Reid Kleckner // If CurBase didn't have a vbptr, then ReusingBase will reuse the vbptr 969063302a82423cb83f002257a416741850739a70Reid Kleckner // from the first non-virtual base with vbases for its vbptr. 979063302a82423cb83f002257a416741850739a70Reid Kleckner if (ReuseVBPtrFromBase) { 989063302a82423cb83f002257a416741850739a70Reid Kleckner NextReusingBase = ReusingBase; 999063302a82423cb83f002257a416741850739a70Reid Kleckner ReuseVBPtrFromBase = false; 1009063302a82423cb83f002257a416741850739a70Reid Kleckner } 1019063302a82423cb83f002257a416741850739a70Reid Kleckner } 1029063302a82423cb83f002257a416741850739a70Reid Kleckner 1039063302a82423cb83f002257a416741850739a70Reid Kleckner size_t NumPaths = Paths.size(); 1049063302a82423cb83f002257a416741850739a70Reid Kleckner findUnambiguousPaths(NextReusingBase, BaseSubobject(Base, NextOffset), 1059063302a82423cb83f002257a416741850739a70Reid Kleckner Paths); 1069063302a82423cb83f002257a416741850739a70Reid Kleckner 1079063302a82423cb83f002257a416741850739a70Reid Kleckner // Tag paths through this base with the base itself. We might use it to 1089063302a82423cb83f002257a416741850739a70Reid Kleckner // disambiguate. 1099063302a82423cb83f002257a416741850739a70Reid Kleckner for (size_t I = NumPaths, E = Paths.size(); I != E; ++I) 1109063302a82423cb83f002257a416741850739a70Reid Kleckner Paths[I]->NextBase = Base; 1119063302a82423cb83f002257a416741850739a70Reid Kleckner } 1129063302a82423cb83f002257a416741850739a70Reid Kleckner 1139063302a82423cb83f002257a416741850739a70Reid Kleckner bool AmbiguousPaths = rebucketPaths(Paths, PathsStart); 1149063302a82423cb83f002257a416741850739a70Reid Kleckner if (AmbiguousPaths) 1159063302a82423cb83f002257a416741850739a70Reid Kleckner rebucketPaths(Paths, PathsStart, /*SecondPass=*/true); 1169063302a82423cb83f002257a416741850739a70Reid Kleckner 1179063302a82423cb83f002257a416741850739a70Reid Kleckner#ifndef NDEBUG 1189063302a82423cb83f002257a416741850739a70Reid Kleckner // Check that the paths are in fact unique. 1199063302a82423cb83f002257a416741850739a70Reid Kleckner for (size_t I = PathsStart + 1, E = Paths.size(); I != E; ++I) { 1209063302a82423cb83f002257a416741850739a70Reid Kleckner assert(Paths[I]->Path != Paths[I - 1]->Path && "vbtable paths are not unique"); 1219063302a82423cb83f002257a416741850739a70Reid Kleckner } 1229063302a82423cb83f002257a416741850739a70Reid Kleckner#endif 1239063302a82423cb83f002257a416741850739a70Reid Kleckner} 1249063302a82423cb83f002257a416741850739a70Reid Kleckner 1259063302a82423cb83f002257a416741850739a70Reid Klecknerstatic bool pathCompare(VBTablePath *LHS, VBTablePath *RHS) { 1269063302a82423cb83f002257a416741850739a70Reid Kleckner return LHS->Path < RHS->Path; 1279063302a82423cb83f002257a416741850739a70Reid Kleckner} 1289063302a82423cb83f002257a416741850739a70Reid Kleckner 1299063302a82423cb83f002257a416741850739a70Reid Klecknervoid VBTableBuilder::extendPath(VBTablePath *P, bool SecondPass) { 1309063302a82423cb83f002257a416741850739a70Reid Kleckner assert(P->NextBase || SecondPass); 1319063302a82423cb83f002257a416741850739a70Reid Kleckner if (P->NextBase) { 1329063302a82423cb83f002257a416741850739a70Reid Kleckner P->Path.push_back(P->NextBase); 1339063302a82423cb83f002257a416741850739a70Reid Kleckner P->NextBase = 0; // Prevent the path from being extended twice. 1349063302a82423cb83f002257a416741850739a70Reid Kleckner } 1359063302a82423cb83f002257a416741850739a70Reid Kleckner} 1369063302a82423cb83f002257a416741850739a70Reid Kleckner 1379063302a82423cb83f002257a416741850739a70Reid Klecknerbool VBTableBuilder::rebucketPaths(VBTablePathVector &Paths, size_t PathsStart, 1389063302a82423cb83f002257a416741850739a70Reid Kleckner bool SecondPass) { 1399063302a82423cb83f002257a416741850739a70Reid Kleckner // What we're essentially doing here is bucketing together ambiguous paths. 1409063302a82423cb83f002257a416741850739a70Reid Kleckner // Any bucket with more than one path in it gets extended by NextBase, which 1419063302a82423cb83f002257a416741850739a70Reid Kleckner // is usually the direct base of the inherited the vbptr. This code uses a 1429063302a82423cb83f002257a416741850739a70Reid Kleckner // sorted vector to implement a multiset to form the buckets. Note that the 1439063302a82423cb83f002257a416741850739a70Reid Kleckner // ordering is based on pointers, but it doesn't change our output order. The 1449063302a82423cb83f002257a416741850739a70Reid Kleckner // current algorithm is designed to match MSVC 2012's names. 1459063302a82423cb83f002257a416741850739a70Reid Kleckner // TODO: Implement MSVC 2010 or earlier names to avoid extra vbtable cruft. 1469063302a82423cb83f002257a416741850739a70Reid Kleckner VBTablePathVector PathsSorted(&Paths[PathsStart], &Paths.back() + 1); 1479063302a82423cb83f002257a416741850739a70Reid Kleckner std::sort(PathsSorted.begin(), PathsSorted.end(), pathCompare); 1489063302a82423cb83f002257a416741850739a70Reid Kleckner bool AmbiguousPaths = false; 1499063302a82423cb83f002257a416741850739a70Reid Kleckner for (size_t I = 0, E = PathsSorted.size(); I != E;) { 1509063302a82423cb83f002257a416741850739a70Reid Kleckner // Scan forward to find the end of the bucket. 1519063302a82423cb83f002257a416741850739a70Reid Kleckner size_t BucketStart = I; 1529063302a82423cb83f002257a416741850739a70Reid Kleckner do { 1539063302a82423cb83f002257a416741850739a70Reid Kleckner ++I; 1549063302a82423cb83f002257a416741850739a70Reid Kleckner } while (I != E && PathsSorted[BucketStart]->Path == PathsSorted[I]->Path); 1559063302a82423cb83f002257a416741850739a70Reid Kleckner 1569063302a82423cb83f002257a416741850739a70Reid Kleckner // If this bucket has multiple paths, extend them all. 1579063302a82423cb83f002257a416741850739a70Reid Kleckner if (I - BucketStart > 1) { 1589063302a82423cb83f002257a416741850739a70Reid Kleckner AmbiguousPaths = true; 1599063302a82423cb83f002257a416741850739a70Reid Kleckner for (size_t II = BucketStart; II != I; ++II) 1609063302a82423cb83f002257a416741850739a70Reid Kleckner extendPath(PathsSorted[II], SecondPass); 1619063302a82423cb83f002257a416741850739a70Reid Kleckner } 1629063302a82423cb83f002257a416741850739a70Reid Kleckner } 1639063302a82423cb83f002257a416741850739a70Reid Kleckner return AmbiguousPaths; 1649063302a82423cb83f002257a416741850739a70Reid Kleckner} 1659063302a82423cb83f002257a416741850739a70Reid Kleckner 1669063302a82423cb83f002257a416741850739a70Reid Klecknerllvm::GlobalVariable * 1679063302a82423cb83f002257a416741850739a70Reid KlecknerVBTableBuilder::getAddrOfVBTable(const CXXRecordDecl *ReusingBase, 1689063302a82423cb83f002257a416741850739a70Reid Kleckner ArrayRef<const CXXRecordDecl *> BasePath) { 1699063302a82423cb83f002257a416741850739a70Reid Kleckner // Caching at this layer is redundant with the caching in EnumerateVBTables(). 1709063302a82423cb83f002257a416741850739a70Reid Kleckner 1719063302a82423cb83f002257a416741850739a70Reid Kleckner SmallString<256> OutName; 1729063302a82423cb83f002257a416741850739a70Reid Kleckner llvm::raw_svector_ostream Out(OutName); 1739063302a82423cb83f002257a416741850739a70Reid Kleckner MangleContext &Mangler = CGM.getCXXABI().getMangleContext(); 1749063302a82423cb83f002257a416741850739a70Reid Kleckner Mangler.mangleCXXVBTable(MostDerived, BasePath, Out); 1759063302a82423cb83f002257a416741850739a70Reid Kleckner Out.flush(); 1769063302a82423cb83f002257a416741850739a70Reid Kleckner StringRef Name = OutName.str(); 1779063302a82423cb83f002257a416741850739a70Reid Kleckner 1789063302a82423cb83f002257a416741850739a70Reid Kleckner llvm::ArrayType *VBTableType = 1799063302a82423cb83f002257a416741850739a70Reid Kleckner llvm::ArrayType::get(CGM.IntTy, 1 + ReusingBase->getNumVBases()); 1809063302a82423cb83f002257a416741850739a70Reid Kleckner 1819063302a82423cb83f002257a416741850739a70Reid Kleckner assert(!CGM.getModule().getNamedGlobal(Name) && 1829063302a82423cb83f002257a416741850739a70Reid Kleckner "vbtable with this name already exists: mangling bug?"); 1839063302a82423cb83f002257a416741850739a70Reid Kleckner llvm::GlobalVariable *VBTable = 1849063302a82423cb83f002257a416741850739a70Reid Kleckner CGM.CreateOrReplaceCXXRuntimeVariable(Name, VBTableType, 1859063302a82423cb83f002257a416741850739a70Reid Kleckner llvm::GlobalValue::ExternalLinkage); 1869063302a82423cb83f002257a416741850739a70Reid Kleckner VBTable->setUnnamedAddr(true); 1879063302a82423cb83f002257a416741850739a70Reid Kleckner return VBTable; 1889063302a82423cb83f002257a416741850739a70Reid Kleckner} 1899063302a82423cb83f002257a416741850739a70Reid Kleckner 1909063302a82423cb83f002257a416741850739a70Reid Klecknervoid VBTableInfo::EmitVBTableDefinition( 1919063302a82423cb83f002257a416741850739a70Reid Kleckner CodeGenModule &CGM, const CXXRecordDecl *RD, 1929063302a82423cb83f002257a416741850739a70Reid Kleckner llvm::GlobalVariable::LinkageTypes Linkage) const { 1939063302a82423cb83f002257a416741850739a70Reid Kleckner assert(RD->getNumVBases() && ReusingBase->getNumVBases() && 1949063302a82423cb83f002257a416741850739a70Reid Kleckner "should only emit vbtables for classes with vbtables"); 1959063302a82423cb83f002257a416741850739a70Reid Kleckner 1969063302a82423cb83f002257a416741850739a70Reid Kleckner const ASTRecordLayout &BaseLayout = 1979063302a82423cb83f002257a416741850739a70Reid Kleckner CGM.getContext().getASTRecordLayout(VBPtrSubobject.getBase()); 1989063302a82423cb83f002257a416741850739a70Reid Kleckner const ASTRecordLayout &DerivedLayout = 1999063302a82423cb83f002257a416741850739a70Reid Kleckner CGM.getContext().getASTRecordLayout(RD); 2009063302a82423cb83f002257a416741850739a70Reid Kleckner 2019063302a82423cb83f002257a416741850739a70Reid Kleckner SmallVector<llvm::Constant *, 4> Offsets; 2029063302a82423cb83f002257a416741850739a70Reid Kleckner 2039063302a82423cb83f002257a416741850739a70Reid Kleckner // The offset from ReusingBase's vbptr to itself always leads. 2049063302a82423cb83f002257a416741850739a70Reid Kleckner CharUnits VBPtrOffset = BaseLayout.getVBPtrOffset(); 2059063302a82423cb83f002257a416741850739a70Reid Kleckner Offsets.push_back( 2069063302a82423cb83f002257a416741850739a70Reid Kleckner llvm::ConstantInt::get(CGM.IntTy, -VBPtrOffset.getQuantity())); 2079063302a82423cb83f002257a416741850739a70Reid Kleckner 2089063302a82423cb83f002257a416741850739a70Reid Kleckner // These are laid out in the same order as in Itanium, which is the same as 2099063302a82423cb83f002257a416741850739a70Reid Kleckner // the order of the vbase iterator. 2109063302a82423cb83f002257a416741850739a70Reid Kleckner for (CXXRecordDecl::base_class_const_iterator I = ReusingBase->vbases_begin(), 2119063302a82423cb83f002257a416741850739a70Reid Kleckner E = ReusingBase->vbases_end(); I != E; ++I) { 2129063302a82423cb83f002257a416741850739a70Reid Kleckner const CXXRecordDecl *VBase = I->getType()->getAsCXXRecordDecl(); 2139063302a82423cb83f002257a416741850739a70Reid Kleckner CharUnits Offset = DerivedLayout.getVBaseClassOffset(VBase); 2149063302a82423cb83f002257a416741850739a70Reid Kleckner assert(!Offset.isNegative()); 2159063302a82423cb83f002257a416741850739a70Reid Kleckner // Make it relative to the subobject vbptr. 2169063302a82423cb83f002257a416741850739a70Reid Kleckner Offset -= VBPtrSubobject.getBaseOffset() + VBPtrOffset; 2179063302a82423cb83f002257a416741850739a70Reid Kleckner Offsets.push_back(llvm::ConstantInt::get(CGM.IntTy, Offset.getQuantity())); 2189063302a82423cb83f002257a416741850739a70Reid Kleckner } 2199063302a82423cb83f002257a416741850739a70Reid Kleckner 2209063302a82423cb83f002257a416741850739a70Reid Kleckner assert(Offsets.size() == 2219063302a82423cb83f002257a416741850739a70Reid Kleckner cast<llvm::ArrayType>(cast<llvm::PointerType>(GV->getType()) 2229063302a82423cb83f002257a416741850739a70Reid Kleckner ->getElementType())->getNumElements()); 2239063302a82423cb83f002257a416741850739a70Reid Kleckner llvm::ArrayType *VBTableType = 2249063302a82423cb83f002257a416741850739a70Reid Kleckner llvm::ArrayType::get(CGM.IntTy, Offsets.size()); 2259063302a82423cb83f002257a416741850739a70Reid Kleckner llvm::Constant *Init = llvm::ConstantArray::get(VBTableType, Offsets); 2269063302a82423cb83f002257a416741850739a70Reid Kleckner GV->setInitializer(Init); 2279063302a82423cb83f002257a416741850739a70Reid Kleckner 2289063302a82423cb83f002257a416741850739a70Reid Kleckner // Set the correct linkage. 2299063302a82423cb83f002257a416741850739a70Reid Kleckner GV->setLinkage(Linkage); 2309063302a82423cb83f002257a416741850739a70Reid Kleckner 2319063302a82423cb83f002257a416741850739a70Reid Kleckner // Set the right visibility. 2329063302a82423cb83f002257a416741850739a70Reid Kleckner CGM.setTypeVisibility(GV, RD, CodeGenModule::TVK_ForVTable); 2339063302a82423cb83f002257a416741850739a70Reid Kleckner} 2349063302a82423cb83f002257a416741850739a70Reid Kleckner 2359063302a82423cb83f002257a416741850739a70Reid Kleckner} // namespace CodeGen 2369063302a82423cb83f002257a416741850739a70Reid Kleckner} // namespace clang 237