clang 23.0.0git
VTableBuilder.cpp
Go to the documentation of this file.
1//===--- VTableBuilder.cpp - C++ vtable layout builder --------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This contains code dealing with generation of the layout of virtual tables.
10//
11//===----------------------------------------------------------------------===//
12
19#include "llvm/ADT/SetOperations.h"
20#include "llvm/ADT/SetVector.h"
21#include "llvm/ADT/SmallPtrSet.h"
22#include "llvm/Support/Format.h"
23#include "llvm/Support/raw_ostream.h"
24#include <algorithm>
25#include <cstdio>
26
27using namespace clang;
28
29#define DUMP_OVERRIDERS 0
30
31namespace {
32
33/// BaseOffset - Represents an offset from a derived class to a direct or
34/// indirect base class.
35struct BaseOffset {
36 /// DerivedClass - The derived class.
37 const CXXRecordDecl *DerivedClass;
38
39 /// VirtualBase - If the path from the derived class to the base class
40 /// involves virtual base classes, this holds the declaration of the last
41 /// virtual base in this path (i.e. closest to the base class).
43
44 /// NonVirtualOffset - The offset from the derived class to the base class.
45 /// (Or the offset from the virtual base class to the base class, if the
46 /// path from the derived class to the base class involves a virtual base
47 /// class.
48 CharUnits NonVirtualOffset;
49
50 BaseOffset() : DerivedClass(nullptr), VirtualBase(nullptr),
51 NonVirtualOffset(CharUnits::Zero()) { }
52 BaseOffset(const CXXRecordDecl *DerivedClass,
53 const CXXRecordDecl *VirtualBase, CharUnits NonVirtualOffset)
54 : DerivedClass(DerivedClass), VirtualBase(VirtualBase),
55 NonVirtualOffset(NonVirtualOffset) { }
56
57 bool isEmpty() const { return NonVirtualOffset.isZero() && !VirtualBase; }
58};
59
60/// FinalOverriders - Contains the final overrider member functions for all
61/// member functions in the base subobjects of a class.
62class FinalOverriders {
63public:
64 /// OverriderInfo - Information about a final overrider.
65 struct OverriderInfo {
66 /// Method - The method decl of the overrider.
67 const CXXMethodDecl *Method;
68
69 /// VirtualBase - The virtual base class subobject of this overrider.
70 /// Note that this records the closest derived virtual base class subobject.
72
73 /// Offset - the base offset of the overrider's parent in the layout class.
74 CharUnits Offset;
75
76 OverriderInfo() : Method(nullptr), VirtualBase(nullptr),
77 Offset(CharUnits::Zero()) { }
78 };
79
80private:
81 /// MostDerivedClass - The most derived class for which the final overriders
82 /// are stored.
83 const CXXRecordDecl *MostDerivedClass;
84
85 /// MostDerivedClassOffset - If we're building final overriders for a
86 /// construction vtable, this holds the offset from the layout class to the
87 /// most derived class.
88 const CharUnits MostDerivedClassOffset;
89
90 /// LayoutClass - The class we're using for layout information. Will be
91 /// different than the most derived class if the final overriders are for a
92 /// construction vtable.
93 const CXXRecordDecl *LayoutClass;
94
95 ASTContext &Context;
96
97 /// MostDerivedClassLayout - the AST record layout of the most derived class.
98 const ASTRecordLayout &MostDerivedClassLayout;
99
100 /// MethodBaseOffsetPairTy - Uniquely identifies a member function
101 /// in a base subobject.
102 typedef std::pair<const CXXMethodDecl *, CharUnits> MethodBaseOffsetPairTy;
103
104 typedef llvm::DenseMap<MethodBaseOffsetPairTy,
105 OverriderInfo> OverridersMapTy;
106
107 /// OverridersMap - The final overriders for all virtual member functions of
108 /// all the base subobjects of the most derived class.
109 OverridersMapTy OverridersMap;
110
111 /// SubobjectsToOffsetsMapTy - A mapping from a base subobject (represented
112 /// as a record decl and a subobject number) and its offsets in the most
113 /// derived class as well as the layout class.
114 typedef llvm::DenseMap<std::pair<const CXXRecordDecl *, unsigned>,
115 CharUnits> SubobjectOffsetMapTy;
116
117 typedef llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCountMapTy;
118
119 /// ComputeBaseOffsets - Compute the offsets for all base subobjects of the
120 /// given base.
121 void ComputeBaseOffsets(BaseSubobject Base, bool IsVirtual,
122 CharUnits OffsetInLayoutClass,
123 SubobjectOffsetMapTy &SubobjectOffsets,
124 SubobjectOffsetMapTy &SubobjectLayoutClassOffsets,
125 SubobjectCountMapTy &SubobjectCounts);
126
127 typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
128
129 /// dump - dump the final overriders for a base subobject, and all its direct
130 /// and indirect base subobjects.
131 void dump(raw_ostream &Out, BaseSubobject Base,
132 VisitedVirtualBasesSetTy& VisitedVirtualBases);
133
134public:
135 FinalOverriders(const CXXRecordDecl *MostDerivedClass,
136 CharUnits MostDerivedClassOffset,
137 const CXXRecordDecl *LayoutClass);
138
139 /// getOverrider - Get the final overrider for the given method declaration in
140 /// the subobject with the given base offset.
141 OverriderInfo getOverrider(const CXXMethodDecl *MD,
142 CharUnits BaseOffset) const {
143 assert(OverridersMap.count(std::make_pair(MD, BaseOffset)) &&
144 "Did not find overrider!");
145
146 return OverridersMap.lookup(std::make_pair(MD, BaseOffset));
147 }
148
149 /// dump - dump the final overriders.
150 void dump() {
151 VisitedVirtualBasesSetTy VisitedVirtualBases;
152 dump(llvm::errs(), BaseSubobject(MostDerivedClass, CharUnits::Zero()),
153 VisitedVirtualBases);
154 }
155
156};
157
158FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass,
159 CharUnits MostDerivedClassOffset,
160 const CXXRecordDecl *LayoutClass)
161 : MostDerivedClass(MostDerivedClass),
162 MostDerivedClassOffset(MostDerivedClassOffset), LayoutClass(LayoutClass),
163 Context(MostDerivedClass->getASTContext()),
164 MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)) {
165
166 // Compute base offsets.
167 SubobjectOffsetMapTy SubobjectOffsets;
168 SubobjectOffsetMapTy SubobjectLayoutClassOffsets;
169 SubobjectCountMapTy SubobjectCounts;
170 ComputeBaseOffsets(BaseSubobject(MostDerivedClass, CharUnits::Zero()),
171 /*IsVirtual=*/false,
172 MostDerivedClassOffset,
173 SubobjectOffsets, SubobjectLayoutClassOffsets,
174 SubobjectCounts);
175
176 // Get the final overriders.
177 CXXFinalOverriderMap FinalOverriders;
178 MostDerivedClass->getFinalOverriders(FinalOverriders);
179
180 for (const auto &Overrider : FinalOverriders) {
181 const CXXMethodDecl *MD = Overrider.first;
182 const OverridingMethods &Methods = Overrider.second;
183
184 for (const auto &M : Methods) {
185 unsigned SubobjectNumber = M.first;
186 assert(SubobjectOffsets.count(std::make_pair(MD->getParent(),
187 SubobjectNumber)) &&
188 "Did not find subobject offset!");
189
190 CharUnits BaseOffset = SubobjectOffsets[std::make_pair(MD->getParent(),
191 SubobjectNumber)];
192
193 assert(M.second.size() == 1 && "Final overrider is not unique!");
194 const UniqueVirtualMethod &Method = M.second.front();
195
196 const CXXRecordDecl *OverriderRD = Method.Method->getParent();
197 assert(SubobjectLayoutClassOffsets.count(
198 std::make_pair(OverriderRD, Method.Subobject))
199 && "Did not find subobject offset!");
200 CharUnits OverriderOffset =
201 SubobjectLayoutClassOffsets[std::make_pair(OverriderRD,
202 Method.Subobject)];
203
204 OverriderInfo& Overrider = OverridersMap[std::make_pair(MD, BaseOffset)];
205 assert(!Overrider.Method && "Overrider should not exist yet!");
206
207 Overrider.Offset = OverriderOffset;
208 Overrider.Method = Method.Method;
209 Overrider.VirtualBase = Method.InVirtualSubobject;
210 }
211 }
212
213#if DUMP_OVERRIDERS
214 // And dump them (for now).
215 dump();
216#endif
217}
218
219static BaseOffset ComputeBaseOffset(const ASTContext &Context,
220 const CXXRecordDecl *DerivedRD,
221 const CXXBasePath &Path) {
222 CharUnits NonVirtualOffset = CharUnits::Zero();
223
224 unsigned NonVirtualStart = 0;
225 const CXXRecordDecl *VirtualBase = nullptr;
226
227 // First, look for the virtual base class.
228 for (int I = Path.size(), E = 0; I != E; --I) {
229 const CXXBasePathElement &Element = Path[I - 1];
230
231 if (Element.Base->isVirtual()) {
232 NonVirtualStart = I;
233 QualType VBaseType = Element.Base->getType();
234 VirtualBase = VBaseType->getAsCXXRecordDecl();
235 break;
236 }
237 }
238
239 // Now compute the non-virtual offset.
240 for (unsigned I = NonVirtualStart, E = Path.size(); I != E; ++I) {
241 const CXXBasePathElement &Element = Path[I];
242
243 // Check the base class offset.
244 const ASTRecordLayout &Layout = Context.getASTRecordLayout(Element.Class);
245
246 const CXXRecordDecl *Base = Element.Base->getType()->getAsCXXRecordDecl();
247
248 NonVirtualOffset += Layout.getBaseClassOffset(Base);
249 }
250
251 // FIXME: This should probably use CharUnits or something. Maybe we should
252 // even change the base offsets in ASTRecordLayout to be specified in
253 // CharUnits.
254 return BaseOffset(DerivedRD, VirtualBase, NonVirtualOffset);
255
256}
257
258static BaseOffset ComputeBaseOffset(const ASTContext &Context,
259 const CXXRecordDecl *BaseRD,
260 const CXXRecordDecl *DerivedRD) {
261 CXXBasePaths Paths(/*FindAmbiguities=*/false,
262 /*RecordPaths=*/true, /*DetectVirtual=*/false);
263
264 if (!DerivedRD->isDerivedFrom(BaseRD, Paths))
265 llvm_unreachable("Class must be derived from the passed in base class!");
266
267 return ComputeBaseOffset(Context, DerivedRD, Paths.front());
268}
269
270static BaseOffset
271ComputeReturnAdjustmentBaseOffset(ASTContext &Context,
272 const CXXMethodDecl *DerivedMD,
273 const CXXMethodDecl *BaseMD) {
274 const auto *BaseFT = BaseMD->getType()->castAs<FunctionType>();
275 const auto *DerivedFT = DerivedMD->getType()->castAs<FunctionType>();
276
277 // Canonicalize the return types.
278 CanQualType CanDerivedReturnType =
279 Context.getCanonicalType(DerivedFT->getReturnType());
280 CanQualType CanBaseReturnType =
281 Context.getCanonicalType(BaseFT->getReturnType());
282
283 assert(CanDerivedReturnType->getTypeClass() ==
284 CanBaseReturnType->getTypeClass() &&
285 "Types must have same type class!");
286
287 if (CanDerivedReturnType == CanBaseReturnType) {
288 // No adjustment needed.
289 return BaseOffset();
290 }
291
292 if (isa<ReferenceType>(CanDerivedReturnType)) {
293 CanDerivedReturnType =
294 CanDerivedReturnType->getAs<ReferenceType>()->getPointeeType();
295 CanBaseReturnType =
296 CanBaseReturnType->getAs<ReferenceType>()->getPointeeType();
297 } else if (isa<PointerType>(CanDerivedReturnType)) {
298 CanDerivedReturnType =
299 CanDerivedReturnType->getAs<PointerType>()->getPointeeType();
300 CanBaseReturnType =
301 CanBaseReturnType->getAs<PointerType>()->getPointeeType();
302 } else {
303 llvm_unreachable("Unexpected return type!");
304 }
305
306 // We need to compare unqualified types here; consider
307 // const T *Base::foo();
308 // T *Derived::foo();
309 if (CanDerivedReturnType.getUnqualifiedType() ==
310 CanBaseReturnType.getUnqualifiedType()) {
311 // No adjustment needed.
312 return BaseOffset();
313 }
314
315 const auto *DerivedRD =
316 cast<CXXRecordDecl>(cast<RecordType>(CanDerivedReturnType)->getDecl())
317 ->getDefinitionOrSelf();
318
319 const auto *BaseRD =
320 cast<CXXRecordDecl>(cast<RecordType>(CanBaseReturnType)->getDecl());
321
322 return ComputeBaseOffset(Context, BaseRD, DerivedRD);
323}
324
325void
326FinalOverriders::ComputeBaseOffsets(BaseSubobject Base, bool IsVirtual,
327 CharUnits OffsetInLayoutClass,
328 SubobjectOffsetMapTy &SubobjectOffsets,
329 SubobjectOffsetMapTy &SubobjectLayoutClassOffsets,
330 SubobjectCountMapTy &SubobjectCounts) {
331 const CXXRecordDecl *RD = Base.getBase();
332
333 unsigned SubobjectNumber = 0;
334 if (!IsVirtual)
335 SubobjectNumber = ++SubobjectCounts[RD];
336
337 // Set up the subobject to offset mapping.
338 assert(!SubobjectOffsets.count(std::make_pair(RD, SubobjectNumber))
339 && "Subobject offset already exists!");
340 assert(!SubobjectLayoutClassOffsets.count(std::make_pair(RD, SubobjectNumber))
341 && "Subobject offset already exists!");
342
343 SubobjectOffsets[std::make_pair(RD, SubobjectNumber)] = Base.getBaseOffset();
344 SubobjectLayoutClassOffsets[std::make_pair(RD, SubobjectNumber)] =
345 OffsetInLayoutClass;
346
347 // Traverse our bases.
348 for (const auto &B : RD->bases()) {
349 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
350
351 CharUnits BaseOffset;
352 CharUnits BaseOffsetInLayoutClass;
353 if (B.isVirtual()) {
354 // Check if we've visited this virtual base before.
355 if (SubobjectOffsets.count(std::make_pair(BaseDecl, 0)))
356 continue;
357
358 const ASTRecordLayout &LayoutClassLayout =
359 Context.getASTRecordLayout(LayoutClass);
360
361 BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
362 BaseOffsetInLayoutClass =
363 LayoutClassLayout.getVBaseClassOffset(BaseDecl);
364 } else {
365 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
366 CharUnits Offset = Layout.getBaseClassOffset(BaseDecl);
367
368 BaseOffset = Base.getBaseOffset() + Offset;
369 BaseOffsetInLayoutClass = OffsetInLayoutClass + Offset;
370 }
371
372 ComputeBaseOffsets(BaseSubobject(BaseDecl, BaseOffset),
373 B.isVirtual(), BaseOffsetInLayoutClass,
374 SubobjectOffsets, SubobjectLayoutClassOffsets,
375 SubobjectCounts);
376 }
377}
378
379void FinalOverriders::dump(raw_ostream &Out, BaseSubobject Base,
380 VisitedVirtualBasesSetTy &VisitedVirtualBases) {
381 const CXXRecordDecl *RD = Base.getBase();
382 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
383
384 for (const auto &B : RD->bases()) {
385 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
386
387 // Ignore bases that don't have any virtual member functions.
388 if (!BaseDecl->isPolymorphic())
389 continue;
390
391 CharUnits BaseOffset;
392 if (B.isVirtual()) {
393 if (!VisitedVirtualBases.insert(BaseDecl).second) {
394 // We've visited this base before.
395 continue;
396 }
397
398 BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
399 } else {
400 BaseOffset = Layout.getBaseClassOffset(BaseDecl) + Base.getBaseOffset();
401 }
402
403 dump(Out, BaseSubobject(BaseDecl, BaseOffset), VisitedVirtualBases);
404 }
405
406 Out << "Final overriders for (";
407 RD->printQualifiedName(Out);
408 Out << ", ";
409 Out << Base.getBaseOffset().getQuantity() << ")\n";
410
411 // Now dump the overriders for this base subobject.
412 for (const auto *MD : RD->methods()) {
414 continue;
415 MD = MD->getCanonicalDecl();
416
417 OverriderInfo Overrider = getOverrider(MD, Base.getBaseOffset());
418
419 Out << " ";
420 MD->printQualifiedName(Out);
421 Out << " - (";
422 Overrider.Method->printQualifiedName(Out);
423 Out << ", " << Overrider.Offset.getQuantity() << ')';
424
425 BaseOffset Offset;
426 if (!Overrider.Method->isPureVirtual())
427 Offset = ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
428
429 if (!Offset.isEmpty()) {
430 Out << " [ret-adj: ";
431 if (Offset.VirtualBase) {
432 Offset.VirtualBase->printQualifiedName(Out);
433 Out << " vbase, ";
434 }
435
436 Out << Offset.NonVirtualOffset.getQuantity() << " nv]";
437 }
438
439 Out << "\n";
440 }
441}
442
443/// VCallOffsetMap - Keeps track of vcall offsets when building a vtable.
444struct VCallOffsetMap {
445
446 typedef std::pair<const CXXMethodDecl *, CharUnits> MethodAndOffsetPairTy;
447
448 /// Offsets - Keeps track of methods and their offsets.
449 // FIXME: This should be a real map and not a vector.
451
452 /// MethodsCanShareVCallOffset - Returns whether two virtual member functions
453 /// can share the same vcall offset.
454 static bool MethodsCanShareVCallOffset(const CXXMethodDecl *LHS,
455 const CXXMethodDecl *RHS);
456
457public:
458 /// AddVCallOffset - Adds a vcall offset to the map. Returns true if the
459 /// add was successful, or false if there was already a member function with
460 /// the same signature in the map.
461 bool AddVCallOffset(const CXXMethodDecl *MD, CharUnits OffsetOffset);
462
463 /// getVCallOffsetOffset - Returns the vcall offset offset (relative to the
464 /// vtable address point) for the given virtual member function.
465 CharUnits getVCallOffsetOffset(const CXXMethodDecl *MD);
466
467 // empty - Return whether the offset map is empty or not.
468 bool empty() const { return Offsets.empty(); }
469};
470
471static bool HasSameVirtualSignature(const CXXMethodDecl *LHS,
472 const CXXMethodDecl *RHS) {
473 const FunctionProtoType *LT =
475 const FunctionProtoType *RT =
477
478 // Fast-path matches in the canonical types.
479 if (LT == RT) return true;
480
481 // Force the signatures to match. We can't rely on the overrides
482 // list here because there isn't necessarily an inheritance
483 // relationship between the two methods.
484 if (LT->getMethodQuals() != RT->getMethodQuals())
485 return false;
486 return LT->getParamTypes() == RT->getParamTypes();
487}
488
489bool VCallOffsetMap::MethodsCanShareVCallOffset(const CXXMethodDecl *LHS,
490 const CXXMethodDecl *RHS) {
491 assert(VTableContextBase::hasVtableSlot(LHS) && "LHS must be virtual!");
492 assert(VTableContextBase::hasVtableSlot(RHS) && "RHS must be virtual!");
493
494 // A destructor can share a vcall offset with another destructor.
495 if (isa<CXXDestructorDecl>(LHS))
496 return isa<CXXDestructorDecl>(RHS);
497
498 // FIXME: We need to check more things here.
499
500 // The methods must have the same name.
501 DeclarationName LHSName = LHS->getDeclName();
502 DeclarationName RHSName = RHS->getDeclName();
503 if (LHSName != RHSName)
504 return false;
505
506 // And the same signatures.
507 return HasSameVirtualSignature(LHS, RHS);
508}
509
510bool VCallOffsetMap::AddVCallOffset(const CXXMethodDecl *MD,
511 CharUnits OffsetOffset) {
512 // Check if we can reuse an offset.
513 for (const auto &OffsetPair : Offsets) {
514 if (MethodsCanShareVCallOffset(OffsetPair.first, MD))
515 return false;
516 }
517
518 // Add the offset.
519 Offsets.push_back(MethodAndOffsetPairTy(MD, OffsetOffset));
520 return true;
521}
522
523CharUnits VCallOffsetMap::getVCallOffsetOffset(const CXXMethodDecl *MD) {
524 // Look for an offset.
525 for (const auto &OffsetPair : Offsets) {
526 if (MethodsCanShareVCallOffset(OffsetPair.first, MD))
527 return OffsetPair.second;
528 }
529
530 llvm_unreachable("Should always find a vcall offset offset!");
531}
532
533/// VCallAndVBaseOffsetBuilder - Class for building vcall and vbase offsets.
534class VCallAndVBaseOffsetBuilder {
535public:
536 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
537 VBaseOffsetOffsetsMapTy;
538
539private:
540 /// MostDerivedClass - The most derived class for which we're building vcall
541 /// and vbase offsets.
542 const CXXRecordDecl *MostDerivedClass;
543
544 /// LayoutClass - The class we're using for layout information. Will be
545 /// different than the most derived class if we're building a construction
546 /// vtable.
547 const CXXRecordDecl *LayoutClass;
548
549 /// Context - The ASTContext which we will use for layout information.
550 ASTContext &Context;
551
552 /// Components - vcall and vbase offset components
553 typedef SmallVector<VTableComponent, 64> VTableComponentVectorTy;
554 VTableComponentVectorTy Components;
555
556 /// VisitedVirtualBases - Visited virtual bases.
558
559 /// VCallOffsets - Keeps track of vcall offsets.
560 VCallOffsetMap VCallOffsets;
561
562
563 /// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets,
564 /// relative to the address point.
565 VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
566
567 /// FinalOverriders - The final overriders of the most derived class.
568 /// (Can be null when we're not building a vtable of the most derived class).
569 const FinalOverriders *Overriders;
570
571 /// AddVCallAndVBaseOffsets - Add vcall offsets and vbase offsets for the
572 /// given base subobject.
573 void AddVCallAndVBaseOffsets(BaseSubobject Base, bool BaseIsVirtual,
574 CharUnits RealBaseOffset);
575
576 /// AddVCallOffsets - Add vcall offsets for the given base subobject.
577 void AddVCallOffsets(BaseSubobject Base, CharUnits VBaseOffset);
578
579 /// AddVBaseOffsets - Add vbase offsets for the given class.
580 void AddVBaseOffsets(const CXXRecordDecl *Base,
581 CharUnits OffsetInLayoutClass);
582
583 /// getCurrentOffsetOffset - Get the current vcall or vbase offset offset in
584 /// chars, relative to the vtable address point.
585 CharUnits getCurrentOffsetOffset() const;
586
587public:
588 VCallAndVBaseOffsetBuilder(const CXXRecordDecl *MostDerivedClass,
589 const CXXRecordDecl *LayoutClass,
590 const FinalOverriders *Overriders,
591 BaseSubobject Base, bool BaseIsVirtual,
592 CharUnits OffsetInLayoutClass)
593 : MostDerivedClass(MostDerivedClass), LayoutClass(LayoutClass),
594 Context(MostDerivedClass->getASTContext()), Overriders(Overriders) {
595
596 // Add vcall and vbase offsets.
597 AddVCallAndVBaseOffsets(Base, BaseIsVirtual, OffsetInLayoutClass);
598 }
599
600 /// Methods for iterating over the components.
601 typedef VTableComponentVectorTy::const_reverse_iterator const_iterator;
602 const_iterator components_begin() const { return Components.rbegin(); }
603 const_iterator components_end() const { return Components.rend(); }
604
605 const VCallOffsetMap &getVCallOffsets() const { return VCallOffsets; }
606 const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets() const {
607 return VBaseOffsetOffsets;
608 }
609};
610
611void
612VCallAndVBaseOffsetBuilder::AddVCallAndVBaseOffsets(BaseSubobject Base,
613 bool BaseIsVirtual,
614 CharUnits RealBaseOffset) {
615 const ASTRecordLayout &Layout = Context.getASTRecordLayout(Base.getBase());
616
617 // Itanium C++ ABI 2.5.2:
618 // ..in classes sharing a virtual table with a primary base class, the vcall
619 // and vbase offsets added by the derived class all come before the vcall
620 // and vbase offsets required by the base class, so that the latter may be
621 // laid out as required by the base class without regard to additions from
622 // the derived class(es).
623
624 // (Since we're emitting the vcall and vbase offsets in reverse order, we'll
625 // emit them for the primary base first).
626 if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
627 bool PrimaryBaseIsVirtual = Layout.isPrimaryBaseVirtual();
628
629 CharUnits PrimaryBaseOffset;
630
631 // Get the base offset of the primary base.
632 if (PrimaryBaseIsVirtual) {
633 assert(Layout.getVBaseClassOffset(PrimaryBase).isZero() &&
634 "Primary vbase should have a zero offset!");
635
636 const ASTRecordLayout &MostDerivedClassLayout =
637 Context.getASTRecordLayout(MostDerivedClass);
638
639 PrimaryBaseOffset =
640 MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase);
641 } else {
642 assert(Layout.getBaseClassOffset(PrimaryBase).isZero() &&
643 "Primary base should have a zero offset!");
644
645 PrimaryBaseOffset = Base.getBaseOffset();
646 }
647
648 AddVCallAndVBaseOffsets(
649 BaseSubobject(PrimaryBase,PrimaryBaseOffset),
650 PrimaryBaseIsVirtual, RealBaseOffset);
651 }
652
653 AddVBaseOffsets(Base.getBase(), RealBaseOffset);
654
655 // We only want to add vcall offsets for virtual bases.
656 if (BaseIsVirtual)
657 AddVCallOffsets(Base, RealBaseOffset);
658}
659
660CharUnits VCallAndVBaseOffsetBuilder::getCurrentOffsetOffset() const {
661 // OffsetIndex is the index of this vcall or vbase offset, relative to the
662 // vtable address point. (We subtract 3 to account for the information just
663 // above the address point, the RTTI info, the offset to top, and the
664 // vcall offset itself).
665 size_t NumComponentsAboveAddrPoint = 3;
666 if (Context.getLangOpts().OmitVTableRTTI)
667 NumComponentsAboveAddrPoint--;
668 int64_t OffsetIndex =
669 -(int64_t)(NumComponentsAboveAddrPoint + Components.size());
670
671 // Under the relative ABI, the offset widths are 32-bit ints instead of
672 // pointer widths.
673 CharUnits OffsetWidth = Context.toCharUnitsFromBits(
674 Context.getLangOpts().RelativeCXXABIVTables
675 ? 32
676 : Context.getTargetInfo().getPointerWidth(LangAS::Default));
677 CharUnits OffsetOffset = OffsetWidth * OffsetIndex;
678
679 return OffsetOffset;
680}
681
682void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base,
683 CharUnits VBaseOffset) {
684 const CXXRecordDecl *RD = Base.getBase();
685 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
686
687 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
688
689 // Handle the primary base first.
690 // We only want to add vcall offsets if the base is non-virtual; a virtual
691 // primary base will have its vcall and vbase offsets emitted already.
692 if (PrimaryBase && !Layout.isPrimaryBaseVirtual()) {
693 // Get the base offset of the primary base.
694 assert(Layout.getBaseClassOffset(PrimaryBase).isZero() &&
695 "Primary base should have a zero offset!");
696
697 AddVCallOffsets(BaseSubobject(PrimaryBase, Base.getBaseOffset()),
698 VBaseOffset);
699 }
700
701 // Add the vcall offsets.
702 for (const auto *MD : RD->methods()) {
704 continue;
705 MD = MD->getCanonicalDecl();
706
707 CharUnits OffsetOffset = getCurrentOffsetOffset();
708
709 // Don't add a vcall offset if we already have one for this member function
710 // signature.
711 if (!VCallOffsets.AddVCallOffset(MD, OffsetOffset))
712 continue;
713
714 CharUnits Offset = CharUnits::Zero();
715
716 if (Overriders) {
717 // Get the final overrider.
718 FinalOverriders::OverriderInfo Overrider =
719 Overriders->getOverrider(MD, Base.getBaseOffset());
720
721 /// The vcall offset is the offset from the virtual base to the object
722 /// where the function was overridden.
723 Offset = Overrider.Offset - VBaseOffset;
724 }
725
726 Components.push_back(
728 }
729
730 // And iterate over all non-virtual bases (ignoring the primary base).
731 for (const auto &B : RD->bases()) {
732 if (B.isVirtual())
733 continue;
734
735 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
736 if (BaseDecl == PrimaryBase)
737 continue;
738
739 // Get the base offset of this base.
740 CharUnits BaseOffset = Base.getBaseOffset() +
741 Layout.getBaseClassOffset(BaseDecl);
742
743 AddVCallOffsets(BaseSubobject(BaseDecl, BaseOffset),
744 VBaseOffset);
745 }
746}
747
748void
749VCallAndVBaseOffsetBuilder::AddVBaseOffsets(const CXXRecordDecl *RD,
750 CharUnits OffsetInLayoutClass) {
751 const ASTRecordLayout &LayoutClassLayout =
752 Context.getASTRecordLayout(LayoutClass);
753
754 // Add vbase offsets.
755 for (const auto &B : RD->bases()) {
756 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
757
758 // Check if this is a virtual base that we haven't visited before.
759 if (B.isVirtual() && VisitedVirtualBases.insert(BaseDecl).second) {
760 CharUnits Offset =
761 LayoutClassLayout.getVBaseClassOffset(BaseDecl) - OffsetInLayoutClass;
762
763 // Add the vbase offset offset.
764 assert(!VBaseOffsetOffsets.count(BaseDecl) &&
765 "vbase offset offset already exists!");
766
767 CharUnits VBaseOffsetOffset = getCurrentOffsetOffset();
768 VBaseOffsetOffsets.insert(
769 std::make_pair(BaseDecl, VBaseOffsetOffset));
770
771 Components.push_back(
773 }
774
775 // Check the base class looking for more vbase offsets.
776 AddVBaseOffsets(BaseDecl, OffsetInLayoutClass);
777 }
778}
779
780/// ItaniumVTableBuilder - Class for building vtable layout information.
781class ItaniumVTableBuilder {
782public:
783 /// PrimaryBasesSetVectorTy - A set vector of direct and indirect
784 /// primary bases.
786 PrimaryBasesSetVectorTy;
787
788 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
789 VBaseOffsetOffsetsMapTy;
790
791 typedef VTableLayout::AddressPointsMapTy AddressPointsMapTy;
792
793 typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy;
794
795private:
796 /// VTables - Global vtable information.
797 ItaniumVTableContext &VTables;
798
799 /// MostDerivedClass - The most derived class for which we're building this
800 /// vtable.
801 const CXXRecordDecl *MostDerivedClass;
802
803 /// MostDerivedClassOffset - If we're building a construction vtable, this
804 /// holds the offset from the layout class to the most derived class.
805 const CharUnits MostDerivedClassOffset;
806
807 /// MostDerivedClassIsVirtual - Whether the most derived class is a virtual
808 /// base. (This only makes sense when building a construction vtable).
809 bool MostDerivedClassIsVirtual;
810
811 /// LayoutClass - The class we're using for layout information. Will be
812 /// different than the most derived class if we're building a construction
813 /// vtable.
814 const CXXRecordDecl *LayoutClass;
815
816 /// Context - The ASTContext which we will use for layout information.
817 ASTContext &Context;
818
819 /// FinalOverriders - The final overriders of the most derived class.
820 const FinalOverriders Overriders;
821
822 /// VCallOffsetsForVBases - Keeps track of vcall offsets for the virtual
823 /// bases in this vtable.
824 llvm::DenseMap<const CXXRecordDecl *, VCallOffsetMap> VCallOffsetsForVBases;
825
826 /// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets for
827 /// the most derived class.
828 VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
829
830 /// Components - The components of the vtable being built.
832
833 /// AddressPoints - Address points for the vtable being built.
834 AddressPointsMapTy AddressPoints;
835
836 /// MethodInfo - Contains information about a method in a vtable.
837 /// (Used for computing 'this' pointer adjustment thunks.
838 struct MethodInfo {
839 /// BaseOffset - The base offset of this method.
840 const CharUnits BaseOffset;
841
842 /// BaseOffsetInLayoutClass - The base offset in the layout class of this
843 /// method.
844 const CharUnits BaseOffsetInLayoutClass;
845
846 /// VTableIndex - The index in the vtable that this method has.
847 /// (For destructors, this is the index of the complete destructor).
848 const uint64_t VTableIndex;
849
850 MethodInfo(CharUnits BaseOffset, CharUnits BaseOffsetInLayoutClass,
851 uint64_t VTableIndex)
852 : BaseOffset(BaseOffset),
853 BaseOffsetInLayoutClass(BaseOffsetInLayoutClass),
854 VTableIndex(VTableIndex) { }
855
856 MethodInfo()
857 : BaseOffset(CharUnits::Zero()),
858 BaseOffsetInLayoutClass(CharUnits::Zero()),
859 VTableIndex(0) { }
860
861 MethodInfo(MethodInfo const&) = default;
862 };
863
864 typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
865
866 /// MethodInfoMap - The information for all methods in the vtable we're
867 /// currently building.
868 MethodInfoMapTy MethodInfoMap;
869
870 /// MethodVTableIndices - Contains the index (relative to the vtable address
871 /// point) where the function pointer for a virtual function is stored.
872 MethodVTableIndicesTy MethodVTableIndices;
873
874 typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
875
876 /// VTableThunks - The thunks by vtable index in the vtable currently being
877 /// built.
878 VTableThunksMapTy VTableThunks;
879
880 typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy;
881 typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
882
883 /// Thunks - A map that contains all the thunks needed for all methods in the
884 /// most derived class for which the vtable is currently being built.
885 ThunksMapTy Thunks;
886
887 /// AddThunk - Add a thunk for the given method.
888 void AddThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk);
889
890 /// ComputeThisAdjustments - Compute the 'this' pointer adjustments for the
891 /// part of the vtable we're currently building.
892 void ComputeThisAdjustments();
893
894 typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
895
896 /// PrimaryVirtualBases - All known virtual bases who are a primary base of
897 /// some other base.
898 VisitedVirtualBasesSetTy PrimaryVirtualBases;
899
900 /// ComputeReturnAdjustment - Compute the return adjustment given a return
901 /// adjustment base offset.
902 ReturnAdjustment ComputeReturnAdjustment(BaseOffset Offset);
903
904 /// ComputeThisAdjustmentBaseOffset - Compute the base offset for adjusting
905 /// the 'this' pointer from the base subobject to the derived subobject.
906 BaseOffset ComputeThisAdjustmentBaseOffset(BaseSubobject Base,
907 BaseSubobject Derived) const;
908
909 /// ComputeThisAdjustment - Compute the 'this' pointer adjustment for the
910 /// given virtual member function, its offset in the layout class and its
911 /// final overrider.
913 ComputeThisAdjustment(const CXXMethodDecl *MD,
914 CharUnits BaseOffsetInLayoutClass,
915 FinalOverriders::OverriderInfo Overrider);
916
917 /// AddMethod - Add a single virtual member function to the vtable
918 /// components vector.
919 void AddMethod(const CXXMethodDecl *MD, ReturnAdjustment ReturnAdjustment);
920
921 /// IsOverriderUsed - Returns whether the overrider will ever be used in this
922 /// part of the vtable.
923 ///
924 /// Itanium C++ ABI 2.5.2:
925 ///
926 /// struct A { virtual void f(); };
927 /// struct B : virtual public A { int i; };
928 /// struct C : virtual public A { int j; };
929 /// struct D : public B, public C {};
930 ///
931 /// When B and C are declared, A is a primary base in each case, so although
932 /// vcall offsets are allocated in the A-in-B and A-in-C vtables, no this
933 /// adjustment is required and no thunk is generated. However, inside D
934 /// objects, A is no longer a primary base of C, so if we allowed calls to
935 /// C::f() to use the copy of A's vtable in the C subobject, we would need
936 /// to adjust this from C* to B::A*, which would require a third-party
937 /// thunk. Since we require that a call to C::f() first convert to A*,
938 /// C-in-D's copy of A's vtable is never referenced, so this is not
939 /// necessary.
940 bool IsOverriderUsed(const CXXMethodDecl *Overrider,
941 CharUnits BaseOffsetInLayoutClass,
942 const CXXRecordDecl *FirstBaseInPrimaryBaseChain,
943 CharUnits FirstBaseOffsetInLayoutClass) const;
944
945
946 /// AddMethods - Add the methods of this base subobject and all its
947 /// primary bases to the vtable components vector.
948 void AddMethods(BaseSubobject Base, CharUnits BaseOffsetInLayoutClass,
949 const CXXRecordDecl *FirstBaseInPrimaryBaseChain,
950 CharUnits FirstBaseOffsetInLayoutClass,
951 PrimaryBasesSetVectorTy &PrimaryBases);
952
953 // LayoutVTable - Layout the vtable for the given base class, including its
954 // secondary vtables and any vtables for virtual bases.
955 void LayoutVTable();
956
957 /// LayoutPrimaryAndSecondaryVTables - Layout the primary vtable for the
958 /// given base subobject, as well as all its secondary vtables.
959 ///
960 /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base
961 /// or a direct or indirect base of a virtual base.
962 ///
963 /// \param BaseIsVirtualInLayoutClass - Whether the base subobject is virtual
964 /// in the layout class.
965 void LayoutPrimaryAndSecondaryVTables(BaseSubobject Base,
966 bool BaseIsMorallyVirtual,
967 bool BaseIsVirtualInLayoutClass,
968 CharUnits OffsetInLayoutClass);
969
970 /// LayoutSecondaryVTables - Layout the secondary vtables for the given base
971 /// subobject.
972 ///
973 /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base
974 /// or a direct or indirect base of a virtual base.
975 void LayoutSecondaryVTables(BaseSubobject Base, bool BaseIsMorallyVirtual,
976 CharUnits OffsetInLayoutClass);
977
978 /// DeterminePrimaryVirtualBases - Determine the primary virtual bases in this
979 /// class hierarchy.
980 void DeterminePrimaryVirtualBases(const CXXRecordDecl *RD,
981 CharUnits OffsetInLayoutClass,
982 VisitedVirtualBasesSetTy &VBases);
983
984 /// LayoutVTablesForVirtualBases - Layout vtables for all virtual bases of the
985 /// given base (excluding any primary bases).
986 void LayoutVTablesForVirtualBases(const CXXRecordDecl *RD,
987 VisitedVirtualBasesSetTy &VBases);
988
989 /// isBuildingConstructionVTable - Return whether this vtable builder is
990 /// building a construction vtable.
991 bool isBuildingConstructorVTable() const {
992 return MostDerivedClass != LayoutClass;
993 }
994
995public:
996 /// Component indices of the first component of each of the vtables in the
997 /// vtable group.
998 VTableLayout::VTableIndicesTy VTableIndices;
999
1000 ItaniumVTableBuilder(ItaniumVTableContext &VTables,
1001 const CXXRecordDecl *MostDerivedClass,
1002 CharUnits MostDerivedClassOffset,
1003 bool MostDerivedClassIsVirtual,
1004 const CXXRecordDecl *LayoutClass)
1005 : VTables(VTables), MostDerivedClass(MostDerivedClass),
1006 MostDerivedClassOffset(MostDerivedClassOffset),
1007 MostDerivedClassIsVirtual(MostDerivedClassIsVirtual),
1008 LayoutClass(LayoutClass), Context(MostDerivedClass->getASTContext()),
1009 Overriders(MostDerivedClass, MostDerivedClassOffset, LayoutClass) {
1010 assert(!Context.getTargetInfo().getCXXABI().isMicrosoft());
1011
1012 LayoutVTable();
1013
1014 if (Context.getLangOpts().DumpVTableLayouts)
1015 dumpLayout(llvm::outs());
1016 }
1017
1018 uint64_t getNumThunks() const {
1019 return Thunks.size();
1020 }
1021
1022 ThunksMapTy::const_iterator thunks_begin() const {
1023 return Thunks.begin();
1024 }
1025
1026 ThunksMapTy::const_iterator thunks_end() const {
1027 return Thunks.end();
1028 }
1029
1030 const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets() const {
1031 return VBaseOffsetOffsets;
1032 }
1033
1034 const AddressPointsMapTy &getAddressPoints() const {
1035 return AddressPoints;
1036 }
1037
1038 MethodVTableIndicesTy::const_iterator vtable_indices_begin() const {
1039 return MethodVTableIndices.begin();
1040 }
1041
1042 MethodVTableIndicesTy::const_iterator vtable_indices_end() const {
1043 return MethodVTableIndices.end();
1044 }
1045
1046 ArrayRef<VTableComponent> vtable_components() const { return Components; }
1047
1048 AddressPointsMapTy::const_iterator address_points_begin() const {
1049 return AddressPoints.begin();
1050 }
1051
1052 AddressPointsMapTy::const_iterator address_points_end() const {
1053 return AddressPoints.end();
1054 }
1055
1056 VTableThunksMapTy::const_iterator vtable_thunks_begin() const {
1057 return VTableThunks.begin();
1058 }
1059
1060 VTableThunksMapTy::const_iterator vtable_thunks_end() const {
1061 return VTableThunks.end();
1062 }
1063
1064 /// dumpLayout - Dump the vtable layout.
1065 void dumpLayout(raw_ostream&);
1066};
1067
1068void ItaniumVTableBuilder::AddThunk(const CXXMethodDecl *MD,
1069 const ThunkInfo &Thunk) {
1070 assert(!isBuildingConstructorVTable() &&
1071 "Can't add thunks for construction vtable");
1072
1073 SmallVectorImpl<ThunkInfo> &ThunksVector = Thunks[MD];
1074
1075 // Check if we have this thunk already.
1076 if (llvm::is_contained(ThunksVector, Thunk))
1077 return;
1078
1079 ThunksVector.push_back(Thunk);
1080}
1081
1082typedef llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverriddenMethodsSetTy;
1083
1084/// Visit all the methods overridden by the given method recursively,
1085/// in a depth-first pre-order. The Visitor's visitor method returns a bool
1086/// indicating whether to continue the recursion for the given overridden
1087/// method (i.e. returning false stops the iteration).
1088template <class VisitorTy>
1089static void
1090visitAllOverriddenMethods(const CXXMethodDecl *MD, VisitorTy &Visitor) {
1091 assert(VTableContextBase::hasVtableSlot(MD) && "Method is not virtual!");
1092
1093 for (const CXXMethodDecl *OverriddenMD : MD->overridden_methods()) {
1094 if (!Visitor(OverriddenMD))
1095 continue;
1096 visitAllOverriddenMethods(OverriddenMD, Visitor);
1097 }
1098}
1099
1100/// ComputeAllOverriddenMethods - Given a method decl, will return a set of all
1101/// the overridden methods that the function decl overrides.
1102static void
1103ComputeAllOverriddenMethods(const CXXMethodDecl *MD,
1104 OverriddenMethodsSetTy& OverriddenMethods) {
1105 auto OverriddenMethodsCollector = [&](const CXXMethodDecl *MD) {
1106 // Don't recurse on this method if we've already collected it.
1107 return OverriddenMethods.insert(MD).second;
1108 };
1109 visitAllOverriddenMethods(MD, OverriddenMethodsCollector);
1110}
1111
1112void ItaniumVTableBuilder::ComputeThisAdjustments() {
1113 // Now go through the method info map and see if any of the methods need
1114 // 'this' pointer adjustments.
1115 for (const auto &MI : MethodInfoMap) {
1116 const CXXMethodDecl *MD = MI.first;
1117 const MethodInfo &MethodInfo = MI.second;
1118
1119 // Ignore adjustments for unused function pointers.
1120 uint64_t VTableIndex = MethodInfo.VTableIndex;
1121 if (Components[VTableIndex].getKind() ==
1123 continue;
1124
1125 // Get the final overrider for this method.
1126 FinalOverriders::OverriderInfo Overrider =
1127 Overriders.getOverrider(MD, MethodInfo.BaseOffset);
1128
1129 // Check if we need an adjustment at all.
1130 if (MethodInfo.BaseOffsetInLayoutClass == Overrider.Offset) {
1131 // When a return thunk is needed by a derived class that overrides a
1132 // virtual base, gcc uses a virtual 'this' adjustment as well.
1133 // While the thunk itself might be needed by vtables in subclasses or
1134 // in construction vtables, there doesn't seem to be a reason for using
1135 // the thunk in this vtable. Still, we do so to match gcc.
1136 if (VTableThunks.lookup(VTableIndex).Return.isEmpty())
1137 continue;
1138 }
1139
1141 ComputeThisAdjustment(MD, MethodInfo.BaseOffsetInLayoutClass, Overrider);
1142
1143 if (ThisAdjustment.isEmpty())
1144 continue;
1145
1146 // Add it.
1147 auto SetThisAdjustmentThunk = [&](uint64_t Idx) {
1148 // If a this pointer adjustment is required, record the method that
1149 // created the vtable entry. MD is not necessarily the method that
1150 // created the entry since derived classes overwrite base class
1151 // information in MethodInfoMap, hence findOriginalMethodInMap is called
1152 // here.
1153 //
1154 // For example, in the following class hierarchy, if MD = D1::m and
1155 // Overrider = D2:m, the original method that created the entry is B0:m,
1156 // which is what findOriginalMethodInMap(MD) returns:
1157 //
1158 // struct B0 { int a; virtual void m(); };
1159 // struct D0 : B0 { int a; void m() override; };
1160 // struct D1 : B0 { int a; void m() override; };
1161 // struct D2 : D0, D1 { int a; void m() override; };
1162 //
1163 // We need to record the method because we cannot
1164 // call findOriginalMethod to find the method that created the entry if
1165 // the method in the entry requires adjustment.
1166 //
1167 // Do not set ThunkInfo::Method if Idx is already in VTableThunks. This
1168 // can happen when covariant return adjustment is required too.
1169 auto [It, Inserted] = VTableThunks.try_emplace(Idx);
1170 if (Inserted) {
1171 const CXXMethodDecl *Method = VTables.findOriginalMethodInMap(MD);
1172 It->second.Method = Method;
1173 It->second.ThisType = Method->getThisType().getTypePtr();
1174 }
1175 It->second.This = ThisAdjustment;
1176 };
1177
1178 SetThisAdjustmentThunk(VTableIndex);
1179
1180 if (isa<CXXDestructorDecl>(MD)) {
1181 // Add an adjustment for the deleting destructor as well.
1182 SetThisAdjustmentThunk(VTableIndex + 1);
1183 }
1184 }
1185
1186 /// Clear the method info map.
1187 MethodInfoMap.clear();
1188
1189 if (isBuildingConstructorVTable()) {
1190 // We don't need to store thunk information for construction vtables.
1191 return;
1192 }
1193
1194 for (const auto &TI : VTableThunks) {
1195 const VTableComponent &Component = Components[TI.first];
1196 const ThunkInfo &Thunk = TI.second;
1197 const CXXMethodDecl *MD;
1198
1199 switch (Component.getKind()) {
1200 default:
1201 llvm_unreachable("Unexpected vtable component kind!");
1203 MD = Component.getFunctionDecl();
1204 break;
1206 MD = Component.getDestructorDecl();
1207 break;
1209 // We've already added the thunk when we saw the complete dtor pointer.
1210 continue;
1211 }
1212
1213 if (MD->getParent() == MostDerivedClass)
1214 AddThunk(MD, Thunk);
1215 }
1216}
1217
1219ItaniumVTableBuilder::ComputeReturnAdjustment(BaseOffset Offset) {
1220 ReturnAdjustment Adjustment;
1221
1222 if (!Offset.isEmpty()) {
1223 if (Offset.VirtualBase) {
1224 // Get the virtual base offset offset.
1225 if (Offset.DerivedClass == MostDerivedClass) {
1226 // We can get the offset offset directly from our map.
1227 Adjustment.Virtual.Itanium.VBaseOffsetOffset =
1228 VBaseOffsetOffsets.lookup(Offset.VirtualBase).getQuantity();
1229 } else {
1230 Adjustment.Virtual.Itanium.VBaseOffsetOffset =
1231 VTables.getVirtualBaseOffsetOffset(Offset.DerivedClass,
1232 Offset.VirtualBase).getQuantity();
1233 }
1234 }
1235
1236 Adjustment.NonVirtual = Offset.NonVirtualOffset.getQuantity();
1237 }
1238
1239 return Adjustment;
1240}
1241
1242BaseOffset ItaniumVTableBuilder::ComputeThisAdjustmentBaseOffset(
1243 BaseSubobject Base, BaseSubobject Derived) const {
1244 const CXXRecordDecl *BaseRD = Base.getBase();
1245 const CXXRecordDecl *DerivedRD = Derived.getBase();
1246
1247 CXXBasePaths Paths(/*FindAmbiguities=*/true,
1248 /*RecordPaths=*/true, /*DetectVirtual=*/true);
1249
1250 if (!DerivedRD->isDerivedFrom(BaseRD, Paths))
1251 llvm_unreachable("Class must be derived from the passed in base class!");
1252
1253 // We have to go through all the paths, and see which one leads us to the
1254 // right base subobject.
1255 for (const CXXBasePath &Path : Paths) {
1256 BaseOffset Offset = ComputeBaseOffset(Context, DerivedRD, Path);
1257
1258 CharUnits OffsetToBaseSubobject = Offset.NonVirtualOffset;
1259
1260 if (Offset.VirtualBase) {
1261 // If we have a virtual base class, the non-virtual offset is relative
1262 // to the virtual base class offset.
1263 const ASTRecordLayout &LayoutClassLayout =
1264 Context.getASTRecordLayout(LayoutClass);
1265
1266 /// Get the virtual base offset, relative to the most derived class
1267 /// layout.
1268 OffsetToBaseSubobject +=
1269 LayoutClassLayout.getVBaseClassOffset(Offset.VirtualBase);
1270 } else {
1271 // Otherwise, the non-virtual offset is relative to the derived class
1272 // offset.
1273 OffsetToBaseSubobject += Derived.getBaseOffset();
1274 }
1275
1276 // Check if this path gives us the right base subobject.
1277 if (OffsetToBaseSubobject == Base.getBaseOffset()) {
1278 // Since we're going from the base class _to_ the derived class, we'll
1279 // invert the non-virtual offset here.
1280 Offset.NonVirtualOffset = -Offset.NonVirtualOffset;
1281 return Offset;
1282 }
1283 }
1284
1285 return BaseOffset();
1286}
1287
1288ThisAdjustment ItaniumVTableBuilder::ComputeThisAdjustment(
1289 const CXXMethodDecl *MD, CharUnits BaseOffsetInLayoutClass,
1290 FinalOverriders::OverriderInfo Overrider) {
1291 // Ignore adjustments for pure virtual member functions.
1292 if (Overrider.Method->isPureVirtual())
1293 return ThisAdjustment();
1294
1295 BaseSubobject OverriddenBaseSubobject(MD->getParent(),
1296 BaseOffsetInLayoutClass);
1297
1298 BaseSubobject OverriderBaseSubobject(Overrider.Method->getParent(),
1299 Overrider.Offset);
1300
1301 // Compute the adjustment offset.
1302 BaseOffset Offset = ComputeThisAdjustmentBaseOffset(OverriddenBaseSubobject,
1303 OverriderBaseSubobject);
1304 if (Offset.isEmpty())
1305 return ThisAdjustment();
1306
1307 ThisAdjustment Adjustment;
1308
1309 if (Offset.VirtualBase) {
1310 // Get the vcall offset map for this virtual base.
1311 VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Offset.VirtualBase];
1312
1313 if (VCallOffsets.empty()) {
1314 // We don't have vcall offsets for this virtual base, go ahead and
1315 // build them.
1316 VCallAndVBaseOffsetBuilder Builder(
1317 MostDerivedClass, MostDerivedClass,
1318 /*Overriders=*/nullptr,
1319 BaseSubobject(Offset.VirtualBase, CharUnits::Zero()),
1320 /*BaseIsVirtual=*/true,
1321 /*OffsetInLayoutClass=*/
1322 CharUnits::Zero());
1323
1324 VCallOffsets = Builder.getVCallOffsets();
1325 }
1326
1327 Adjustment.Virtual.Itanium.VCallOffsetOffset =
1328 VCallOffsets.getVCallOffsetOffset(MD).getQuantity();
1329 }
1330
1331 // Set the non-virtual part of the adjustment.
1332 Adjustment.NonVirtual = Offset.NonVirtualOffset.getQuantity();
1333
1334 return Adjustment;
1335}
1336
1337void ItaniumVTableBuilder::AddMethod(const CXXMethodDecl *MD,
1339 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
1340 assert(ReturnAdjustment.isEmpty() &&
1341 "Destructor can't have return adjustment!");
1342
1343 // Add both the complete destructor and the deleting destructor.
1344 Components.push_back(VTableComponent::MakeCompleteDtor(DD));
1345 Components.push_back(VTableComponent::MakeDeletingDtor(DD));
1346 } else {
1347 // Add the return adjustment if necessary.
1349 VTableThunks[Components.size()].Return = ReturnAdjustment;
1350
1351 // Add the function.
1352 Components.push_back(VTableComponent::MakeFunction(MD));
1353 }
1354}
1355
1356/// OverridesIndirectMethodInBase - Return whether the given member function
1357/// overrides any methods in the set of given bases.
1358/// Unlike OverridesMethodInBase, this checks "overriders of overriders".
1359/// For example, if we have:
1360///
1361/// struct A { virtual void f(); }
1362/// struct B : A { virtual void f(); }
1363/// struct C : B { virtual void f(); }
1364///
1365/// OverridesIndirectMethodInBase will return true if given C::f as the method
1366/// and { A } as the set of bases.
1367static bool OverridesIndirectMethodInBases(
1368 const CXXMethodDecl *MD,
1369 ItaniumVTableBuilder::PrimaryBasesSetVectorTy &Bases) {
1370 if (Bases.count(MD->getParent()))
1371 return true;
1372
1373 for (const CXXMethodDecl *OverriddenMD : MD->overridden_methods()) {
1374 // Check "indirect overriders".
1375 if (OverridesIndirectMethodInBases(OverriddenMD, Bases))
1376 return true;
1377 }
1378
1379 return false;
1380}
1381
1382bool ItaniumVTableBuilder::IsOverriderUsed(
1383 const CXXMethodDecl *Overrider, CharUnits BaseOffsetInLayoutClass,
1384 const CXXRecordDecl *FirstBaseInPrimaryBaseChain,
1385 CharUnits FirstBaseOffsetInLayoutClass) const {
1386 // If the base and the first base in the primary base chain have the same
1387 // offsets, then this overrider will be used.
1388 if (BaseOffsetInLayoutClass == FirstBaseOffsetInLayoutClass)
1389 return true;
1390
1391 // We know now that Base (or a direct or indirect base of it) is a primary
1392 // base in part of the class hierarchy, but not a primary base in the most
1393 // derived class.
1394
1395 // If the overrider is the first base in the primary base chain, we know
1396 // that the overrider will be used.
1397 if (Overrider->getParent() == FirstBaseInPrimaryBaseChain)
1398 return true;
1399
1400 ItaniumVTableBuilder::PrimaryBasesSetVectorTy PrimaryBases;
1401
1402 const CXXRecordDecl *RD = FirstBaseInPrimaryBaseChain;
1403 PrimaryBases.insert(RD);
1404
1405 // Now traverse the base chain, starting with the first base, until we find
1406 // the base that is no longer a primary base.
1407 while (true) {
1408 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
1409 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
1410
1411 if (!PrimaryBase)
1412 break;
1413
1414 if (Layout.isPrimaryBaseVirtual()) {
1415 assert(Layout.getVBaseClassOffset(PrimaryBase).isZero() &&
1416 "Primary base should always be at offset 0!");
1417
1418 const ASTRecordLayout &LayoutClassLayout =
1419 Context.getASTRecordLayout(LayoutClass);
1420
1421 // Now check if this is the primary base that is not a primary base in the
1422 // most derived class.
1423 if (LayoutClassLayout.getVBaseClassOffset(PrimaryBase) !=
1424 FirstBaseOffsetInLayoutClass) {
1425 // We found it, stop walking the chain.
1426 break;
1427 }
1428 } else {
1429 assert(Layout.getBaseClassOffset(PrimaryBase).isZero() &&
1430 "Primary base should always be at offset 0!");
1431 }
1432
1433 if (!PrimaryBases.insert(PrimaryBase))
1434 llvm_unreachable("Found a duplicate primary base!");
1435
1436 RD = PrimaryBase;
1437 }
1438
1439 // If the final overrider is an override of one of the primary bases,
1440 // then we know that it will be used.
1441 return OverridesIndirectMethodInBases(Overrider, PrimaryBases);
1442}
1443
1444typedef llvm::SmallSetVector<const CXXRecordDecl *, 8> BasesSetVectorTy;
1445
1446/// FindNearestOverriddenMethod - Given a method, returns the overridden method
1447/// from the nearest base. Returns null if no method was found.
1448/// The Bases are expected to be sorted in a base-to-derived order.
1449static const CXXMethodDecl *
1450FindNearestOverriddenMethod(const CXXMethodDecl *MD,
1451 BasesSetVectorTy &Bases) {
1452 OverriddenMethodsSetTy OverriddenMethods;
1453 ComputeAllOverriddenMethods(MD, OverriddenMethods);
1454
1455 for (const CXXRecordDecl *PrimaryBase : llvm::reverse(Bases)) {
1456 // Now check the overridden methods.
1457 for (const CXXMethodDecl *OverriddenMD : OverriddenMethods) {
1458 // We found our overridden method.
1459 if (OverriddenMD->getParent() == PrimaryBase)
1460 return OverriddenMD;
1461 }
1462 }
1463
1464 return nullptr;
1465}
1466
1467void ItaniumVTableBuilder::AddMethods(
1468 BaseSubobject Base, CharUnits BaseOffsetInLayoutClass,
1469 const CXXRecordDecl *FirstBaseInPrimaryBaseChain,
1470 CharUnits FirstBaseOffsetInLayoutClass,
1471 PrimaryBasesSetVectorTy &PrimaryBases) {
1472 // Itanium C++ ABI 2.5.2:
1473 // The order of the virtual function pointers in a virtual table is the
1474 // order of declaration of the corresponding member functions in the class.
1475 //
1476 // There is an entry for any virtual function declared in a class,
1477 // whether it is a new function or overrides a base class function,
1478 // unless it overrides a function from the primary base, and conversion
1479 // between their return types does not require an adjustment.
1480
1481 const CXXRecordDecl *RD = Base.getBase();
1482 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
1483
1484 if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
1485 CharUnits PrimaryBaseOffset;
1486 CharUnits PrimaryBaseOffsetInLayoutClass;
1487 if (Layout.isPrimaryBaseVirtual()) {
1488 assert(Layout.getVBaseClassOffset(PrimaryBase).isZero() &&
1489 "Primary vbase should have a zero offset!");
1490
1491 const ASTRecordLayout &MostDerivedClassLayout =
1492 Context.getASTRecordLayout(MostDerivedClass);
1493
1494 PrimaryBaseOffset =
1495 MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase);
1496
1497 const ASTRecordLayout &LayoutClassLayout =
1498 Context.getASTRecordLayout(LayoutClass);
1499
1500 PrimaryBaseOffsetInLayoutClass =
1501 LayoutClassLayout.getVBaseClassOffset(PrimaryBase);
1502 } else {
1503 assert(Layout.getBaseClassOffset(PrimaryBase).isZero() &&
1504 "Primary base should have a zero offset!");
1505
1506 PrimaryBaseOffset = Base.getBaseOffset();
1507 PrimaryBaseOffsetInLayoutClass = BaseOffsetInLayoutClass;
1508 }
1509
1510 AddMethods(BaseSubobject(PrimaryBase, PrimaryBaseOffset),
1511 PrimaryBaseOffsetInLayoutClass, FirstBaseInPrimaryBaseChain,
1512 FirstBaseOffsetInLayoutClass, PrimaryBases);
1513
1514 if (!PrimaryBases.insert(PrimaryBase))
1515 llvm_unreachable("Found a duplicate primary base!");
1516 }
1517
1518 typedef llvm::SmallVector<const CXXMethodDecl *, 8> NewVirtualFunctionsTy;
1519 NewVirtualFunctionsTy NewVirtualFunctions;
1520
1521 llvm::SmallVector<const CXXMethodDecl*, 4> NewImplicitVirtualFunctions;
1522
1523 // Now go through all virtual member functions and add them.
1524 for (const auto *MD : RD->methods()) {
1526 continue;
1527 MD = MD->getCanonicalDecl();
1528
1529 // Get the final overrider.
1530 FinalOverriders::OverriderInfo Overrider =
1531 Overriders.getOverrider(MD, Base.getBaseOffset());
1532
1533 // Check if this virtual member function overrides a method in a primary
1534 // base. If this is the case, and the return type doesn't require adjustment
1535 // then we can just use the member function from the primary base.
1536 if (const CXXMethodDecl *OverriddenMD =
1537 FindNearestOverriddenMethod(MD, PrimaryBases)) {
1538 if (ComputeReturnAdjustmentBaseOffset(Context, MD,
1539 OverriddenMD).isEmpty()) {
1540 VTables.setOriginalMethod(MD, OverriddenMD);
1541
1542 // Replace the method info of the overridden method with our own
1543 // method.
1544 assert(MethodInfoMap.count(OverriddenMD) &&
1545 "Did not find the overridden method!");
1546 MethodInfo &OverriddenMethodInfo = MethodInfoMap[OverriddenMD];
1547
1548 MethodInfo MethodInfo(Base.getBaseOffset(), BaseOffsetInLayoutClass,
1549 OverriddenMethodInfo.VTableIndex);
1550
1551 assert(!MethodInfoMap.count(MD) &&
1552 "Should not have method info for this method yet!");
1553
1554 MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
1555 MethodInfoMap.erase(OverriddenMD);
1556
1557 // If the overridden method exists in a virtual base class or a direct
1558 // or indirect base class of a virtual base class, we need to emit a
1559 // thunk if we ever have a class hierarchy where the base class is not
1560 // a primary base in the complete object.
1561 if (!isBuildingConstructorVTable() && OverriddenMD != MD) {
1562 // Compute the this adjustment.
1564 ComputeThisAdjustment(OverriddenMD, BaseOffsetInLayoutClass,
1565 Overrider);
1566
1568 Overrider.Method->getParent() == MostDerivedClass) {
1569
1570 // There's no return adjustment from OverriddenMD and MD,
1571 // but that doesn't mean there isn't one between MD and
1572 // the final overrider.
1573 BaseOffset ReturnAdjustmentOffset =
1574 ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
1576 ComputeReturnAdjustment(ReturnAdjustmentOffset);
1577
1578 // This is a virtual thunk for the most derived class, add it.
1579 AddThunk(Overrider.Method,
1581 OverriddenMD->getThisType().getTypePtr()));
1582 }
1583 }
1584
1585 continue;
1586 }
1587 }
1588
1589 if (MD->isImplicit())
1590 NewImplicitVirtualFunctions.push_back(MD);
1591 else
1592 NewVirtualFunctions.push_back(MD);
1593 }
1594
1595 llvm::stable_sort(
1596 NewImplicitVirtualFunctions,
1597 [](const CXXMethodDecl *A, const CXXMethodDecl *B) {
1598 if (A == B)
1599 return false;
1601 return A->isCopyAssignmentOperator();
1603 return A->isMoveAssignmentOperator();
1605 return isa<CXXDestructorDecl>(A);
1606 assert(A->getOverloadedOperator() == OO_EqualEqual &&
1607 B->getOverloadedOperator() == OO_EqualEqual &&
1608 "unexpected or duplicate implicit virtual function");
1609 // We rely on Sema to have declared the operator== members in the
1610 // same order as the corresponding operator<=> members.
1611 return false;
1612 });
1613 NewVirtualFunctions.append(NewImplicitVirtualFunctions.begin(),
1614 NewImplicitVirtualFunctions.end());
1615
1616 for (const CXXMethodDecl *MD : NewVirtualFunctions) {
1617 // Get the final overrider.
1618 FinalOverriders::OverriderInfo Overrider =
1619 Overriders.getOverrider(MD, Base.getBaseOffset());
1620
1621 // Insert the method info for this method.
1622 MethodInfo MethodInfo(Base.getBaseOffset(), BaseOffsetInLayoutClass,
1623 Components.size());
1624
1625 assert(!MethodInfoMap.count(MD) &&
1626 "Should not have method info for this method yet!");
1627 MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
1628
1629 // Check if this overrider is going to be used.
1630 const CXXMethodDecl *OverriderMD = Overrider.Method;
1631 if (!IsOverriderUsed(OverriderMD, BaseOffsetInLayoutClass,
1632 FirstBaseInPrimaryBaseChain,
1633 FirstBaseOffsetInLayoutClass)) {
1634 Components.push_back(VTableComponent::MakeUnusedFunction(OverriderMD));
1635 continue;
1636 }
1637
1638 // Check if this overrider needs a return adjustment.
1639 // We don't want to do this for pure virtual member functions.
1640 BaseOffset ReturnAdjustmentOffset;
1641 if (!OverriderMD->isPureVirtual()) {
1642 ReturnAdjustmentOffset =
1643 ComputeReturnAdjustmentBaseOffset(Context, OverriderMD, MD);
1644 }
1645
1647 ComputeReturnAdjustment(ReturnAdjustmentOffset);
1648
1649 // If a return adjustment is required, record the method that created the
1650 // vtable entry. We need to record the method because we cannot call
1651 // findOriginalMethod to find the method that created the entry if the
1652 // method in the entry requires adjustment.
1653 if (!ReturnAdjustment.isEmpty()) {
1654 auto &VTT = VTableThunks[Components.size()];
1655 VTT.Method = MD;
1656 VTT.ThisType = MD->getThisType().getTypePtr();
1657 }
1658
1659 AddMethod(Overrider.Method, ReturnAdjustment);
1660 }
1661}
1662
1663void ItaniumVTableBuilder::LayoutVTable() {
1664 LayoutPrimaryAndSecondaryVTables(BaseSubobject(MostDerivedClass,
1665 CharUnits::Zero()),
1666 /*BaseIsMorallyVirtual=*/false,
1667 MostDerivedClassIsVirtual,
1668 MostDerivedClassOffset);
1669
1670 VisitedVirtualBasesSetTy VBases;
1671
1672 // Determine the primary virtual bases.
1673 DeterminePrimaryVirtualBases(MostDerivedClass, MostDerivedClassOffset,
1674 VBases);
1675 VBases.clear();
1676
1677 LayoutVTablesForVirtualBases(MostDerivedClass, VBases);
1678
1679 // -fapple-kext adds an extra entry at end of vtbl.
1680 bool IsAppleKext = Context.getLangOpts().AppleKext;
1681 if (IsAppleKext)
1682 Components.push_back(VTableComponent::MakeVCallOffset(CharUnits::Zero()));
1683}
1684
1685void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
1686 BaseSubobject Base, bool BaseIsMorallyVirtual,
1687 bool BaseIsVirtualInLayoutClass, CharUnits OffsetInLayoutClass) {
1688 assert(Base.getBase()->isDynamicClass() && "class does not have a vtable!");
1689
1690 unsigned VTableIndex = Components.size();
1691 VTableIndices.push_back(VTableIndex);
1692
1693 // Add vcall and vbase offsets for this vtable.
1694 VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, LayoutClass, &Overriders,
1695 Base, BaseIsVirtualInLayoutClass,
1696 OffsetInLayoutClass);
1697 Components.append(Builder.components_begin(), Builder.components_end());
1698
1699 // Check if we need to add these vcall offsets.
1700 if (BaseIsVirtualInLayoutClass && !Builder.getVCallOffsets().empty()) {
1701 VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Base.getBase()];
1702
1703 if (VCallOffsets.empty())
1704 VCallOffsets = Builder.getVCallOffsets();
1705 }
1706
1707 // If we're laying out the most derived class we want to keep track of the
1708 // virtual base class offset offsets.
1709 if (Base.getBase() == MostDerivedClass)
1710 VBaseOffsetOffsets = Builder.getVBaseOffsetOffsets();
1711
1712 // Add the offset to top.
1713 CharUnits OffsetToTop = MostDerivedClassOffset - OffsetInLayoutClass;
1714 Components.push_back(VTableComponent::MakeOffsetToTop(OffsetToTop));
1715
1716 // Next, add the RTTI.
1717 if (!Context.getLangOpts().OmitVTableRTTI)
1718 Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass));
1719
1720 uint64_t AddressPoint = Components.size();
1721
1722 // Now go through all virtual member functions and add them.
1723 PrimaryBasesSetVectorTy PrimaryBases;
1724 AddMethods(Base, OffsetInLayoutClass,
1725 Base.getBase(), OffsetInLayoutClass,
1726 PrimaryBases);
1727
1728 const CXXRecordDecl *RD = Base.getBase();
1729 if (RD == MostDerivedClass) {
1730 assert(MethodVTableIndices.empty());
1731 for (const auto &I : MethodInfoMap) {
1732 const CXXMethodDecl *MD = I.first;
1733 const MethodInfo &MI = I.second;
1734 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
1735 MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)]
1736 = MI.VTableIndex - AddressPoint;
1737 MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)]
1738 = MI.VTableIndex + 1 - AddressPoint;
1739 } else {
1740 MethodVTableIndices[MD] = MI.VTableIndex - AddressPoint;
1741 }
1742 }
1743 }
1744
1745 // Compute 'this' pointer adjustments.
1746 ComputeThisAdjustments();
1747
1748 // Add all address points.
1749 while (true) {
1750 AddressPoints.insert(
1751 std::make_pair(BaseSubobject(RD, OffsetInLayoutClass),
1753 unsigned(VTableIndices.size() - 1),
1754 unsigned(AddressPoint - VTableIndex)}));
1755
1756 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
1757 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
1758
1759 if (!PrimaryBase)
1760 break;
1761
1762 if (Layout.isPrimaryBaseVirtual()) {
1763 // Check if this virtual primary base is a primary base in the layout
1764 // class. If it's not, we don't want to add it.
1765 const ASTRecordLayout &LayoutClassLayout =
1766 Context.getASTRecordLayout(LayoutClass);
1767
1768 if (LayoutClassLayout.getVBaseClassOffset(PrimaryBase) !=
1769 OffsetInLayoutClass) {
1770 // We don't want to add this class (or any of its primary bases).
1771 break;
1772 }
1773 }
1774
1775 RD = PrimaryBase;
1776 }
1777
1778 // Layout secondary vtables.
1779 LayoutSecondaryVTables(Base, BaseIsMorallyVirtual, OffsetInLayoutClass);
1780}
1781
1782void
1783ItaniumVTableBuilder::LayoutSecondaryVTables(BaseSubobject Base,
1784 bool BaseIsMorallyVirtual,
1785 CharUnits OffsetInLayoutClass) {
1786 // Itanium C++ ABI 2.5.2:
1787 // Following the primary virtual table of a derived class are secondary
1788 // virtual tables for each of its proper base classes, except any primary
1789 // base(s) with which it shares its primary virtual table.
1790
1791 const CXXRecordDecl *RD = Base.getBase();
1792 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
1793 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
1794
1795 for (const auto &B : RD->bases()) {
1796 // Ignore virtual bases, we'll emit them later.
1797 if (B.isVirtual())
1798 continue;
1799
1800 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1801
1802 // Ignore bases that don't have a vtable.
1803 if (!BaseDecl->isDynamicClass())
1804 continue;
1805
1806 if (isBuildingConstructorVTable()) {
1807 // Itanium C++ ABI 2.6.4:
1808 // Some of the base class subobjects may not need construction virtual
1809 // tables, which will therefore not be present in the construction
1810 // virtual table group, even though the subobject virtual tables are
1811 // present in the main virtual table group for the complete object.
1812 if (!BaseIsMorallyVirtual && !BaseDecl->getNumVBases())
1813 continue;
1814 }
1815
1816 // Get the base offset of this base.
1817 CharUnits RelativeBaseOffset = Layout.getBaseClassOffset(BaseDecl);
1818 CharUnits BaseOffset = Base.getBaseOffset() + RelativeBaseOffset;
1819
1820 CharUnits BaseOffsetInLayoutClass =
1821 OffsetInLayoutClass + RelativeBaseOffset;
1822
1823 // Don't emit a secondary vtable for a primary base. We might however want
1824 // to emit secondary vtables for other bases of this base.
1825 if (BaseDecl == PrimaryBase) {
1826 LayoutSecondaryVTables(BaseSubobject(BaseDecl, BaseOffset),
1827 BaseIsMorallyVirtual, BaseOffsetInLayoutClass);
1828 continue;
1829 }
1830
1831 // Layout the primary vtable (and any secondary vtables) for this base.
1832 LayoutPrimaryAndSecondaryVTables(
1833 BaseSubobject(BaseDecl, BaseOffset),
1834 BaseIsMorallyVirtual,
1835 /*BaseIsVirtualInLayoutClass=*/false,
1836 BaseOffsetInLayoutClass);
1837 }
1838}
1839
1840void ItaniumVTableBuilder::DeterminePrimaryVirtualBases(
1841 const CXXRecordDecl *RD, CharUnits OffsetInLayoutClass,
1842 VisitedVirtualBasesSetTy &VBases) {
1843 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
1844
1845 // Check if this base has a primary base.
1846 if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
1847
1848 // Check if it's virtual.
1849 if (Layout.isPrimaryBaseVirtual()) {
1850 bool IsPrimaryVirtualBase = true;
1851
1852 if (isBuildingConstructorVTable()) {
1853 // Check if the base is actually a primary base in the class we use for
1854 // layout.
1855 const ASTRecordLayout &LayoutClassLayout =
1856 Context.getASTRecordLayout(LayoutClass);
1857
1858 CharUnits PrimaryBaseOffsetInLayoutClass =
1859 LayoutClassLayout.getVBaseClassOffset(PrimaryBase);
1860
1861 // We know that the base is not a primary base in the layout class if
1862 // the base offsets are different.
1863 if (PrimaryBaseOffsetInLayoutClass != OffsetInLayoutClass)
1864 IsPrimaryVirtualBase = false;
1865 }
1866
1867 if (IsPrimaryVirtualBase)
1868 PrimaryVirtualBases.insert(PrimaryBase);
1869 }
1870 }
1871
1872 // Traverse bases, looking for more primary virtual bases.
1873 for (const auto &B : RD->bases()) {
1874 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1875
1876 CharUnits BaseOffsetInLayoutClass;
1877
1878 if (B.isVirtual()) {
1879 if (!VBases.insert(BaseDecl).second)
1880 continue;
1881
1882 const ASTRecordLayout &LayoutClassLayout =
1883 Context.getASTRecordLayout(LayoutClass);
1884
1885 BaseOffsetInLayoutClass =
1886 LayoutClassLayout.getVBaseClassOffset(BaseDecl);
1887 } else {
1888 BaseOffsetInLayoutClass =
1889 OffsetInLayoutClass + Layout.getBaseClassOffset(BaseDecl);
1890 }
1891
1892 DeterminePrimaryVirtualBases(BaseDecl, BaseOffsetInLayoutClass, VBases);
1893 }
1894}
1895
1896void ItaniumVTableBuilder::LayoutVTablesForVirtualBases(
1897 const CXXRecordDecl *RD, VisitedVirtualBasesSetTy &VBases) {
1898 // Itanium C++ ABI 2.5.2:
1899 // Then come the virtual base virtual tables, also in inheritance graph
1900 // order, and again excluding primary bases (which share virtual tables with
1901 // the classes for which they are primary).
1902 for (const auto &B : RD->bases()) {
1903 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1904
1905 // Check if this base needs a vtable. (If it's virtual, not a primary base
1906 // of some other class, and we haven't visited it before).
1907 if (B.isVirtual() && BaseDecl->isDynamicClass() &&
1908 !PrimaryVirtualBases.count(BaseDecl) &&
1909 VBases.insert(BaseDecl).second) {
1910 const ASTRecordLayout &MostDerivedClassLayout =
1911 Context.getASTRecordLayout(MostDerivedClass);
1912 CharUnits BaseOffset =
1913 MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
1914
1915 const ASTRecordLayout &LayoutClassLayout =
1916 Context.getASTRecordLayout(LayoutClass);
1917 CharUnits BaseOffsetInLayoutClass =
1918 LayoutClassLayout.getVBaseClassOffset(BaseDecl);
1919
1920 LayoutPrimaryAndSecondaryVTables(
1921 BaseSubobject(BaseDecl, BaseOffset),
1922 /*BaseIsMorallyVirtual=*/true,
1923 /*BaseIsVirtualInLayoutClass=*/true,
1924 BaseOffsetInLayoutClass);
1925 }
1926
1927 // We only need to check the base for virtual base vtables if it actually
1928 // has virtual bases.
1929 if (BaseDecl->getNumVBases())
1930 LayoutVTablesForVirtualBases(BaseDecl, VBases);
1931 }
1932}
1933
1934static void printThunkMethod(const ThunkInfo &Info, raw_ostream &Out) {
1935 if (!Info.Method)
1936 return;
1937 std::string Str = PredefinedExpr::ComputeName(
1939 Out << " method: " << Str;
1940}
1941
1942/// dumpLayout - Dump the vtable layout.
1943void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
1944 // FIXME: write more tests that actually use the dumpLayout output to prevent
1945 // ItaniumVTableBuilder regressions.
1946
1947 Out << "Original map\n";
1948
1949 for (const auto &P : VTables.getOriginalMethodMap()) {
1950 std::string Str0 =
1952 P.first);
1953 std::string Str1 =
1955 P.second);
1956 Out << " " << Str0 << " -> " << Str1 << "\n";
1957 }
1958
1959 if (isBuildingConstructorVTable()) {
1960 Out << "Construction vtable for ('";
1961 MostDerivedClass->printQualifiedName(Out);
1962 Out << "', ";
1963 Out << MostDerivedClassOffset.getQuantity() << ") in '";
1964 LayoutClass->printQualifiedName(Out);
1965 } else {
1966 Out << "Vtable for '";
1967 MostDerivedClass->printQualifiedName(Out);
1968 }
1969 Out << "' (" << Components.size() << " entries).\n";
1970
1971 // Iterate through the address points and insert them into a new map where
1972 // they are keyed by the index and not the base object.
1973 // Since an address point can be shared by multiple subobjects, we use an
1974 // STL multimap.
1975 std::multimap<uint64_t, BaseSubobject> AddressPointsByIndex;
1976 for (const auto &AP : AddressPoints) {
1977 const BaseSubobject &Base = AP.first;
1978 uint64_t Index =
1979 VTableIndices[AP.second.VTableIndex] + AP.second.AddressPointIndex;
1980
1981 AddressPointsByIndex.insert(std::make_pair(Index, Base));
1982 }
1983
1984 for (unsigned I = 0, E = Components.size(); I != E; ++I) {
1985 uint64_t Index = I;
1986
1987 Out << llvm::format("%4d | ", I);
1988
1989 const VTableComponent &Component = Components[I];
1990
1991 // Dump the component.
1992 switch (Component.getKind()) {
1993
1995 Out << "vcall_offset ("
1996 << Component.getVCallOffset().getQuantity()
1997 << ")";
1998 break;
1999
2001 Out << "vbase_offset ("
2002 << Component.getVBaseOffset().getQuantity()
2003 << ")";
2004 break;
2005
2007 Out << "offset_to_top ("
2008 << Component.getOffsetToTop().getQuantity()
2009 << ")";
2010 break;
2011
2013 Component.getRTTIDecl()->printQualifiedName(Out);
2014 Out << " RTTI";
2015 break;
2016
2018 const CXXMethodDecl *MD = Component.getFunctionDecl();
2019
2020 std::string Str = PredefinedExpr::ComputeName(
2022 Out << Str;
2023 if (MD->isPureVirtual())
2024 Out << " [pure]";
2025
2026 if (MD->isDeleted())
2027 Out << " [deleted]";
2028
2029 ThunkInfo Thunk = VTableThunks.lookup(I);
2030 if (!Thunk.isEmpty()) {
2031 // If this function pointer has a return adjustment, dump it.
2032 if (!Thunk.Return.isEmpty()) {
2033 Out << "\n [return adjustment: ";
2034 Out << Thunk.Return.NonVirtual << " non-virtual";
2035
2037 Out << ", " << Thunk.Return.Virtual.Itanium.VBaseOffsetOffset;
2038 Out << " vbase offset offset";
2039 }
2040
2041 Out << ']';
2042 printThunkMethod(Thunk, Out);
2043 }
2044
2045 // If this function pointer has a 'this' pointer adjustment, dump it.
2046 if (!Thunk.This.isEmpty()) {
2047 Out << "\n [this adjustment: ";
2048 Out << Thunk.This.NonVirtual << " non-virtual";
2049
2051 Out << ", " << Thunk.This.Virtual.Itanium.VCallOffsetOffset;
2052 Out << " vcall offset offset";
2053 }
2054
2055 Out << ']';
2056 printThunkMethod(Thunk, Out);
2057 }
2058 }
2059
2060 break;
2061 }
2062
2065 bool IsComplete =
2067
2068 const CXXDestructorDecl *DD = Component.getDestructorDecl();
2069
2070 DD->printQualifiedName(Out);
2071 if (IsComplete)
2072 Out << "() [complete]";
2073 else
2074 Out << "() [deleting]";
2075
2076 if (DD->isPureVirtual())
2077 Out << " [pure]";
2078
2079 ThunkInfo Thunk = VTableThunks.lookup(I);
2080 if (!Thunk.isEmpty()) {
2081 // If this destructor has a 'this' pointer adjustment, dump it.
2082 if (!Thunk.This.isEmpty()) {
2083 Out << "\n [this adjustment: ";
2084 Out << Thunk.This.NonVirtual << " non-virtual";
2085
2087 Out << ", " << Thunk.This.Virtual.Itanium.VCallOffsetOffset;
2088 Out << " vcall offset offset";
2089 }
2090
2091 Out << ']';
2092 }
2093 printThunkMethod(Thunk, Out);
2094 }
2095
2096 break;
2097 }
2098
2100 const CXXMethodDecl *MD = Component.getUnusedFunctionDecl();
2101
2102 std::string Str = PredefinedExpr::ComputeName(
2104 Out << "[unused] " << Str;
2105 if (MD->isPureVirtual())
2106 Out << " [pure]";
2107 }
2108
2109 }
2110
2111 Out << '\n';
2112
2113 // Dump the next address point.
2114 uint64_t NextIndex = Index + 1;
2115 if (unsigned Count = AddressPointsByIndex.count(NextIndex)) {
2116 if (Count == 1) {
2117 const BaseSubobject &Base =
2118 AddressPointsByIndex.find(NextIndex)->second;
2119
2120 Out << " -- (";
2121 Base.getBase()->printQualifiedName(Out);
2122 Out << ", " << Base.getBaseOffset().getQuantity();
2123 Out << ") vtable address --\n";
2124 } else {
2125 CharUnits BaseOffset =
2126 AddressPointsByIndex.lower_bound(NextIndex)->second.getBaseOffset();
2127
2128 // We store the class names in a set to get a stable order.
2129 std::set<std::string> ClassNames;
2130 for (const auto &I :
2131 llvm::make_range(AddressPointsByIndex.equal_range(NextIndex))) {
2132 assert(I.second.getBaseOffset() == BaseOffset &&
2133 "Invalid base offset!");
2134 const CXXRecordDecl *RD = I.second.getBase();
2135 ClassNames.insert(RD->getQualifiedNameAsString());
2136 }
2137
2138 for (const std::string &Name : ClassNames) {
2139 Out << " -- (" << Name;
2140 Out << ", " << BaseOffset.getQuantity() << ") vtable address --\n";
2141 }
2142 }
2143 }
2144 }
2145
2146 Out << '\n';
2147
2148 if (isBuildingConstructorVTable())
2149 return;
2150
2151 if (MostDerivedClass->getNumVBases()) {
2152 // We store the virtual base class names and their offsets in a map to get
2153 // a stable order.
2154
2155 std::map<std::string, CharUnits> ClassNamesAndOffsets;
2156 for (const auto &I : VBaseOffsetOffsets) {
2157 std::string ClassName = I.first->getQualifiedNameAsString();
2158 CharUnits OffsetOffset = I.second;
2159 ClassNamesAndOffsets.insert(std::make_pair(ClassName, OffsetOffset));
2160 }
2161
2162 Out << "Virtual base offset offsets for '";
2163 MostDerivedClass->printQualifiedName(Out);
2164 Out << "' (";
2165 Out << ClassNamesAndOffsets.size();
2166 Out << (ClassNamesAndOffsets.size() == 1 ? " entry" : " entries") << ").\n";
2167
2168 for (const auto &I : ClassNamesAndOffsets)
2169 Out << " " << I.first << " | " << I.second.getQuantity() << '\n';
2170
2171 Out << "\n";
2172 }
2173
2174 if (!Thunks.empty()) {
2175 // We store the method names in a map to get a stable order.
2176 std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
2177
2178 for (const auto &I : Thunks) {
2179 const CXXMethodDecl *MD = I.first;
2180 std::string MethodName = PredefinedExpr::ComputeName(
2182
2183 MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
2184 }
2185
2186 for (const auto &I : MethodNamesAndDecls) {
2187 const std::string &MethodName = I.first;
2188 const CXXMethodDecl *MD = I.second;
2189
2190 ThunkInfoVectorTy ThunksVector = Thunks[MD];
2191 llvm::sort(ThunksVector, [](const ThunkInfo &LHS, const ThunkInfo &RHS) {
2192 return std::tie(LHS.This, LHS.Return) < std::tie(RHS.This, RHS.Return);
2193 });
2194
2195 Out << "Thunks for '" << MethodName << "' (" << ThunksVector.size();
2196 Out << (ThunksVector.size() == 1 ? " entry" : " entries") << ").\n";
2197
2198 for (unsigned I = 0, E = ThunksVector.size(); I != E; ++I) {
2199 const ThunkInfo &Thunk = ThunksVector[I];
2200
2201 Out << llvm::format("%4d | ", I);
2202
2203 // If this function pointer has a return pointer adjustment, dump it.
2204 if (!Thunk.Return.isEmpty()) {
2205 Out << "return adjustment: " << Thunk.Return.NonVirtual;
2206 Out << " non-virtual";
2208 Out << ", " << Thunk.Return.Virtual.Itanium.VBaseOffsetOffset;
2209 Out << " vbase offset offset";
2210 }
2211
2212 if (!Thunk.This.isEmpty())
2213 Out << "\n ";
2214 }
2215
2216 // If this function pointer has a 'this' pointer adjustment, dump it.
2217 if (!Thunk.This.isEmpty()) {
2218 Out << "this adjustment: ";
2219 Out << Thunk.This.NonVirtual << " non-virtual";
2220
2222 Out << ", " << Thunk.This.Virtual.Itanium.VCallOffsetOffset;
2223 Out << " vcall offset offset";
2224 }
2225 }
2226
2227 Out << '\n';
2228 }
2229
2230 Out << '\n';
2231 }
2232 }
2233
2234 // Compute the vtable indices for all the member functions.
2235 // Store them in a map keyed by the index so we'll get a sorted table.
2236 std::map<uint64_t, std::string> IndicesMap;
2237
2238 for (const auto *MD : MostDerivedClass->methods()) {
2239 // We only want virtual member functions.
2241 continue;
2242 MD = MD->getCanonicalDecl();
2243
2244 std::string MethodName = PredefinedExpr::ComputeName(
2246
2247 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
2248 GlobalDecl GD(DD, Dtor_Complete);
2249 assert(MethodVTableIndices.count(GD));
2250 uint64_t VTableIndex = MethodVTableIndices[GD];
2251 IndicesMap[VTableIndex] = MethodName + " [complete]";
2252 IndicesMap[VTableIndex + 1] = MethodName + " [deleting]";
2253 } else {
2254 assert(MethodVTableIndices.count(MD));
2255 IndicesMap[MethodVTableIndices[MD]] = MethodName;
2256 }
2257 }
2258
2259 // Print the vtable indices for all the member functions.
2260 if (!IndicesMap.empty()) {
2261 Out << "VTable indices for '";
2262 MostDerivedClass->printQualifiedName(Out);
2263 Out << "' (" << IndicesMap.size() << " entries).\n";
2264
2265 for (const auto &I : IndicesMap) {
2266 uint64_t VTableIndex = I.first;
2267 const std::string &MethodName = I.second;
2268
2269 Out << llvm::format("%4" PRIu64 " | ", VTableIndex) << MethodName
2270 << '\n';
2271 }
2272 }
2273
2274 Out << '\n';
2275}
2276}
2277
2280 unsigned numVTables) {
2281 VTableLayout::AddressPointsIndexMapTy indexMap(numVTables);
2282
2283 for (auto it = addressPoints.begin(); it != addressPoints.end(); ++it) {
2284 const auto &addressPointLoc = it->second;
2285 unsigned vtableIndex = addressPointLoc.VTableIndex;
2286 unsigned addressPoint = addressPointLoc.AddressPointIndex;
2287 if (indexMap[vtableIndex]) {
2288 // Multiple BaseSubobjects can map to the same AddressPointLocation, but
2289 // every vtable index should have a unique address point.
2290 assert(indexMap[vtableIndex] == addressPoint &&
2291 "Every vtable index should have a unique address point. Found a "
2292 "vtable that has two different address points.");
2293 } else {
2294 indexMap[vtableIndex] = addressPoint;
2295 }
2296 }
2297
2298 // Note that by this point, not all the address may be initialized if the
2299 // AddressPoints map is empty. This is ok if the map isn't needed. See
2300 // MicrosoftVTableContext::computeVTableRelatedInformation() which uses an
2301 // emprt map.
2302 return indexMap;
2303}
2304
2306 ArrayRef<VTableComponent> VTableComponents,
2307 ArrayRef<VTableThunkTy> VTableThunks,
2308 const AddressPointsMapTy &AddressPoints)
2309 : VTableIndices(std::move(VTableIndices)),
2310 VTableComponents(VTableComponents), VTableThunks(VTableThunks),
2311 AddressPoints(AddressPoints),
2312 AddressPointIndices(
2313 MakeAddressPointIndices(AddressPoints, this->VTableIndices.size())) {
2314 assert(!this->VTableIndices.empty() &&
2315 "VTableLayout requires at least one index.");
2316 assert(this->VTableIndices.front() == 0 &&
2317 "VTableLayout requires the first index is 0.");
2318 llvm::sort(this->VTableThunks, [](const VTableLayout::VTableThunkTy &LHS,
2319 const VTableLayout::VTableThunkTy &RHS) {
2320 assert((LHS.first != RHS.first || LHS.second == RHS.second) &&
2321 "Different thunks should have unique indices!");
2322 return LHS.first < RHS.first;
2323 });
2324}
2325
2327
2329 return MD->isVirtual() && !MD->isImmediateFunction();
2330}
2331
2334
2336
2338 GD = GD.getCanonicalDecl();
2339 MethodVTableIndicesTy::iterator I = MethodVTableIndices.find(GD);
2340 if (I != MethodVTableIndices.end())
2341 return I->second;
2342
2343 const CXXRecordDecl *RD = cast<CXXMethodDecl>(GD.getDecl())->getParent();
2344
2345 computeVTableRelatedInformation(RD);
2346
2347 I = MethodVTableIndices.find(GD);
2348 assert(I != MethodVTableIndices.end() && "Did not find index!");
2349 return I->second;
2350}
2351
2354 const CXXRecordDecl *VBase) {
2355 ClassPairTy ClassPair(RD, VBase);
2356
2357 VirtualBaseClassOffsetOffsetsMapTy::iterator I =
2358 VirtualBaseClassOffsetOffsets.find(ClassPair);
2359 if (I != VirtualBaseClassOffsetOffsets.end())
2360 return I->second;
2361
2362 VCallAndVBaseOffsetBuilder Builder(RD, RD, /*Overriders=*/nullptr,
2364 /*BaseIsVirtual=*/false,
2365 /*OffsetInLayoutClass=*/CharUnits::Zero());
2366
2367 for (const auto &I : Builder.getVBaseOffsetOffsets()) {
2368 // Insert all types.
2369 ClassPairTy ClassPair(RD, I.first);
2370
2371 VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second));
2372 }
2373
2374 I = VirtualBaseClassOffsetOffsets.find(ClassPair);
2375 assert(I != VirtualBaseClassOffsetOffsets.end() && "Did not find index!");
2376
2377 return I->second;
2378}
2379
2381 const auto *MD = cast<CXXMethodDecl>(GD.getDecl());
2382 computeVTableRelatedInformation(MD->getParent());
2383 const CXXMethodDecl *OriginalMD = findOriginalMethodInMap(MD);
2384
2385 if (const auto *DD = dyn_cast<CXXDestructorDecl>(OriginalMD))
2386 return GlobalDecl(DD, GD.getDtorType());
2387 return OriginalMD;
2388}
2389
2390const CXXMethodDecl *
2392 // Traverse the chain of virtual methods until we find the method that added
2393 // the v-table slot.
2394 while (true) {
2395 auto I = OriginalMethodMap.find(MD);
2396
2397 // MD doesn't exist in OriginalMethodMap, so it must be the method we are
2398 // looking for.
2399 if (I == OriginalMethodMap.end())
2400 break;
2401
2402 // Set MD to the overridden method.
2403 MD = I->second;
2404 }
2405
2406 return MD;
2407}
2408
2409static std::unique_ptr<VTableLayout>
2410CreateVTableLayout(const ItaniumVTableBuilder &Builder) {
2412 VTableThunks(Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
2413
2414 return std::make_unique<VTableLayout>(
2415 Builder.VTableIndices, Builder.vtable_components(), VTableThunks,
2416 Builder.getAddressPoints());
2417}
2418
2419void
2420ItaniumVTableContext::computeVTableRelatedInformation(const CXXRecordDecl *RD) {
2421 std::unique_ptr<const VTableLayout> &Entry = VTableLayouts[RD];
2422
2423 // Check if we've computed this information before.
2424 if (Entry)
2425 return;
2426
2427 ItaniumVTableBuilder Builder(*this, RD, CharUnits::Zero(),
2428 /*MostDerivedClassIsVirtual=*/false, RD);
2429 Entry = CreateVTableLayout(Builder);
2430
2431 MethodVTableIndices.insert(Builder.vtable_indices_begin(),
2432 Builder.vtable_indices_end());
2433
2434 // Add the known thunks.
2435 Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
2436
2437 // If we don't have the vbase information for this class, insert it.
2438 // getVirtualBaseOffsetOffset will compute it separately without computing
2439 // the rest of the vtable related information.
2440 if (!RD->getNumVBases())
2441 return;
2442
2443 const CXXRecordDecl *VBase =
2445
2446 if (VirtualBaseClassOffsetOffsets.count(std::make_pair(RD, VBase)))
2447 return;
2448
2449 for (const auto &I : Builder.getVBaseOffsetOffsets()) {
2450 // Insert all types.
2451 ClassPairTy ClassPair(RD, I.first);
2452
2453 VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second));
2454 }
2455}
2456
2457std::unique_ptr<VTableLayout>
2459 const CXXRecordDecl *MostDerivedClass, CharUnits MostDerivedClassOffset,
2460 bool MostDerivedClassIsVirtual, const CXXRecordDecl *LayoutClass) {
2461 ItaniumVTableBuilder Builder(*this, MostDerivedClass, MostDerivedClassOffset,
2462 MostDerivedClassIsVirtual, LayoutClass);
2463 return CreateVTableLayout(Builder);
2464}
2465
2466namespace {
2467
2468// Vtables in the Microsoft ABI are different from the Itanium ABI.
2469//
2470// The main differences are:
2471// 1. Separate vftable and vbtable.
2472//
2473// 2. Each subobject with a vfptr gets its own vftable rather than an address
2474// point in a single vtable shared between all the subobjects.
2475// Each vftable is represented by a separate section and virtual calls
2476// must be done using the vftable which has a slot for the function to be
2477// called.
2478//
2479// 3. Virtual method definitions expect their 'this' parameter to point to the
2480// first vfptr whose table provides a compatible overridden method. In many
2481// cases, this permits the original vf-table entry to directly call
2482// the method instead of passing through a thunk.
2483// See example before VFTableBuilder::ComputeThisOffset below.
2484//
2485// A compatible overridden method is one which does not have a non-trivial
2486// covariant-return adjustment.
2487//
2488// The first vfptr is the one with the lowest offset in the complete-object
2489// layout of the defining class, and the method definition will subtract
2490// that constant offset from the parameter value to get the real 'this'
2491// value. Therefore, if the offset isn't really constant (e.g. if a virtual
2492// function defined in a virtual base is overridden in a more derived
2493// virtual base and these bases have a reverse order in the complete
2494// object), the vf-table may require a this-adjustment thunk.
2495//
2496// 4. vftables do not contain new entries for overrides that merely require
2497// this-adjustment. Together with #3, this keeps vf-tables smaller and
2498// eliminates the need for this-adjustment thunks in many cases, at the cost
2499// of often requiring redundant work to adjust the "this" pointer.
2500//
2501// 5. Instead of VTT and constructor vtables, vbtables and vtordisps are used.
2502// Vtordisps are emitted into the class layout if a class has
2503// a) a user-defined ctor/dtor
2504// and
2505// b) a method overriding a method in a virtual base.
2506//
2507// To get a better understanding of this code,
2508// you might want to see examples in test/CodeGenCXX/microsoft-abi-vtables-*.cpp
2509
2510class VFTableBuilder {
2511public:
2512 typedef llvm::DenseMap<GlobalDecl, MethodVFTableLocation>
2513 MethodVFTableLocationsTy;
2514
2515 typedef llvm::iterator_range<MethodVFTableLocationsTy::const_iterator>
2516 method_locations_range;
2517
2518private:
2519 /// VTables - Global vtable information.
2520 MicrosoftVTableContext &VTables;
2521
2522 /// Context - The ASTContext which we will use for layout information.
2523 ASTContext &Context;
2524
2525 /// MostDerivedClass - The most derived class for which we're building this
2526 /// vtable.
2527 const CXXRecordDecl *MostDerivedClass;
2528
2529 const ASTRecordLayout &MostDerivedClassLayout;
2530
2531 const VPtrInfo &WhichVFPtr;
2532
2533 /// FinalOverriders - The final overriders of the most derived class.
2534 const FinalOverriders Overriders;
2535
2536 /// Components - The components of the vftable being built.
2538
2539 MethodVFTableLocationsTy MethodVFTableLocations;
2540
2541 /// Does this class have an RTTI component?
2542 bool HasRTTIComponent = false;
2543
2544 /// MethodInfo - Contains information about a method in a vtable.
2545 /// (Used for computing 'this' pointer adjustment thunks.
2546 struct MethodInfo {
2547 /// VBTableIndex - The nonzero index in the vbtable that
2548 /// this method's base has, or zero.
2549 const uint64_t VBTableIndex;
2550
2551 /// VFTableIndex - The index in the vftable that this method has.
2552 const uint64_t VFTableIndex;
2553
2554 /// Shadowed - Indicates if this vftable slot is shadowed by
2555 /// a slot for a covariant-return override. If so, it shouldn't be printed
2556 /// or used for vcalls in the most derived class.
2557 bool Shadowed;
2558
2559 /// UsesExtraSlot - Indicates if this vftable slot was created because
2560 /// any of the overridden slots required a return adjusting thunk.
2561 bool UsesExtraSlot;
2562
2563 MethodInfo(uint64_t VBTableIndex, uint64_t VFTableIndex,
2564 bool UsesExtraSlot = false)
2565 : VBTableIndex(VBTableIndex), VFTableIndex(VFTableIndex),
2566 Shadowed(false), UsesExtraSlot(UsesExtraSlot) {}
2567
2568 MethodInfo()
2569 : VBTableIndex(0), VFTableIndex(0), Shadowed(false),
2570 UsesExtraSlot(false) {}
2571 };
2572
2573 typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
2574
2575 /// MethodInfoMap - The information for all methods in the vftable we're
2576 /// currently building.
2577 MethodInfoMapTy MethodInfoMap;
2578
2579 typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
2580
2581 /// VTableThunks - The thunks by vftable index in the vftable currently being
2582 /// built.
2583 VTableThunksMapTy VTableThunks;
2584
2585 typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy;
2586 typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
2587
2588 /// Thunks - A map that contains all the thunks needed for all methods in the
2589 /// most derived class for which the vftable is currently being built.
2590 ThunksMapTy Thunks;
2591
2592 /// AddThunk - Add a thunk for the given method.
2593 void AddThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk) {
2594 SmallVector<ThunkInfo, 1> &ThunksVector = Thunks[MD];
2595
2596 // Check if we have this thunk already.
2597 if (llvm::is_contained(ThunksVector, Thunk))
2598 return;
2599
2600 ThunksVector.push_back(Thunk);
2601 }
2602
2603 /// ComputeThisOffset - Returns the 'this' argument offset for the given
2604 /// method, relative to the beginning of the MostDerivedClass.
2605 CharUnits ComputeThisOffset(FinalOverriders::OverriderInfo Overrider);
2606
2607 void CalculateVtordispAdjustment(FinalOverriders::OverriderInfo Overrider,
2608 CharUnits ThisOffset, ThisAdjustment &TA);
2609
2610 /// AddMethod - Add a single virtual member function to the vftable
2611 /// components vector.
2612 void AddMethod(const CXXMethodDecl *MD, ThunkInfo TI) {
2613 if (!TI.isEmpty()) {
2614 VTableThunks[Components.size()] = TI;
2615 AddThunk(MD, TI);
2616 }
2617 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
2618 assert(TI.Return.isEmpty() &&
2619 "Destructor can't have return adjustment!");
2620 Components.push_back(VTableComponent::MakeDeletingDtor(DD));
2621 } else {
2622 Components.push_back(VTableComponent::MakeFunction(MD));
2623 }
2624 }
2625
2626 /// AddMethods - Add the methods of this base subobject and the relevant
2627 /// subbases to the vftable we're currently laying out.
2628 void AddMethods(BaseSubobject Base, unsigned BaseDepth,
2629 const CXXRecordDecl *LastVBase,
2630 BasesSetVectorTy &VisitedBases);
2631
2632 void LayoutVFTable() {
2633 // RTTI data goes before all other entries.
2634 if (HasRTTIComponent)
2635 Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass));
2636
2637 BasesSetVectorTy VisitedBases;
2638 AddMethods(BaseSubobject(MostDerivedClass, CharUnits::Zero()), 0, nullptr,
2639 VisitedBases);
2640 // Note that it is possible for the vftable to contain only an RTTI
2641 // pointer, if all virtual functions are constewval.
2642 assert(!Components.empty() && "vftable can't be empty");
2643
2644 assert(MethodVFTableLocations.empty());
2645 for (const auto &I : MethodInfoMap) {
2646 const CXXMethodDecl *MD = I.first;
2647 const MethodInfo &MI = I.second;
2648 assert(MD == MD->getCanonicalDecl());
2649
2650 // Skip the methods that the MostDerivedClass didn't override
2651 // and the entries shadowed by return adjusting thunks.
2652 if (MD->getParent() != MostDerivedClass || MI.Shadowed)
2653 continue;
2654 MethodVFTableLocation Loc(MI.VBTableIndex, WhichVFPtr.getVBaseWithVPtr(),
2655 WhichVFPtr.NonVirtualOffset, MI.VFTableIndex);
2656 if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
2657 // In Microsoft ABI vftable always references vector deleting dtor.
2659 Context.getLangOpts())
2661 : Dtor_Deleting;
2662 MethodVFTableLocations[GlobalDecl(DD, DtorTy)] = Loc;
2663 } else {
2664 MethodVFTableLocations[MD] = Loc;
2665 }
2666 }
2667 }
2668
2669public:
2670 VFTableBuilder(MicrosoftVTableContext &VTables,
2671 const CXXRecordDecl *MostDerivedClass, const VPtrInfo &Which)
2672 : VTables(VTables),
2673 Context(MostDerivedClass->getASTContext()),
2674 MostDerivedClass(MostDerivedClass),
2675 MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)),
2676 WhichVFPtr(Which),
2677 Overriders(MostDerivedClass, CharUnits(), MostDerivedClass) {
2678 // Provide the RTTI component if RTTIData is enabled. If the vftable would
2679 // be available externally, we should not provide the RTTI componenent. It
2680 // is currently impossible to get available externally vftables with either
2681 // dllimport or extern template instantiations, but eventually we may add a
2682 // flag to support additional devirtualization that needs this.
2683 if (Context.getLangOpts().RTTIData)
2684 HasRTTIComponent = true;
2685
2686 LayoutVFTable();
2687
2688 if (Context.getLangOpts().DumpVTableLayouts)
2689 dumpLayout(llvm::outs());
2690 }
2691
2692 uint64_t getNumThunks() const { return Thunks.size(); }
2693
2694 ThunksMapTy::const_iterator thunks_begin() const { return Thunks.begin(); }
2695
2696 ThunksMapTy::const_iterator thunks_end() const { return Thunks.end(); }
2697
2698 method_locations_range vtable_locations() const {
2699 return method_locations_range(MethodVFTableLocations.begin(),
2700 MethodVFTableLocations.end());
2701 }
2702
2703 ArrayRef<VTableComponent> vtable_components() const { return Components; }
2704
2705 VTableThunksMapTy::const_iterator vtable_thunks_begin() const {
2706 return VTableThunks.begin();
2707 }
2708
2709 VTableThunksMapTy::const_iterator vtable_thunks_end() const {
2710 return VTableThunks.end();
2711 }
2712
2713 void dumpLayout(raw_ostream &);
2714};
2715
2716} // end namespace
2717
2718// Let's study one class hierarchy as an example:
2719// struct A {
2720// virtual void f();
2721// int x;
2722// };
2723//
2724// struct B : virtual A {
2725// virtual void f();
2726// };
2727//
2728// Record layouts:
2729// struct A:
2730// 0 | (A vftable pointer)
2731// 4 | int x
2732//
2733// struct B:
2734// 0 | (B vbtable pointer)
2735// 4 | struct A (virtual base)
2736// 4 | (A vftable pointer)
2737// 8 | int x
2738//
2739// Let's assume we have a pointer to the A part of an object of dynamic type B:
2740// B b;
2741// A *a = (A*)&b;
2742// a->f();
2743//
2744// In this hierarchy, f() belongs to the vftable of A, so B::f() expects
2745// "this" parameter to point at the A subobject, which is B+4.
2746// In the B::f() prologue, it adjusts "this" back to B by subtracting 4,
2747// performed as a *static* adjustment.
2748//
2749// Interesting thing happens when we alter the relative placement of A and B
2750// subobjects in a class:
2751// struct C : virtual B { };
2752//
2753// C c;
2754// A *a = (A*)&c;
2755// a->f();
2756//
2757// Respective record layout is:
2758// 0 | (C vbtable pointer)
2759// 4 | struct A (virtual base)
2760// 4 | (A vftable pointer)
2761// 8 | int x
2762// 12 | struct B (virtual base)
2763// 12 | (B vbtable pointer)
2764//
2765// The final overrider of f() in class C is still B::f(), so B+4 should be
2766// passed as "this" to that code. However, "a" points at B-8, so the respective
2767// vftable entry should hold a thunk that adds 12 to the "this" argument before
2768// performing a tail call to B::f().
2769//
2770// With this example in mind, we can now calculate the 'this' argument offset
2771// for the given method, relative to the beginning of the MostDerivedClass.
2773VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) {
2774 BasesSetVectorTy Bases;
2775
2776 {
2777 // Find the set of least derived bases that define the given method.
2778 OverriddenMethodsSetTy VisitedOverriddenMethods;
2779 auto InitialOverriddenDefinitionCollector = [&](
2780 const CXXMethodDecl *OverriddenMD) {
2781 if (OverriddenMD->size_overridden_methods() == 0)
2782 Bases.insert(OverriddenMD->getParent());
2783 // Don't recurse on this method if we've already collected it.
2784 return VisitedOverriddenMethods.insert(OverriddenMD).second;
2785 };
2786 visitAllOverriddenMethods(Overrider.Method,
2787 InitialOverriddenDefinitionCollector);
2788 }
2789
2790 // If there are no overrides then 'this' is located
2791 // in the base that defines the method.
2792 if (Bases.size() == 0)
2793 return Overrider.Offset;
2794
2795 CXXBasePaths Paths;
2796 Overrider.Method->getParent()->lookupInBases(
2797 [&Bases](const CXXBaseSpecifier *Specifier, CXXBasePath &) {
2798 return Bases.count(Specifier->getType()->getAsCXXRecordDecl());
2799 },
2800 Paths);
2801
2802 // This will hold the smallest this offset among overridees of MD.
2803 // This implies that an offset of a non-virtual base will dominate an offset
2804 // of a virtual base to potentially reduce the number of thunks required
2805 // in the derived classes that inherit this method.
2806 CharUnits Ret;
2807 bool First = true;
2808
2809 const ASTRecordLayout &OverriderRDLayout =
2810 Context.getASTRecordLayout(Overrider.Method->getParent());
2811 for (const CXXBasePath &Path : Paths) {
2812 CharUnits ThisOffset = Overrider.Offset;
2813 CharUnits LastVBaseOffset;
2814
2815 // For each path from the overrider to the parents of the overridden
2816 // methods, traverse the path, calculating the this offset in the most
2817 // derived class.
2818 for (const CXXBasePathElement &Element : Path) {
2819 QualType CurTy = Element.Base->getType();
2820 const CXXRecordDecl *PrevRD = Element.Class,
2821 *CurRD = CurTy->getAsCXXRecordDecl();
2822 const ASTRecordLayout &Layout = Context.getASTRecordLayout(PrevRD);
2823
2824 if (Element.Base->isVirtual()) {
2825 // The interesting things begin when you have virtual inheritance.
2826 // The final overrider will use a static adjustment equal to the offset
2827 // of the vbase in the final overrider class.
2828 // For example, if the final overrider is in a vbase B of the most
2829 // derived class and it overrides a method of the B's own vbase A,
2830 // it uses A* as "this". In its prologue, it can cast A* to B* with
2831 // a static offset. This offset is used regardless of the actual
2832 // offset of A from B in the most derived class, requiring an
2833 // this-adjusting thunk in the vftable if A and B are laid out
2834 // differently in the most derived class.
2835 LastVBaseOffset = ThisOffset =
2836 Overrider.Offset + OverriderRDLayout.getVBaseClassOffset(CurRD);
2837 } else {
2838 ThisOffset += Layout.getBaseClassOffset(CurRD);
2839 }
2840 }
2841
2842 if (isa<CXXDestructorDecl>(Overrider.Method)) {
2843 if (LastVBaseOffset.isZero()) {
2844 // If a "Base" class has at least one non-virtual base with a virtual
2845 // destructor, the "Base" virtual destructor will take the address
2846 // of the "Base" subobject as the "this" argument.
2847 ThisOffset = Overrider.Offset;
2848 } else {
2849 // A virtual destructor of a virtual base takes the address of the
2850 // virtual base subobject as the "this" argument.
2851 ThisOffset = LastVBaseOffset;
2852 }
2853 }
2854
2855 if (Ret > ThisOffset || First) {
2856 First = false;
2857 Ret = ThisOffset;
2858 }
2859 }
2860
2861 assert(!First && "Method not found in the given subobject?");
2862 return Ret;
2863}
2864
2865// Things are getting even more complex when the "this" adjustment has to
2866// use a dynamic offset instead of a static one, or even two dynamic offsets.
2867// This is sometimes required when a virtual call happens in the middle of
2868// a non-most-derived class construction or destruction.
2869//
2870// Let's take a look at the following example:
2871// struct A {
2872// virtual void f();
2873// };
2874//
2875// void foo(A *a) { a->f(); } // Knows nothing about siblings of A.
2876//
2877// struct B : virtual A {
2878// virtual void f();
2879// B() {
2880// foo(this);
2881// }
2882// };
2883//
2884// struct C : virtual B {
2885// virtual void f();
2886// };
2887//
2888// Record layouts for these classes are:
2889// struct A
2890// 0 | (A vftable pointer)
2891//
2892// struct B
2893// 0 | (B vbtable pointer)
2894// 4 | (vtordisp for vbase A)
2895// 8 | struct A (virtual base)
2896// 8 | (A vftable pointer)
2897//
2898// struct C
2899// 0 | (C vbtable pointer)
2900// 4 | (vtordisp for vbase A)
2901// 8 | struct A (virtual base) // A precedes B!
2902// 8 | (A vftable pointer)
2903// 12 | struct B (virtual base)
2904// 12 | (B vbtable pointer)
2905//
2906// When one creates an object of type C, the C constructor:
2907// - initializes all the vbptrs, then
2908// - calls the A subobject constructor
2909// (initializes A's vfptr with an address of A vftable), then
2910// - calls the B subobject constructor
2911// (initializes A's vfptr with an address of B vftable and vtordisp for A),
2912// that in turn calls foo(), then
2913// - initializes A's vfptr with an address of C vftable and zeroes out the
2914// vtordisp
2915// FIXME: if a structor knows it belongs to MDC, why doesn't it use a vftable
2916// without vtordisp thunks?
2917// FIXME: how are vtordisp handled in the presence of nooverride/final?
2918//
2919// When foo() is called, an object with a layout of class C has a vftable
2920// referencing B::f() that assumes a B layout, so the "this" adjustments are
2921// incorrect, unless an extra adjustment is done. This adjustment is called
2922// "vtordisp adjustment". Vtordisp basically holds the difference between the
2923// actual location of a vbase in the layout class and the location assumed by
2924// the vftable of the class being constructed/destructed. Vtordisp is only
2925// needed if "this" escapes a
2926// structor (or we can't prove otherwise).
2927// [i.e. vtordisp is a dynamic adjustment for a static adjustment, which is an
2928// estimation of a dynamic adjustment]
2929//
2930// foo() gets a pointer to the A vbase and doesn't know anything about B or C,
2931// so it just passes that pointer as "this" in a virtual call.
2932// If there was no vtordisp, that would just dispatch to B::f().
2933// However, B::f() assumes B+8 is passed as "this",
2934// yet the pointer foo() passes along is B-4 (i.e. C+8).
2935// An extra adjustment is needed, so we emit a thunk into the B vftable.
2936// This vtordisp thunk subtracts the value of vtordisp
2937// from the "this" argument (-12) before making a tailcall to B::f().
2938//
2939// Let's consider an even more complex example:
2940// struct D : virtual B, virtual C {
2941// D() {
2942// foo(this);
2943// }
2944// };
2945//
2946// struct D
2947// 0 | (D vbtable pointer)
2948// 4 | (vtordisp for vbase A)
2949// 8 | struct A (virtual base) // A precedes both B and C!
2950// 8 | (A vftable pointer)
2951// 12 | struct B (virtual base) // B precedes C!
2952// 12 | (B vbtable pointer)
2953// 16 | struct C (virtual base)
2954// 16 | (C vbtable pointer)
2955//
2956// When D::D() calls foo(), we find ourselves in a thunk that should tailcall
2957// to C::f(), which assumes C+8 as its "this" parameter. This time, foo()
2958// passes along A, which is C-8. The A vtordisp holds
2959// "D.vbptr[index_of_A] - offset_of_A_in_D"
2960// and we statically know offset_of_A_in_D, so can get a pointer to D.
2961// When we know it, we can make an extra vbtable lookup to locate the C vbase
2962// and one extra static adjustment to calculate the expected value of C+8.
2963void VFTableBuilder::CalculateVtordispAdjustment(
2964 FinalOverriders::OverriderInfo Overrider, CharUnits ThisOffset,
2965 ThisAdjustment &TA) {
2966 const ASTRecordLayout::VBaseOffsetsMapTy &VBaseMap =
2967 MostDerivedClassLayout.getVBaseOffsetsMap();
2968 const ASTRecordLayout::VBaseOffsetsMapTy::const_iterator &VBaseMapEntry =
2969 VBaseMap.find(WhichVFPtr.getVBaseWithVPtr());
2970 assert(VBaseMapEntry != VBaseMap.end());
2971
2972 // If there's no vtordisp or the final overrider is defined in the same vbase
2973 // as the initial declaration, we don't need any vtordisp adjustment.
2974 if (!VBaseMapEntry->second.hasVtorDisp() ||
2975 Overrider.VirtualBase == WhichVFPtr.getVBaseWithVPtr())
2976 return;
2977
2978 // OK, now we know we need to use a vtordisp thunk.
2979 // The implicit vtordisp field is located right before the vbase.
2980 CharUnits OffsetOfVBaseWithVFPtr = VBaseMapEntry->second.VBaseOffset;
2982 (OffsetOfVBaseWithVFPtr - WhichVFPtr.FullOffsetInMDC).getQuantity() - 4;
2983
2984 // A simple vtordisp thunk will suffice if the final overrider is defined
2985 // in either the most derived class or its non-virtual base.
2986 if (Overrider.Method->getParent() == MostDerivedClass ||
2987 !Overrider.VirtualBase)
2988 return;
2989
2990 // Otherwise, we need to do use the dynamic offset of the final overrider
2991 // in order to get "this" adjustment right.
2993 (OffsetOfVBaseWithVFPtr + WhichVFPtr.NonVirtualOffset -
2994 MostDerivedClassLayout.getVBPtrOffset()).getQuantity();
2996 Context.getTypeSizeInChars(Context.IntTy).getQuantity() *
2997 VTables.getVBTableIndex(MostDerivedClass, Overrider.VirtualBase);
2998
2999 TA.NonVirtual = (ThisOffset - Overrider.Offset).getQuantity();
3000}
3001
3003 const CXXRecordDecl *RD,
3005 // Put the virtual methods into VirtualMethods in the proper order:
3006 // 1) Group overloads by declaration name. New groups are added to the
3007 // vftable in the order of their first declarations in this class
3008 // (including overrides, non-virtual methods and any other named decl that
3009 // might be nested within the class).
3010 // 2) In each group, new overloads appear in the reverse order of declaration.
3011 typedef SmallVector<const CXXMethodDecl *, 1> MethodGroup;
3013 typedef llvm::DenseMap<DeclarationName, unsigned> VisitedGroupIndicesTy;
3014 VisitedGroupIndicesTy VisitedGroupIndices;
3015 for (const auto *D : RD->decls()) {
3016 const auto *ND = dyn_cast<NamedDecl>(D);
3017 if (!ND)
3018 continue;
3019 VisitedGroupIndicesTy::iterator J;
3020 bool Inserted;
3021 std::tie(J, Inserted) = VisitedGroupIndices.insert(
3022 std::make_pair(ND->getDeclName(), Groups.size()));
3023 if (Inserted)
3024 Groups.push_back(MethodGroup());
3025 if (const auto *MD = dyn_cast<CXXMethodDecl>(ND))
3027 Groups[J->second].push_back(MD->getCanonicalDecl());
3028 }
3029
3030 for (const MethodGroup &Group : Groups)
3031 VirtualMethods.append(Group.rbegin(), Group.rend());
3032}
3033
3034static bool isDirectVBase(const CXXRecordDecl *Base, const CXXRecordDecl *RD) {
3035 for (const auto &B : RD->bases()) {
3036 if (B.isVirtual() && B.getType()->getAsCXXRecordDecl() == Base)
3037 return true;
3038 }
3039 return false;
3040}
3041
3042void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
3043 const CXXRecordDecl *LastVBase,
3044 BasesSetVectorTy &VisitedBases) {
3045 const CXXRecordDecl *RD = Base.getBase();
3046 if (!RD->isPolymorphic())
3047 return;
3048
3049 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
3050
3051 // See if this class expands a vftable of the base we look at, which is either
3052 // the one defined by the vfptr base path or the primary base of the current
3053 // class.
3054 const CXXRecordDecl *NextBase = nullptr, *NextLastVBase = LastVBase;
3055 CharUnits NextBaseOffset;
3056 if (BaseDepth < WhichVFPtr.PathToIntroducingObject.size()) {
3057 NextBase = WhichVFPtr.PathToIntroducingObject[BaseDepth];
3058 if (isDirectVBase(NextBase, RD)) {
3059 NextLastVBase = NextBase;
3060 NextBaseOffset = MostDerivedClassLayout.getVBaseClassOffset(NextBase);
3061 } else {
3062 NextBaseOffset =
3063 Base.getBaseOffset() + Layout.getBaseClassOffset(NextBase);
3064 }
3065 } else if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
3066 assert(!Layout.isPrimaryBaseVirtual() &&
3067 "No primary virtual bases in this ABI");
3068 NextBase = PrimaryBase;
3069 NextBaseOffset = Base.getBaseOffset();
3070 }
3071
3072 if (NextBase) {
3073 AddMethods(BaseSubobject(NextBase, NextBaseOffset), BaseDepth + 1,
3074 NextLastVBase, VisitedBases);
3075 if (!VisitedBases.insert(NextBase))
3076 llvm_unreachable("Found a duplicate primary base!");
3077 }
3078
3080 // Put virtual methods in the proper order.
3081 GroupNewVirtualOverloads(RD, VirtualMethods);
3082
3083 // Now go through all virtual member functions and add them to the current
3084 // vftable. This is done by
3085 // - replacing overridden methods in their existing slots, as long as they
3086 // don't require return adjustment; calculating This adjustment if needed.
3087 // - adding new slots for methods of the current base not present in any
3088 // sub-bases;
3089 // - adding new slots for methods that require Return adjustment.
3090 // We keep track of the methods visited in the sub-bases in MethodInfoMap.
3091 for (const CXXMethodDecl *MD : VirtualMethods) {
3092 FinalOverriders::OverriderInfo FinalOverrider =
3093 Overriders.getOverrider(MD, Base.getBaseOffset());
3094 const CXXMethodDecl *FinalOverriderMD = FinalOverrider.Method;
3095 const CXXMethodDecl *OverriddenMD =
3096 FindNearestOverriddenMethod(MD, VisitedBases);
3097
3098 ThisAdjustment ThisAdjustmentOffset;
3099 bool ReturnAdjustingThunk = false, ForceReturnAdjustmentMangling = false;
3100 CharUnits ThisOffset = ComputeThisOffset(FinalOverrider);
3101 ThisAdjustmentOffset.NonVirtual =
3102 (ThisOffset - WhichVFPtr.FullOffsetInMDC).getQuantity();
3103 if ((OverriddenMD || FinalOverriderMD != MD) &&
3104 WhichVFPtr.getVBaseWithVPtr())
3105 CalculateVtordispAdjustment(FinalOverrider, ThisOffset,
3106 ThisAdjustmentOffset);
3107
3108 unsigned VBIndex =
3109 LastVBase ? VTables.getVBTableIndex(MostDerivedClass, LastVBase) : 0;
3110
3111 if (OverriddenMD) {
3112 // If MD overrides anything in this vftable, we need to update the
3113 // entries.
3114 MethodInfoMapTy::iterator OverriddenMDIterator =
3115 MethodInfoMap.find(OverriddenMD);
3116
3117 // If the overridden method went to a different vftable, skip it.
3118 if (OverriddenMDIterator == MethodInfoMap.end())
3119 continue;
3120
3121 MethodInfo &OverriddenMethodInfo = OverriddenMDIterator->second;
3122
3123 VBIndex = OverriddenMethodInfo.VBTableIndex;
3124
3125 // Let's check if the overrider requires any return adjustments.
3126 // We must create a new slot if the MD's return type is not trivially
3127 // convertible to the OverriddenMD's one.
3128 // Once a chain of method overrides adds a return adjusting vftable slot,
3129 // all subsequent overrides will also use an extra method slot.
3130 ReturnAdjustingThunk = !ComputeReturnAdjustmentBaseOffset(
3131 Context, MD, OverriddenMD).isEmpty() ||
3132 OverriddenMethodInfo.UsesExtraSlot;
3133
3134 if (!ReturnAdjustingThunk) {
3135 // No return adjustment needed - just replace the overridden method info
3136 // with the current info.
3137 MethodInfo MI(VBIndex, OverriddenMethodInfo.VFTableIndex);
3138 MethodInfoMap.erase(OverriddenMDIterator);
3139
3140 assert(!MethodInfoMap.count(MD) &&
3141 "Should not have method info for this method yet!");
3142 MethodInfoMap.insert(std::make_pair(MD, MI));
3143 continue;
3144 }
3145
3146 // In case we need a return adjustment, we'll add a new slot for
3147 // the overrider. Mark the overridden method as shadowed by the new slot.
3148 OverriddenMethodInfo.Shadowed = true;
3149
3150 // Force a special name mangling for a return-adjusting thunk
3151 // unless the method is the final overrider without this adjustment.
3152 ForceReturnAdjustmentMangling =
3153 !(MD == FinalOverriderMD && ThisAdjustmentOffset.isEmpty());
3154 } else if (Base.getBaseOffset() != WhichVFPtr.FullOffsetInMDC ||
3156 // Skip methods that don't belong to the vftable of the current class,
3157 // e.g. each method that wasn't seen in any of the visited sub-bases
3158 // but overrides multiple methods of other sub-bases.
3159 continue;
3160 }
3161
3162 // If we got here, MD is a method not seen in any of the sub-bases or
3163 // it requires return adjustment. Insert the method info for this method.
3164 MethodInfo MI(VBIndex,
3165 HasRTTIComponent ? Components.size() - 1 : Components.size(),
3166 ReturnAdjustingThunk);
3167
3168 assert(!MethodInfoMap.count(MD) &&
3169 "Should not have method info for this method yet!");
3170 MethodInfoMap.insert(std::make_pair(MD, MI));
3171
3172 // Check if this overrider needs a return adjustment.
3173 // We don't want to do this for pure virtual member functions.
3174 BaseOffset ReturnAdjustmentOffset;
3176 if (!FinalOverriderMD->isPureVirtual()) {
3177 ReturnAdjustmentOffset =
3178 ComputeReturnAdjustmentBaseOffset(Context, FinalOverriderMD, MD);
3179 }
3180 if (!ReturnAdjustmentOffset.isEmpty()) {
3181 ForceReturnAdjustmentMangling = true;
3183 ReturnAdjustmentOffset.NonVirtualOffset.getQuantity();
3184 if (ReturnAdjustmentOffset.VirtualBase) {
3185 const ASTRecordLayout &DerivedLayout =
3186 Context.getASTRecordLayout(ReturnAdjustmentOffset.DerivedClass);
3188 DerivedLayout.getVBPtrOffset().getQuantity();
3190 VTables.getVBTableIndex(ReturnAdjustmentOffset.DerivedClass,
3191 ReturnAdjustmentOffset.VirtualBase);
3192 }
3193 }
3194 auto ThisType = (OverriddenMD ? OverriddenMD : MD)->getThisType().getTypePtr();
3195 AddMethod(FinalOverriderMD,
3196 ThunkInfo(ThisAdjustmentOffset, ReturnAdjustment, ThisType,
3197 ForceReturnAdjustmentMangling ? MD : nullptr));
3198 }
3199}
3200
3201static void PrintBasePath(const VPtrInfo::BasePath &Path, raw_ostream &Out) {
3202 for (const CXXRecordDecl *Elem : llvm::reverse(Path)) {
3203 Out << "'";
3204 Elem->printQualifiedName(Out);
3205 Out << "' in ";
3206 }
3207}
3208
3209static void dumpMicrosoftThunkAdjustment(const ThunkInfo &TI, raw_ostream &Out,
3210 bool ContinueFirstLine) {
3211 const ReturnAdjustment &R = TI.Return;
3212 bool Multiline = false;
3213 const char *LinePrefix = "\n ";
3214 if (!R.isEmpty() || TI.Method) {
3215 if (!ContinueFirstLine)
3216 Out << LinePrefix;
3217 Out << "[return adjustment (to type '"
3218 << TI.Method->getReturnType().getCanonicalType() << "'): ";
3219 if (R.Virtual.Microsoft.VBPtrOffset)
3220 Out << "vbptr at offset " << R.Virtual.Microsoft.VBPtrOffset << ", ";
3221 if (R.Virtual.Microsoft.VBIndex)
3222 Out << "vbase #" << R.Virtual.Microsoft.VBIndex << ", ";
3223 Out << R.NonVirtual << " non-virtual]";
3224 Multiline = true;
3225 }
3226
3227 const ThisAdjustment &T = TI.This;
3228 if (!T.isEmpty()) {
3229 if (Multiline || !ContinueFirstLine)
3230 Out << LinePrefix;
3231 Out << "[this adjustment: ";
3232 if (!TI.This.Virtual.isEmpty()) {
3233 assert(T.Virtual.Microsoft.VtordispOffset < 0);
3234 Out << "vtordisp at " << T.Virtual.Microsoft.VtordispOffset << ", ";
3235 if (T.Virtual.Microsoft.VBPtrOffset) {
3236 Out << "vbptr at " << T.Virtual.Microsoft.VBPtrOffset
3237 << " to the left,";
3238 assert(T.Virtual.Microsoft.VBOffsetOffset > 0);
3239 Out << LinePrefix << " vboffset at "
3240 << T.Virtual.Microsoft.VBOffsetOffset << " in the vbtable, ";
3241 }
3242 }
3243 Out << T.NonVirtual << " non-virtual]";
3244 }
3245}
3246
3247void VFTableBuilder::dumpLayout(raw_ostream &Out) {
3248 Out << "VFTable for ";
3249 PrintBasePath(WhichVFPtr.PathToIntroducingObject, Out);
3250 Out << "'";
3251 MostDerivedClass->printQualifiedName(Out);
3252 Out << "' (" << Components.size()
3253 << (Components.size() == 1 ? " entry" : " entries") << ").\n";
3254
3255 for (unsigned I = 0, E = Components.size(); I != E; ++I) {
3256 Out << llvm::format("%4d | ", I);
3257
3258 const VTableComponent &Component = Components[I];
3259
3260 // Dump the component.
3261 switch (Component.getKind()) {
3263 Component.getRTTIDecl()->printQualifiedName(Out);
3264 Out << " RTTI";
3265 break;
3266
3268 const CXXMethodDecl *MD = Component.getFunctionDecl();
3269
3270 // FIXME: Figure out how to print the real thunk type, since they can
3271 // differ in the return type.
3272 std::string Str = PredefinedExpr::ComputeName(
3274 Out << Str;
3275 if (MD->isPureVirtual())
3276 Out << " [pure]";
3277
3278 if (MD->isDeleted())
3279 Out << " [deleted]";
3280
3281 ThunkInfo Thunk = VTableThunks.lookup(I);
3282 if (!Thunk.isEmpty())
3283 dumpMicrosoftThunkAdjustment(Thunk, Out, /*ContinueFirstLine=*/false);
3284
3285 break;
3286 }
3287
3289 const CXXDestructorDecl *DD = Component.getDestructorDecl();
3290
3291 DD->printQualifiedName(Out);
3293 Context.getLangOpts()))
3294 Out << "() [vector deleting]";
3295 else
3296 Out << "() [scalar deleting]";
3297
3298 if (DD->isPureVirtual())
3299 Out << " [pure]";
3300
3301 ThunkInfo Thunk = VTableThunks.lookup(I);
3302 if (!Thunk.isEmpty()) {
3303 assert(Thunk.Return.isEmpty() &&
3304 "No return adjustment needed for destructors!");
3305 dumpMicrosoftThunkAdjustment(Thunk, Out, /*ContinueFirstLine=*/false);
3306 }
3307
3308 break;
3309 }
3310
3311 default:
3312 DiagnosticsEngine &Diags = Context.getDiagnostics();
3313 Diags.Report(MostDerivedClass->getLocation(),
3314 diag::err_unexpected_vftable_component)
3315 << Component.getKind() << I;
3316 }
3317
3318 Out << '\n';
3319 }
3320
3321 Out << '\n';
3322
3323 if (!Thunks.empty()) {
3324 // We store the method names in a map to get a stable order.
3325 std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
3326
3327 for (const auto &I : Thunks) {
3328 const CXXMethodDecl *MD = I.first;
3329 std::string MethodName = PredefinedExpr::ComputeName(
3331
3332 MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
3333 }
3334
3335 for (const auto &MethodNameAndDecl : MethodNamesAndDecls) {
3336 const std::string &MethodName = MethodNameAndDecl.first;
3337 const CXXMethodDecl *MD = MethodNameAndDecl.second;
3338
3339 ThunkInfoVectorTy ThunksVector = Thunks[MD];
3340 llvm::stable_sort(ThunksVector, [](const ThunkInfo &LHS,
3341 const ThunkInfo &RHS) {
3342 // Keep different thunks with the same adjustments in the order they
3343 // were put into the vector.
3344 return std::tie(LHS.This, LHS.Return) < std::tie(RHS.This, RHS.Return);
3345 });
3346
3347 Out << "Thunks for '" << MethodName << "' (" << ThunksVector.size();
3348 Out << (ThunksVector.size() == 1 ? " entry" : " entries") << ").\n";
3349
3350 for (unsigned I = 0, E = ThunksVector.size(); I != E; ++I) {
3351 const ThunkInfo &Thunk = ThunksVector[I];
3352
3353 Out << llvm::format("%4d | ", I);
3354 dumpMicrosoftThunkAdjustment(Thunk, Out, /*ContinueFirstLine=*/true);
3355 Out << '\n';
3356 }
3357
3358 Out << '\n';
3359 }
3360 }
3361
3362 Out.flush();
3363}
3364
3367 for (const CXXRecordDecl *Decl : B) {
3368 if (A.count(Decl))
3369 return true;
3370 }
3371 return false;
3372}
3373
3374static bool rebucketPaths(VPtrInfoVector &Paths);
3375
3376/// Produces MSVC-compatible vbtable data. The symbols produced by this
3377/// algorithm match those produced by MSVC 2012 and newer, which is different
3378/// from MSVC 2010.
3379///
3380/// MSVC 2012 appears to minimize the vbtable names using the following
3381/// algorithm. First, walk the class hierarchy in the usual order, depth first,
3382/// left to right, to find all of the subobjects which contain a vbptr field.
3383/// Visiting each class node yields a list of inheritance paths to vbptrs. Each
3384/// record with a vbptr creates an initially empty path.
3385///
3386/// To combine paths from child nodes, the paths are compared to check for
3387/// ambiguity. Paths are "ambiguous" if multiple paths have the same set of
3388/// components in the same order. Each group of ambiguous paths is extended by
3389/// appending the class of the base from which it came. If the current class
3390/// node produced an ambiguous path, its path is extended with the current class.
3391/// After extending paths, MSVC again checks for ambiguity, and extends any
3392/// ambiguous path which wasn't already extended. Because each node yields an
3393/// unambiguous set of paths, MSVC doesn't need to extend any path more than once
3394/// to produce an unambiguous set of paths.
3395///
3396/// TODO: Presumably vftables use the same algorithm.
3397void MicrosoftVTableContext::computeVTablePaths(bool ForVBTables,
3398 const CXXRecordDecl *RD,
3399 VPtrInfoVector &Paths) {
3400 assert(Paths.empty());
3401 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
3402
3403 // Base case: this subobject has its own vptr.
3404 if (ForVBTables ? Layout.hasOwnVBPtr() : Layout.hasOwnVFPtr())
3405 Paths.push_back(std::make_unique<VPtrInfo>(RD));
3406
3407 // Recursive case: get all the vbtables from our bases and remove anything
3408 // that shares a virtual base.
3409 llvm::SmallPtrSet<const CXXRecordDecl*, 4> VBasesSeen;
3410 for (const auto &B : RD->bases()) {
3411 const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl();
3412 if (B.isVirtual() && VBasesSeen.count(Base))
3413 continue;
3414
3415 if (!Base->isDynamicClass())
3416 continue;
3417
3418 const VPtrInfoVector &BasePaths =
3419 ForVBTables ? enumerateVBTables(Base) : getVFPtrOffsets(Base);
3420
3421 for (const std::unique_ptr<VPtrInfo> &BaseInfo : BasePaths) {
3422 // Don't include the path if it goes through a virtual base that we've
3423 // already included.
3424 if (setsIntersect(VBasesSeen, BaseInfo->ContainingVBases))
3425 continue;
3426
3427 // Copy the path and adjust it as necessary.
3428 auto P = std::make_unique<VPtrInfo>(*BaseInfo);
3429
3430 // We mangle Base into the path if the path would've been ambiguous and it
3431 // wasn't already extended with Base.
3432 if (P->MangledPath.empty() || P->MangledPath.back() != Base)
3433 P->NextBaseToMangle = Base;
3434
3435 // Keep track of which vtable the derived class is going to extend with
3436 // new methods or bases. We append to either the vftable of our primary
3437 // base, or the first non-virtual base that has a vbtable.
3438 if (P->ObjectWithVPtr == Base &&
3439 Base == (ForVBTables ? Layout.getBaseSharingVBPtr()
3440 : Layout.getPrimaryBase()))
3441 P->ObjectWithVPtr = RD;
3442
3443 // Keep track of the full adjustment from the MDC to this vtable. The
3444 // adjustment is captured by an optional vbase and a non-virtual offset.
3445 if (B.isVirtual())
3446 P->ContainingVBases.push_back(Base);
3447 else if (P->ContainingVBases.empty())
3448 P->NonVirtualOffset += Layout.getBaseClassOffset(Base);
3449
3450 // Update the full offset in the MDC.
3451 P->FullOffsetInMDC = P->NonVirtualOffset;
3452 if (const CXXRecordDecl *VB = P->getVBaseWithVPtr())
3453 P->FullOffsetInMDC += Layout.getVBaseClassOffset(VB);
3454
3455 Paths.push_back(std::move(P));
3456 }
3457
3458 if (B.isVirtual())
3459 VBasesSeen.insert(Base);
3460
3461 // After visiting any direct base, we've transitively visited all of its
3462 // morally virtual bases.
3463 for (const auto &VB : Base->vbases())
3464 VBasesSeen.insert(VB.getType()->getAsCXXRecordDecl());
3465 }
3466
3467 // Sort the paths into buckets, and if any of them are ambiguous, extend all
3468 // paths in ambiguous buckets.
3469 bool Changed = true;
3470 while (Changed)
3471 Changed = rebucketPaths(Paths);
3472}
3473
3474static bool extendPath(VPtrInfo &P) {
3475 if (P.NextBaseToMangle) {
3476 P.MangledPath.push_back(P.NextBaseToMangle);
3477 P.NextBaseToMangle = nullptr;// Prevent the path from being extended twice.
3478 return true;
3479 }
3480 return false;
3481}
3482
3483static bool rebucketPaths(VPtrInfoVector &Paths) {
3484 // What we're essentially doing here is bucketing together ambiguous paths.
3485 // Any bucket with more than one path in it gets extended by NextBase, which
3486 // is usually the direct base of the inherited the vbptr. This code uses a
3487 // sorted vector to implement a multiset to form the buckets. Note that the
3488 // ordering is based on pointers, but it doesn't change our output order. The
3489 // current algorithm is designed to match MSVC 2012's names.
3491 llvm::make_pointee_range(Paths));
3492 llvm::sort(PathsSorted, [](const VPtrInfo &LHS, const VPtrInfo &RHS) {
3493 return LHS.MangledPath < RHS.MangledPath;
3494 });
3495 bool Changed = false;
3496 for (size_t I = 0, E = PathsSorted.size(); I != E;) {
3497 // Scan forward to find the end of the bucket.
3498 size_t BucketStart = I;
3499 do {
3500 ++I;
3501 } while (I != E &&
3502 PathsSorted[BucketStart].get().MangledPath ==
3503 PathsSorted[I].get().MangledPath);
3504
3505 // If this bucket has multiple paths, extend them all.
3506 if (I - BucketStart > 1) {
3507 for (size_t II = BucketStart; II != I; ++II)
3508 Changed |= extendPath(PathsSorted[II]);
3509 assert(Changed && "no paths were extended to fix ambiguity");
3510 }
3511 }
3512 return Changed;
3513}
3514
3516
3517namespace {
3518typedef llvm::SetVector<BaseSubobject, std::vector<BaseSubobject>,
3519 llvm::DenseSet<BaseSubobject>> FullPathTy;
3520}
3521
3522// This recursive function finds all paths from a subobject centered at
3523// (RD, Offset) to the subobject located at IntroducingObject.
3525 const ASTRecordLayout &MostDerivedLayout,
3526 const CXXRecordDecl *RD, CharUnits Offset,
3527 BaseSubobject IntroducingObject,
3528 FullPathTy &FullPath,
3529 std::list<FullPathTy> &Paths) {
3530 if (BaseSubobject(RD, Offset) == IntroducingObject) {
3531 Paths.push_back(FullPath);
3532 return;
3533 }
3534
3535 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
3536
3537 for (const CXXBaseSpecifier &BS : RD->bases()) {
3538 const CXXRecordDecl *Base = BS.getType()->getAsCXXRecordDecl();
3539 CharUnits NewOffset = BS.isVirtual()
3540 ? MostDerivedLayout.getVBaseClassOffset(Base)
3541 : Offset + Layout.getBaseClassOffset(Base);
3542 FullPath.insert(BaseSubobject(Base, NewOffset));
3543 findPathsToSubobject(Context, MostDerivedLayout, Base, NewOffset,
3544 IntroducingObject, FullPath, Paths);
3545 FullPath.pop_back();
3546 }
3547}
3548
3549// Return the paths which are not subsets of other paths.
3550static void removeRedundantPaths(std::list<FullPathTy> &FullPaths) {
3551 FullPaths.remove_if([&](const FullPathTy &SpecificPath) {
3552 for (const FullPathTy &OtherPath : FullPaths) {
3553 if (&SpecificPath == &OtherPath)
3554 continue;
3555 if (llvm::all_of(SpecificPath, [&](const BaseSubobject &BSO) {
3556 return OtherPath.contains(BSO);
3557 })) {
3558 return true;
3559 }
3560 }
3561 return false;
3562 });
3563}
3564
3566 const CXXRecordDecl *RD,
3567 const FullPathTy &FullPath) {
3568 const ASTRecordLayout &MostDerivedLayout =
3569 Context.getASTRecordLayout(RD);
3571 for (const BaseSubobject &BSO : FullPath) {
3572 const CXXRecordDecl *Base = BSO.getBase();
3573 // The first entry in the path is always the most derived record, skip it.
3574 if (Base == RD) {
3575 assert(Offset.getQuantity() == -1);
3576 Offset = CharUnits::Zero();
3577 continue;
3578 }
3579 assert(Offset.getQuantity() != -1);
3580 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
3581 // While we know which base has to be traversed, we don't know if that base
3582 // was a virtual base.
3583 const CXXBaseSpecifier *BaseBS = std::find_if(
3584 RD->bases_begin(), RD->bases_end(), [&](const CXXBaseSpecifier &BS) {
3585 return BS.getType()->getAsCXXRecordDecl() == Base;
3586 });
3587 Offset = BaseBS->isVirtual() ? MostDerivedLayout.getVBaseClassOffset(Base)
3588 : Offset + Layout.getBaseClassOffset(Base);
3589 RD = Base;
3590 }
3591 return Offset;
3592}
3593
3594// We want to select the path which introduces the most covariant overrides. If
3595// two paths introduce overrides which the other path doesn't contain, issue a
3596// diagnostic.
3597static const FullPathTy *selectBestPath(ASTContext &Context,
3598 const CXXRecordDecl *RD,
3599 const VPtrInfo &Info,
3600 std::list<FullPathTy> &FullPaths) {
3601 // Handle some easy cases first.
3602 if (FullPaths.empty())
3603 return nullptr;
3604 if (FullPaths.size() == 1)
3605 return &FullPaths.front();
3606
3607 const FullPathTy *BestPath = nullptr;
3608 typedef std::set<const CXXMethodDecl *> OverriderSetTy;
3609 OverriderSetTy LastOverrides;
3610 for (const FullPathTy &SpecificPath : FullPaths) {
3611 assert(!SpecificPath.empty());
3612 OverriderSetTy CurrentOverrides;
3613 const CXXRecordDecl *TopLevelRD = SpecificPath.begin()->getBase();
3614 // Find the distance from the start of the path to the subobject with the
3615 // VPtr.
3616 CharUnits BaseOffset =
3617 getOffsetOfFullPath(Context, TopLevelRD, SpecificPath);
3618 FinalOverriders Overriders(TopLevelRD, CharUnits::Zero(), TopLevelRD);
3619 for (const CXXMethodDecl *MD : Info.IntroducingObject->methods()) {
3621 continue;
3622 FinalOverriders::OverriderInfo OI =
3623 Overriders.getOverrider(MD->getCanonicalDecl(), BaseOffset);
3624 const CXXMethodDecl *OverridingMethod = OI.Method;
3625 // Only overriders which have a return adjustment introduce problematic
3626 // thunks.
3627 if (ComputeReturnAdjustmentBaseOffset(Context, OverridingMethod, MD)
3628 .isEmpty())
3629 continue;
3630 // It's possible that the overrider isn't in this path. If so, skip it
3631 // because this path didn't introduce it.
3632 const CXXRecordDecl *OverridingParent = OverridingMethod->getParent();
3633 if (llvm::none_of(SpecificPath, [&](const BaseSubobject &BSO) {
3634 return BSO.getBase() == OverridingParent;
3635 }))
3636 continue;
3637 CurrentOverrides.insert(OverridingMethod);
3638 }
3639 OverriderSetTy NewOverrides =
3640 llvm::set_difference(CurrentOverrides, LastOverrides);
3641 if (NewOverrides.empty())
3642 continue;
3643 OverriderSetTy MissingOverrides =
3644 llvm::set_difference(LastOverrides, CurrentOverrides);
3645 if (MissingOverrides.empty()) {
3646 // This path is a strict improvement over the last path, let's use it.
3647 BestPath = &SpecificPath;
3648 std::swap(CurrentOverrides, LastOverrides);
3649 } else {
3650 // This path introduces an overrider with a conflicting covariant thunk.
3651 DiagnosticsEngine &Diags = Context.getDiagnostics();
3652 const CXXMethodDecl *CovariantMD = *NewOverrides.begin();
3653 const CXXMethodDecl *ConflictMD = *MissingOverrides.begin();
3654 Diags.Report(RD->getLocation(), diag::err_vftable_ambiguous_component)
3655 << RD;
3656 Diags.Report(CovariantMD->getLocation(), diag::note_covariant_thunk)
3657 << CovariantMD;
3658 Diags.Report(ConflictMD->getLocation(), diag::note_covariant_thunk)
3659 << ConflictMD;
3660 }
3661 }
3662 // Go with the path that introduced the most covariant overrides. If there is
3663 // no such path, pick the first path.
3664 return BestPath ? BestPath : &FullPaths.front();
3665}
3666
3668 const CXXRecordDecl *RD,
3669 VPtrInfoVector &Paths) {
3670 const ASTRecordLayout &MostDerivedLayout = Context.getASTRecordLayout(RD);
3671 FullPathTy FullPath;
3672 std::list<FullPathTy> FullPaths;
3673 for (const std::unique_ptr<VPtrInfo>& Info : Paths) {
3675 Context, MostDerivedLayout, RD, CharUnits::Zero(),
3676 BaseSubobject(Info->IntroducingObject, Info->FullOffsetInMDC), FullPath,
3677 FullPaths);
3678 FullPath.clear();
3679 removeRedundantPaths(FullPaths);
3680 Info->PathToIntroducingObject.clear();
3681 if (const FullPathTy *BestPath =
3682 selectBestPath(Context, RD, *Info, FullPaths))
3683 for (const BaseSubobject &BSO : *BestPath)
3684 Info->PathToIntroducingObject.push_back(BSO.getBase());
3685 FullPaths.clear();
3686 }
3687}
3688
3689static bool vfptrIsEarlierInMDC(const ASTRecordLayout &Layout,
3690 const MethodVFTableLocation &LHS,
3691 const MethodVFTableLocation &RHS) {
3692 CharUnits L = LHS.VFPtrOffset;
3693 CharUnits R = RHS.VFPtrOffset;
3694 if (LHS.VBase)
3695 L += Layout.getVBaseClassOffset(LHS.VBase);
3696 if (RHS.VBase)
3697 R += Layout.getVBaseClassOffset(RHS.VBase);
3698 return L < R;
3699}
3700
3701void MicrosoftVTableContext::computeVTableRelatedInformation(
3702 const CXXRecordDecl *RD) {
3703 assert(RD->isDynamicClass());
3704
3705 // Check if we've computed this information before.
3706 if (VFPtrLocations.count(RD))
3707 return;
3708
3709 const VTableLayout::AddressPointsMapTy EmptyAddressPointsMap;
3710
3711 {
3712 auto VFPtrs = std::make_unique<VPtrInfoVector>();
3713 computeVTablePaths(/*ForVBTables=*/false, RD, *VFPtrs);
3714 computeFullPathsForVFTables(Context, RD, *VFPtrs);
3715 VFPtrLocations[RD] = std::move(VFPtrs);
3716 }
3717
3718 MethodVFTableLocationsTy NewMethodLocations;
3719 for (const std::unique_ptr<VPtrInfo> &VFPtr : *VFPtrLocations[RD]) {
3720 VFTableBuilder Builder(*this, RD, *VFPtr);
3721
3722 VFTableIdTy id(RD, VFPtr->FullOffsetInMDC);
3723 assert(VFTableLayouts.count(id) == 0);
3724 SmallVector<VTableLayout::VTableThunkTy, 1> VTableThunks(
3725 Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
3726 VFTableLayouts[id] = std::make_unique<VTableLayout>(
3727 VTableLayout::VTableIndicesTy{0}, Builder.vtable_components(),
3728 VTableThunks, EmptyAddressPointsMap);
3729 Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
3730
3731 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
3732 for (const auto &Loc : Builder.vtable_locations()) {
3733 auto Insert = NewMethodLocations.insert(Loc);
3734 if (!Insert.second) {
3735 const MethodVFTableLocation &NewLoc = Loc.second;
3736 MethodVFTableLocation &OldLoc = Insert.first->second;
3737 if (vfptrIsEarlierInMDC(Layout, NewLoc, OldLoc))
3738 OldLoc = NewLoc;
3739 }
3740 }
3741 }
3742
3743 MethodVFTableLocations.insert_range(NewMethodLocations);
3744 if (Context.getLangOpts().DumpVTableLayouts)
3745 dumpMethodLocations(RD, NewMethodLocations, llvm::outs());
3746}
3747
3748void MicrosoftVTableContext::dumpMethodLocations(
3749 const CXXRecordDecl *RD, const MethodVFTableLocationsTy &NewMethods,
3750 raw_ostream &Out) {
3751 // Compute the vtable indices for all the member functions.
3752 // Store them in a map keyed by the location so we'll get a sorted table.
3753 std::map<MethodVFTableLocation, std::string> IndicesMap;
3754 bool HasNonzeroOffset = false;
3755
3756 for (const auto &I : NewMethods) {
3757 const CXXMethodDecl *MD = cast<const CXXMethodDecl>(I.first.getDecl());
3758 assert(hasVtableSlot(MD));
3759
3760 std::string MethodName = PredefinedExpr::ComputeName(
3762
3763 if (isa<CXXDestructorDecl>(MD)) {
3764 IndicesMap[I.second] = MethodName + " [vector deleting]";
3765 } else {
3766 IndicesMap[I.second] = MethodName;
3767 }
3768
3769 if (!I.second.VFPtrOffset.isZero() || I.second.VBTableIndex != 0)
3770 HasNonzeroOffset = true;
3771 }
3772
3773 // Print the vtable indices for all the member functions.
3774 if (!IndicesMap.empty()) {
3775 Out << "VFTable indices for ";
3776 Out << "'";
3777 RD->printQualifiedName(Out);
3778 Out << "' (" << IndicesMap.size()
3779 << (IndicesMap.size() == 1 ? " entry" : " entries") << ").\n";
3780
3781 CharUnits LastVFPtrOffset = CharUnits::fromQuantity(-1);
3782 uint64_t LastVBIndex = 0;
3783 for (const auto &I : IndicesMap) {
3784 CharUnits VFPtrOffset = I.first.VFPtrOffset;
3785 uint64_t VBIndex = I.first.VBTableIndex;
3786 if (HasNonzeroOffset &&
3787 (VFPtrOffset != LastVFPtrOffset || VBIndex != LastVBIndex)) {
3788 assert(VBIndex > LastVBIndex || VFPtrOffset > LastVFPtrOffset);
3789 Out << " -- accessible via ";
3790 if (VBIndex)
3791 Out << "vbtable index " << VBIndex << ", ";
3792 Out << "vfptr at offset " << VFPtrOffset.getQuantity() << " --\n";
3793 LastVFPtrOffset = VFPtrOffset;
3794 LastVBIndex = VBIndex;
3795 }
3796
3797 uint64_t VTableIndex = I.first.Index;
3798 const std::string &MethodName = I.second;
3799 Out << llvm::format("%4" PRIu64 " | ", VTableIndex) << MethodName << '\n';
3800 }
3801 Out << '\n';
3802 }
3803
3804 Out.flush();
3805}
3806
3807const VirtualBaseInfo &MicrosoftVTableContext::computeVBTableRelatedInformation(
3808 const CXXRecordDecl *RD) {
3809 VirtualBaseInfo *VBI;
3810
3811 {
3812 // Get or create a VBI for RD. Don't hold a reference to the DenseMap cell,
3813 // as it may be modified and rehashed under us.
3814 std::unique_ptr<VirtualBaseInfo> &Entry = VBaseInfo[RD];
3815 if (Entry)
3816 return *Entry;
3817 Entry = std::make_unique<VirtualBaseInfo>();
3818 VBI = Entry.get();
3819 }
3820
3821 computeVTablePaths(/*ForVBTables=*/true, RD, VBI->VBPtrPaths);
3822
3823 // First, see if the Derived class shared the vbptr with a non-virtual base.
3824 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
3825 if (const CXXRecordDecl *VBPtrBase = Layout.getBaseSharingVBPtr()) {
3826 // If the Derived class shares the vbptr with a non-virtual base, the shared
3827 // virtual bases come first so that the layout is the same.
3828 const VirtualBaseInfo &BaseInfo =
3829 computeVBTableRelatedInformation(VBPtrBase);
3830 VBI->VBTableIndices.insert_range(BaseInfo.VBTableIndices);
3831 }
3832
3833 // New vbases are added to the end of the vbtable.
3834 // Skip the self entry and vbases visited in the non-virtual base, if any.
3835 unsigned VBTableIndex = 1 + VBI->VBTableIndices.size();
3836 for (const auto &VB : RD->vbases()) {
3837 const CXXRecordDecl *CurVBase = VB.getType()->getAsCXXRecordDecl();
3838 if (VBI->VBTableIndices.try_emplace(CurVBase, VBTableIndex).second)
3839 ++VBTableIndex;
3840 }
3841
3842 return *VBI;
3843}
3844
3846 const CXXRecordDecl *VBase) {
3847 const VirtualBaseInfo &VBInfo = computeVBTableRelatedInformation(Derived);
3848 assert(VBInfo.VBTableIndices.count(VBase));
3849 return VBInfo.VBTableIndices.find(VBase)->second;
3850}
3851
3852const VPtrInfoVector &
3854 return computeVBTableRelatedInformation(RD).VBPtrPaths;
3855}
3856
3857const VPtrInfoVector &
3859 computeVTableRelatedInformation(RD);
3860
3861 assert(VFPtrLocations.count(RD) && "Couldn't find vfptr locations");
3862 return *VFPtrLocations[RD];
3863}
3864
3865const VTableLayout &
3867 CharUnits VFPtrOffset) {
3868 computeVTableRelatedInformation(RD);
3869
3870 VFTableIdTy id(RD, VFPtrOffset);
3871 assert(VFTableLayouts.count(id) && "Couldn't find a VFTable at this offset");
3872 return *VFTableLayouts[id];
3873}
3874
3878 "Only use this method for virtual methods or dtors");
3880 assert(GD.getDtorType() == Dtor_VectorDeleting ||
3881 GD.getDtorType() == Dtor_Deleting);
3882
3883 GD = GD.getCanonicalDecl();
3884
3885 MethodVFTableLocationsTy::iterator I = MethodVFTableLocations.find(GD);
3886 if (I != MethodVFTableLocations.end())
3887 return I->second;
3888
3889 const CXXRecordDecl *RD = cast<CXXMethodDecl>(GD.getDecl())->getParent();
3890
3891 computeVTableRelatedInformation(RD);
3892
3893 I = MethodVFTableLocations.find(GD);
3894 assert(I != MethodVFTableLocations.end() && "Did not find index!");
3895 return I->second;
3896}
Defines the clang::ASTContext interface.
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
static Decl::Kind getKind(const Decl *D)
static QualType getPointeeType(const MemRegion *R)
static void findPathsToSubobject(ASTContext &Context, const ASTRecordLayout &MostDerivedLayout, const CXXRecordDecl *RD, CharUnits Offset, BaseSubobject IntroducingObject, FullPathTy &FullPath, std::list< FullPathTy > &Paths)
static const FullPathTy * selectBestPath(ASTContext &Context, const CXXRecordDecl *RD, const VPtrInfo &Info, std::list< FullPathTy > &FullPaths)
static CharUnits getOffsetOfFullPath(ASTContext &Context, const CXXRecordDecl *RD, const FullPathTy &FullPath)
static void removeRedundantPaths(std::list< FullPathTy > &FullPaths)
static std::unique_ptr< VTableLayout > CreateVTableLayout(const ItaniumVTableBuilder &Builder)
static bool vfptrIsEarlierInMDC(const ASTRecordLayout &Layout, const MethodVFTableLocation &LHS, const MethodVFTableLocation &RHS)
static bool isDirectVBase(const CXXRecordDecl *Base, const CXXRecordDecl *RD)
static void PrintBasePath(const VPtrInfo::BasePath &Path, raw_ostream &Out)
static VTableLayout::AddressPointsIndexMapTy MakeAddressPointIndices(const VTableLayout::AddressPointsMapTy &addressPoints, unsigned numVTables)
static bool rebucketPaths(VPtrInfoVector &Paths)
static bool extendPath(VPtrInfo &P)
static void dumpMicrosoftThunkAdjustment(const ThunkInfo &TI, raw_ostream &Out, bool ContinueFirstLine)
static void GroupNewVirtualOverloads(const CXXRecordDecl *RD, SmallVector< const CXXMethodDecl *, 10 > &VirtualMethods)
static void computeFullPathsForVFTables(ASTContext &Context, const CXXRecordDecl *RD, VPtrInfoVector &Paths)
static bool setsIntersect(const llvm::SmallPtrSet< const CXXRecordDecl *, 4 > &A, ArrayRef< const CXXRecordDecl * > B)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:226
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
const LangOptions & getLangOpts() const
Definition ASTContext.h:952
CanQualType IntTy
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
DiagnosticsEngine & getDiagnostics() const
const TargetInfo & getTargetInfo() const
Definition ASTContext.h:917
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
bool hasOwnVFPtr() const
hasOwnVFPtr - Does this class provide its own virtual-function table pointer, rather than inheriting ...
const CXXRecordDecl * getBaseSharingVBPtr() const
bool hasOwnVBPtr() const
hasOwnVBPtr - Does this class provide its own virtual-base table pointer, rather than inheriting one ...
llvm::DenseMap< const CXXRecordDecl *, VBaseInfo > VBaseOffsetsMapTy
CharUnits getVBPtrOffset() const
getVBPtrOffset - Get the offset for virtual base table pointer.
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const
getVBaseClassOffset - Get the offset, in chars, for the given base class.
const VBaseOffsetsMapTy & getVBaseOffsetsMap() const
const CXXRecordDecl * getPrimaryBase() const
getPrimaryBase - Get the primary base for this record.
bool isPrimaryBaseVirtual() const
isPrimaryBaseVirtual - Get whether the primary base for this record is virtual or not.
const CXXRecordDecl * getBase() const
getBase - Returns the base class declaration.
CharUnits getBaseOffset() const
getBaseOffset - Returns the base class offset.
Represents a path from a specific derived class (which is not represented as part of the path) to a p...
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
CXXBasePath & front()
Represents a base class of a C++ class.
Definition DeclCXX.h:146
bool isVirtual() const
Determines whether the base class is a virtual base class (or not).
Definition DeclCXX.h:203
QualType getType() const
Retrieves the type of the base class.
Definition DeclCXX.h:249
Represents a C++ destructor within a class.
Definition DeclCXX.h:2889
A mapping from each virtual member function to its set of final overriders.
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2136
bool isVirtual() const
Definition DeclCXX.h:2191
overridden_method_range overridden_methods() const
Definition DeclCXX.cpp:2830
unsigned size_overridden_methods() const
Definition DeclCXX.cpp:2824
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Definition DeclCXX.h:2275
QualType getThisType() const
Return the type of the this pointer.
Definition DeclCXX.cpp:2861
bool isMoveAssignmentOperator() const
Determine whether this is a move assignment operator.
Definition DeclCXX.cpp:2753
bool isCopyAssignmentOperator() const
Determine whether this is a copy-assignment operator, regardless of whether it was declared implicitl...
Definition DeclCXX.cpp:2732
CXXMethodDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition DeclCXX.h:2245
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
base_class_iterator bases_end()
Definition DeclCXX.h:617
base_class_range bases()
Definition DeclCXX.h:608
method_range methods() const
Definition DeclCXX.h:650
bool isPolymorphic() const
Whether this class is polymorphic (C++ [class.virtual]), which means that the class contains or inher...
Definition DeclCXX.h:1214
bool lookupInBases(BaseMatchesCallback BaseMatches, CXXBasePaths &Paths, bool LookupInDependent=false) const
Look for entities within the base classes of this C++ class, transitively searching all base class su...
base_class_iterator bases_begin()
Definition DeclCXX.h:615
base_class_range vbases()
Definition DeclCXX.h:625
base_class_iterator vbases_begin()
Definition DeclCXX.h:632
bool isDynamicClass() const
Definition DeclCXX.h:574
void getFinalOverriders(CXXFinalOverriderMap &FinaOverriders) const
Retrieve the final overriders for each virtual member function in the class hierarchy where this clas...
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
Definition DeclCXX.h:623
bool isDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is derived from the class Base.
CanQual< T > getUnqualifiedType() const
Retrieve the unqualified form of this type.
CanProxy< U > getAs() const
Retrieve a canonical type pointer with a different static type, upcasting or downcasting as needed.
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
bool isZero() const
isZero - Test whether the quantity equals zero.
Definition CharUnits.h:122
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition CharUnits.h:185
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition CharUnits.h:63
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
Definition CharUnits.h:53
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2122
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition DeclBase.h:2386
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
ASTContext & getASTContext() const LLVM_READONLY
Definition DeclBase.cpp:547
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition DeclBase.h:601
SourceLocation getLocation() const
Definition DeclBase.h:447
The name of a declaration.
Concrete class used by the front-end to report problems and issues.
Definition Diagnostic.h:233
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
bool isImmediateFunction() const
Definition Decl.cpp:3342
QualType getReturnType() const
Definition Decl.h:2860
bool isDeleted() const
Whether this function has been deleted.
Definition Decl.h:2555
bool isPureVirtual() const
Whether this virtual function is pure, i.e.
Definition Decl.h:2368
OverloadedOperatorKind getOverloadedOperator() const
getOverloadedOperator - Which C++ overloaded operator this function represents, if any.
Definition Decl.cpp:4132
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5357
Qualifiers getMethodQuals() const
Definition TypeBase.h:5783
ArrayRef< QualType > getParamTypes() const
Definition TypeBase.h:5642
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4553
QualType getReturnType() const
Definition TypeBase.h:4893
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:57
GlobalDecl getCanonicalDecl() const
Definition GlobalDecl.h:97
CXXDtorType getDtorType() const
Definition GlobalDecl.h:113
const Decl * getDecl() const
Definition GlobalDecl.h:106
const CXXMethodDecl * findOriginalMethodInMap(const CXXMethodDecl *MD) const
const OriginalMethodMapTy & getOriginalMethodMap()
This method is reserved for the implementation and shouldn't be used directly.
uint64_t getMethodVTableIndex(GlobalDecl GD)
Locate a virtual function in the vtable.
std::unique_ptr< VTableLayout > createConstructionVTableLayout(const CXXRecordDecl *MostDerivedClass, CharUnits MostDerivedClassOffset, bool MostDerivedClassIsVirtual, const CXXRecordDecl *LayoutClass)
CharUnits getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, const CXXRecordDecl *VBase)
Return the offset in chars (relative to the vtable address point) where the offset of the virtual bas...
GlobalDecl findOriginalMethod(GlobalDecl GD)
Return the method that added the v-table slot that will be used to call the given method.
void setOriginalMethod(const CXXMethodDecl *Key, const CXXMethodDecl *Val)
ItaniumVTableContext(ASTContext &Context)
unsigned getVBTableIndex(const CXXRecordDecl *Derived, const CXXRecordDecl *VBase)
Returns the index of VBase in the vbtable of Derived.
const VPtrInfoVector & enumerateVBTables(const CXXRecordDecl *RD)
MethodVFTableLocation getMethodVFTableLocation(GlobalDecl GD)
const VPtrInfoVector & getVFPtrOffsets(const CXXRecordDecl *RD)
const VTableLayout & getVFTableLayout(const CXXRecordDecl *RD, CharUnits VFPtrOffset)
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition Decl.h:340
std::string getQualifiedNameAsString() const
Definition Decl.cpp:1681
void printQualifiedName(raw_ostream &OS) const
Returns a human-readable qualified name for this declaration, like A::B::i, for i being member of nam...
Definition Decl.cpp:1688
The set of methods that override a given virtual method in each subobject where it occurs.
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3378
static std::string ComputeName(PredefinedIdentKind IK, const Decl *CurrentDecl, bool ForceElaboratedPrinting=false)
Definition Expr.cpp:673
A (possibly-)qualified type.
Definition TypeBase.h:937
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8431
QualType getCanonicalType() const
Definition TypeBase.h:8483
Base for LValueReferenceType and RValueReferenceType.
Definition TypeBase.h:3623
virtual bool emitVectorDeletingDtors(const LangOptions &) const
Controls whether to emit MSVC vector deleting destructors.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9328
Represents a single component in a vtable.
static VTableComponent MakeCompleteDtor(const CXXDestructorDecl *DD)
static VTableComponent MakeRTTI(const CXXRecordDecl *RD)
const CXXMethodDecl * getUnusedFunctionDecl() const
static VTableComponent MakeOffsetToTop(CharUnits Offset)
CharUnits getVBaseOffset() const
static VTableComponent MakeUnusedFunction(const CXXMethodDecl *MD)
Kind getKind() const
Get the kind of this vtable component.
static VTableComponent MakeFunction(const CXXMethodDecl *MD)
@ CK_DeletingDtorPointer
A pointer to the deleting destructor.
@ CK_UnusedFunctionPointer
An entry that is never used.
@ CK_CompleteDtorPointer
A pointer to the complete destructor.
static VTableComponent MakeVBaseOffset(CharUnits Offset)
const CXXRecordDecl * getRTTIDecl() const
static VTableComponent MakeDeletingDtor(const CXXDestructorDecl *DD)
CharUnits getOffsetToTop() const
const CXXMethodDecl * getFunctionDecl() const
static VTableComponent MakeVCallOffset(CharUnits Offset)
CharUnits getVCallOffset() const
const CXXDestructorDecl * getDestructorDecl() const
static bool hasVtableSlot(const CXXMethodDecl *MD)
Determine whether this function should be assigned a vtable slot.
ThunksMapTy Thunks
Contains all thunks that a given method decl will need.
llvm::SmallVector< std::size_t > VTableIndicesTy
VTableLayout(VTableIndicesTy VTableIndices, ArrayRef< VTableComponent > VTableComponents, ArrayRef< VTableThunkTy > VTableThunks, const AddressPointsMapTy &AddressPoints)
llvm::SmallVector< unsigned, 4 > AddressPointsIndexMapTy
llvm::DenseMap< BaseSubobject, AddressPointLocation > AddressPointsMapTy
std::pair< uint64_t, ThunkInfo > VTableThunkTy
QualType getType() const
Definition Decl.h:723
Defines the clang::TargetInfo interface.
PRESERVE_NONE bool Ret(InterpState &S, CodePtr &PC)
Definition Interp.h:252
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
Definition Address.h:330
SmallVector< std::unique_ptr< VPtrInfo >, 2 > VPtrInfoVector
CXXDtorType
C++ destructor types.
Definition ABI.h:34
@ Dtor_VectorDeleting
Vector deleting dtor.
Definition ABI.h:40
@ Dtor_Complete
Complete object dtor.
Definition ABI.h:36
@ Dtor_Deleting
Deleting dtor.
Definition ABI.h:35
for(const auto &A :T->param_types())
U cast(CodeGen::Address addr)
Definition Address.h:327
@ PrettyFunctionNoVirtual
The same as PrettyFunction, except that the 'virtual' keyword is omitted for virtual member functions...
Definition Expr.h:2002
unsigned long uint64_t
#define false
Definition stdbool.h:26
Represents an element in a path from a derived class to a base class.
const CXXRecordDecl * Class
The record decl of the class that the base is a base of.
const CXXBaseSpecifier * Base
The base specifier that states the link from a derived class to a base class, which will be followed ...
const CXXRecordDecl * VBase
If nonnull, holds the last vbase which contains the vfptr that the method definition is adjusted to.
CharUnits VFPtrOffset
This is the offset of the vfptr from the start of the last vbase, or the complete type if there are n...
A return adjustment.
Definition Thunk.h:27
bool isEmpty() const
Definition Thunk.h:70
union clang::ReturnAdjustment::VirtualAdjustment Virtual
int64_t NonVirtual
The non-virtual adjustment from the derived object to its nearest virtual base.
Definition Thunk.h:30
A this pointer adjustment.
Definition Thunk.h:92
union clang::ThisAdjustment::VirtualAdjustment Virtual
bool isEmpty() const
Definition Thunk.h:137
int64_t NonVirtual
The non-virtual adjustment from the derived object to its nearest virtual base.
Definition Thunk.h:95
The this pointer adjustment as well as an optional return adjustment for a thunk.
Definition Thunk.h:157
bool isEmpty() const
Definition Thunk.h:186
ThisAdjustment This
The this pointer adjustment.
Definition Thunk.h:159
const CXXMethodDecl * Method
Holds a pointer to the overridden method this thunk is for, if needed by the ABI to distinguish diffe...
Definition Thunk.h:172
ReturnAdjustment Return
The return adjustment.
Definition Thunk.h:162
Uniquely identifies a virtual method within a class hierarchy by the method itself and a class subobj...
Holds information about the inheritance path to a virtual base or function table pointer.
CharUnits NonVirtualOffset
IntroducingObject is at this offset from its containing complete object or virtual base.
CharUnits FullOffsetInMDC
Static offset from the top of the most derived class to this vfptr, including any virtual base offset...
const CXXRecordDecl * getVBaseWithVPtr() const
The vptr is stored inside the non-virtual component of this virtual base.
SmallVector< const CXXRecordDecl *, 1 > BasePath
const CXXRecordDecl * IntroducingObject
This is the class that introduced the vptr by declaring new virtual methods or virtual bases.
BasePath MangledPath
The bases from the inheritance path that got used to mangle the vbtable name.
const CXXRecordDecl * NextBaseToMangle
The next base to push onto the mangled path if this path is ambiguous in a derived class.
BasePath PathToIntroducingObject
This holds the base classes path from the complete type to the first base with the given vfptr offset...
All virtual base related information about a given record decl.
VPtrInfoVector VBPtrPaths
Information on all virtual base tables used when this record is the most derived class.
llvm::DenseMap< const CXXRecordDecl *, unsigned > VBTableIndices
A map from virtual base to vbtable index for doing a conversion from the the derived class to the a b...
struct clang::ReturnAdjustment::VirtualAdjustment::@103031170252120233124322035264172076254313213024 Itanium
uint32_t VBPtrOffset
The offset (in bytes) of the vbptr, relative to the beginning of the derived class.
Definition Thunk.h:46
struct clang::ReturnAdjustment::VirtualAdjustment::@167242364125115315334113104006210160165266060257 Microsoft
int64_t VBaseOffsetOffset
The offset (in bytes), relative to the address point of the virtual base class offset.
Definition Thunk.h:39
uint32_t VBIndex
Index of the virtual base in the vbtable.
Definition Thunk.h:49
struct clang::ThisAdjustment::VirtualAdjustment::@106065375072164260365214033034320247050276346205 Itanium
int32_t VtordispOffset
The offset of the vtordisp (in bytes), relative to the ECX.
Definition Thunk.h:109
struct clang::ThisAdjustment::VirtualAdjustment::@312251255113040203233347230177110330127151157305 Microsoft
int32_t VBOffsetOffset
The offset (in bytes) of the vbase offset in the vbtable.
Definition Thunk.h:116
int64_t VCallOffsetOffset
The offset (in bytes), relative to the address point, of the virtual call offset.
Definition Thunk.h:104
int32_t VBPtrOffset
The offset of the vbptr of the derived class (in bytes), relative to the ECX after vtordisp adjustmen...
Definition Thunk.h:113