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/dsymbol.h
9  */
10 
11 #pragma once
12 
13 #include "root/root.h"
14 #include "root/stringtable.h"
15 
16 #include "globals.h"
17 #include "arraytypes.h"
18 #include "visitor.h"
19 
20 class Identifier;
21 struct Scope;
22 class DsymbolTable;
23 class Declaration;
24 class ThisDeclaration;
25 class TypeInfoDeclaration;
26 class TupleDeclaration;
27 class AliasDeclaration;
28 class AggregateDeclaration;
29 class EnumDeclaration;
30 class ClassDeclaration;
31 class InterfaceDeclaration;
32 class StructDeclaration;
33 class UnionDeclaration;
34 class FuncDeclaration;
35 class FuncAliasDeclaration;
36 class OverDeclaration;
37 class FuncLiteralDeclaration;
38 class CtorDeclaration;
39 class PostBlitDeclaration;
40 class DtorDeclaration;
41 class StaticCtorDeclaration;
42 class StaticDtorDeclaration;
43 class SharedStaticCtorDeclaration;
44 class SharedStaticDtorDeclaration;
45 class InvariantDeclaration;
46 class UnitTestDeclaration;
47 class NewDeclaration;
48 class VarDeclaration;
49 class AttribDeclaration;
50 class Package;
51 class Module;
52 class Import;
53 class Type;
54 class TypeTuple;
55 class WithStatement;
56 class LabelDsymbol;
57 class ScopeDsymbol;
58 class ForwardingScopeDsymbol;
59 class TemplateDeclaration;
60 class TemplateInstance;
61 class TemplateMixin;
62 class ForwardingAttribDeclaration;
63 class Nspace;
64 class EnumMember;
65 class WithScopeSymbol;
66 class ArrayScopeSymbol;
67 class SymbolDeclaration;
68 class Expression;
69 class DeleteDeclaration;
70 class OverloadSet;
71 struct AA;
72 #ifdef IN_GCC
73 typedef union tree_node Symbol;
74 #else
75 struct Symbol;
76 #endif
77 
78 struct Ungag
79 {
80     unsigned oldgag;
81 
UngagUngag82     Ungag(unsigned old) : oldgag(old) {}
~UngagUngag83     ~Ungag() { global.gag = oldgag; }
84 };
85 
86 enum PROTKIND
87 {
88     PROTundefined,
89     PROTnone,           // no access
90     PROTprivate,
91     PROTpackage,
92     PROTprotected,
93     PROTpublic,
94     PROTexport
95 };
96 
97 struct Prot
98 {
99     PROTKIND kind;
100     Package *pkg;
101 
102     Prot();
103     Prot(PROTKIND kind);
104 
105     bool isMoreRestrictiveThan(const Prot other) const;
106     bool operator==(const Prot& other) const;
107     bool isSubsetOf(const Prot& other) const;
108 };
109 
110 // in hdrgen.c
111 void protectionToBuffer(OutBuffer *buf, Prot prot);
112 const char *protectionToChars(PROTKIND kind);
113 
114 /* State of symbol in winding its way through the passes of the compiler
115  */
116 enum PASS
117 {
118     PASSinit,           // initial state
119     PASSsemantic,       // semantic() started
120     PASSsemanticdone,   // semantic() done
121     PASSsemantic2,      // semantic2() started
122     PASSsemantic2done,  // semantic2() done
123     PASSsemantic3,      // semantic3() started
124     PASSsemantic3done,  // semantic3() done
125     PASSinline,         // inline started
126     PASSinlinedone,     // inline done
127     PASSobj             // toObjFile() run
128 };
129 
130 /* Flags for symbol search
131  */
132 enum
133 {
134     IgnoreNone              = 0x00, // default
135     IgnorePrivateImports    = 0x01, // don't search private imports
136     IgnoreErrors            = 0x02, // don't give error messages
137     IgnoreAmbiguous         = 0x04, // return NULL if ambiguous
138     SearchLocalsOnly        = 0x08, // only look at locals (don't search imports)
139     SearchImportsOnly       = 0x10, // only look in imports
140     SearchUnqualifiedModule = 0x20, // the module scope search is unqualified,
141                                     // meaning don't search imports in that scope,
142                                     // because qualified module searches search
143                                     // their imports
144     IgnoreSymbolVisibility  = 0x80  // also find private and package protected symbols
145 };
146 
147 typedef int (*Dsymbol_apply_ft_t)(Dsymbol *, void *);
148 
149 class Dsymbol : public RootObject
150 {
151 public:
152     Identifier *ident;
153     Dsymbol *parent;
154     Symbol *csym;               // symbol for code generator
155     Symbol *isym;               // import version of csym
156     const utf8_t *comment;      // documentation comment for this Dsymbol
157     Loc loc;                    // where defined
158     Scope *_scope;               // !=NULL means context to use for semantic()
159     const utf8_t *prettystring;
160     bool errors;                // this symbol failed to pass semantic()
161     PASS semanticRun;
162     DeprecatedDeclaration *depdecl; // customized deprecation message
163     UserAttributeDeclaration *userAttribDecl;   // user defined attributes
164     UnitTestDeclaration *ddocUnittest; // !=NULL means there's a ddoc unittest associated with this symbol (only use this with ddoc)
165 
166     Dsymbol();
167     Dsymbol(Identifier *);
168     static Dsymbol *create(Identifier *);
169     const char *toChars();
170     virtual const char *toPrettyCharsHelper(); // helper to print fully qualified (template) arguments
171     Loc& getLoc();
172     const char *locToChars();
173     bool equals(RootObject *o);
174     bool isAnonymous();
175     void error(Loc loc, const char *format, ...);
176     void error(const char *format, ...);
177     void deprecation(Loc loc, const char *format, ...);
178     void deprecation(const char *format, ...);
179     void checkDeprecated(Loc loc, Scope *sc);
180     Module *getModule();
181     Module *getAccessModule();
182     Dsymbol *pastMixin();
183     Dsymbol *pastMixinAndNspace();
184     Dsymbol *toParent();
185     Dsymbol *toParent2();
186     Dsymbol *toParent3();
187     TemplateInstance *isInstantiated();
188     TemplateInstance *isSpeculative();
189     Ungag ungagSpeculative();
190 
191     // kludge for template.isSymbol()
dyncast()192     int dyncast() const { return DYNCAST_DSYMBOL; }
193 
194     static Dsymbols *arraySyntaxCopy(Dsymbols *a);
195 
196     virtual Identifier *getIdent();
197     virtual const char *toPrettyChars(bool QualifyTypes = false);
198     virtual const char *kind() const;
199     virtual Dsymbol *toAlias();                 // resolve real symbol
200     virtual Dsymbol *toAlias2();
201     virtual int apply(Dsymbol_apply_ft_t fp, void *param);
202     virtual void addMember(Scope *sc, ScopeDsymbol *sds);
203     virtual void setScope(Scope *sc);
204     virtual void importAll(Scope *sc);
205     virtual void semantic(Scope *sc);
206     virtual void semantic2(Scope *sc);
207     virtual void semantic3(Scope *sc);
208     virtual Dsymbol *search(const Loc &loc, Identifier *ident, int flags = IgnoreNone);
209     Dsymbol *search_correct(Identifier *id);
210     Dsymbol *searchX(Loc loc, Scope *sc, RootObject *id);
211     virtual bool overloadInsert(Dsymbol *s);
212     virtual d_uns64 size(Loc loc);
213     virtual bool isforwardRef();
214     virtual AggregateDeclaration *isThis();     // is a 'this' required to access the member
215     virtual bool isExport() const;              // is Dsymbol exported?
216     virtual bool isImportedSymbol() const;      // is Dsymbol imported?
217     virtual bool isDeprecated();                // is Dsymbol deprecated?
218     virtual bool isOverloadable();
219     virtual LabelDsymbol *isLabel();            // is this a LabelDsymbol?
220     AggregateDeclaration *isMember();           // is this a member of an AggregateDeclaration?
221     AggregateDeclaration *isMember2();          // is this a member of an AggregateDeclaration?
222     ClassDeclaration *isClassMember();          // is this a member of a ClassDeclaration?
223     virtual Type *getType();                    // is this a type?
224     virtual bool needThis();                    // need a 'this' pointer?
225     virtual Prot prot();
226     virtual Dsymbol *syntaxCopy(Dsymbol *s);    // copy only syntax trees
227     virtual bool oneMember(Dsymbol **ps, Identifier *ident);
228     static bool oneMembers(Dsymbols *members, Dsymbol **ps, Identifier *ident);
229     virtual void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
230     virtual bool hasPointers();
231     virtual bool hasStaticCtorOrDtor();
addLocalClass(ClassDeclarations *)232     virtual void addLocalClass(ClassDeclarations *) { }
checkCtorConstInit()233     virtual void checkCtorConstInit() { }
234 
235     virtual void addComment(const utf8_t *comment);
236 
237     bool inNonRoot();
238 
239     // Eliminate need for dynamic_cast
isPackage()240     virtual Package *isPackage() { return NULL; }
isModule()241     virtual Module *isModule() { return NULL; }
isEnumMember()242     virtual EnumMember *isEnumMember() { return NULL; }
isTemplateDeclaration()243     virtual TemplateDeclaration *isTemplateDeclaration() { return NULL; }
isTemplateInstance()244     virtual TemplateInstance *isTemplateInstance() { return NULL; }
isTemplateMixin()245     virtual TemplateMixin *isTemplateMixin() { return NULL; }
isForwardingAttribDeclaration()246     virtual ForwardingAttribDeclaration *isForwardingAttribDeclaration() { return NULL; }
isNspace()247     virtual Nspace *isNspace() { return NULL; }
isDeclaration()248     virtual Declaration *isDeclaration() { return NULL; }
isStorageClassDeclaration()249     virtual StorageClassDeclaration *isStorageClassDeclaration(){ return NULL; }
isThisDeclaration()250     virtual ThisDeclaration *isThisDeclaration() { return NULL; }
isTypeInfoDeclaration()251     virtual TypeInfoDeclaration *isTypeInfoDeclaration() { return NULL; }
isTupleDeclaration()252     virtual TupleDeclaration *isTupleDeclaration() { return NULL; }
isAliasDeclaration()253     virtual AliasDeclaration *isAliasDeclaration() { return NULL; }
isAggregateDeclaration()254     virtual AggregateDeclaration *isAggregateDeclaration() { return NULL; }
isFuncDeclaration()255     virtual FuncDeclaration *isFuncDeclaration() { return NULL; }
isFuncAliasDeclaration()256     virtual FuncAliasDeclaration *isFuncAliasDeclaration() { return NULL; }
isOverDeclaration()257     virtual OverDeclaration *isOverDeclaration() { return NULL; }
isFuncLiteralDeclaration()258     virtual FuncLiteralDeclaration *isFuncLiteralDeclaration() { return NULL; }
isCtorDeclaration()259     virtual CtorDeclaration *isCtorDeclaration() { return NULL; }
isPostBlitDeclaration()260     virtual PostBlitDeclaration *isPostBlitDeclaration() { return NULL; }
isDtorDeclaration()261     virtual DtorDeclaration *isDtorDeclaration() { return NULL; }
isStaticCtorDeclaration()262     virtual StaticCtorDeclaration *isStaticCtorDeclaration() { return NULL; }
isStaticDtorDeclaration()263     virtual StaticDtorDeclaration *isStaticDtorDeclaration() { return NULL; }
isSharedStaticCtorDeclaration()264     virtual SharedStaticCtorDeclaration *isSharedStaticCtorDeclaration() { return NULL; }
isSharedStaticDtorDeclaration()265     virtual SharedStaticDtorDeclaration *isSharedStaticDtorDeclaration() { return NULL; }
isInvariantDeclaration()266     virtual InvariantDeclaration *isInvariantDeclaration() { return NULL; }
isUnitTestDeclaration()267     virtual UnitTestDeclaration *isUnitTestDeclaration() { return NULL; }
isNewDeclaration()268     virtual NewDeclaration *isNewDeclaration() { return NULL; }
isVarDeclaration()269     virtual VarDeclaration *isVarDeclaration() { return NULL; }
isClassDeclaration()270     virtual ClassDeclaration *isClassDeclaration() { return NULL; }
isStructDeclaration()271     virtual StructDeclaration *isStructDeclaration() { return NULL; }
isUnionDeclaration()272     virtual UnionDeclaration *isUnionDeclaration() { return NULL; }
isInterfaceDeclaration()273     virtual InterfaceDeclaration *isInterfaceDeclaration() { return NULL; }
isScopeDsymbol()274     virtual ScopeDsymbol *isScopeDsymbol() { return NULL; }
isForwardingScopeDsymbol()275     virtual ForwardingScopeDsymbol *isForwardingScopeDsymbol() { return NULL; }
isWithScopeSymbol()276     virtual WithScopeSymbol *isWithScopeSymbol() { return NULL; }
isArrayScopeSymbol()277     virtual ArrayScopeSymbol *isArrayScopeSymbol() { return NULL; }
isImport()278     virtual Import *isImport() { return NULL; }
isEnumDeclaration()279     virtual EnumDeclaration *isEnumDeclaration() { return NULL; }
isDeleteDeclaration()280     virtual DeleteDeclaration *isDeleteDeclaration() { return NULL; }
isSymbolDeclaration()281     virtual SymbolDeclaration *isSymbolDeclaration() { return NULL; }
isAttribDeclaration()282     virtual AttribDeclaration *isAttribDeclaration() { return NULL; }
isAnonDeclaration()283     virtual AnonDeclaration *isAnonDeclaration() { return NULL; }
isOverloadSet()284     virtual OverloadSet *isOverloadSet() { return NULL; }
accept(Visitor * v)285     virtual void accept(Visitor *v) { v->visit(this); }
286 };
287 
288 // Dsymbol that generates a scope
289 
290 class ScopeDsymbol : public Dsymbol
291 {
292 public:
293     Dsymbols *members;          // all Dsymbol's in this scope
294     DsymbolTable *symtab;       // members[] sorted into table
295     unsigned endlinnum;         // the linnumber of the statement after the scope (0 if unknown)
296 
297 private:
298     Dsymbols *importedScopes;   // imported Dsymbol's
299     PROTKIND *prots;            // array of PROTKIND, one for each import
300 
301     BitArray accessiblePackages, privateAccessiblePackages;
302 
303 public:
304     ScopeDsymbol();
305     ScopeDsymbol(Identifier *id);
306     Dsymbol *syntaxCopy(Dsymbol *s);
307     Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly);
308     OverloadSet *mergeOverloadSet(Identifier *ident, OverloadSet *os, Dsymbol *s);
309     virtual void importScope(Dsymbol *s, Prot protection);
310     void addAccessiblePackage(Package *p, Prot protection);
311     virtual bool isPackageAccessible(Package *p, Prot protection, int flags = 0);
312     bool isforwardRef();
313     static void multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2);
314     const char *kind() const;
315     FuncDeclaration *findGetMembers();
316     virtual Dsymbol *symtabInsert(Dsymbol *s);
317     virtual Dsymbol *symtabLookup(Dsymbol *s, Identifier *id);
318     bool hasStaticCtorOrDtor();
319 
320     static size_t dim(Dsymbols *members);
321     static Dsymbol *getNth(Dsymbols *members, size_t nth, size_t *pn = NULL);
322 
isScopeDsymbol()323     ScopeDsymbol *isScopeDsymbol() { return this; }
324     void semantic(Scope *sc);
accept(Visitor * v)325     void accept(Visitor *v) { v->visit(this); }
326 };
327 
328 // With statement scope
329 
330 class WithScopeSymbol : public ScopeDsymbol
331 {
332 public:
333     WithStatement *withstate;
334 
335     WithScopeSymbol(WithStatement *withstate);
336     Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly);
337 
isWithScopeSymbol()338     WithScopeSymbol *isWithScopeSymbol() { return this; }
accept(Visitor * v)339     void accept(Visitor *v) { v->visit(this); }
340 };
341 
342 // Array Index/Slice scope
343 
344 class ArrayScopeSymbol : public ScopeDsymbol
345 {
346 public:
347     Expression *exp;    // IndexExp or SliceExp
348     TypeTuple *type;    // for tuple[length]
349     TupleDeclaration *td;       // for tuples of objects
350     Scope *sc;
351 
352     ArrayScopeSymbol(Scope *sc, Expression *e);
353     ArrayScopeSymbol(Scope *sc, TypeTuple *t);
354     ArrayScopeSymbol(Scope *sc, TupleDeclaration *td);
355     Dsymbol *search(const Loc &loc, Identifier *ident, int flags = IgnoreNone);
356 
isArrayScopeSymbol()357     ArrayScopeSymbol *isArrayScopeSymbol() { return this; }
accept(Visitor * v)358     void accept(Visitor *v) { v->visit(this); }
359 };
360 
361 // Overload Sets
362 
363 class OverloadSet : public Dsymbol
364 {
365 public:
366     Dsymbols a;         // array of Dsymbols
367 
368     OverloadSet(Identifier *ident, OverloadSet *os = NULL);
369     void push(Dsymbol *s);
isOverloadSet()370     OverloadSet *isOverloadSet() { return this; }
371     const char *kind() const;
accept(Visitor * v)372     void accept(Visitor *v) { v->visit(this); }
373 };
374 
375 // Forwarding ScopeDsymbol
376 
377 class ForwardingScopeDsymbol : public ScopeDsymbol
378 {
379     ScopeDsymbol *forward;
380 
381     Dsymbol *symtabInsert(Dsymbol *s);
382     Dsymbol *symtabLookup(Dsymbol *s, Identifier *id);
383     void importScope(Dsymbol *s, Prot protection);
384     void semantic(Scope *sc);
385     const char *kind() const;
386 
isForwardingScopeDsymbol()387     ForwardingScopeDsymbol *isForwardingScopeDsymbol() { return this; }
388 };
389 
390 // Table of Dsymbol's
391 
392 class DsymbolTable : public RootObject
393 {
394 public:
395     AA *tab;
396 
397     DsymbolTable();
398 
399     // Look up Identifier. Return Dsymbol if found, NULL if not.
400     Dsymbol *lookup(Identifier const * const ident);
401 
402     // Insert Dsymbol in table. Return NULL if already there.
403     Dsymbol *insert(Dsymbol *s);
404 
405     // Look for Dsymbol in table. If there, return it. If not, insert s and return that.
406     Dsymbol *update(Dsymbol *s);
407     Dsymbol *insert(Identifier const * const ident, Dsymbol *s);     // when ident and s are not the same
408 };
409