]>
Commit | Line | Data |
---|---|---|
b4c522fa IB |
1 | |
2 | /* Compiler implementation of the D programming language | |
3 | * Copyright (C) 1999-2018 by The D Language Foundation, All Rights Reserved | |
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 | ||
74 | class AggregateDeclaration : public ScopeDsymbol | |
75 | { | |
76 | public: | |
77 | Type *type; | |
78 | StorageClass storage_class; | |
79 | Prot protection; | |
80 | unsigned structsize; // size of struct | |
81 | unsigned alignsize; // size of struct for alignment purposes | |
82 | VarDeclarations fields; // VarDeclaration fields | |
83 | Sizeok sizeok; // set when structsize contains valid data | |
84 | Dsymbol *deferred; // any deferred semantic2() or semantic3() symbol | |
85 | bool isdeprecated; // true if deprecated | |
86 | ||
87 | /* !=NULL if is nested | |
88 | * pointing to the dsymbol that directly enclosing it. | |
89 | * 1. The function that enclosing it (nested struct and class) | |
90 | * 2. The class that enclosing it (nested class only) | |
91 | * 3. If enclosing aggregate is template, its enclosing dsymbol. | |
92 | * See AggregateDeclaraton::makeNested for the details. | |
93 | */ | |
94 | Dsymbol *enclosing; | |
95 | VarDeclaration *vthis; // 'this' parameter if this aggregate is nested | |
96 | // Special member functions | |
97 | FuncDeclarations invs; // Array of invariants | |
98 | FuncDeclaration *inv; // invariant | |
99 | NewDeclaration *aggNew; // allocator | |
100 | DeleteDeclaration *aggDelete; // deallocator | |
101 | ||
102 | Dsymbol *ctor; // CtorDeclaration or TemplateDeclaration | |
103 | ||
104 | // default constructor - should have no arguments, because | |
105 | // it would be stored in TypeInfo_Class.defaultConstructor | |
106 | CtorDeclaration *defaultCtor; | |
107 | ||
108 | Dsymbol *aliasthis; // forward unresolved lookups to aliasthis | |
109 | bool noDefaultCtor; // no default construction | |
110 | ||
111 | FuncDeclarations dtors; // Array of destructors | |
112 | FuncDeclaration *dtor; // aggregate destructor | |
113 | ||
114 | Expression *getRTInfo; // pointer to GC info generated by object.RTInfo(this) | |
115 | ||
116 | AggregateDeclaration(Loc loc, Identifier *id); | |
117 | virtual Scope *newScope(Scope *sc); | |
118 | void setScope(Scope *sc); | |
119 | void semantic2(Scope *sc); | |
120 | void semantic3(Scope *sc); | |
121 | bool determineFields(); | |
122 | bool determineSize(Loc loc); | |
123 | virtual void finalizeSize() = 0; | |
124 | d_uns64 size(Loc loc); | |
125 | bool checkOverlappedFields(); | |
126 | bool fill(Loc loc, Expressions *elements, bool ctorinit); | |
127 | static void alignmember(structalign_t salign, unsigned size, unsigned *poffset); | |
128 | static unsigned placeField(unsigned *nextoffset, | |
129 | unsigned memsize, unsigned memalignsize, structalign_t memalign, | |
130 | unsigned *paggsize, unsigned *paggalignsize, bool isunion); | |
131 | Type *getType(); | |
132 | bool isDeprecated(); // is aggregate deprecated? | |
133 | bool isNested(); | |
134 | void makeNested(); | |
135 | bool isExport() const; | |
136 | Dsymbol *searchCtor(); | |
137 | ||
138 | Prot prot(); | |
139 | ||
140 | // 'this' type | |
141 | Type *handleType() { return type; } | |
142 | ||
143 | // Back end | |
144 | Symbol *stag; // tag symbol for debug data | |
145 | Symbol *sinit; | |
146 | ||
147 | AggregateDeclaration *isAggregateDeclaration() { return this; } | |
148 | void accept(Visitor *v) { v->visit(this); } | |
149 | }; | |
150 | ||
151 | struct StructFlags | |
152 | { | |
153 | typedef unsigned Type; | |
154 | enum Enum | |
155 | { | |
156 | none = 0x0, | |
157 | hasPointers = 0x1 // NB: should use noPointers as in ClassFlags | |
158 | }; | |
159 | }; | |
160 | ||
161 | class StructDeclaration : public AggregateDeclaration | |
162 | { | |
163 | public: | |
164 | int zeroInit; // !=0 if initialize with 0 fill | |
165 | bool hasIdentityAssign; // true if has identity opAssign | |
166 | bool hasIdentityEquals; // true if has identity opEquals | |
167 | FuncDeclarations postblits; // Array of postblit functions | |
168 | FuncDeclaration *postblit; // aggregate postblit | |
169 | ||
170 | FuncDeclaration *xeq; // TypeInfo_Struct.xopEquals | |
171 | FuncDeclaration *xcmp; // TypeInfo_Struct.xopCmp | |
172 | FuncDeclaration *xhash; // TypeInfo_Struct.xtoHash | |
173 | static FuncDeclaration *xerreq; // object.xopEquals | |
174 | static FuncDeclaration *xerrcmp; // object.xopCmp | |
175 | ||
176 | structalign_t alignment; // alignment applied outside of the struct | |
177 | StructPOD ispod; // if struct is POD | |
178 | ||
179 | // For 64 bit Efl function call/return ABI | |
180 | Type *arg1type; | |
181 | Type *arg2type; | |
182 | ||
183 | // Even if struct is defined as non-root symbol, some built-in operations | |
184 | // (e.g. TypeidExp, NewExp, ArrayLiteralExp, etc) request its TypeInfo. | |
185 | // For those, today TypeInfo_Struct is generated in COMDAT. | |
186 | bool requestTypeInfo; | |
187 | ||
188 | StructDeclaration(Loc loc, Identifier *id, bool inObject); | |
189 | static StructDeclaration *create(Loc loc, Identifier *id, bool inObject); | |
190 | Dsymbol *syntaxCopy(Dsymbol *s); | |
191 | void semantic(Scope *sc); | |
192 | void semanticTypeInfoMembers(); | |
193 | Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly); | |
f9ab59ff | 194 | const char *kind() const; |
b4c522fa IB |
195 | void finalizeSize(); |
196 | bool fit(Loc loc, Scope *sc, Expressions *elements, Type *stype); | |
197 | bool isPOD(); | |
198 | ||
199 | StructDeclaration *isStructDeclaration() { return this; } | |
200 | void accept(Visitor *v) { v->visit(this); } | |
201 | }; | |
202 | ||
203 | class UnionDeclaration : public StructDeclaration | |
204 | { | |
205 | public: | |
206 | UnionDeclaration(Loc loc, Identifier *id); | |
207 | Dsymbol *syntaxCopy(Dsymbol *s); | |
f9ab59ff | 208 | const char *kind() const; |
b4c522fa IB |
209 | |
210 | UnionDeclaration *isUnionDeclaration() { return this; } | |
211 | void accept(Visitor *v) { 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 | BaseClass(); | |
228 | BaseClass(Type *type); | |
229 | ||
230 | bool fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newinstance); | |
231 | void copyBaseInterfaces(BaseClasses *); | |
232 | }; | |
233 | ||
234 | struct ClassFlags | |
235 | { | |
236 | typedef unsigned Type; | |
237 | enum Enum | |
238 | { | |
239 | isCOMclass = 0x1, | |
240 | noPointers = 0x2, | |
241 | hasOffTi = 0x4, | |
242 | hasCtor = 0x8, | |
243 | hasGetMembers = 0x10, | |
244 | hasTypeInfo = 0x20, | |
245 | isAbstract = 0x40, | |
246 | isCPPclass = 0x80, | |
247 | hasDtor = 0x100 | |
248 | }; | |
249 | }; | |
250 | ||
251 | class ClassDeclaration : public AggregateDeclaration | |
252 | { | |
253 | public: | |
254 | static ClassDeclaration *object; | |
255 | static ClassDeclaration *throwable; | |
256 | static ClassDeclaration *exception; | |
257 | static ClassDeclaration *errorException; | |
258 | static ClassDeclaration *cpp_type_info_ptr; | |
259 | ||
260 | ClassDeclaration *baseClass; // NULL only if this is Object | |
261 | FuncDeclaration *staticCtor; | |
262 | FuncDeclaration *staticDtor; | |
263 | Dsymbols vtbl; // Array of FuncDeclaration's making up the vtbl[] | |
264 | Dsymbols vtblFinal; // More FuncDeclaration's that aren't in vtbl[] | |
265 | ||
266 | BaseClasses *baseclasses; // Array of BaseClass's; first is super, | |
267 | // rest are Interface's | |
268 | ||
269 | DArray<BaseClass*> interfaces; // interfaces[interfaces_dim] for this class | |
270 | // (does not include baseClass) | |
271 | ||
272 | BaseClasses *vtblInterfaces; // array of base interfaces that have | |
273 | // their own vtbl[] | |
274 | ||
275 | TypeInfoClassDeclaration *vclassinfo; // the ClassInfo object for this ClassDeclaration | |
276 | bool com; // true if this is a COM class (meaning it derives from IUnknown) | |
277 | bool cpp; // true if this is a C++ interface | |
278 | bool isobjc; // true if this is an Objective-C class/interface | |
279 | bool isscope; // true if this is a scope class | |
280 | Abstract isabstract; // 0: fwdref, 1: is abstract class, 2: not abstract | |
281 | int inuse; // to prevent recursive attempts | |
282 | Baseok baseok; // set the progress of base classes resolving | |
283 | Symbol *cpp_type_info_ptr_sym; // cached instance of class Id.cpp_type_info_ptr | |
284 | ||
285 | ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses, Dsymbols *members, bool inObject = false); | |
286 | static ClassDeclaration *create(Loc loc, Identifier *id, BaseClasses *baseclasses, Dsymbols *members, bool inObject); | |
287 | Dsymbol *syntaxCopy(Dsymbol *s); | |
288 | Scope *newScope(Scope *sc); | |
289 | void semantic(Scope *sc); | |
290 | bool isBaseOf2(ClassDeclaration *cd); | |
291 | ||
292 | #define OFFSET_RUNTIME 0x76543210 | |
293 | #define OFFSET_FWDREF 0x76543211 | |
294 | virtual bool isBaseOf(ClassDeclaration *cd, int *poffset); | |
295 | ||
296 | bool isBaseInfoComplete(); | |
297 | Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly); | |
298 | ClassDeclaration *searchBase(Identifier *ident); | |
299 | void finalizeSize(); | |
300 | bool isFuncHidden(FuncDeclaration *fd); | |
301 | FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf); | |
302 | void interfaceSemantic(Scope *sc); | |
303 | bool isCOMclass() const; | |
304 | virtual bool isCOMinterface() const; | |
305 | bool isCPPclass() const; | |
306 | virtual bool isCPPinterface() const; | |
307 | bool isAbstract(); | |
308 | virtual int vtblOffset() const; | |
f9ab59ff | 309 | const char *kind() const; |
b4c522fa IB |
310 | |
311 | void addLocalClass(ClassDeclarations *); | |
312 | ||
313 | // Back end | |
314 | Symbol *vtblsym; | |
315 | ||
316 | ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; } | |
317 | void accept(Visitor *v) { v->visit(this); } | |
318 | }; | |
319 | ||
320 | class InterfaceDeclaration : public ClassDeclaration | |
321 | { | |
322 | public: | |
323 | InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses); | |
324 | Dsymbol *syntaxCopy(Dsymbol *s); | |
325 | Scope *newScope(Scope *sc); | |
326 | void semantic(Scope *sc); | |
327 | bool isBaseOf(ClassDeclaration *cd, int *poffset); | |
328 | bool isBaseOf(BaseClass *bc, int *poffset); | |
f9ab59ff | 329 | const char *kind() const; |
b4c522fa IB |
330 | int vtblOffset() const; |
331 | bool isCPPinterface() const; | |
332 | bool isCOMinterface() const; | |
333 | ||
334 | InterfaceDeclaration *isInterfaceDeclaration() { return this; } | |
335 | void accept(Visitor *v) { v->visit(this); } | |
336 | }; |