1
2 /* Compiler implementation of the D programming language
3 * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved
4 * written by Walter Bright
5 * https://www.digitalmars.com
6 * Distributed under the Boost Software License, Version 1.0.
7 * https://www.boost.org/LICENSE_1_0.txt
8 * https://github.com/dlang/dmd/blob/master/src/dmd/aggregate.h
9 */
10
11 #pragma once
12
13 #include "dsymbol.h"
14 #include "objc.h"
15
16 class AliasThis;
17 class Identifier;
18 class Type;
19 class TypeFunction;
20 class Expression;
21 class FuncDeclaration;
22 class CtorDeclaration;
23 class DtorDeclaration;
24 class InterfaceDeclaration;
25 class TypeInfoClassDeclaration;
26 class VarDeclaration;
27
28 enum class Sizeok : uint8_t
29 {
30 none, // size of aggregate is not yet able to compute
31 fwd, // size of aggregate is ready to compute
32 inProcess, // in the midst of computing the size
33 done // size of aggregate is set correctly
34 };
35
36 enum class Baseok : uint8_t
37 {
38 none, // base classes not computed yet
39 in, // in process of resolving base classes
40 done, // all base classes are resolved
41 semanticdone // all base classes semantic done
42 };
43
44 FuncDeclaration *search_toString(StructDeclaration *sd);
45
46 enum class ClassKind : uint8_t
47 {
48 /// the aggregate is a d(efault) struct/class/interface
49 d,
50 /// the aggregate is a C++ struct/class/interface
51 cpp,
52 /// the aggregate is an Objective-C class/interface
53 objc,
54 /// the aggregate is a C struct
55 c,
56 };
57
58 struct MangleOverride
59 {
60 Dsymbol *agg;
61 Identifier *id;
62 };
63
64 class AggregateDeclaration : public ScopeDsymbol
65 {
66 public:
67 Type *type;
68 StorageClass storage_class;
69 unsigned structsize; // size of struct
70 unsigned alignsize; // size of struct for alignment purposes
71 VarDeclarations fields; // VarDeclaration fields
72 Dsymbol *deferred; // any deferred semantic2() or semantic3() symbol
73
74 ClassKind classKind; // specifies the linkage type
75 CPPMANGLE cppmangle;
76
77 // overridden symbol with pragma(mangle, "...")
78 MangleOverride *pMangleOverride;
79 /* !=NULL if is nested
80 * pointing to the dsymbol that directly enclosing it.
81 * 1. The function that enclosing it (nested struct and class)
82 * 2. The class that enclosing it (nested class only)
83 * 3. If enclosing aggregate is template, its enclosing dsymbol.
84 * See AggregateDeclaraton::makeNested for the details.
85 */
86 Dsymbol *enclosing;
87 VarDeclaration *vthis; // 'this' parameter if this aggregate is nested
88 VarDeclaration *vthis2; // 'this' parameter if this aggregate is a template and is nested
89 // Special member functions
90 FuncDeclarations invs; // Array of invariants
91 FuncDeclaration *inv; // invariant
92
93 Dsymbol *ctor; // CtorDeclaration or TemplateDeclaration
94
95 // default constructor - should have no arguments, because
96 // it would be stored in TypeInfo_Class.defaultConstructor
97 CtorDeclaration *defaultCtor;
98
99 AliasThis *aliasthis; // forward unresolved lookups to aliasthis
100
101 DtorDeclarations userDtors; // user-defined destructors (`~this()`) - mixins can yield multiple ones
102 DtorDeclaration *aggrDtor; // aggregate destructor calling userDtors and fieldDtor (and base class aggregate dtor for C++ classes)
103 DtorDeclaration *dtor; // the aggregate destructor exposed as `__xdtor` alias
104 // (same as aggrDtor, except for C++ classes with virtual dtor on Windows)
105 DtorDeclaration *tidtor; // aggregate destructor used in TypeInfo (must have extern(D) ABI)
106 DtorDeclaration *fieldDtor; // function destructing (non-inherited) fields
107
108 Expression *getRTInfo; // pointer to GC info generated by object.RTInfo(this)
109
110 Visibility visibility;
111 d_bool noDefaultCtor; // no default construction
112 d_bool disableNew; // disallow allocations using `new`
113 Sizeok sizeok; // set when structsize contains valid data
114
115 virtual Scope *newScope(Scope *sc);
116 void setScope(Scope *sc) override final;
117 size_t nonHiddenFields();
118 bool determineSize(const Loc &loc);
119 virtual void finalizeSize() = 0;
120 uinteger_t size(const Loc &loc) override final;
121 bool fill(const Loc &loc, Expressions &elements, bool ctorinit);
122 Type *getType() override final;
123 bool isDeprecated() const override final; // is aggregate deprecated?
124 void setDeprecated();
125 bool isNested() const;
126 bool isExport() const override final;
127 Dsymbol *searchCtor();
128
129 Visibility visible() override final;
130
131 // 'this' type
132 Type *handleType() { return type; }
133
134 bool hasInvariant();
135
136 // Back end
137 void *sinit;
138
139 AggregateDeclaration *isAggregateDeclaration() override final { return this; }
140 void accept(Visitor *v) override { v->visit(this); }
141 };
142
143 struct StructFlags
144 {
145 enum Type
146 {
147 none = 0x0,
148 hasPointers = 0x1 // NB: should use noPointers as in ClassFlags
149 };
150 };
151
152 class StructDeclaration : public AggregateDeclaration
153 {
154 public:
155 FuncDeclarations postblits; // Array of postblit functions
156 FuncDeclaration *postblit; // aggregate postblit
157
158 FuncDeclaration *xeq; // TypeInfo_Struct.xopEquals
159 FuncDeclaration *xcmp; // TypeInfo_Struct.xopCmp
160 FuncDeclaration *xhash; // TypeInfo_Struct.xtoHash
161 static FuncDeclaration *xerreq; // object.xopEquals
162 static FuncDeclaration *xerrcmp; // object.xopCmp
163
164 // ABI-specific type(s) if the struct can be passed in registers
165 TypeTuple *argTypes;
166
167 structalign_t alignment; // alignment applied outside of the struct
168 ThreeState ispod; // if struct is POD
169 private:
170 uint16_t bitFields;
171 public:
172 static StructDeclaration *create(const Loc &loc, Identifier *id, bool inObject);
173 StructDeclaration *syntaxCopy(Dsymbol *s) override;
174 Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override final;
175 const char *kind() const override;
176 void finalizeSize() override final;
177 bool isPOD();
178 bool zeroInit() const; // !=0 if initialize with 0 fill
179 bool zeroInit(bool v);
180 bool hasIdentityAssign() const; // true if has identity opAssign
181 bool hasIdentityAssign(bool v);
182 bool hasBlitAssign() const; // true if opAssign is a blit
183 bool hasBlitAssign(bool v);
184 bool hasIdentityEquals() const; // true if has identity opEquals
185 bool hasIdentityEquals(bool v);
186 bool hasNoFields() const; // has no fields
187 bool hasNoFields(bool v);
188 bool hasCopyCtor() const; // copy constructor
189 bool hasCopyCtor(bool v);
190 // Even if struct is defined as non-root symbol, some built-in operations
191 // (e.g. TypeidExp, NewExp, ArrayLiteralExp, etc) request its TypeInfo.
192 // For those, today TypeInfo_Struct is generated in COMDAT.
193 bool requestTypeInfo() const;
194 bool requestTypeInfo(bool v);
195
196 StructDeclaration *isStructDeclaration() override final { return this; }
197 void accept(Visitor *v) override { v->visit(this); }
198
199 unsigned numArgTypes() const;
200 Type *argType(unsigned index);
201 bool hasRegularCtor(bool checkDisabled = false);
202 };
203
204 class UnionDeclaration final : public StructDeclaration
205 {
206 public:
207 UnionDeclaration *syntaxCopy(Dsymbol *s) override;
208 const char *kind() const override;
209
210 UnionDeclaration *isUnionDeclaration() override { return this; }
211 void accept(Visitor *v) override { v->visit(this); }
212 };
213
214 struct BaseClass
215 {
216 Type *type; // (before semantic processing)
217
218 ClassDeclaration *sym;
219 unsigned offset; // 'this' pointer offset
220 // for interfaces: Array of FuncDeclaration's
221 // making up the vtbl[]
222 FuncDeclarations vtbl;
223
224 DArray<BaseClass> baseInterfaces; // if BaseClass is an interface, these
225 // are a copy of the InterfaceDeclaration::interfaces
226
227 bool fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newinstance);
228 };
229
230 struct ClassFlags
231 {
232 enum Type
233 {
234 none = 0x0,
235 isCOMclass = 0x1,
236 noPointers = 0x2,
237 hasOffTi = 0x4,
238 hasCtor = 0x8,
239 hasGetMembers = 0x10,
240 hasTypeInfo = 0x20,
241 isAbstract = 0x40,
242 isCPPclass = 0x80,
243 hasDtor = 0x100
244 };
245 };
246
247 class ClassDeclaration : public AggregateDeclaration
248 {
249 public:
250 static ClassDeclaration *object;
251 static ClassDeclaration *throwable;
252 static ClassDeclaration *exception;
253 static ClassDeclaration *errorException;
254 static ClassDeclaration *cpp_type_info_ptr;
255
256 ClassDeclaration *baseClass; // NULL only if this is Object
257 FuncDeclaration *staticCtor;
258 FuncDeclaration *staticDtor;
259 Dsymbols vtbl; // Array of FuncDeclaration's making up the vtbl[]
260 Dsymbols vtblFinal; // More FuncDeclaration's that aren't in vtbl[]
261
262 BaseClasses *baseclasses; // Array of BaseClass's; first is super,
263 // rest are Interface's
264
265 DArray<BaseClass*> interfaces; // interfaces[interfaces_dim] for this class
266 // (does not include baseClass)
267
268 BaseClasses *vtblInterfaces; // array of base interfaces that have
269 // their own vtbl[]
270
271 TypeInfoClassDeclaration *vclassinfo; // the ClassInfo object for this ClassDeclaration
272 d_bool com; // true if this is a COM class (meaning it derives from IUnknown)
273 d_bool stack; // true if this is a scope class
274 int cppDtorVtblIndex; // slot reserved for the virtual destructor [extern(C++)]
275 d_bool inuse; // to prevent recursive attempts
276
277 ThreeState isabstract; // if abstract class
278 Baseok baseok; // set the progress of base classes resolving
279 ObjcClassDeclaration objc; // Data for a class declaration that is needed for the Objective-C integration
280 Symbol *cpp_type_info_ptr_sym; // cached instance of class Id.cpp_type_info_ptr
281
282 static ClassDeclaration *create(const Loc &loc, Identifier *id, BaseClasses *baseclasses, Dsymbols *members, bool inObject);
283 const char *toPrettyChars(bool QualifyTypes = false) override;
284 ClassDeclaration *syntaxCopy(Dsymbol *s) override;
285 Scope *newScope(Scope *sc) override;
286 bool isBaseOf2(ClassDeclaration *cd);
287
288 #define OFFSET_RUNTIME 0x76543210
289 #define OFFSET_FWDREF 0x76543211
290 virtual bool isBaseOf(ClassDeclaration *cd, int *poffset);
291
292 bool isBaseInfoComplete();
293 Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override final;
294 ClassDeclaration *searchBase(Identifier *ident);
295 void finalizeSize() override;
296 bool hasMonitor();
297 bool isFuncHidden(FuncDeclaration *fd);
298 FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf);
299 bool isCOMclass() const;
300 virtual bool isCOMinterface() const;
301 bool isCPPclass() const;
302 virtual bool isCPPinterface() const;
303 bool isAbstract();
304 virtual int vtblOffset() const;
305 const char *kind() const override;
306
307 void addObjcSymbols(ClassDeclarations *classes, ClassDeclarations *categories) override final;
308
309 // Back end
310 Dsymbol *vtblsym;
311 Dsymbol *vtblSymbol();
312
313 ClassDeclaration *isClassDeclaration() override final { return (ClassDeclaration *)this; }
314 void accept(Visitor *v) override { v->visit(this); }
315 };
316
317 class InterfaceDeclaration final : public ClassDeclaration
318 {
319 public:
320 InterfaceDeclaration *syntaxCopy(Dsymbol *s) override;
321 Scope *newScope(Scope *sc) override;
322 bool isBaseOf(ClassDeclaration *cd, int *poffset) override;
323 const char *kind() const override;
324 int vtblOffset() const override;
325 bool isCPPinterface() const override;
326 bool isCOMinterface() const override;
327
328 InterfaceDeclaration *isInterfaceDeclaration() override { return this; }
329 void accept(Visitor *v) override { v->visit(this); }
330 };