1  
       2  /* Compiler implementation of the D programming language
       3   * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved
       4   * written by Walter Bright
       5   * https://www.digitalmars.com
       6   * Distributed under the Boost Software License, Version 1.0.
       7   * https://www.boost.org/LICENSE_1_0.txt
       8   * https://github.com/dlang/dmd/blob/master/src/dmd/dsymbol.h
       9   */
      10  
      11  #pragma once
      12  
      13  #include "root/port.h"
      14  #include "ast_node.h"
      15  #include "globals.h"
      16  #include "arraytypes.h"
      17  #include "visitor.h"
      18  
      19  class CPPNamespaceDeclaration;
      20  class Identifier;
      21  struct Scope;
      22  class DsymbolTable;
      23  class Declaration;
      24  class ThisDeclaration;
      25  class BitFieldDeclaration;
      26  class TypeInfoDeclaration;
      27  class TupleDeclaration;
      28  class AliasDeclaration;
      29  class AggregateDeclaration;
      30  class EnumDeclaration;
      31  class ClassDeclaration;
      32  class InterfaceDeclaration;
      33  class StructDeclaration;
      34  class UnionDeclaration;
      35  class FuncDeclaration;
      36  class FuncAliasDeclaration;
      37  class OverDeclaration;
      38  class FuncLiteralDeclaration;
      39  class CtorDeclaration;
      40  class PostBlitDeclaration;
      41  class DtorDeclaration;
      42  class StaticCtorDeclaration;
      43  class StaticDtorDeclaration;
      44  class SharedStaticCtorDeclaration;
      45  class SharedStaticDtorDeclaration;
      46  class InvariantDeclaration;
      47  class UnitTestDeclaration;
      48  class NewDeclaration;
      49  class VarDeclaration;
      50  class AttribDeclaration;
      51  class VisibilityDeclaration;
      52  class Package;
      53  class Module;
      54  class Import;
      55  class Type;
      56  class TypeTuple;
      57  class WithStatement;
      58  class LabelDsymbol;
      59  class ScopeDsymbol;
      60  class ForwardingScopeDsymbol;
      61  class TemplateDeclaration;
      62  class TemplateInstance;
      63  class TemplateMixin;
      64  class ForwardingAttribDeclaration;
      65  class Nspace;
      66  class EnumMember;
      67  class WithScopeSymbol;
      68  class ArrayScopeSymbol;
      69  class SymbolDeclaration;
      70  class Expression;
      71  class ExpressionDsymbol;
      72  class AliasAssign;
      73  class OverloadSet;
      74  class StaticAssert;
      75  class StaticIfDeclaration;
      76  struct AA;
      77  #ifdef IN_GCC
      78  typedef union tree_node Symbol;
      79  #else
      80  struct Symbol;
      81  #endif
      82  
      83  struct Ungag
      84  {
      85      unsigned oldgag;
      86  
      87      Ungag(unsigned old) : oldgag(old) {}
      88      ~Ungag() { global.gag = oldgag; }
      89  };
      90  
      91  enum class ThreeState : uint8_t
      92  {
      93      none,         // value not yet computed
      94      no,           // value is false
      95      yes,          // value is true
      96  };
      97  
      98  void dsymbolSemantic(Dsymbol *dsym, Scope *sc);
      99  void semantic2(Dsymbol *dsym, Scope *sc);
     100  void semantic3(Dsymbol *dsym, Scope* sc);
     101  
     102  struct Visibility
     103  {
     104      enum Kind
     105      {
     106          undefined,
     107          none,           // no access
     108          private_,
     109          package_,
     110          protected_,
     111          public_,
     112          export_
     113      };
     114      Kind kind;
     115      Package *pkg;
     116  };
     117  
     118  /* State of symbol in winding its way through the passes of the compiler
     119   */
     120  enum class PASS : uint8_t
     121  {
     122      initial,        // initial state
     123      semantic,       // semantic() started
     124      semanticdone,   // semantic() done
     125      semantic2,      // semantic2() started
     126      semantic2done,  // semantic2() done
     127      semantic3,      // semantic3() started
     128      semantic3done,  // semantic3() done
     129      inline_,         // inline started
     130      inlinedone,     // inline done
     131      obj             // toObjFile() run
     132  };
     133  
     134  enum
     135  {
     136      PASSinit,           // initial state
     137      PASSsemantic,       // semantic() started
     138      PASSsemanticdone,   // semantic() done
     139      PASSsemantic2,      // semantic2() started
     140      PASSsemantic2done,  // semantic2() done
     141      PASSsemantic3,      // semantic3() started
     142      PASSsemantic3done,  // semantic3() done
     143      PASSinline,         // inline started
     144      PASSinlinedone,     // inline done
     145      PASSobj             // toObjFile() run
     146  };
     147  
     148  /* Flags for symbol search
     149   */
     150  enum
     151  {
     152      IgnoreNone              = 0x00, // default
     153      IgnorePrivateImports    = 0x01, // don't search private imports
     154      IgnoreErrors            = 0x02, // don't give error messages
     155      IgnoreAmbiguous         = 0x04, // return NULL if ambiguous
     156      SearchLocalsOnly        = 0x08, // only look at locals (don't search imports)
     157      SearchImportsOnly       = 0x10, // only look in imports
     158      SearchUnqualifiedModule = 0x20, // the module scope search is unqualified,
     159                                      // meaning don't search imports in that scope,
     160                                      // because qualified module searches search
     161                                      // their imports
     162      IgnoreSymbolVisibility  = 0x80,  // also find private and package protected symbols
     163      TagNameSpace            = 0x100, // search ImportC tag symbol table
     164  };
     165  
     166  struct FieldState
     167  {
     168      unsigned offset;
     169  
     170      unsigned fieldOffset;
     171      unsigned fieldSize;
     172      unsigned fieldAlign;
     173      unsigned bitOffset;
     174  
     175      d_bool inFlight;
     176  };
     177  
     178  struct DsymbolAttributes;
     179  
     180  class Dsymbol : public ASTNode
     181  {
     182  public:
     183      Identifier *ident;
     184      Dsymbol *parent;
     185      Symbol *csym;               // symbol for code generator
     186      Loc loc;                    // where defined
     187      Scope *_scope;               // !=NULL means context to use for semantic()
     188      const utf8_t *prettystring;
     189  private:
     190      DsymbolAttributes* atts;
     191  public:
     192      d_bool errors;                // this symbol failed to pass semantic()
     193      PASS semanticRun;
     194      unsigned short localNum;        // perturb mangled name to avoid collisions with those in FuncDeclaration.localsymtab
     195      static Dsymbol *create(Identifier *);
     196      const char *toChars() const override;
     197      DeprecatedDeclaration* depdecl();
     198      CPPNamespaceDeclaration* cppnamespace();
     199      UserAttributeDeclaration* userAttribDecl();
     200      DeprecatedDeclaration* depdecl(DeprecatedDeclaration* dd);
     201      CPPNamespaceDeclaration* cppnamespace(CPPNamespaceDeclaration* ns);
     202      UserAttributeDeclaration* userAttribDecl(UserAttributeDeclaration* uad);
     203      virtual const char *toPrettyCharsHelper(); // helper to print fully qualified (template) arguments
     204      Loc getLoc();
     205      const char *locToChars();
     206      bool equals(const RootObject * const o) const override;
     207      bool isAnonymous() const;
     208      void error(const Loc &loc, const char *format, ...);
     209      void error(const char *format, ...);
     210      void deprecation(const Loc &loc, const char *format, ...);
     211      void deprecation(const char *format, ...);
     212      bool checkDeprecated(const Loc &loc, Scope *sc);
     213      Module *getModule();
     214      bool isCsymbol();
     215      Module *getAccessModule();
     216      Dsymbol *pastMixin();
     217      Dsymbol *toParent();
     218      Dsymbol *toParent2();
     219      Dsymbol *toParentDecl();
     220      Dsymbol *toParentLocal();
     221      Dsymbol *toParentP(Dsymbol *p1, Dsymbol *p2 = NULL);
     222      TemplateInstance *isInstantiated();
     223      bool followInstantiationContext(Dsymbol *p1, Dsymbol *p2 = NULL);
     224      TemplateInstance *isSpeculative();
     225      Ungag ungagSpeculative();
     226  
     227      // kludge for template.isSymbol()
     228      DYNCAST dyncast() const override final { return DYNCAST_DSYMBOL; }
     229  
     230      virtual Identifier *getIdent();
     231      virtual const char *toPrettyChars(bool QualifyTypes = false);
     232      virtual const char *kind() const;
     233      virtual Dsymbol *toAlias();                 // resolve real symbol
     234      virtual Dsymbol *toAlias2();
     235      virtual void addMember(Scope *sc, ScopeDsymbol *sds);
     236      virtual void setScope(Scope *sc);
     237      virtual void importAll(Scope *sc);
     238      virtual Dsymbol *search(const Loc &loc, Identifier *ident, int flags = IgnoreNone);
     239      virtual bool overloadInsert(Dsymbol *s);
     240      virtual uinteger_t size(const Loc &loc);
     241      virtual bool isforwardRef();
     242      virtual AggregateDeclaration *isThis();     // is a 'this' required to access the member
     243      virtual bool isExport() const;              // is Dsymbol exported?
     244      virtual bool isImportedSymbol() const;      // is Dsymbol imported?
     245      virtual bool isDeprecated() const;                // is Dsymbol deprecated?
     246      virtual bool isOverloadable() const;
     247      virtual LabelDsymbol *isLabel();            // is this a LabelDsymbol?
     248      AggregateDeclaration *isMember();           // is toParent() an AggregateDeclaration?
     249      AggregateDeclaration *isMember2();          // is toParent2() an AggregateDeclaration?
     250      AggregateDeclaration *isMemberDecl();       // is toParentDecl() an AggregateDeclaration?
     251      AggregateDeclaration *isMemberLocal();      // is toParentLocal() an AggregateDeclaration?
     252      ClassDeclaration *isClassMember();          // isMember() is a ClassDeclaration?
     253      virtual Type *getType();                    // is this a type?
     254      virtual bool needThis();                    // need a 'this' pointer?
     255      virtual Visibility visible();
     256      virtual Dsymbol *syntaxCopy(Dsymbol *s);    // copy only syntax trees
     257      virtual bool oneMember(Dsymbol **ps, Identifier *ident);
     258      virtual void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion);
     259      virtual bool hasPointers();
     260      virtual bool hasStaticCtorOrDtor();
     261      virtual void addObjcSymbols(ClassDeclarations *, ClassDeclarations *) { }
     262      virtual void checkCtorConstInit() { }
     263  
     264      virtual void addComment(const utf8_t *comment);
     265      const utf8_t *comment();                      // current value of comment
     266  
     267      UnitTestDeclaration *ddocUnittest();
     268      void ddocUnittest(UnitTestDeclaration *);
     269  
     270      bool inNonRoot();
     271  
     272      // Eliminate need for dynamic_cast
     273      virtual Package *isPackage() { return NULL; }
     274      virtual Module *isModule() { return NULL; }
     275      virtual EnumMember *isEnumMember() { return NULL; }
     276      virtual TemplateDeclaration *isTemplateDeclaration() { return NULL; }
     277      virtual TemplateInstance *isTemplateInstance() { return NULL; }
     278      virtual TemplateMixin *isTemplateMixin() { return NULL; }
     279      virtual ForwardingAttribDeclaration *isForwardingAttribDeclaration() { return NULL; }
     280      virtual Nspace *isNspace() { return NULL; }
     281      virtual Declaration *isDeclaration() { return NULL; }
     282      virtual StorageClassDeclaration *isStorageClassDeclaration(){ return NULL; }
     283      virtual ExpressionDsymbol *isExpressionDsymbol() { return NULL; }
     284      virtual AliasAssign *isAliasAssign() { return NULL; }
     285      virtual ThisDeclaration *isThisDeclaration() { return NULL; }
     286      virtual BitFieldDeclaration *isBitFieldDeclaration() { return NULL; }
     287      virtual TypeInfoDeclaration *isTypeInfoDeclaration() { return NULL; }
     288      virtual TupleDeclaration *isTupleDeclaration() { return NULL; }
     289      virtual AliasDeclaration *isAliasDeclaration() { return NULL; }
     290      virtual AggregateDeclaration *isAggregateDeclaration() { return NULL; }
     291      virtual FuncDeclaration *isFuncDeclaration() { return NULL; }
     292      virtual FuncAliasDeclaration *isFuncAliasDeclaration() { return NULL; }
     293      virtual OverDeclaration *isOverDeclaration() { return NULL; }
     294      virtual FuncLiteralDeclaration *isFuncLiteralDeclaration() { return NULL; }
     295      virtual CtorDeclaration *isCtorDeclaration() { return NULL; }
     296      virtual PostBlitDeclaration *isPostBlitDeclaration() { return NULL; }
     297      virtual DtorDeclaration *isDtorDeclaration() { return NULL; }
     298      virtual StaticCtorDeclaration *isStaticCtorDeclaration() { return NULL; }
     299      virtual StaticDtorDeclaration *isStaticDtorDeclaration() { return NULL; }
     300      virtual SharedStaticCtorDeclaration *isSharedStaticCtorDeclaration() { return NULL; }
     301      virtual SharedStaticDtorDeclaration *isSharedStaticDtorDeclaration() { return NULL; }
     302      virtual InvariantDeclaration *isInvariantDeclaration() { return NULL; }
     303      virtual UnitTestDeclaration *isUnitTestDeclaration() { return NULL; }
     304      virtual NewDeclaration *isNewDeclaration() { return NULL; }
     305      virtual VarDeclaration *isVarDeclaration() { return NULL; }
     306      virtual VersionSymbol *isVersionSymbol() { return NULL; }
     307      virtual DebugSymbol *isDebugSymbol() { return NULL; }
     308      virtual ClassDeclaration *isClassDeclaration() { return NULL; }
     309      virtual StructDeclaration *isStructDeclaration() { return NULL; }
     310      virtual UnionDeclaration *isUnionDeclaration() { return NULL; }
     311      virtual InterfaceDeclaration *isInterfaceDeclaration() { return NULL; }
     312      virtual ScopeDsymbol *isScopeDsymbol() { return NULL; }
     313      virtual ForwardingScopeDsymbol *isForwardingScopeDsymbol() { return NULL; }
     314      virtual WithScopeSymbol *isWithScopeSymbol() { return NULL; }
     315      virtual ArrayScopeSymbol *isArrayScopeSymbol() { return NULL; }
     316      virtual Import *isImport() { return NULL; }
     317      virtual EnumDeclaration *isEnumDeclaration() { return NULL; }
     318      virtual SymbolDeclaration *isSymbolDeclaration() { return NULL; }
     319      virtual AttribDeclaration *isAttribDeclaration() { return NULL; }
     320      virtual AnonDeclaration *isAnonDeclaration() { return NULL; }
     321      virtual CPPNamespaceDeclaration *isCPPNamespaceDeclaration() { return NULL; }
     322      virtual VisibilityDeclaration *isVisibilityDeclaration() { return NULL; }
     323      virtual OverloadSet *isOverloadSet() { return NULL; }
     324      virtual CompileDeclaration *isCompileDeclaration() { return NULL; }
     325      virtual StaticAssert *isStaticAssert() { return NULL; }
     326      virtual StaticIfDeclaration *isStaticIfDeclaration() { return NULL; }
     327      void accept(Visitor *v) override { v->visit(this); }
     328  };
     329  
     330  // Dsymbol that generates a scope
     331  
     332  class ScopeDsymbol : public Dsymbol
     333  {
     334  public:
     335      Dsymbols *members;          // all Dsymbol's in this scope
     336      DsymbolTable *symtab;       // members[] sorted into table
     337      unsigned endlinnum;         // the linnumber of the statement after the scope (0 if unknown)
     338  
     339  private:
     340      Dsymbols *importedScopes;   // imported Dsymbol's
     341      Visibility::Kind *visibilities;   // array of `Visibility.Kind`, one for each import
     342  
     343      BitArray accessiblePackages, privateAccessiblePackages;
     344  
     345  public:
     346      ScopeDsymbol *syntaxCopy(Dsymbol *s) override;
     347      Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override;
     348      virtual void importScope(Dsymbol *s, Visibility visibility);
     349      virtual bool isPackageAccessible(Package *p, Visibility visibility, int flags = 0);
     350      bool isforwardRef() override final;
     351      static void multiplyDefined(const Loc &loc, Dsymbol *s1, Dsymbol *s2);
     352      const char *kind() const override;
     353      FuncDeclaration *findGetMembers();
     354      virtual Dsymbol *symtabInsert(Dsymbol *s);
     355      virtual Dsymbol *symtabLookup(Dsymbol *s, Identifier *id);
     356      bool hasStaticCtorOrDtor() override;
     357  
     358      ScopeDsymbol *isScopeDsymbol() override final { return this; }
     359      void accept(Visitor *v) override { v->visit(this); }
     360  };
     361  
     362  // With statement scope
     363  
     364  class WithScopeSymbol final : public ScopeDsymbol
     365  {
     366  public:
     367      WithStatement *withstate;
     368  
     369      Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override;
     370  
     371      WithScopeSymbol *isWithScopeSymbol() override { return this; }
     372      void accept(Visitor *v) override { v->visit(this); }
     373  };
     374  
     375  // Array Index/Slice scope
     376  
     377  class ArrayScopeSymbol final : public ScopeDsymbol
     378  {
     379  private:
     380      RootObject *arrayContent;
     381  public:
     382      Scope *sc;
     383  
     384      Dsymbol *search(const Loc &loc, Identifier *ident, int flags = IgnoreNone) override;
     385  
     386      ArrayScopeSymbol *isArrayScopeSymbol() override { return this; }
     387      void accept(Visitor *v) override { v->visit(this); }
     388  };
     389  
     390  // Overload Sets
     391  
     392  class OverloadSet final : public Dsymbol
     393  {
     394  public:
     395      Dsymbols a;         // array of Dsymbols
     396  
     397      void push(Dsymbol *s);
     398      OverloadSet *isOverloadSet() override { return this; }
     399      const char *kind() const override;
     400      void accept(Visitor *v) override { v->visit(this); }
     401  };
     402  
     403  // Forwarding ScopeDsymbol
     404  
     405  class ForwardingScopeDsymbol final : public ScopeDsymbol
     406  {
     407  public:
     408      Dsymbol *symtabInsert(Dsymbol *s) override;
     409      Dsymbol *symtabLookup(Dsymbol *s, Identifier *id) override;
     410      void importScope(Dsymbol *s, Visibility visibility) override;
     411      const char *kind() const override;
     412  
     413      ForwardingScopeDsymbol *isForwardingScopeDsymbol() override { return this; }
     414  };
     415  
     416  class ExpressionDsymbol final : public Dsymbol
     417  {
     418  public:
     419      Expression *exp;
     420  
     421      ExpressionDsymbol *isExpressionDsymbol() override { return this; }
     422  };
     423  
     424  // Table of Dsymbol's
     425  
     426  class DsymbolTable final : public RootObject
     427  {
     428  public:
     429      AA *tab;
     430  
     431      // Look up Identifier. Return Dsymbol if found, NULL if not.
     432      Dsymbol *lookup(Identifier const * const ident);
     433  
     434      // Look for Dsymbol in table. If there, return it. If not, insert s and return that.
     435      void update(Dsymbol *s);
     436  
     437      // Insert Dsymbol in table. Return NULL if already there.
     438      Dsymbol *insert(Dsymbol *s);
     439      Dsymbol *insert(Identifier const * const ident, Dsymbol *s);     // when ident and s are not the same
     440  
     441      // Number of symbols in symbol table
     442      size_t length() const;
     443  };