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