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