/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/AST/RecordLayout.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===- RecordLayout.h - Layout information for a struct/union ---*- C++ -*-===// |
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 file defines the RecordLayout interface. |
10 | | // |
11 | | //===----------------------------------------------------------------------===// |
12 | | |
13 | | #ifndef LLVM_CLANG_AST_RECORDLAYOUT_H |
14 | | #define LLVM_CLANG_AST_RECORDLAYOUT_H |
15 | | |
16 | | #include "clang/AST/ASTVector.h" |
17 | | #include "clang/AST/CharUnits.h" |
18 | | #include "clang/AST/DeclCXX.h" |
19 | | #include "clang/Basic/LLVM.h" |
20 | | #include "llvm/ADT/ArrayRef.h" |
21 | | #include "llvm/ADT/DenseMap.h" |
22 | | #include "llvm/ADT/PointerIntPair.h" |
23 | | #include <cassert> |
24 | | #include <cstdint> |
25 | | |
26 | | namespace clang { |
27 | | |
28 | | class ASTContext; |
29 | | class CXXRecordDecl; |
30 | | |
31 | | /// ASTRecordLayout - |
32 | | /// This class contains layout information for one RecordDecl, |
33 | | /// which is a struct/union/class. The decl represented must be a definition, |
34 | | /// not a forward declaration. |
35 | | /// This class is also used to contain layout information for one |
36 | | /// ObjCInterfaceDecl. FIXME - Find appropriate name. |
37 | | /// These objects are managed by ASTContext. |
38 | | class ASTRecordLayout { |
39 | | public: |
40 | | struct VBaseInfo { |
41 | | /// The offset to this virtual base in the complete-object layout |
42 | | /// of this class. |
43 | | CharUnits VBaseOffset; |
44 | | |
45 | | private: |
46 | | /// Whether this virtual base requires a vtordisp field in the |
47 | | /// Microsoft ABI. These fields are required for certain operations |
48 | | /// in constructors and destructors. |
49 | | bool HasVtorDisp = false; |
50 | | |
51 | | public: |
52 | 0 | VBaseInfo() = default; |
53 | | VBaseInfo(CharUnits VBaseOffset, bool hasVtorDisp) |
54 | 2.86k | : VBaseOffset(VBaseOffset), HasVtorDisp(hasVtorDisp) {} |
55 | | |
56 | 3.37k | bool hasVtorDisp() const { return HasVtorDisp; } |
57 | | }; |
58 | | |
59 | | using VBaseOffsetsMapTy = llvm::DenseMap<const CXXRecordDecl *, VBaseInfo>; |
60 | | |
61 | | private: |
62 | | friend class ASTContext; |
63 | | |
64 | | /// Size - Size of record in characters. |
65 | | CharUnits Size; |
66 | | |
67 | | /// DataSize - Size of record in characters without tail padding. |
68 | | CharUnits DataSize; |
69 | | |
70 | | // Alignment - Alignment of record in characters. |
71 | | CharUnits Alignment; |
72 | | |
73 | | // PreferredAlignment - Preferred alignment of record in characters. This |
74 | | // can be different than Alignment in cases where it is beneficial for |
75 | | // performance or backwards compatibility preserving (e.g. AIX-ABI). |
76 | | CharUnits PreferredAlignment; |
77 | | |
78 | | // UnadjustedAlignment - Maximum of the alignments of the record members in |
79 | | // characters. |
80 | | CharUnits UnadjustedAlignment; |
81 | | |
82 | | /// RequiredAlignment - The required alignment of the object. In the MS-ABI |
83 | | /// the __declspec(align()) trumps #pramga pack and must always be obeyed. |
84 | | CharUnits RequiredAlignment; |
85 | | |
86 | | /// FieldOffsets - Array of field offsets in bits. |
87 | | ASTVector<uint64_t> FieldOffsets; |
88 | | |
89 | | /// CXXRecordLayoutInfo - Contains C++ specific layout information. |
90 | | struct CXXRecordLayoutInfo { |
91 | | /// NonVirtualSize - The non-virtual size (in chars) of an object, which is |
92 | | /// the size of the object without virtual bases. |
93 | | CharUnits NonVirtualSize; |
94 | | |
95 | | /// NonVirtualAlignment - The non-virtual alignment (in chars) of an object, |
96 | | /// which is the alignment of the object without virtual bases. |
97 | | CharUnits NonVirtualAlignment; |
98 | | |
99 | | /// PreferredNVAlignment - The preferred non-virtual alignment (in chars) of |
100 | | /// an object, which is the preferred alignment of the object without |
101 | | /// virtual bases. |
102 | | CharUnits PreferredNVAlignment; |
103 | | |
104 | | /// SizeOfLargestEmptySubobject - The size of the largest empty subobject |
105 | | /// (either a base or a member). Will be zero if the class doesn't contain |
106 | | /// any empty subobjects. |
107 | | CharUnits SizeOfLargestEmptySubobject; |
108 | | |
109 | | /// VBPtrOffset - Virtual base table offset (Microsoft-only). |
110 | | CharUnits VBPtrOffset; |
111 | | |
112 | | /// HasOwnVFPtr - Does this class provide a virtual function table |
113 | | /// (vtable in Itanium, vftbl in Microsoft) that is independent from |
114 | | /// its base classes? |
115 | | bool HasOwnVFPtr : 1; |
116 | | |
117 | | /// HasVFPtr - Does this class have a vftable that could be extended by |
118 | | /// a derived class. The class may have inherited this pointer from |
119 | | /// a primary base class. |
120 | | bool HasExtendableVFPtr : 1; |
121 | | |
122 | | /// EndsWithZeroSizedObject - True if this class contains a zero sized |
123 | | /// member or base or a base with a zero sized member or base. |
124 | | /// Only used for MS-ABI. |
125 | | bool EndsWithZeroSizedObject : 1; |
126 | | |
127 | | /// True if this class is zero sized or first base is zero sized or |
128 | | /// has this property. Only used for MS-ABI. |
129 | | bool LeadsWithZeroSizedBase : 1; |
130 | | |
131 | | /// PrimaryBase - The primary base info for this record. |
132 | | llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> PrimaryBase; |
133 | | |
134 | | /// BaseSharingVBPtr - The base we share vbptr with. |
135 | | const CXXRecordDecl *BaseSharingVBPtr; |
136 | | |
137 | | /// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :) |
138 | | using BaseOffsetsMapTy = llvm::DenseMap<const CXXRecordDecl *, CharUnits>; |
139 | | |
140 | | /// BaseOffsets - Contains a map from base classes to their offset. |
141 | | BaseOffsetsMapTy BaseOffsets; |
142 | | |
143 | | /// VBaseOffsets - Contains a map from vbase classes to their offset. |
144 | | VBaseOffsetsMapTy VBaseOffsets; |
145 | | }; |
146 | | |
147 | | /// CXXInfo - If the record layout is for a C++ record, this will have |
148 | | /// C++ specific information about the record. |
149 | | CXXRecordLayoutInfo *CXXInfo = nullptr; |
150 | | |
151 | | ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment, |
152 | | CharUnits preferredAlignment, CharUnits unadjustedAlignment, |
153 | | CharUnits requiredAlignment, CharUnits datasize, |
154 | | ArrayRef<uint64_t> fieldoffsets); |
155 | | |
156 | | using BaseOffsetsMapTy = CXXRecordLayoutInfo::BaseOffsetsMapTy; |
157 | | |
158 | | // Constructor for C++ records. |
159 | | ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment, |
160 | | CharUnits preferredAlignment, CharUnits unadjustedAlignment, |
161 | | CharUnits requiredAlignment, bool hasOwnVFPtr, |
162 | | bool hasExtendableVFPtr, CharUnits vbptroffset, |
163 | | CharUnits datasize, ArrayRef<uint64_t> fieldoffsets, |
164 | | CharUnits nonvirtualsize, CharUnits nonvirtualalignment, |
165 | | CharUnits preferrednvalignment, |
166 | | CharUnits SizeOfLargestEmptySubobject, |
167 | | const CXXRecordDecl *PrimaryBase, bool IsPrimaryBaseVirtual, |
168 | | const CXXRecordDecl *BaseSharingVBPtr, |
169 | | bool EndsWithZeroSizedObject, bool LeadsWithZeroSizedBase, |
170 | | const BaseOffsetsMapTy &BaseOffsets, |
171 | | const VBaseOffsetsMapTy &VBaseOffsets); |
172 | | |
173 | 420k | ~ASTRecordLayout() = default; |
174 | | |
175 | | void Destroy(ASTContext &Ctx); |
176 | | |
177 | | public: |
178 | | ASTRecordLayout(const ASTRecordLayout &) = delete; |
179 | | ASTRecordLayout &operator=(const ASTRecordLayout &) = delete; |
180 | | |
181 | | /// getAlignment - Get the record alignment in characters. |
182 | 485k | CharUnits getAlignment() const { return Alignment; } |
183 | | |
184 | | /// getPreferredFieldAlignment - Get the record preferred alignment in |
185 | | /// characters. |
186 | 288 | CharUnits getPreferredAlignment() const { return PreferredAlignment; } |
187 | | |
188 | | /// getUnadjustedAlignment - Get the record alignment in characters, before |
189 | | /// alignment adjustement. |
190 | 628 | CharUnits getUnadjustedAlignment() const { return UnadjustedAlignment; } |
191 | | |
192 | | /// getSize - Get the record size in characters. |
193 | 838k | CharUnits getSize() const { return Size; } |
194 | | |
195 | | /// getFieldCount - Get the number of fields in the layout. |
196 | 215k | unsigned getFieldCount() const { return FieldOffsets.size(); } |
197 | | |
198 | | /// getFieldOffset - Get the offset of the given field index, in |
199 | | /// bits. |
200 | 1.36M | uint64_t getFieldOffset(unsigned FieldNo) const { |
201 | 1.36M | return FieldOffsets[FieldNo]; |
202 | 1.36M | } |
203 | | |
204 | | /// getDataSize() - Get the record data size, which is the record size |
205 | | /// without tail padding, in characters. |
206 | 17.2k | CharUnits getDataSize() const { return DataSize; } |
207 | | |
208 | | /// getNonVirtualSize - Get the non-virtual size (in chars) of an object, |
209 | | /// which is the size of the object without virtual bases. |
210 | 764k | CharUnits getNonVirtualSize() const { |
211 | 764k | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
212 | | |
213 | 0 | return CXXInfo->NonVirtualSize; |
214 | 764k | } |
215 | | |
216 | | /// getNonVirtualAlignment - Get the non-virtual alignment (in chars) of an |
217 | | /// object, which is the alignment of the object without virtual bases. |
218 | 791k | CharUnits getNonVirtualAlignment() const { |
219 | 791k | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
220 | | |
221 | 0 | return CXXInfo->NonVirtualAlignment; |
222 | 791k | } |
223 | | |
224 | | /// getPreferredNVAlignment - Get the preferred non-virtual alignment (in |
225 | | /// chars) of an object, which is the preferred alignment of the object |
226 | | /// without virtual bases. |
227 | 70.5k | CharUnits getPreferredNVAlignment() const { |
228 | 70.5k | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
229 | | |
230 | 0 | return CXXInfo->PreferredNVAlignment; |
231 | 70.5k | } |
232 | | |
233 | | /// getPrimaryBase - Get the primary base for this record. |
234 | 482k | const CXXRecordDecl *getPrimaryBase() const { |
235 | 482k | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
236 | | |
237 | 0 | return CXXInfo->PrimaryBase.getPointer(); |
238 | 482k | } |
239 | | |
240 | | /// isPrimaryBaseVirtual - Get whether the primary base for this record |
241 | | /// is virtual or not. |
242 | 138k | bool isPrimaryBaseVirtual() const { |
243 | 138k | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
244 | | |
245 | 0 | return CXXInfo->PrimaryBase.getInt(); |
246 | 138k | } |
247 | | |
248 | | /// getBaseClassOffset - Get the offset, in chars, for the given base class. |
249 | 2.29M | CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const { |
250 | 2.29M | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
251 | | |
252 | 0 | Base = Base->getDefinition(); |
253 | 2.29M | assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!"); |
254 | | |
255 | 0 | return CXXInfo->BaseOffsets[Base]; |
256 | 2.29M | } |
257 | | |
258 | | /// getVBaseClassOffset - Get the offset, in chars, for the given base class. |
259 | 20.2k | CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const { |
260 | 20.2k | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
261 | | |
262 | 0 | VBase = VBase->getDefinition(); |
263 | 20.2k | assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!"); |
264 | | |
265 | 0 | return CXXInfo->VBaseOffsets[VBase].VBaseOffset; |
266 | 20.2k | } |
267 | | |
268 | 102k | CharUnits getSizeOfLargestEmptySubobject() const { |
269 | 102k | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
270 | 0 | return CXXInfo->SizeOfLargestEmptySubobject; |
271 | 102k | } |
272 | | |
273 | | /// hasOwnVFPtr - Does this class provide its own virtual-function |
274 | | /// table pointer, rather than inheriting one from a primary base |
275 | | /// class? If so, it is at offset zero. |
276 | | /// |
277 | | /// This implies that the ABI has no primary base class, meaning |
278 | | /// that it has no base classes that are suitable under the conditions |
279 | | /// of the ABI. |
280 | 112k | bool hasOwnVFPtr() const { |
281 | 112k | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
282 | 0 | return CXXInfo->HasOwnVFPtr; |
283 | 112k | } |
284 | | |
285 | | /// hasVFPtr - Does this class have a virtual function table pointer |
286 | | /// that can be extended by a derived class? This is synonymous with |
287 | | /// this class having a VFPtr at offset zero. |
288 | 6.67k | bool hasExtendableVFPtr() const { |
289 | 6.67k | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
290 | 0 | return CXXInfo->HasExtendableVFPtr; |
291 | 6.67k | } |
292 | | |
293 | | /// hasOwnVBPtr - Does this class provide its own virtual-base |
294 | | /// table pointer, rather than inheriting one from a primary base |
295 | | /// class? |
296 | | /// |
297 | | /// This implies that the ABI has no primary base class, meaning |
298 | | /// that it has no base classes that are suitable under the conditions |
299 | | /// of the ABI. |
300 | 107k | bool hasOwnVBPtr() const { |
301 | 107k | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
302 | 107k | return hasVBPtr() && !CXXInfo->BaseSharingVBPtr1.81k ; |
303 | 107k | } |
304 | | |
305 | | /// hasVBPtr - Does this class have a virtual function table pointer. |
306 | 108k | bool hasVBPtr() const { |
307 | 108k | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
308 | 0 | return !CXXInfo->VBPtrOffset.isNegative(); |
309 | 108k | } |
310 | | |
311 | 7.82k | CharUnits getRequiredAlignment() const { return RequiredAlignment; } |
312 | | |
313 | 4.38k | bool endsWithZeroSizedObject() const { |
314 | 4.38k | return CXXInfo && CXXInfo->EndsWithZeroSizedObject4.37k ; |
315 | 4.38k | } |
316 | | |
317 | 1.64k | bool leadsWithZeroSizedBase() const { |
318 | 1.64k | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
319 | 0 | return CXXInfo->LeadsWithZeroSizedBase; |
320 | 1.64k | } |
321 | | |
322 | | /// getVBPtrOffset - Get the offset for virtual base table pointer. |
323 | | /// This is only meaningful with the Microsoft ABI. |
324 | 3.07k | CharUnits getVBPtrOffset() const { |
325 | 3.07k | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
326 | 0 | return CXXInfo->VBPtrOffset; |
327 | 3.07k | } |
328 | | |
329 | 908 | const CXXRecordDecl *getBaseSharingVBPtr() const { |
330 | 908 | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
331 | 0 | return CXXInfo->BaseSharingVBPtr; |
332 | 908 | } |
333 | | |
334 | 4.94k | const VBaseOffsetsMapTy &getVBaseOffsetsMap() const { |
335 | 4.94k | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
336 | 0 | return CXXInfo->VBaseOffsets; |
337 | 4.94k | } |
338 | | }; |
339 | | |
340 | | } // namespace clang |
341 | | |
342 | | #endif // LLVM_CLANG_AST_RECORDLAYOUT_H |