/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/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.52k | : VBaseOffset(VBaseOffset), HasVtorDisp(hasVtorDisp) {} |
55 | | |
56 | 3.57k | 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 | | // UnadjustedAlignment - Maximum of the alignments of the record members in |
74 | | // characters. |
75 | | CharUnits UnadjustedAlignment; |
76 | | |
77 | | /// RequiredAlignment - The required alignment of the object. In the MS-ABI |
78 | | /// the __declspec(align()) trumps #pramga pack and must always be obeyed. |
79 | | CharUnits RequiredAlignment; |
80 | | |
81 | | /// FieldOffsets - Array of field offsets in bits. |
82 | | ASTVector<uint64_t> FieldOffsets; |
83 | | |
84 | | /// CXXRecordLayoutInfo - Contains C++ specific layout information. |
85 | | struct CXXRecordLayoutInfo { |
86 | | /// NonVirtualSize - The non-virtual size (in chars) of an object, which is |
87 | | /// the size of the object without virtual bases. |
88 | | CharUnits NonVirtualSize; |
89 | | |
90 | | /// NonVirtualAlignment - The non-virtual alignment (in chars) of an object, |
91 | | /// which is the alignment of the object without virtual bases. |
92 | | CharUnits NonVirtualAlignment; |
93 | | |
94 | | /// SizeOfLargestEmptySubobject - The size of the largest empty subobject |
95 | | /// (either a base or a member). Will be zero if the class doesn't contain |
96 | | /// any empty subobjects. |
97 | | CharUnits SizeOfLargestEmptySubobject; |
98 | | |
99 | | /// VBPtrOffset - Virtual base table offset (Microsoft-only). |
100 | | CharUnits VBPtrOffset; |
101 | | |
102 | | /// HasOwnVFPtr - Does this class provide a virtual function table |
103 | | /// (vtable in Itanium, vftbl in Microsoft) that is independent from |
104 | | /// its base classes? |
105 | | bool HasOwnVFPtr : 1; |
106 | | |
107 | | /// HasVFPtr - Does this class have a vftable that could be extended by |
108 | | /// a derived class. The class may have inherited this pointer from |
109 | | /// a primary base class. |
110 | | bool HasExtendableVFPtr : 1; |
111 | | |
112 | | /// EndsWithZeroSizedObject - True if this class contains a zero sized |
113 | | /// member or base or a base with a zero sized member or base. |
114 | | /// Only used for MS-ABI. |
115 | | bool EndsWithZeroSizedObject : 1; |
116 | | |
117 | | /// True if this class is zero sized or first base is zero sized or |
118 | | /// has this property. Only used for MS-ABI. |
119 | | bool LeadsWithZeroSizedBase : 1; |
120 | | |
121 | | /// PrimaryBase - The primary base info for this record. |
122 | | llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> PrimaryBase; |
123 | | |
124 | | /// BaseSharingVBPtr - The base we share vbptr with. |
125 | | const CXXRecordDecl *BaseSharingVBPtr; |
126 | | |
127 | | /// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :) |
128 | | using BaseOffsetsMapTy = llvm::DenseMap<const CXXRecordDecl *, CharUnits>; |
129 | | |
130 | | /// BaseOffsets - Contains a map from base classes to their offset. |
131 | | BaseOffsetsMapTy BaseOffsets; |
132 | | |
133 | | /// VBaseOffsets - Contains a map from vbase classes to their offset. |
134 | | VBaseOffsetsMapTy VBaseOffsets; |
135 | | }; |
136 | | |
137 | | /// CXXInfo - If the record layout is for a C++ record, this will have |
138 | | /// C++ specific information about the record. |
139 | | CXXRecordLayoutInfo *CXXInfo = nullptr; |
140 | | |
141 | | ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment, |
142 | | CharUnits unadjustedAlignment, |
143 | | CharUnits requiredAlignment, CharUnits datasize, |
144 | | ArrayRef<uint64_t> fieldoffsets); |
145 | | |
146 | | using BaseOffsetsMapTy = CXXRecordLayoutInfo::BaseOffsetsMapTy; |
147 | | |
148 | | // Constructor for C++ records. |
149 | | ASTRecordLayout(const ASTContext &Ctx, |
150 | | CharUnits size, CharUnits alignment, |
151 | | CharUnits unadjustedAlignment, |
152 | | CharUnits requiredAlignment, |
153 | | bool hasOwnVFPtr, bool hasExtendableVFPtr, |
154 | | CharUnits vbptroffset, |
155 | | CharUnits datasize, |
156 | | ArrayRef<uint64_t> fieldoffsets, |
157 | | CharUnits nonvirtualsize, CharUnits nonvirtualalignment, |
158 | | CharUnits SizeOfLargestEmptySubobject, |
159 | | const CXXRecordDecl *PrimaryBase, |
160 | | bool IsPrimaryBaseVirtual, |
161 | | const CXXRecordDecl *BaseSharingVBPtr, |
162 | | bool EndsWithZeroSizedObject, |
163 | | bool LeadsWithZeroSizedBase, |
164 | | const BaseOffsetsMapTy& BaseOffsets, |
165 | | const VBaseOffsetsMapTy& VBaseOffsets); |
166 | | |
167 | 42.6k | ~ASTRecordLayout() = default; |
168 | | |
169 | | void Destroy(ASTContext &Ctx); |
170 | | |
171 | | public: |
172 | | ASTRecordLayout(const ASTRecordLayout &) = delete; |
173 | | ASTRecordLayout &operator=(const ASTRecordLayout &) = delete; |
174 | | |
175 | | /// getAlignment - Get the record alignment in characters. |
176 | 320k | CharUnits getAlignment() const { return Alignment; } |
177 | | |
178 | | /// getUnadjustedAlignment - Get the record alignment in characters, before |
179 | | /// alignment adjustement. |
180 | 239 | CharUnits getUnadjustedAlignment() const { return UnadjustedAlignment; } |
181 | | |
182 | | /// getSize - Get the record size in characters. |
183 | 393k | CharUnits getSize() const { return Size; } |
184 | | |
185 | | /// getFieldCount - Get the number of fields in the layout. |
186 | 1.23k | unsigned getFieldCount() const { return FieldOffsets.size(); } |
187 | | |
188 | | /// getFieldOffset - Get the offset of the given field index, in |
189 | | /// bits. |
190 | 1.71M | uint64_t getFieldOffset(unsigned FieldNo) const { |
191 | 1.71M | return FieldOffsets[FieldNo]; |
192 | 1.71M | } |
193 | | |
194 | | /// getDataSize() - Get the record data size, which is the record size |
195 | | /// without tail padding, in characters. |
196 | 12.5k | CharUnits getDataSize() const { |
197 | 12.5k | return DataSize; |
198 | 12.5k | } |
199 | | |
200 | | /// getNonVirtualSize - Get the non-virtual size (in chars) of an object, |
201 | | /// which is the size of the object without virtual bases. |
202 | 322k | CharUnits getNonVirtualSize() const { |
203 | 322k | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
204 | 322k | |
205 | 322k | return CXXInfo->NonVirtualSize; |
206 | 322k | } |
207 | | |
208 | | /// getNonVirtualSize - Get the non-virtual alignment (in chars) of an object, |
209 | | /// which is the alignment of the object without virtual bases. |
210 | 773k | CharUnits getNonVirtualAlignment() const { |
211 | 773k | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
212 | 773k | |
213 | 773k | return CXXInfo->NonVirtualAlignment; |
214 | 773k | } |
215 | | |
216 | | /// getPrimaryBase - Get the primary base for this record. |
217 | 101k | const CXXRecordDecl *getPrimaryBase() const { |
218 | 101k | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
219 | 101k | |
220 | 101k | return CXXInfo->PrimaryBase.getPointer(); |
221 | 101k | } |
222 | | |
223 | | /// isPrimaryBaseVirtual - Get whether the primary base for this record |
224 | | /// is virtual or not. |
225 | 144k | bool isPrimaryBaseVirtual() const { |
226 | 144k | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
227 | 144k | |
228 | 144k | return CXXInfo->PrimaryBase.getInt(); |
229 | 144k | } |
230 | | |
231 | | /// getBaseClassOffset - Get the offset, in chars, for the given base class. |
232 | 1.34M | CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const { |
233 | 1.34M | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
234 | 1.34M | assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!"); |
235 | 1.34M | |
236 | 1.34M | return CXXInfo->BaseOffsets[Base]; |
237 | 1.34M | } |
238 | | |
239 | | /// getVBaseClassOffset - Get the offset, in chars, for the given base class. |
240 | 25.0k | CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const { |
241 | 25.0k | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
242 | 25.0k | assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!"); |
243 | 25.0k | |
244 | 25.0k | return CXXInfo->VBaseOffsets[VBase].VBaseOffset; |
245 | 25.0k | } |
246 | | |
247 | 76.4k | CharUnits getSizeOfLargestEmptySubobject() const { |
248 | 76.4k | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
249 | 76.4k | return CXXInfo->SizeOfLargestEmptySubobject; |
250 | 76.4k | } |
251 | | |
252 | | /// hasOwnVFPtr - Does this class provide its own virtual-function |
253 | | /// table pointer, rather than inheriting one from a primary base |
254 | | /// class? If so, it is at offset zero. |
255 | | /// |
256 | | /// This implies that the ABI has no primary base class, meaning |
257 | | /// that it has no base classes that are suitable under the conditions |
258 | | /// of the ABI. |
259 | 107k | bool hasOwnVFPtr() const { |
260 | 107k | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
261 | 107k | return CXXInfo->HasOwnVFPtr; |
262 | 107k | } |
263 | | |
264 | | /// hasVFPtr - Does this class have a virtual function table pointer |
265 | | /// that can be extended by a derived class? This is synonymous with |
266 | | /// this class having a VFPtr at offset zero. |
267 | 3.09k | bool hasExtendableVFPtr() const { |
268 | 3.09k | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
269 | 3.09k | return CXXInfo->HasExtendableVFPtr; |
270 | 3.09k | } |
271 | | |
272 | | /// hasOwnVBPtr - Does this class provide its own virtual-base |
273 | | /// table pointer, rather than inheriting one from a primary base |
274 | | /// class? |
275 | | /// |
276 | | /// This implies that the ABI has no primary base class, meaning |
277 | | /// that it has no base classes that are suitable under the conditions |
278 | | /// of the ABI. |
279 | 106k | bool hasOwnVBPtr() const { |
280 | 106k | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
281 | 106k | return hasVBPtr() && !CXXInfo->BaseSharingVBPtr1.79k ; |
282 | 106k | } |
283 | | |
284 | | /// hasVBPtr - Does this class have a virtual function table pointer. |
285 | 107k | bool hasVBPtr() const { |
286 | 107k | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
287 | 107k | return !CXXInfo->VBPtrOffset.isNegative(); |
288 | 107k | } |
289 | | |
290 | 6.83k | CharUnits getRequiredAlignment() const { |
291 | 6.83k | return RequiredAlignment; |
292 | 6.83k | } |
293 | | |
294 | 3.78k | bool endsWithZeroSizedObject() const { |
295 | 3.78k | return CXXInfo && CXXInfo->EndsWithZeroSizedObject3.77k ; |
296 | 3.78k | } |
297 | | |
298 | 1.27k | bool leadsWithZeroSizedBase() const { |
299 | 1.27k | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
300 | 1.27k | return CXXInfo->LeadsWithZeroSizedBase; |
301 | 1.27k | } |
302 | | |
303 | | /// getVBPtrOffset - Get the offset for virtual base table pointer. |
304 | | /// This is only meaningful with the Microsoft ABI. |
305 | 3.03k | CharUnits getVBPtrOffset() const { |
306 | 3.03k | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
307 | 3.03k | return CXXInfo->VBPtrOffset; |
308 | 3.03k | } |
309 | | |
310 | 893 | const CXXRecordDecl *getBaseSharingVBPtr() const { |
311 | 893 | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
312 | 893 | return CXXInfo->BaseSharingVBPtr; |
313 | 893 | } |
314 | | |
315 | 4.87k | const VBaseOffsetsMapTy &getVBaseOffsetsMap() const { |
316 | 4.87k | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
317 | 4.87k | return CXXInfo->VBaseOffsets; |
318 | 4.87k | } |
319 | | }; |
320 | | |
321 | | } // namespace clang |
322 | | |
323 | | #endif // LLVM_CLANG_AST_RECORDLAYOUT_H |