]>
Commit | Line | Data |
---|---|---|
b4c522fa IB |
1 | |
2 | /* Compiler implementation of the D programming language | |
8e788ac6 | 3 | * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved |
b4c522fa IB |
4 | * written by Walter Bright |
5 | * http://www.digitalmars.com | |
6 | * Distributed under the Boost Software License, Version 1.0. | |
7 | * http://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 "root/root.h" | |
14 | ||
15 | #include "dsymbol.h" | |
16 | #include "declaration.h" | |
17 | #include "objc.h" | |
18 | ||
19 | class Identifier; | |
20 | class Type; | |
21 | class TypeFunction; | |
22 | class Expression; | |
23 | class FuncDeclaration; | |
24 | class CtorDeclaration; | |
25 | class DtorDeclaration; | |
26 | class InvariantDeclaration; | |
27 | class NewDeclaration; | |
28 | class DeleteDeclaration; | |
29 | class InterfaceDeclaration; | |
30 | class TypeInfoClassDeclaration; | |
31 | class VarDeclaration; | |
32 | ||
33 | enum Sizeok | |
34 | { | |
35 | SIZEOKnone, // size of aggregate is not yet able to compute | |
36 | SIZEOKfwd, // size of aggregate is ready to compute | |
37 | SIZEOKdone // size of aggregate is set correctly | |
38 | }; | |
39 | ||
40 | enum Baseok | |
41 | { | |
42 | BASEOKnone, // base classes not computed yet | |
43 | BASEOKin, // in process of resolving base classes | |
44 | BASEOKdone, // all base classes are resolved | |
45 | BASEOKsemanticdone // all base classes semantic done | |
46 | }; | |
47 | ||
48 | enum StructPOD | |
49 | { | |
50 | ISPODno, // struct is not POD | |
51 | ISPODyes, // struct is POD | |
52 | ISPODfwd // POD not yet computed | |
53 | }; | |
54 | ||
55 | enum Abstract | |
56 | { | |
57 | ABSfwdref = 0, // whether an abstract class is not yet computed | |
58 | ABSyes, // is abstract class | |
59 | ABSno // is not abstract class | |
60 | }; | |
61 | ||
62 | FuncDeclaration *hasIdentityOpAssign(AggregateDeclaration *ad, Scope *sc); | |
63 | FuncDeclaration *buildOpAssign(StructDeclaration *sd, Scope *sc); | |
64 | bool needOpEquals(StructDeclaration *sd); | |
65 | FuncDeclaration *buildOpEquals(StructDeclaration *sd, Scope *sc); | |
66 | FuncDeclaration *buildXopEquals(StructDeclaration *sd, Scope *sc); | |
67 | FuncDeclaration *buildXopCmp(StructDeclaration *sd, Scope *sc); | |
68 | FuncDeclaration *buildXtoHash(StructDeclaration *ad, Scope *sc); | |
69 | FuncDeclaration *buildPostBlit(StructDeclaration *sd, Scope *sc); | |
70 | FuncDeclaration *buildDtor(AggregateDeclaration *ad, Scope *sc); | |
71 | FuncDeclaration *buildInv(AggregateDeclaration *ad, Scope *sc); | |
72 | FuncDeclaration *search_toString(StructDeclaration *sd); | |
73 | ||
75f758a7 IB |
74 | struct ClassKind |
75 | { | |
76 | enum Type | |
77 | { | |
78 | /// the class is a d(efault) class | |
79 | d, | |
80 | /// the class is a C++ interface | |
81 | cpp, | |
82 | /// the class is an Objective-C class/interface | |
83 | objc, | |
84 | }; | |
85 | }; | |
86 | ||
b4c522fa IB |
87 | class AggregateDeclaration : public ScopeDsymbol |
88 | { | |
89 | public: | |
90 | Type *type; | |
91 | StorageClass storage_class; | |
92 | Prot protection; | |
93 | unsigned structsize; // size of struct | |
94 | unsigned alignsize; // size of struct for alignment purposes | |
95 | VarDeclarations fields; // VarDeclaration fields | |
96 | Sizeok sizeok; // set when structsize contains valid data | |
97 | Dsymbol *deferred; // any deferred semantic2() or semantic3() symbol | |
98 | bool isdeprecated; // true if deprecated | |
99 | ||
75f758a7 IB |
100 | ClassKind::Type classKind; // specifies the linkage type |
101 | ||
b4c522fa IB |
102 | /* !=NULL if is nested |
103 | * pointing to the dsymbol that directly enclosing it. | |
104 | * 1. The function that enclosing it (nested struct and class) | |
105 | * 2. The class that enclosing it (nested class only) | |
106 | * 3. If enclosing aggregate is template, its enclosing dsymbol. | |
107 | * See AggregateDeclaraton::makeNested for the details. | |
108 | */ | |
109 | Dsymbol *enclosing; | |
110 | VarDeclaration *vthis; // 'this' parameter if this aggregate is nested | |
111 | // Special member functions | |
112 | FuncDeclarations invs; // Array of invariants | |
113 | FuncDeclaration *inv; // invariant | |
114 | NewDeclaration *aggNew; // allocator | |
115 | DeleteDeclaration *aggDelete; // deallocator | |
116 | ||
117 | Dsymbol *ctor; // CtorDeclaration or TemplateDeclaration | |
118 | ||
119 | // default constructor - should have no arguments, because | |
120 | // it would be stored in TypeInfo_Class.defaultConstructor | |
121 | CtorDeclaration *defaultCtor; | |
122 | ||
123 | Dsymbol *aliasthis; // forward unresolved lookups to aliasthis | |
124 | bool noDefaultCtor; // no default construction | |
125 | ||
126 | FuncDeclarations dtors; // Array of destructors | |
127 | FuncDeclaration *dtor; // aggregate destructor | |
128 | ||
129 | Expression *getRTInfo; // pointer to GC info generated by object.RTInfo(this) | |
130 | ||
131 | AggregateDeclaration(Loc loc, Identifier *id); | |
132 | virtual Scope *newScope(Scope *sc); | |
133 | void setScope(Scope *sc); | |
134 | void semantic2(Scope *sc); | |
135 | void semantic3(Scope *sc); | |
136 | bool determineFields(); | |
137 | bool determineSize(Loc loc); | |
138 | virtual void finalizeSize() = 0; | |
139 | d_uns64 size(Loc loc); | |
140 | bool checkOverlappedFields(); | |
141 | bool fill(Loc loc, Expressions *elements, bool ctorinit); | |
142 | static void alignmember(structalign_t salign, unsigned size, unsigned *poffset); | |
143 | static unsigned placeField(unsigned *nextoffset, | |
144 | unsigned memsize, unsigned memalignsize, structalign_t memalign, | |
145 | unsigned *paggsize, unsigned *paggalignsize, bool isunion); | |
146 | Type *getType(); | |
147 | bool isDeprecated(); // is aggregate deprecated? | |
148 | bool isNested(); | |
149 | void makeNested(); | |
150 | bool isExport() const; | |
151 | Dsymbol *searchCtor(); | |
152 | ||
153 | Prot prot(); | |
154 | ||
155 | // 'this' type | |
156 | Type *handleType() { return type; } | |
157 | ||
158 | // Back end | |
159 | Symbol *stag; // tag symbol for debug data | |
160 | Symbol *sinit; | |
161 | ||
162 | AggregateDeclaration *isAggregateDeclaration() { return this; } | |
163 | void accept(Visitor *v) { v->visit(this); } | |
164 | }; | |
165 | ||
166 | struct StructFlags | |
167 | { | |
168 | typedef unsigned Type; | |
169 | enum Enum | |
170 | { | |
171 | none = 0x0, | |
172 | hasPointers = 0x1 // NB: should use noPointers as in ClassFlags | |
173 | }; | |
174 | }; | |
175 | ||
176 | class StructDeclaration : public AggregateDeclaration | |
177 | { | |
178 | public: | |
179 | int zeroInit; // !=0 if initialize with 0 fill | |
180 | bool hasIdentityAssign; // true if has identity opAssign | |
181 | bool hasIdentityEquals; // true if has identity opEquals | |
182 | FuncDeclarations postblits; // Array of postblit functions | |
183 | FuncDeclaration *postblit; // aggregate postblit | |
184 | ||
185 | FuncDeclaration *xeq; // TypeInfo_Struct.xopEquals | |
186 | FuncDeclaration *xcmp; // TypeInfo_Struct.xopCmp | |
187 | FuncDeclaration *xhash; // TypeInfo_Struct.xtoHash | |
188 | static FuncDeclaration *xerreq; // object.xopEquals | |
189 | static FuncDeclaration *xerrcmp; // object.xopCmp | |
190 | ||
191 | structalign_t alignment; // alignment applied outside of the struct | |
192 | StructPOD ispod; // if struct is POD | |
193 | ||
194 | // For 64 bit Efl function call/return ABI | |
195 | Type *arg1type; | |
196 | Type *arg2type; | |
197 | ||
198 | // Even if struct is defined as non-root symbol, some built-in operations | |
199 | // (e.g. TypeidExp, NewExp, ArrayLiteralExp, etc) request its TypeInfo. | |
200 | // For those, today TypeInfo_Struct is generated in COMDAT. | |
201 | bool requestTypeInfo; | |
202 | ||
203 | StructDeclaration(Loc loc, Identifier *id, bool inObject); | |
204 | static StructDeclaration *create(Loc loc, Identifier *id, bool inObject); | |
205 | Dsymbol *syntaxCopy(Dsymbol *s); | |
206 | void semantic(Scope *sc); | |
207 | void semanticTypeInfoMembers(); | |
208 | Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly); | |
f9ab59ff | 209 | const char *kind() const; |
b4c522fa IB |
210 | void finalizeSize(); |
211 | bool fit(Loc loc, Scope *sc, Expressions *elements, Type *stype); | |
212 | bool isPOD(); | |
213 | ||
214 | StructDeclaration *isStructDeclaration() { return this; } | |
215 | void accept(Visitor *v) { v->visit(this); } | |
216 | }; | |
217 | ||
218 | class UnionDeclaration : public StructDeclaration | |
219 | { | |
220 | public: | |
221 | UnionDeclaration(Loc loc, Identifier *id); | |
222 | Dsymbol *syntaxCopy(Dsymbol *s); | |
f9ab59ff | 223 | const char *kind() const; |
b4c522fa IB |
224 | |
225 | UnionDeclaration *isUnionDeclaration() { return this; } | |
226 | void accept(Visitor *v) { v->visit(this); } | |
227 | }; | |
228 | ||
229 | struct BaseClass | |
230 | { | |
231 | Type *type; // (before semantic processing) | |
232 | ||
233 | ClassDeclaration *sym; | |
234 | unsigned offset; // 'this' pointer offset | |
235 | // for interfaces: Array of FuncDeclaration's | |
236 | // making up the vtbl[] | |
237 | FuncDeclarations vtbl; | |
238 | ||
239 | DArray<BaseClass> baseInterfaces; // if BaseClass is an interface, these | |
240 | // are a copy of the InterfaceDeclaration::interfaces | |
241 | ||
242 | BaseClass(); | |
243 | BaseClass(Type *type); | |
244 | ||
245 | bool fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newinstance); | |
246 | void copyBaseInterfaces(BaseClasses *); | |
247 | }; | |
248 | ||
249 | struct ClassFlags | |
250 | { | |
251 | typedef unsigned Type; | |
252 | enum Enum | |
253 | { | |
254 | isCOMclass = 0x1, | |
255 | noPointers = 0x2, | |
256 | hasOffTi = 0x4, | |
257 | hasCtor = 0x8, | |
258 | hasGetMembers = 0x10, | |
259 | hasTypeInfo = 0x20, | |
260 | isAbstract = 0x40, | |
261 | isCPPclass = 0x80, | |
262 | hasDtor = 0x100 | |
263 | }; | |
264 | }; | |
265 | ||
266 | class ClassDeclaration : public AggregateDeclaration | |
267 | { | |
268 | public: | |
269 | static ClassDeclaration *object; | |
270 | static ClassDeclaration *throwable; | |
271 | static ClassDeclaration *exception; | |
272 | static ClassDeclaration *errorException; | |
273 | static ClassDeclaration *cpp_type_info_ptr; | |
274 | ||
275 | ClassDeclaration *baseClass; // NULL only if this is Object | |
276 | FuncDeclaration *staticCtor; | |
277 | FuncDeclaration *staticDtor; | |
278 | Dsymbols vtbl; // Array of FuncDeclaration's making up the vtbl[] | |
279 | Dsymbols vtblFinal; // More FuncDeclaration's that aren't in vtbl[] | |
280 | ||
281 | BaseClasses *baseclasses; // Array of BaseClass's; first is super, | |
282 | // rest are Interface's | |
283 | ||
284 | DArray<BaseClass*> interfaces; // interfaces[interfaces_dim] for this class | |
285 | // (does not include baseClass) | |
286 | ||
287 | BaseClasses *vtblInterfaces; // array of base interfaces that have | |
288 | // their own vtbl[] | |
289 | ||
290 | TypeInfoClassDeclaration *vclassinfo; // the ClassInfo object for this ClassDeclaration | |
291 | bool com; // true if this is a COM class (meaning it derives from IUnknown) | |
b4c522fa IB |
292 | bool isscope; // true if this is a scope class |
293 | Abstract isabstract; // 0: fwdref, 1: is abstract class, 2: not abstract | |
294 | int inuse; // to prevent recursive attempts | |
295 | Baseok baseok; // set the progress of base classes resolving | |
296 | Symbol *cpp_type_info_ptr_sym; // cached instance of class Id.cpp_type_info_ptr | |
297 | ||
298 | ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses, Dsymbols *members, bool inObject = false); | |
299 | static ClassDeclaration *create(Loc loc, Identifier *id, BaseClasses *baseclasses, Dsymbols *members, bool inObject); | |
300 | Dsymbol *syntaxCopy(Dsymbol *s); | |
301 | Scope *newScope(Scope *sc); | |
302 | void semantic(Scope *sc); | |
303 | bool isBaseOf2(ClassDeclaration *cd); | |
304 | ||
305 | #define OFFSET_RUNTIME 0x76543210 | |
306 | #define OFFSET_FWDREF 0x76543211 | |
307 | virtual bool isBaseOf(ClassDeclaration *cd, int *poffset); | |
308 | ||
309 | bool isBaseInfoComplete(); | |
310 | Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly); | |
311 | ClassDeclaration *searchBase(Identifier *ident); | |
312 | void finalizeSize(); | |
98866120 | 313 | bool hasMonitor(); |
b4c522fa IB |
314 | bool isFuncHidden(FuncDeclaration *fd); |
315 | FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf); | |
316 | void interfaceSemantic(Scope *sc); | |
317 | bool isCOMclass() const; | |
318 | virtual bool isCOMinterface() const; | |
319 | bool isCPPclass() const; | |
320 | virtual bool isCPPinterface() const; | |
321 | bool isAbstract(); | |
322 | virtual int vtblOffset() const; | |
f9ab59ff | 323 | const char *kind() const; |
b4c522fa IB |
324 | |
325 | void addLocalClass(ClassDeclarations *); | |
326 | ||
327 | // Back end | |
328 | Symbol *vtblsym; | |
329 | ||
330 | ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; } | |
331 | void accept(Visitor *v) { v->visit(this); } | |
332 | }; | |
333 | ||
334 | class InterfaceDeclaration : public ClassDeclaration | |
335 | { | |
336 | public: | |
337 | InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses); | |
338 | Dsymbol *syntaxCopy(Dsymbol *s); | |
339 | Scope *newScope(Scope *sc); | |
340 | void semantic(Scope *sc); | |
341 | bool isBaseOf(ClassDeclaration *cd, int *poffset); | |
342 | bool isBaseOf(BaseClass *bc, int *poffset); | |
f9ab59ff | 343 | const char *kind() const; |
b4c522fa IB |
344 | int vtblOffset() const; |
345 | bool isCPPinterface() const; | |
346 | bool isCOMinterface() const; | |
347 | ||
348 | InterfaceDeclaration *isInterfaceDeclaration() { return this; } | |
349 | void accept(Visitor *v) { v->visit(this); } | |
350 | }; |