CGVTT.cpp revision 206084
1235368Sgnn//===--- CGVTT.cpp - Emit LLVM Code for C++ VTTs --------------------------===//
2235368Sgnn//
3235368Sgnn//                     The LLVM Compiler Infrastructure
4235368Sgnn//
5235368Sgnn// This file is distributed under the University of Illinois Open Source
6235368Sgnn// License. See LICENSE.TXT for details.
7235368Sgnn//
8235368Sgnn//===----------------------------------------------------------------------===//
9235368Sgnn//
10235368Sgnn// This contains code dealing with C++ code generation of VTTs (vtable tables).
11235368Sgnn//
12235368Sgnn//===----------------------------------------------------------------------===//
13235368Sgnn
14235368Sgnn#include "CodeGenModule.h"
15235368Sgnn#include "clang/AST/RecordLayout.h"
16235368Sgnnusing namespace clang;
17235368Sgnnusing namespace CodeGen;
18235368Sgnn
19235368Sgnn#define D1(x)
20235368Sgnn
21235368Sgnnnamespace {
22235368Sgnn
23235368Sgnn/// VTT builder - Class for building VTT layout information.
24235368Sgnnclass VTTBuilder {
25235368Sgnn
26235368Sgnn  CodeGenModule &CGM;
27235368Sgnn
28235368Sgnn  /// MostDerivedClass - The most derived class for which we're building this
29235368Sgnn  /// vtable.
30235368Sgnn  const CXXRecordDecl *MostDerivedClass;
31235368Sgnn
32235368Sgnn  typedef llvm::SmallVector<llvm::Constant *, 64> VTTComponentsVectorTy;
33235368Sgnn
34235368Sgnn  /// VTTComponents - The VTT components.
35235368Sgnn  VTTComponentsVectorTy VTTComponents;
36235368Sgnn
37235368Sgnn  /// MostDerivedClassLayout - the AST record layout of the most derived class.
38235368Sgnn  const ASTRecordLayout &MostDerivedClassLayout;
39235368Sgnn
40235368Sgnn  typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
41235368Sgnn
42235368Sgnn  typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy;
43235368Sgnn
44235368Sgnn  /// SubVTTIndicies - The sub-VTT indices for the bases of the most derived
45235368Sgnn  /// class.
46235368Sgnn  llvm::DenseMap<const CXXRecordDecl *, uint64_t> SubVTTIndicies;
47235368Sgnn
48235368Sgnn  /// SecondaryVirtualPointerIndices - The secondary virtual pointer indices of
49235368Sgnn  /// all subobjects of the most derived class.
50235368Sgnn  llvm::DenseMap<BaseSubobject, uint64_t> SecondaryVirtualPointerIndices;
51235368Sgnn
52235368Sgnn  /// GenerateDefinition - Whether the VTT builder should generate LLVM IR for
53235368Sgnn  /// the VTT.
54235368Sgnn  bool GenerateDefinition;
55235368Sgnn
56235368Sgnn  /// GetAddrOfVTable - Returns the address of the vtable for the base class in
57235368Sgnn  /// the given vtable class.
58235368Sgnn  ///
59235368Sgnn  /// \param AddressPoints - If the returned vtable is a construction vtable,
60235368Sgnn  /// this will hold the address points for it.
61235368Sgnn  llvm::Constant *GetAddrOfVTable(BaseSubobject Base, bool BaseIsVirtual,
62235368Sgnn                                  AddressPointsMapTy& AddressPoints);
63235368Sgnn
64235368Sgnn  /// AddVTablePointer - Add a vtable pointer to the VTT currently being built.
65235368Sgnn  ///
66235368Sgnn  /// \param AddressPoints - If the vtable is a construction vtable, this has
67235368Sgnn  /// the address points for it.
68235368Sgnn  void AddVTablePointer(BaseSubobject Base, llvm::Constant *VTable,
69235368Sgnn                        const CXXRecordDecl *VTableClass,
70235368Sgnn                        const AddressPointsMapTy& AddressPoints);
71235368Sgnn
72235368Sgnn  /// LayoutSecondaryVTTs - Lay out the secondary VTTs of the given base
73235368Sgnn  /// subobject.
74235368Sgnn  void LayoutSecondaryVTTs(BaseSubobject Base);
75235368Sgnn
76235368Sgnn  /// LayoutSecondaryVirtualPointers - Lay out the secondary virtual pointers
77235368Sgnn  /// for the given base subobject.
78235368Sgnn  ///
79235368Sgnn  /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base
80235368Sgnn  /// or a direct or indirect base of a virtual base.
81235368Sgnn  ///
82235368Sgnn  /// \param AddressPoints - If the vtable is a construction vtable, this has
83235368Sgnn  /// the address points for it.
84235368Sgnn  void LayoutSecondaryVirtualPointers(BaseSubobject Base,
85235368Sgnn                                      bool BaseIsMorallyVirtual,
86235368Sgnn                                      llvm::Constant *VTable,
87235368Sgnn                                      const CXXRecordDecl *VTableClass,
88235368Sgnn                                      const AddressPointsMapTy& AddressPoints,
89235368Sgnn                                      VisitedVirtualBasesSetTy &VBases);
90235368Sgnn
91235368Sgnn  /// LayoutSecondaryVirtualPointers - Lay out the secondary virtual pointers
92235368Sgnn  /// for the given base subobject.
93235368Sgnn  ///
94235368Sgnn  /// \param AddressPoints - If the vtable is a construction vtable, this has
95235368Sgnn  /// the address points for it.
96235368Sgnn  void LayoutSecondaryVirtualPointers(BaseSubobject Base,
97235368Sgnn                                      llvm::Constant *VTable,
98235368Sgnn                                      const AddressPointsMapTy& AddressPoints);
99235368Sgnn
100235368Sgnn  /// LayoutVirtualVTTs - Lay out the VTTs for the virtual base classes of the
101235368Sgnn  /// given record decl.
102235368Sgnn  void LayoutVirtualVTTs(const CXXRecordDecl *RD,
103235368Sgnn                         VisitedVirtualBasesSetTy &VBases);
104235368Sgnn
105235368Sgnn  /// LayoutVTT - Will lay out the VTT for the given subobject, including any
106235368Sgnn  /// secondary VTTs, secondary virtual pointers and virtual VTTs.
107235368Sgnn  void LayoutVTT(BaseSubobject Base, bool BaseIsVirtual);
108235368Sgnn
109235368Sgnnpublic:
110235368Sgnn  VTTBuilder(CodeGenModule &CGM, const CXXRecordDecl *MostDerivedClass,
111235368Sgnn             bool GenerateDefinition);
112235368Sgnn
113235368Sgnn  // getVTTComponents - Returns a reference to the VTT components.
114235368Sgnn  const VTTComponentsVectorTy &getVTTComponents() const {
115235368Sgnn    return VTTComponents;
116235368Sgnn  }
117235368Sgnn
118235368Sgnn  /// getSubVTTIndicies - Returns a reference to the sub-VTT indices.
119235368Sgnn  const llvm::DenseMap<const CXXRecordDecl *, uint64_t> &
120235368Sgnn  getSubVTTIndicies() const {
121235368Sgnn    return SubVTTIndicies;
122235368Sgnn  }
123235368Sgnn
124235368Sgnn  /// getSecondaryVirtualPointerIndices - Returns a reference to the secondary
125235368Sgnn  /// virtual pointer indices.
126235368Sgnn  const llvm::DenseMap<BaseSubobject, uint64_t> &
127235368Sgnn  getSecondaryVirtualPointerIndices() const {
128235368Sgnn    return SecondaryVirtualPointerIndices;
129235368Sgnn  }
130235368Sgnn
131235368Sgnn};
132235368Sgnn
133235368SgnnVTTBuilder::VTTBuilder(CodeGenModule &CGM,
134235368Sgnn                       const CXXRecordDecl *MostDerivedClass,
135235368Sgnn                       bool GenerateDefinition)
136235368Sgnn  : CGM(CGM), MostDerivedClass(MostDerivedClass),
137235368Sgnn  MostDerivedClassLayout(CGM.getContext().getASTRecordLayout(MostDerivedClass)),
138235368Sgnn  GenerateDefinition(GenerateDefinition) {
139235368Sgnn
140235368Sgnn  // Lay out this VTT.
141235368Sgnn  LayoutVTT(BaseSubobject(MostDerivedClass, 0), /*BaseIsVirtual=*/false);
142235368Sgnn}
143235368Sgnn
144235368Sgnnllvm::Constant *
145235368SgnnVTTBuilder::GetAddrOfVTable(BaseSubobject Base, bool BaseIsVirtual,
146235368Sgnn                            AddressPointsMapTy& AddressPoints) {
147235368Sgnn  if (!GenerateDefinition)
148235368Sgnn    return 0;
149235368Sgnn
150235368Sgnn  if (Base.getBase() == MostDerivedClass) {
151235368Sgnn    assert(Base.getBaseOffset() == 0 &&
152235368Sgnn           "Most derived class vtable must have a zero offset!");
153235368Sgnn    // This is a regular vtable.
154235368Sgnn    return CGM.getVTables().GetAddrOfVTable(MostDerivedClass);
155235368Sgnn  }
156235368Sgnn
157235368Sgnn  return CGM.getVTables().GenerateConstructionVTable(MostDerivedClass,
158235368Sgnn                                                     Base, BaseIsVirtual,
159235368Sgnn                                                     AddressPoints);
160235368Sgnn}
161235368Sgnn
162235368Sgnnvoid VTTBuilder::AddVTablePointer(BaseSubobject Base, llvm::Constant *VTable,
163235368Sgnn                                  const CXXRecordDecl *VTableClass,
164235368Sgnn                                  const AddressPointsMapTy& AddressPoints) {
165235368Sgnn  // Store the vtable pointer index if we're generating the primary VTT.
166235368Sgnn  if (VTableClass == MostDerivedClass) {
167235368Sgnn    assert(!SecondaryVirtualPointerIndices.count(Base) &&
168235368Sgnn           "A virtual pointer index already exists for this base subobject!");
169235368Sgnn    SecondaryVirtualPointerIndices[Base] = VTTComponents.size();
170235368Sgnn  }
171235368Sgnn
172235368Sgnn  if (!GenerateDefinition) {
173235368Sgnn    VTTComponents.push_back(0);
174235368Sgnn    return;
175235368Sgnn  }
176235368Sgnn
177235368Sgnn  uint64_t AddressPoint;
178235368Sgnn  if (VTableClass != MostDerivedClass) {
179235368Sgnn    // The vtable is a construction vtable, look in the construction vtable
180235368Sgnn    // address points.
181235368Sgnn    AddressPoint = AddressPoints.lookup(Base);
182235368Sgnn  } else {
183235368Sgnn    // Just get the address point for the regular vtable.
184235368Sgnn    AddressPoint = CGM.getVTables().getAddressPoint(Base, VTableClass);
185235368Sgnn  }
186235368Sgnn
187235368Sgnn  if (!AddressPoint) AddressPoint = 0;
188235368Sgnn  assert(AddressPoint != 0 && "Did not find an address point!");
189235368Sgnn
190235368Sgnn  llvm::Value *Idxs[] = {
191235368Sgnn    llvm::ConstantInt::get(llvm::Type::getInt64Ty(CGM.getLLVMContext()), 0),
192235368Sgnn    llvm::ConstantInt::get(llvm::Type::getInt64Ty(CGM.getLLVMContext()),
193235368Sgnn                           AddressPoint)
194235368Sgnn  };
195235368Sgnn
196235368Sgnn  llvm::Constant *Init =
197235368Sgnn    llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Idxs, 2);
198235368Sgnn
199235368Sgnn  const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
200235368Sgnn  Init = llvm::ConstantExpr::getBitCast(Init, Int8PtrTy);
201235368Sgnn
202235368Sgnn  VTTComponents.push_back(Init);
203235368Sgnn}
204235368Sgnn
205235368Sgnnvoid VTTBuilder::LayoutSecondaryVTTs(BaseSubobject Base) {
206235368Sgnn  const CXXRecordDecl *RD = Base.getBase();
207235368Sgnn
208235368Sgnn  for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
209235368Sgnn       E = RD->bases_end(); I != E; ++I) {
210235368Sgnn
211235368Sgnn    // Don't layout virtual bases.
212235368Sgnn    if (I->isVirtual())
213235368Sgnn        continue;
214235368Sgnn
215235368Sgnn    const CXXRecordDecl *BaseDecl =
216235368Sgnn      cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
217235368Sgnn
218235368Sgnn    const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
219235368Sgnn    uint64_t BaseOffset = Base.getBaseOffset() +
220235368Sgnn      Layout.getBaseClassOffset(BaseDecl);
221235368Sgnn
222235368Sgnn    // Layout the VTT for this base.
223235368Sgnn    LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/false);
224235368Sgnn  }
225235368Sgnn}
226235368Sgnn
227235368Sgnnvoid
228235368SgnnVTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base,
229235368Sgnn                                        bool BaseIsMorallyVirtual,
230235368Sgnn                                        llvm::Constant *VTable,
231235368Sgnn                                        const CXXRecordDecl *VTableClass,
232235368Sgnn                                        const AddressPointsMapTy& AddressPoints,
233235368Sgnn                                        VisitedVirtualBasesSetTy &VBases) {
234235368Sgnn  const CXXRecordDecl *RD = Base.getBase();
235235368Sgnn
236235368Sgnn  // We're not interested in bases that don't have virtual bases, and not
237235368Sgnn  // morally virtual bases.
238235368Sgnn  if (!RD->getNumVBases() && !BaseIsMorallyVirtual)
239235368Sgnn    return;
240235368Sgnn
241235368Sgnn  for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
242235368Sgnn       E = RD->bases_end(); I != E; ++I) {
243235368Sgnn    const CXXRecordDecl *BaseDecl =
244235368Sgnn      cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
245235368Sgnn
246235368Sgnn    // Itanium C++ ABI 2.6.2:
247235368Sgnn    //   Secondary virtual pointers are present for all bases with either
248235368Sgnn    //   virtual bases or virtual function declarations overridden along a
249235368Sgnn    //   virtual path.
250235368Sgnn    //
251235368Sgnn    // If the base class is not dynamic, we don't want to add it, nor any
252235368Sgnn    // of its base classes.
253235368Sgnn    if (!BaseDecl->isDynamicClass())
254235368Sgnn      continue;
255235368Sgnn
256235368Sgnn    bool BaseDeclIsMorallyVirtual = BaseIsMorallyVirtual;
257235368Sgnn    bool BaseDeclIsNonVirtualPrimaryBase = false;
258235368Sgnn    uint64_t BaseOffset;
259235368Sgnn    if (I->isVirtual()) {
260235368Sgnn      // Ignore virtual bases that we've already visited.
261235368Sgnn      if (!VBases.insert(BaseDecl))
262235368Sgnn        continue;
263235368Sgnn
264235368Sgnn      BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
265235368Sgnn      BaseDeclIsMorallyVirtual = true;
266235368Sgnn    } else {
267235368Sgnn      const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
268235368Sgnn
269      BaseOffset = Base.getBaseOffset() + Layout.getBaseClassOffset(BaseDecl);
270
271      if (!Layout.getPrimaryBaseWasVirtual() &&
272          Layout.getPrimaryBase() == BaseDecl)
273        BaseDeclIsNonVirtualPrimaryBase = true;
274    }
275
276    // Itanium C++ ABI 2.6.2:
277    //   Secondary virtual pointers: for each base class X which (a) has virtual
278    //   bases or is reachable along a virtual path from D, and (b) is not a
279    //   non-virtual primary base, the address of the virtual table for X-in-D
280    //   or an appropriate construction virtual table.
281    if (!BaseDeclIsNonVirtualPrimaryBase &&
282        (BaseDecl->getNumVBases() || BaseDeclIsMorallyVirtual)) {
283      // Add the vtable pointer.
284      AddVTablePointer(BaseSubobject(BaseDecl, BaseOffset), VTable, VTableClass,
285                       AddressPoints);
286    }
287
288    // And lay out the secondary virtual pointers for the base class.
289    LayoutSecondaryVirtualPointers(BaseSubobject(BaseDecl, BaseOffset),
290                                   BaseDeclIsMorallyVirtual, VTable,
291                                   VTableClass, AddressPoints, VBases);
292  }
293}
294
295void
296VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base,
297                                      llvm::Constant *VTable,
298                                      const AddressPointsMapTy& AddressPoints) {
299  VisitedVirtualBasesSetTy VBases;
300  LayoutSecondaryVirtualPointers(Base, /*BaseIsMorallyVirtual=*/false,
301                                 VTable, Base.getBase(), AddressPoints, VBases);
302}
303
304void VTTBuilder::LayoutVirtualVTTs(const CXXRecordDecl *RD,
305                                   VisitedVirtualBasesSetTy &VBases) {
306  for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
307       E = RD->bases_end(); I != E; ++I) {
308    const CXXRecordDecl *BaseDecl =
309      cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
310
311    // Check if this is a virtual base.
312    if (I->isVirtual()) {
313      // Check if we've seen this base before.
314      if (!VBases.insert(BaseDecl))
315        continue;
316
317      uint64_t BaseOffset =
318        MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
319
320      LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/true);
321    }
322
323    // We only need to layout virtual VTTs for this base if it actually has
324    // virtual bases.
325    if (BaseDecl->getNumVBases())
326      LayoutVirtualVTTs(BaseDecl, VBases);
327  }
328}
329
330void VTTBuilder::LayoutVTT(BaseSubobject Base, bool BaseIsVirtual) {
331  const CXXRecordDecl *RD = Base.getBase();
332
333  // Itanium C++ ABI 2.6.2:
334  //   An array of virtual table addresses, called the VTT, is declared for
335  //   each class type that has indirect or direct virtual base classes.
336  if (RD->getNumVBases() == 0)
337    return;
338
339  bool IsPrimaryVTT = Base.getBase() == MostDerivedClass;
340
341  if (!IsPrimaryVTT) {
342    // Remember the sub-VTT index.
343    SubVTTIndicies[RD] = VTTComponents.size();
344  }
345
346  AddressPointsMapTy AddressPoints;
347  llvm::Constant *VTable = GetAddrOfVTable(Base, BaseIsVirtual, AddressPoints);
348
349  // Add the primary vtable pointer.
350  AddVTablePointer(Base, VTable, RD, AddressPoints);
351
352  // Add the secondary VTTs.
353  LayoutSecondaryVTTs(Base);
354
355  // Add the secondary virtual pointers.
356  LayoutSecondaryVirtualPointers(Base, VTable, AddressPoints);
357
358  // If this is the primary VTT, we want to lay out virtual VTTs as well.
359  if (IsPrimaryVTT) {
360    VisitedVirtualBasesSetTy VBases;
361    LayoutVirtualVTTs(Base.getBase(), VBases);
362  }
363}
364
365}
366
367llvm::GlobalVariable *
368CodeGenVTables::GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage,
369                            bool GenerateDefinition,
370                            const CXXRecordDecl *RD) {
371  // Only classes that have virtual bases need a VTT.
372  if (RD->getNumVBases() == 0)
373    return 0;
374
375  llvm::SmallString<256> OutName;
376  CGM.getMangleContext().mangleCXXVTT(RD, OutName);
377  llvm::StringRef Name = OutName.str();
378
379  D1(printf("vtt %s\n", RD->getNameAsCString()));
380
381  llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
382  if (GV == 0 || GV->isDeclaration()) {
383    const llvm::Type *Int8PtrTy =
384      llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
385
386    VTTBuilder Builder(CGM, RD, GenerateDefinition);
387
388    const llvm::ArrayType *Type =
389      llvm::ArrayType::get(Int8PtrTy, Builder.getVTTComponents().size());
390
391    llvm::Constant *Init = 0;
392    if (GenerateDefinition)
393      Init = llvm::ConstantArray::get(Type, Builder.getVTTComponents().data(),
394                                      Builder.getVTTComponents().size());
395
396    llvm::GlobalVariable *OldGV = GV;
397    GV = new llvm::GlobalVariable(CGM.getModule(), Type, /*isConstant=*/true,
398                                  Linkage, Init, Name);
399    CGM.setGlobalVisibility(GV, RD);
400
401    if (OldGV) {
402      GV->takeName(OldGV);
403      llvm::Constant *NewPtr =
404        llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
405      OldGV->replaceAllUsesWith(NewPtr);
406      OldGV->eraseFromParent();
407    }
408  }
409
410  return GV;
411}
412
413llvm::GlobalVariable *CodeGenVTables::getVTT(const CXXRecordDecl *RD) {
414  return GenerateVTT(llvm::GlobalValue::ExternalLinkage,
415                     /*GenerateDefinition=*/false, RD);
416}
417
418bool CodeGenVTables::needsVTTParameter(GlobalDecl GD) {
419  const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
420
421  // We don't have any virtual bases, just return early.
422  if (!MD->getParent()->getNumVBases())
423    return false;
424
425  // Check if we have a base constructor.
426  if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base)
427    return true;
428
429  // Check if we have a base destructor.
430  if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
431    return true;
432
433  return false;
434}
435
436uint64_t CodeGenVTables::getSubVTTIndex(const CXXRecordDecl *RD,
437                                        const CXXRecordDecl *Base) {
438  ClassPairTy ClassPair(RD, Base);
439
440  SubVTTIndiciesMapTy::iterator I = SubVTTIndicies.find(ClassPair);
441  if (I != SubVTTIndicies.end())
442    return I->second;
443
444  VTTBuilder Builder(CGM, RD, /*GenerateDefinition=*/false);
445
446  for (llvm::DenseMap<const CXXRecordDecl *, uint64_t>::const_iterator I =
447       Builder.getSubVTTIndicies().begin(),
448       E = Builder.getSubVTTIndicies().end(); I != E; ++I) {
449    // Insert all indices.
450    ClassPairTy ClassPair(RD, I->first);
451
452    SubVTTIndicies.insert(std::make_pair(ClassPair, I->second));
453  }
454
455  I = SubVTTIndicies.find(ClassPair);
456  assert(I != SubVTTIndicies.end() && "Did not find index!");
457
458  return I->second;
459}
460
461uint64_t
462CodeGenVTables::getSecondaryVirtualPointerIndex(const CXXRecordDecl *RD,
463                                                BaseSubobject Base) {
464  SecondaryVirtualPointerIndicesMapTy::iterator I =
465    SecondaryVirtualPointerIndices.find(std::make_pair(RD, Base));
466
467  if (I != SecondaryVirtualPointerIndices.end())
468    return I->second;
469
470  VTTBuilder Builder(CGM, RD, /*GenerateDefinition=*/false);
471
472  // Insert all secondary vpointer indices.
473  for (llvm::DenseMap<BaseSubobject, uint64_t>::const_iterator I =
474       Builder.getSecondaryVirtualPointerIndices().begin(),
475       E = Builder.getSecondaryVirtualPointerIndices().end(); I != E; ++I) {
476    std::pair<const CXXRecordDecl *, BaseSubobject> Pair =
477      std::make_pair(RD, I->first);
478
479    SecondaryVirtualPointerIndices.insert(std::make_pair(Pair, I->second));
480  }
481
482  I = SecondaryVirtualPointerIndices.find(std::make_pair(RD, Base));
483  assert(I != SecondaryVirtualPointerIndices.end() && "Did not find index!");
484
485  return I->second;
486}
487
488