1 
2 /* Compiler implementation of the D programming language
3  * Copyright (C) 1999-2021 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 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 
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 
100     ClassKind::Type classKind;  // specifies the linkage type
101 
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     bool determineFields();
135     bool determineSize(Loc loc);
136     virtual void finalizeSize() = 0;
137     d_uns64 size(Loc loc);
138     bool checkOverlappedFields();
139     bool fill(Loc loc, Expressions *elements, bool ctorinit);
140     static void alignmember(structalign_t salign, unsigned size, unsigned *poffset);
141     static unsigned placeField(unsigned *nextoffset,
142         unsigned memsize, unsigned memalignsize, structalign_t memalign,
143         unsigned *paggsize, unsigned *paggalignsize, bool isunion);
144     Type *getType();
145     bool isDeprecated();         // is aggregate deprecated?
146     bool isNested();
147     void makeNested();
148     bool isExport() const;
149     Dsymbol *searchCtor();
150 
151     Prot prot();
152 
153     // 'this' type
handleType()154     Type *handleType() { return type; }
155 
156     // Back end
157     Symbol *stag;               // tag symbol for debug data
158     Symbol *sinit;
159 
isAggregateDeclaration()160     AggregateDeclaration *isAggregateDeclaration() { return this; }
accept(Visitor * v)161     void accept(Visitor *v) { v->visit(this); }
162 };
163 
164 struct StructFlags
165 {
166     typedef unsigned Type;
167     enum Enum
168     {
169         none = 0x0,
170         hasPointers = 0x1  // NB: should use noPointers as in ClassFlags
171     };
172 };
173 
174 class StructDeclaration : public AggregateDeclaration
175 {
176 public:
177     int zeroInit;               // !=0 if initialize with 0 fill
178     bool hasIdentityAssign;     // true if has identity opAssign
179     bool hasIdentityEquals;     // true if has identity opEquals
180     FuncDeclarations postblits; // Array of postblit functions
181     FuncDeclaration *postblit;  // aggregate postblit
182 
183     FuncDeclaration *xeq;       // TypeInfo_Struct.xopEquals
184     FuncDeclaration *xcmp;      // TypeInfo_Struct.xopCmp
185     FuncDeclaration *xhash;     // TypeInfo_Struct.xtoHash
186     static FuncDeclaration *xerreq;      // object.xopEquals
187     static FuncDeclaration *xerrcmp;     // object.xopCmp
188 
189     structalign_t alignment;    // alignment applied outside of the struct
190     StructPOD ispod;            // if struct is POD
191 
192     // For 64 bit Efl function call/return ABI
193     Type *arg1type;
194     Type *arg2type;
195 
196     // Even if struct is defined as non-root symbol, some built-in operations
197     // (e.g. TypeidExp, NewExp, ArrayLiteralExp, etc) request its TypeInfo.
198     // For those, today TypeInfo_Struct is generated in COMDAT.
199     bool requestTypeInfo;
200 
201     StructDeclaration(Loc loc, Identifier *id, bool inObject);
202     static StructDeclaration *create(Loc loc, Identifier *id, bool inObject);
203     Dsymbol *syntaxCopy(Dsymbol *s);
204     void semanticTypeInfoMembers();
205     Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly);
206     const char *kind() const;
207     void finalizeSize();
208     bool fit(Loc loc, Scope *sc, Expressions *elements, Type *stype);
209     bool isPOD();
210 
isStructDeclaration()211     StructDeclaration *isStructDeclaration() { return this; }
accept(Visitor * v)212     void accept(Visitor *v) { v->visit(this); }
213 };
214 
215 class UnionDeclaration : public StructDeclaration
216 {
217 public:
218     UnionDeclaration(Loc loc, Identifier *id);
219     Dsymbol *syntaxCopy(Dsymbol *s);
220     const char *kind() const;
221 
isUnionDeclaration()222     UnionDeclaration *isUnionDeclaration() { return this; }
accept(Visitor * v)223     void accept(Visitor *v) { v->visit(this); }
224 };
225 
226 struct BaseClass
227 {
228     Type *type;                         // (before semantic processing)
229 
230     ClassDeclaration *sym;
231     unsigned offset;                    // 'this' pointer offset
232     // for interfaces: Array of FuncDeclaration's
233     // making up the vtbl[]
234     FuncDeclarations vtbl;
235 
236     DArray<BaseClass> baseInterfaces;   // if BaseClass is an interface, these
237                                         // are a copy of the InterfaceDeclaration::interfaces
238 
239     BaseClass();
240     BaseClass(Type *type);
241 
242     bool fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newinstance);
243     void copyBaseInterfaces(BaseClasses *);
244 };
245 
246 struct ClassFlags
247 {
248     typedef unsigned Type;
249     enum Enum
250     {
251         isCOMclass = 0x1,
252         noPointers = 0x2,
253         hasOffTi = 0x4,
254         hasCtor = 0x8,
255         hasGetMembers = 0x10,
256         hasTypeInfo = 0x20,
257         isAbstract = 0x40,
258         isCPPclass = 0x80,
259         hasDtor = 0x100
260     };
261 };
262 
263 class ClassDeclaration : public AggregateDeclaration
264 {
265 public:
266     static ClassDeclaration *object;
267     static ClassDeclaration *throwable;
268     static ClassDeclaration *exception;
269     static ClassDeclaration *errorException;
270     static ClassDeclaration *cpp_type_info_ptr;
271 
272     ClassDeclaration *baseClass;        // NULL only if this is Object
273     FuncDeclaration *staticCtor;
274     FuncDeclaration *staticDtor;
275     Dsymbols vtbl;                      // Array of FuncDeclaration's making up the vtbl[]
276     Dsymbols vtblFinal;                 // More FuncDeclaration's that aren't in vtbl[]
277 
278     BaseClasses *baseclasses;           // Array of BaseClass's; first is super,
279                                         // rest are Interface's
280 
281     DArray<BaseClass*> interfaces;      // interfaces[interfaces_dim] for this class
282                                         // (does not include baseClass)
283 
284     BaseClasses *vtblInterfaces;        // array of base interfaces that have
285                                         // their own vtbl[]
286 
287     TypeInfoClassDeclaration *vclassinfo;       // the ClassInfo object for this ClassDeclaration
288     bool com;                           // true if this is a COM class (meaning it derives from IUnknown)
289     bool isscope;                       // true if this is a scope class
290     Abstract isabstract;                // 0: fwdref, 1: is abstract class, 2: not abstract
291     int inuse;                          // to prevent recursive attempts
292     Baseok baseok;                      // set the progress of base classes resolving
293     Symbol *cpp_type_info_ptr_sym;      // cached instance of class Id.cpp_type_info_ptr
294 
295     ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses, Dsymbols *members, bool inObject = false);
296     static ClassDeclaration *create(Loc loc, Identifier *id, BaseClasses *baseclasses, Dsymbols *members, bool inObject);
297     Dsymbol *syntaxCopy(Dsymbol *s);
298     Scope *newScope(Scope *sc);
299     bool isBaseOf2(ClassDeclaration *cd);
300 
301     #define OFFSET_RUNTIME 0x76543210
302     #define OFFSET_FWDREF 0x76543211
303     virtual bool isBaseOf(ClassDeclaration *cd, int *poffset);
304 
305     bool isBaseInfoComplete();
306     Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly);
307     ClassDeclaration *searchBase(Identifier *ident);
308     void finalizeSize();
309     bool hasMonitor();
310     bool isFuncHidden(FuncDeclaration *fd);
311     FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf);
312     bool isCOMclass() const;
313     virtual bool isCOMinterface() const;
314     bool isCPPclass() const;
315     virtual bool isCPPinterface() const;
316     bool isAbstract();
317     virtual int vtblOffset() const;
318     const char *kind() const;
319 
320     void addLocalClass(ClassDeclarations *);
321 
322     // Back end
323     Symbol *vtblsym;
324 
isClassDeclaration()325     ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; }
accept(Visitor * v)326     void accept(Visitor *v) { v->visit(this); }
327 };
328 
329 class InterfaceDeclaration : public ClassDeclaration
330 {
331 public:
332     InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses);
333     Dsymbol *syntaxCopy(Dsymbol *s);
334     Scope *newScope(Scope *sc);
335     bool isBaseOf(ClassDeclaration *cd, int *poffset);
336     bool isBaseOf(BaseClass *bc, int *poffset);
337     const char *kind() const;
338     int vtblOffset() const;
339     bool isCPPinterface() const;
340     bool isCOMinterface() const;
341 
isInterfaceDeclaration()342     InterfaceDeclaration *isInterfaceDeclaration() { return this; }
accept(Visitor * v)343     void accept(Visitor *v) { v->visit(this); }
344 };
345