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