[clang-tidy][NFC]remove deps of clang in clang tidy test (#116588)
[llvm-project.git] / clang / lib / AST / VTTBuilder.cpp
blobde011848a721e3032c8fdf42eca7c88ea1afef76
1 //===- VTTBuilder.cpp - C++ VTT 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 table
10 // tables (VTT).
12 //===----------------------------------------------------------------------===//
14 #include "clang/AST/VTTBuilder.h"
15 #include "clang/AST/ASTContext.h"
16 #include "clang/AST/BaseSubobject.h"
17 #include "clang/AST/CharUnits.h"
18 #include "clang/AST/Decl.h"
19 #include "clang/AST/DeclCXX.h"
20 #include "clang/AST/RecordLayout.h"
21 #include "clang/AST/Type.h"
22 #include "clang/Basic/LLVM.h"
23 #include <cassert>
24 #include <cstdint>
26 using namespace clang;
28 #define DUMP_OVERRIDERS 0
30 VTTBuilder::VTTBuilder(ASTContext &Ctx,
31 const CXXRecordDecl *MostDerivedClass,
32 bool GenerateDefinition)
33 : Ctx(Ctx), MostDerivedClass(MostDerivedClass),
34 MostDerivedClassLayout(Ctx.getASTRecordLayout(MostDerivedClass)),
35 GenerateDefinition(GenerateDefinition) {
36 // Lay out this VTT.
37 LayoutVTT(BaseSubobject(MostDerivedClass, CharUnits::Zero()),
38 /*BaseIsVirtual=*/false);
41 void VTTBuilder::AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex,
42 const CXXRecordDecl *VTableClass) {
43 // Store the vtable pointer index if we're generating the primary VTT.
44 if (VTableClass == MostDerivedClass) {
45 assert(!SecondaryVirtualPointerIndices.count(Base) &&
46 "A virtual pointer index already exists for this base subobject!");
47 SecondaryVirtualPointerIndices[Base] = VTTComponents.size();
50 if (!GenerateDefinition) {
51 VTTComponents.push_back(VTTComponent());
52 return;
55 VTTComponents.push_back(VTTComponent(VTableIndex, Base));
58 void VTTBuilder::LayoutSecondaryVTTs(BaseSubobject Base) {
59 const CXXRecordDecl *RD = Base.getBase();
61 for (const auto &I : RD->bases()) {
62 // Don't layout virtual bases.
63 if (I.isVirtual())
64 continue;
66 const auto *BaseDecl =
67 cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
69 const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
70 CharUnits BaseOffset = Base.getBaseOffset() +
71 Layout.getBaseClassOffset(BaseDecl);
73 // Layout the VTT for this base.
74 LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/false);
78 void
79 VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base,
80 bool BaseIsMorallyVirtual,
81 uint64_t VTableIndex,
82 const CXXRecordDecl *VTableClass,
83 VisitedVirtualBasesSetTy &VBases) {
84 const CXXRecordDecl *RD = Base.getBase();
86 // We're not interested in bases that don't have virtual bases, and not
87 // morally virtual bases.
88 if (!RD->getNumVBases() && !BaseIsMorallyVirtual)
89 return;
91 for (const auto &I : RD->bases()) {
92 const auto *BaseDecl =
93 cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
95 // Itanium C++ ABI 2.6.2:
96 // Secondary virtual pointers are present for all bases with either
97 // virtual bases or virtual function declarations overridden along a
98 // virtual path.
100 // If the base class is not dynamic, we don't want to add it, nor any
101 // of its base classes.
102 if (!BaseDecl->isDynamicClass())
103 continue;
105 bool BaseDeclIsMorallyVirtual = BaseIsMorallyVirtual;
106 bool BaseDeclIsNonVirtualPrimaryBase = false;
107 CharUnits BaseOffset;
108 if (I.isVirtual()) {
109 // Ignore virtual bases that we've already visited.
110 if (!VBases.insert(BaseDecl).second)
111 continue;
113 BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
114 BaseDeclIsMorallyVirtual = true;
115 } else {
116 const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
118 BaseOffset = Base.getBaseOffset() +
119 Layout.getBaseClassOffset(BaseDecl);
121 if (!Layout.isPrimaryBaseVirtual() &&
122 Layout.getPrimaryBase() == BaseDecl)
123 BaseDeclIsNonVirtualPrimaryBase = true;
126 // Itanium C++ ABI 2.6.2:
127 // Secondary virtual pointers: for each base class X which (a) has virtual
128 // bases or is reachable along a virtual path from D, and (b) is not a
129 // non-virtual primary base, the address of the virtual table for X-in-D
130 // or an appropriate construction virtual table.
131 if (!BaseDeclIsNonVirtualPrimaryBase &&
132 (BaseDecl->getNumVBases() || BaseDeclIsMorallyVirtual)) {
133 // Add the vtable pointer.
134 AddVTablePointer(BaseSubobject(BaseDecl, BaseOffset), VTableIndex,
135 VTableClass);
138 // And lay out the secondary virtual pointers for the base class.
139 LayoutSecondaryVirtualPointers(BaseSubobject(BaseDecl, BaseOffset),
140 BaseDeclIsMorallyVirtual, VTableIndex,
141 VTableClass, VBases);
145 void
146 VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base,
147 uint64_t VTableIndex) {
148 VisitedVirtualBasesSetTy VBases;
149 LayoutSecondaryVirtualPointers(Base, /*BaseIsMorallyVirtual=*/false,
150 VTableIndex, Base.getBase(), VBases);
153 void VTTBuilder::LayoutVirtualVTTs(const CXXRecordDecl *RD,
154 VisitedVirtualBasesSetTy &VBases) {
155 for (const auto &I : RD->bases()) {
156 const auto *BaseDecl =
157 cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
159 // Check if this is a virtual base.
160 if (I.isVirtual()) {
161 // Check if we've seen this base before.
162 if (!VBases.insert(BaseDecl).second)
163 continue;
165 CharUnits BaseOffset =
166 MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
168 LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/true);
171 // We only need to layout virtual VTTs for this base if it actually has
172 // virtual bases.
173 if (BaseDecl->getNumVBases())
174 LayoutVirtualVTTs(BaseDecl, VBases);
178 void VTTBuilder::LayoutVTT(BaseSubobject Base, bool BaseIsVirtual) {
179 const CXXRecordDecl *RD = Base.getBase();
181 // Itanium C++ ABI 2.6.2:
182 // An array of virtual table addresses, called the VTT, is declared for
183 // each class type that has indirect or direct virtual base classes.
184 if (RD->getNumVBases() == 0)
185 return;
187 bool IsPrimaryVTT = Base.getBase() == MostDerivedClass;
189 if (!IsPrimaryVTT) {
190 // Remember the sub-VTT index.
191 SubVTTIndices[Base] = VTTComponents.size();
194 uint64_t VTableIndex = VTTVTables.size();
195 VTTVTables.push_back(VTTVTable(Base, BaseIsVirtual));
197 // Add the primary vtable pointer.
198 AddVTablePointer(Base, VTableIndex, RD);
200 // Add the secondary VTTs.
201 LayoutSecondaryVTTs(Base);
203 // Add the secondary virtual pointers.
204 LayoutSecondaryVirtualPointers(Base, VTableIndex);
206 // If this is the primary VTT, we want to lay out virtual VTTs as well.
207 if (IsPrimaryVTT) {
208 VisitedVirtualBasesSetTy VBases;
209 LayoutVirtualVTTs(Base.getBase(), VBases);