1 
2 /* Compiler implementation of the D programming language
3  * Copyright (C) 1999-2019 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
handleType()141     Type *handleType() { return type; }
142 
143     // Back end
144     Symbol *stag;               // tag symbol for debug data
145     Symbol *sinit;
146 
isAggregateDeclaration()147     AggregateDeclaration *isAggregateDeclaration() { return this; }
accept(Visitor * v)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);
194     const char *kind() const;
195     void finalizeSize();
196     bool fit(Loc loc, Scope *sc, Expressions *elements, Type *stype);
197     bool isPOD();
198 
isStructDeclaration()199     StructDeclaration *isStructDeclaration() { return this; }
accept(Visitor * v)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);
208     const char *kind() const;
209 
isUnionDeclaration()210     UnionDeclaration *isUnionDeclaration() { return this; }
accept(Visitor * v)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;
309     const char *kind() const;
310 
311     void addLocalClass(ClassDeclarations *);
312 
313     // Back end
314     Symbol *vtblsym;
315 
isClassDeclaration()316     ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; }
accept(Visitor * v)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);
329     const char *kind() const;
330     int vtblOffset() const;
331     bool isCPPinterface() const;
332     bool isCOMinterface() const;
333 
isInterfaceDeclaration()334     InterfaceDeclaration *isInterfaceDeclaration() { return this; }
accept(Visitor * v)335     void accept(Visitor *v) { v->visit(this); }
336 };
337