/* Compiler implementation of the D programming language * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved * written by Walter Bright * http://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. * http://www.boost.org/LICENSE_1_0.txt * https://github.com/dlang/dmd/blob/master/src/dmd/aggregate.h */ #pragma once #include "root/root.h" #include "dsymbol.h" #include "declaration.h" #include "objc.h" class Identifier; class Type; class TypeFunction; class Expression; class FuncDeclaration; class CtorDeclaration; class DtorDeclaration; class InvariantDeclaration; class NewDeclaration; class DeleteDeclaration; class InterfaceDeclaration; class TypeInfoClassDeclaration; class VarDeclaration; enum Sizeok { SIZEOKnone, // size of aggregate is not yet able to compute SIZEOKfwd, // size of aggregate is ready to compute SIZEOKdone // size of aggregate is set correctly }; enum Baseok { BASEOKnone, // base classes not computed yet BASEOKin, // in process of resolving base classes BASEOKdone, // all base classes are resolved BASEOKsemanticdone // all base classes semantic done }; enum StructPOD { ISPODno, // struct is not POD ISPODyes, // struct is POD ISPODfwd // POD not yet computed }; enum Abstract { ABSfwdref = 0, // whether an abstract class is not yet computed ABSyes, // is abstract class ABSno // is not abstract class }; FuncDeclaration *hasIdentityOpAssign(AggregateDeclaration *ad, Scope *sc); FuncDeclaration *buildOpAssign(StructDeclaration *sd, Scope *sc); bool needOpEquals(StructDeclaration *sd); FuncDeclaration *buildOpEquals(StructDeclaration *sd, Scope *sc); FuncDeclaration *buildXopEquals(StructDeclaration *sd, Scope *sc); FuncDeclaration *buildXopCmp(StructDeclaration *sd, Scope *sc); FuncDeclaration *buildXtoHash(StructDeclaration *ad, Scope *sc); FuncDeclaration *buildPostBlit(StructDeclaration *sd, Scope *sc); FuncDeclaration *buildDtor(AggregateDeclaration *ad, Scope *sc); FuncDeclaration *buildInv(AggregateDeclaration *ad, Scope *sc); FuncDeclaration *search_toString(StructDeclaration *sd); struct ClassKind { enum Type { /// the class is a d(efault) class d, /// the class is a C++ interface cpp, /// the class is an Objective-C class/interface objc, }; }; class AggregateDeclaration : public ScopeDsymbol { public: Type *type; StorageClass storage_class; Prot protection; unsigned structsize; // size of struct unsigned alignsize; // size of struct for alignment purposes VarDeclarations fields; // VarDeclaration fields Sizeok sizeok; // set when structsize contains valid data Dsymbol *deferred; // any deferred semantic2() or semantic3() symbol bool isdeprecated; // true if deprecated ClassKind::Type classKind; // specifies the linkage type /* !=NULL if is nested * pointing to the dsymbol that directly enclosing it. * 1. The function that enclosing it (nested struct and class) * 2. The class that enclosing it (nested class only) * 3. If enclosing aggregate is template, its enclosing dsymbol. * See AggregateDeclaraton::makeNested for the details. */ Dsymbol *enclosing; VarDeclaration *vthis; // 'this' parameter if this aggregate is nested // Special member functions FuncDeclarations invs; // Array of invariants FuncDeclaration *inv; // invariant NewDeclaration *aggNew; // allocator DeleteDeclaration *aggDelete; // deallocator Dsymbol *ctor; // CtorDeclaration or TemplateDeclaration // default constructor - should have no arguments, because // it would be stored in TypeInfo_Class.defaultConstructor CtorDeclaration *defaultCtor; Dsymbol *aliasthis; // forward unresolved lookups to aliasthis bool noDefaultCtor; // no default construction FuncDeclarations dtors; // Array of destructors FuncDeclaration *dtor; // aggregate destructor Expression *getRTInfo; // pointer to GC info generated by object.RTInfo(this) AggregateDeclaration(Loc loc, Identifier *id); virtual Scope *newScope(Scope *sc); void setScope(Scope *sc); void semantic2(Scope *sc); void semantic3(Scope *sc); bool determineFields(); bool determineSize(Loc loc); virtual void finalizeSize() = 0; d_uns64 size(Loc loc); bool checkOverlappedFields(); bool fill(Loc loc, Expressions *elements, bool ctorinit); static void alignmember(structalign_t salign, unsigned size, unsigned *poffset); static unsigned placeField(unsigned *nextoffset, unsigned memsize, unsigned memalignsize, structalign_t memalign, unsigned *paggsize, unsigned *paggalignsize, bool isunion); Type *getType(); bool isDeprecated(); // is aggregate deprecated? bool isNested(); void makeNested(); bool isExport() const; Dsymbol *searchCtor(); Prot prot(); // 'this' type Type *handleType() { return type; } // Back end Symbol *stag; // tag symbol for debug data Symbol *sinit; AggregateDeclaration *isAggregateDeclaration() { return this; } void accept(Visitor *v) { v->visit(this); } }; struct StructFlags { typedef unsigned Type; enum Enum { none = 0x0, hasPointers = 0x1 // NB: should use noPointers as in ClassFlags }; }; class StructDeclaration : public AggregateDeclaration { public: int zeroInit; // !=0 if initialize with 0 fill bool hasIdentityAssign; // true if has identity opAssign bool hasIdentityEquals; // true if has identity opEquals FuncDeclarations postblits; // Array of postblit functions FuncDeclaration *postblit; // aggregate postblit FuncDeclaration *xeq; // TypeInfo_Struct.xopEquals FuncDeclaration *xcmp; // TypeInfo_Struct.xopCmp FuncDeclaration *xhash; // TypeInfo_Struct.xtoHash static FuncDeclaration *xerreq; // object.xopEquals static FuncDeclaration *xerrcmp; // object.xopCmp structalign_t alignment; // alignment applied outside of the struct StructPOD ispod; // if struct is POD // For 64 bit Efl function call/return ABI Type *arg1type; Type *arg2type; // Even if struct is defined as non-root symbol, some built-in operations // (e.g. TypeidExp, NewExp, ArrayLiteralExp, etc) request its TypeInfo. // For those, today TypeInfo_Struct is generated in COMDAT. bool requestTypeInfo; StructDeclaration(Loc loc, Identifier *id, bool inObject); static StructDeclaration *create(Loc loc, Identifier *id, bool inObject); Dsymbol *syntaxCopy(Dsymbol *s); void semantic(Scope *sc); void semanticTypeInfoMembers(); Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly); const char *kind() const; void finalizeSize(); bool fit(Loc loc, Scope *sc, Expressions *elements, Type *stype); bool isPOD(); StructDeclaration *isStructDeclaration() { return this; } void accept(Visitor *v) { v->visit(this); } }; class UnionDeclaration : public StructDeclaration { public: UnionDeclaration(Loc loc, Identifier *id); Dsymbol *syntaxCopy(Dsymbol *s); const char *kind() const; UnionDeclaration *isUnionDeclaration() { return this; } void accept(Visitor *v) { v->visit(this); } }; struct BaseClass { Type *type; // (before semantic processing) ClassDeclaration *sym; unsigned offset; // 'this' pointer offset // for interfaces: Array of FuncDeclaration's // making up the vtbl[] FuncDeclarations vtbl; DArray baseInterfaces; // if BaseClass is an interface, these // are a copy of the InterfaceDeclaration::interfaces BaseClass(); BaseClass(Type *type); bool fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newinstance); void copyBaseInterfaces(BaseClasses *); }; struct ClassFlags { typedef unsigned Type; enum Enum { isCOMclass = 0x1, noPointers = 0x2, hasOffTi = 0x4, hasCtor = 0x8, hasGetMembers = 0x10, hasTypeInfo = 0x20, isAbstract = 0x40, isCPPclass = 0x80, hasDtor = 0x100 }; }; class ClassDeclaration : public AggregateDeclaration { public: static ClassDeclaration *object; static ClassDeclaration *throwable; static ClassDeclaration *exception; static ClassDeclaration *errorException; static ClassDeclaration *cpp_type_info_ptr; ClassDeclaration *baseClass; // NULL only if this is Object FuncDeclaration *staticCtor; FuncDeclaration *staticDtor; Dsymbols vtbl; // Array of FuncDeclaration's making up the vtbl[] Dsymbols vtblFinal; // More FuncDeclaration's that aren't in vtbl[] BaseClasses *baseclasses; // Array of BaseClass's; first is super, // rest are Interface's DArray interfaces; // interfaces[interfaces_dim] for this class // (does not include baseClass) BaseClasses *vtblInterfaces; // array of base interfaces that have // their own vtbl[] TypeInfoClassDeclaration *vclassinfo; // the ClassInfo object for this ClassDeclaration bool com; // true if this is a COM class (meaning it derives from IUnknown) bool isscope; // true if this is a scope class Abstract isabstract; // 0: fwdref, 1: is abstract class, 2: not abstract int inuse; // to prevent recursive attempts Baseok baseok; // set the progress of base classes resolving Symbol *cpp_type_info_ptr_sym; // cached instance of class Id.cpp_type_info_ptr ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses, Dsymbols *members, bool inObject = false); static ClassDeclaration *create(Loc loc, Identifier *id, BaseClasses *baseclasses, Dsymbols *members, bool inObject); Dsymbol *syntaxCopy(Dsymbol *s); Scope *newScope(Scope *sc); void semantic(Scope *sc); bool isBaseOf2(ClassDeclaration *cd); #define OFFSET_RUNTIME 0x76543210 #define OFFSET_FWDREF 0x76543211 virtual bool isBaseOf(ClassDeclaration *cd, int *poffset); bool isBaseInfoComplete(); Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly); ClassDeclaration *searchBase(Identifier *ident); void finalizeSize(); bool isFuncHidden(FuncDeclaration *fd); FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf); void interfaceSemantic(Scope *sc); bool isCOMclass() const; virtual bool isCOMinterface() const; bool isCPPclass() const; virtual bool isCPPinterface() const; bool isAbstract(); virtual int vtblOffset() const; const char *kind() const; void addLocalClass(ClassDeclarations *); // Back end Symbol *vtblsym; ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; } void accept(Visitor *v) { v->visit(this); } }; class InterfaceDeclaration : public ClassDeclaration { public: InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses); Dsymbol *syntaxCopy(Dsymbol *s); Scope *newScope(Scope *sc); void semantic(Scope *sc); bool isBaseOf(ClassDeclaration *cd, int *poffset); bool isBaseOf(BaseClass *bc, int *poffset); const char *kind() const; int vtblOffset() const; bool isCPPinterface() const; bool isCOMinterface() const; InterfaceDeclaration *isInterfaceDeclaration() { return this; } void accept(Visitor *v) { v->visit(this); } };