1 //===- VTTBuilder.cpp - C++ VTT layout builder ----------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This contains code dealing with generation of the layout of virtual table
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"
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
) {
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());
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.
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);
79 VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base
,
80 bool BaseIsMorallyVirtual
,
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
)
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
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())
105 bool BaseDeclIsMorallyVirtual
= BaseIsMorallyVirtual
;
106 bool BaseDeclIsNonVirtualPrimaryBase
= false;
107 CharUnits BaseOffset
;
109 // Ignore virtual bases that we've already visited.
110 if (!VBases
.insert(BaseDecl
).second
)
113 BaseOffset
= MostDerivedClassLayout
.getVBaseClassOffset(BaseDecl
);
114 BaseDeclIsMorallyVirtual
= true;
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
,
138 // And lay out the secondary virtual pointers for the base class.
139 LayoutSecondaryVirtualPointers(BaseSubobject(BaseDecl
, BaseOffset
),
140 BaseDeclIsMorallyVirtual
, VTableIndex
,
141 VTableClass
, VBases
);
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.
161 // Check if we've seen this base before.
162 if (!VBases
.insert(BaseDecl
).second
)
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
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)
187 bool IsPrimaryVTT
= Base
.getBase() == MostDerivedClass
;
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.
208 VisitedVirtualBasesSetTy VBases
;
209 LayoutVirtualVTTs(Base
.getBase(), VBases
);