2 /* Compiler implementation of the D programming language
3 * Copyright (C) 1999-2018 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/D-Programming-Language/dmd/blob/master/src/scope.c
13 #include <string.h> // strlen()
15 #include "root/root.h"
16 #include "root/rmem.h"
17 #include "root/speller.h"
21 #include "identifier.h"
25 #include "declaration.h"
26 #include "statement.h"
27 #include "aggregate.h"
32 Scope
*Scope::freelist
= NULL
;
34 void allocFieldinit(Scope
*sc
, size_t dim
)
36 sc
->fieldinit
= (unsigned *)mem
.xcalloc(sizeof(unsigned), dim
);
37 sc
->fieldinit_dim
= dim
;
40 void freeFieldinit(Scope
*sc
)
43 mem
.xfree(sc
->fieldinit
);
45 sc
->fieldinit_dim
= 0;
53 freelist
= s
->enclosing
;
54 //printf("freelist %p\n", s);
55 assert(s
->flags
& SCOPEfree
);
56 s
->flags
&= ~SCOPEfree
;
67 //printf("Scope::Scope() %p\n", this);
69 this->scopesym
= NULL
;
71 this->enclosing
= NULL
;
79 this->scontinue
= NULL
;
82 this->aligndecl
= NULL
;
85 this->linkage
= LINKd
;
86 this->cppmangle
= CPPMANGLEdefault
;
87 this->inlining
= PINLINEdefault
;
88 this->protection
= Prot(PROTpublic
);
89 this->explicitProtection
= 0;
98 this->fieldinit
= NULL
;
99 this->fieldinit_dim
= 0;
102 this->anchorCounts
= NULL
;
103 this->prevAnchor
= NULL
;
104 this->userAttribDecl
= NULL
;
109 Scope
*sc
= Scope::alloc();
110 *sc
= *this; // memcpy
112 /* Bugzilla 11777: The copied scope should not inherit fieldinit.
114 sc
->fieldinit
= NULL
;
119 Scope
*Scope::createGlobal(Module
*_module
)
121 Scope
*sc
= Scope::alloc();
122 *sc
= Scope(); // memset
124 sc
->aligndecl
= NULL
;
126 sc
->inlining
= PINLINEdefault
;
127 sc
->protection
= Prot(PROTpublic
);
129 sc
->_module
= _module
;
134 sc
->scopesym
= new ScopeDsymbol();
135 sc
->scopesym
->symtab
= new DsymbolTable();
137 // Add top level package as member of this global scope
138 Dsymbol
*m
= _module
;
141 m
->addMember(NULL
, sc
->scopesym
);
142 m
->parent
= NULL
; // got changed by addMember()
144 // Create the module scope underneath the global scope
145 sc
= sc
->push(_module
);
146 sc
->parent
= _module
;
154 //printf("Scope::push(this = %p) new = %p\n", this, s);
155 assert(!(flags
& SCOPEfree
));
161 s
->fieldinit
= saveFieldInit();
162 s
->flags
= (flags
& (SCOPEcontract
| SCOPEdebug
| SCOPEctfe
| SCOPEcompile
| SCOPEconstraint
|
163 SCOPEnoaccesscheck
| SCOPEignoresymbolvisibility
));
170 Scope
*Scope::push(ScopeDsymbol
*ss
)
172 //printf("Scope::push(%s)\n", ss->toChars());
180 //printf("Scope::pop() %p nofree = %d\n", this, nofree);
181 Scope
*enc
= enclosing
;
185 enclosing
->callSuper
|= callSuper
;
188 if (enclosing
->fieldinit
)
190 assert(fieldinit
!= enclosing
->fieldinit
);
191 size_t dim
= fieldinit_dim
;
192 for (size_t i
= 0; i
< dim
; i
++)
193 enclosing
->fieldinit
[i
] |= fieldinit
[i
];
201 enclosing
= freelist
;
209 Scope
*Scope::startCTFE()
211 Scope
*sc
= this->push();
212 sc
->flags
= this->flags
| SCOPEctfe
;
216 Scope
*Scope::endCTFE()
218 assert(flags
& SCOPEctfe
);
222 void Scope::mergeCallSuper(Loc loc
, unsigned cs
)
224 // This does a primitive flow analysis to support the restrictions
225 // regarding when and how constructors can appear.
226 // It merges the results of two paths.
227 // The two paths are callSuper and cs; the result is merged into callSuper.
231 // Have ALL branches called a constructor?
232 int aAll
= (cs
& (CSXthis_ctor
| CSXsuper_ctor
)) != 0;
233 int bAll
= (callSuper
& (CSXthis_ctor
| CSXsuper_ctor
)) != 0;
235 // Have ANY branches called a constructor?
236 bool aAny
= (cs
& CSXany_ctor
) != 0;
237 bool bAny
= (callSuper
& CSXany_ctor
) != 0;
239 // Have any branches returned?
240 bool aRet
= (cs
& CSXreturn
) != 0;
241 bool bRet
= (callSuper
& CSXreturn
) != 0;
243 // Have any branches halted?
244 bool aHalt
= (cs
& CSXhalt
) != 0;
245 bool bHalt
= (callSuper
& CSXhalt
) != 0;
253 else if ((!aHalt
&& aRet
&& !aAny
&& bAny
) ||
254 (!bHalt
&& bRet
&& !bAny
&& aAny
))
256 // If one has returned without a constructor call, there must be never
257 // have been ctor calls in the other.
260 else if (aHalt
|| (aRet
&& aAll
))
262 // If one branch has called a ctor and then exited, anything the
263 // other branch has done is OK (except returning without a
264 // ctor call, but we already checked that).
265 callSuper
|= cs
& (CSXany_ctor
| CSXlabel
);
267 else if (bHalt
|| (bRet
&& bAll
))
269 callSuper
= cs
| (callSuper
& (CSXany_ctor
| CSXlabel
));
273 // Both branches must have called ctors, or both not.
275 // If one returned without a ctor, we must remember that
276 // (Don't bother if we've already found an error)
277 if (ok
&& aRet
&& !aAny
)
278 callSuper
|= CSXreturn
;
279 callSuper
|= cs
& (CSXany_ctor
| CSXlabel
);
282 error(loc
, "one path skips constructor");
286 unsigned *Scope::saveFieldInit()
289 if (fieldinit
) // copy
291 size_t dim
= fieldinit_dim
;
292 fi
= (unsigned *)mem
.xmalloc(sizeof(unsigned) * dim
);
293 for (size_t i
= 0; i
< dim
; i
++)
294 fi
[i
] = fieldinit
[i
];
299 static bool mergeFieldInit(unsigned &fieldInit
, unsigned fi
, bool mustInit
)
303 // Have any branches returned?
304 bool aRet
= (fi
& CSXreturn
) != 0;
305 bool bRet
= (fieldInit
& CSXreturn
) != 0;
307 // Have any branches halted?
308 bool aHalt
= (fi
& CSXhalt
) != 0;
309 bool bHalt
= (fieldInit
& CSXhalt
) != 0;
318 else if (!aHalt
&& aRet
)
320 ok
= !mustInit
|| (fi
& CSXthis_ctor
);
321 fieldInit
= fieldInit
;
323 else if (!bHalt
&& bRet
)
325 ok
= !mustInit
|| (fieldInit
& CSXthis_ctor
);
330 ok
= !mustInit
|| (fieldInit
& CSXthis_ctor
);
331 fieldInit
= fieldInit
;
335 ok
= !mustInit
|| (fi
& CSXthis_ctor
);
340 ok
= !mustInit
|| !((fieldInit
^ fi
) & CSXthis_ctor
);
349 void Scope::mergeFieldInit(Loc loc
, unsigned *fies
)
351 if (fieldinit
&& fies
)
353 FuncDeclaration
*f
= func
;
354 if (fes
) f
= fes
->func
;
355 AggregateDeclaration
*ad
= f
->isMember2();
358 for (size_t i
= 0; i
< ad
->fields
.dim
; i
++)
360 VarDeclaration
*v
= ad
->fields
[i
];
361 bool mustInit
= (v
->storage_class
& STCnodefaultctor
||
362 v
->type
->needsNested());
364 if (!::mergeFieldInit(fieldinit
[i
], fies
[i
], mustInit
))
366 ::error(loc
, "one path skips field %s", ad
->fields
[i
]->toChars());
372 Module
*Scope::instantiatingModule()
374 // TODO: in speculative context, returning 'module' is correct?
375 return minst
? minst
: _module
;
378 static Dsymbol
*searchScopes(Scope
*scope
, Loc loc
, Identifier
*ident
, Dsymbol
**pscopesym
, int flags
)
380 for (Scope
*sc
= scope
; sc
; sc
= sc
->enclosing
)
382 assert(sc
!= sc
->enclosing
);
385 //printf("\tlooking in scopesym '%s', kind = '%s', flags = x%x\n", sc->scopesym->toChars(), sc->scopesym->kind(), flags);
387 if (sc
->scopesym
->isModule())
388 flags
|= SearchUnqualifiedModule
; // tell Module.search() that SearchLocalsOnly is to be obeyed
390 if (Dsymbol
*s
= sc
->scopesym
->search(loc
, ident
, flags
))
392 if (!(flags
& (SearchImportsOnly
| IgnoreErrors
)) &&
393 ident
== Id::length
&& sc
->scopesym
->isArrayScopeSymbol() &&
394 sc
->enclosing
&& sc
->enclosing
->search(loc
, ident
, NULL
, flags
))
396 warning(s
->loc
, "array 'length' hides other 'length' name in outer scope");
399 *pscopesym
= sc
->scopesym
;
402 // Stop when we hit a module, but keep going if that is not just under the global scope
403 if (sc
->scopesym
->isModule() && !(sc
->enclosing
&& !sc
->enclosing
->enclosing
))
409 /************************************
410 * Perform unqualified name lookup by following the chain of scopes up
414 * loc = location to use for error messages
415 * ident = name to look up
416 * pscopesym = if supplied and name is found, set to scope that ident was found in
417 * flags = modify search based on flags
420 * symbol if found, null if not
422 Dsymbol
*Scope::search(Loc loc
, Identifier
*ident
, Dsymbol
**pscopesym
, int flags
)
424 // This function is called only for unqualified lookup
425 assert(!(flags
& (SearchLocalsOnly
| SearchImportsOnly
)));
427 /* If ident is "start at module scope", only look at module scope
429 if (ident
== Id::empty
)
431 // Look for module scope
432 for (Scope
*sc
= this; sc
; sc
= sc
->enclosing
)
434 assert(sc
!= sc
->enclosing
);
438 if (Dsymbol
*s
= sc
->scopesym
->isModule())
441 *pscopesym
= sc
->scopesym
;
448 if (this->flags
& SCOPEignoresymbolvisibility
)
449 flags
|= IgnoreSymbolVisibility
;
451 Dsymbol
*sold
= NULL
;
452 if (global
.params
.bug10378
|| global
.params
.check10378
)
454 sold
= searchScopes(this, loc
, ident
, pscopesym
, flags
| IgnoreSymbolVisibility
);
455 if (!global
.params
.check10378
)
458 if (ident
== Id::dollar
) // Bugzilla 15825
464 // First look in local scopes
465 Dsymbol
*s
= searchScopes(this, loc
, ident
, pscopesym
, flags
| SearchLocalsOnly
);
468 // Second look in imported modules
469 s
= searchScopes(this, loc
, ident
, pscopesym
, flags
| SearchImportsOnly
);
470 /** Still find private symbols, so that symbols that weren't access
471 * checked by the compiler remain usable. Once the deprecation is over,
472 * this should be moved to search_correct instead.
474 if (!s
&& !(flags
& IgnoreSymbolVisibility
))
476 s
= searchScopes(this, loc
, ident
, pscopesym
, flags
| SearchLocalsOnly
| IgnoreSymbolVisibility
);
478 s
= searchScopes(this, loc
, ident
, pscopesym
, flags
| SearchImportsOnly
| IgnoreSymbolVisibility
);
480 if (s
&& !(flags
& IgnoreErrors
))
481 ::deprecation(loc
, "%s is not visible from module %s", s
->toPrettyChars(), _module
->toChars());
485 if (global
.params
.check10378
)
489 deprecation10378(loc
, sold
, snew
);
490 if (global
.params
.bug10378
)
496 Dsymbol
*Scope::insert(Dsymbol
*s
)
498 if (VarDeclaration
*vd
= s
->isVarDeclaration())
501 vd
->lastVar
= lastVar
;
504 else if (WithScopeSymbol
*ss
= s
->isWithScopeSymbol())
506 if (VarDeclaration
*vd
= ss
->withstate
->wthis
)
509 vd
->lastVar
= lastVar
;
514 for (Scope
*sc
= this; sc
; sc
= sc
->enclosing
)
516 //printf("\tsc = %p\n", sc);
519 //printf("\t\tsc->scopesym = %p\n", sc->scopesym);
520 if (!sc
->scopesym
->symtab
)
521 sc
->scopesym
->symtab
= new DsymbolTable();
522 return sc
->scopesym
->symtabInsert(s
);
529 /********************************************
530 * Search enclosing scopes for ClassDeclaration.
533 ClassDeclaration
*Scope::getClassScope()
535 for (Scope
*sc
= this; sc
; sc
= sc
->enclosing
)
540 ClassDeclaration
*cd
= sc
->scopesym
->isClassDeclaration();
547 /********************************************
548 * Search enclosing scopes for ClassDeclaration.
551 AggregateDeclaration
*Scope::getStructClassScope()
553 for (Scope
*sc
= this; sc
; sc
= sc
->enclosing
)
558 AggregateDeclaration
*ad
= sc
->scopesym
->isClassDeclaration();
561 ad
= sc
->scopesym
->isStructDeclaration();
568 /*******************************************
569 * For TemplateDeclarations, we need to remember the Scope
570 * where it was declared. So mark the Scope as not
574 void Scope::setNoFree()
578 //printf("Scope::setNoFree(this = %p)\n", this);
579 for (Scope
*sc
= this; sc
; sc
= sc
->enclosing
)
581 //printf("\tsc = %p\n", sc);
584 assert(!(flags
& SCOPEfree
));
585 //assert(sc != sc->enclosing);
586 //assert(!sc->enclosing || sc != sc->enclosing->enclosing);
592 structalign_t
Scope::alignment()
595 return aligndecl
->getAlignment(this);
597 return STRUCTALIGN_DEFAULT
;
600 /************************************************
601 * Given the failed search attempt, try to find
602 * one with a close spelling.
605 void *scope_search_fp(void *arg
, const char *seed
, int* cost
)
607 //printf("scope_search_fp('%s')\n", seed);
609 /* If not in the lexer's string table, it certainly isn't in the symbol table.
610 * Doing this first is a lot faster.
612 size_t len
= strlen(seed
);
615 Identifier
*id
= Identifier::lookup(seed
, len
);
619 Scope
*sc
= (Scope
*)arg
;
620 Module::clearCache();
621 Dsymbol
*scopesym
= NULL
;
622 Dsymbol
*s
= sc
->search(Loc(), id
, &scopesym
, IgnoreErrors
);
625 for (*cost
= 0; sc
; sc
= sc
->enclosing
, (*cost
)++)
626 if (sc
->scopesym
== scopesym
)
628 if (scopesym
!= s
->parent
)
630 (*cost
)++; // got to the symbol through an import
631 if (s
->prot().kind
== PROTprivate
)
638 void Scope::deprecation10378(Loc loc
, Dsymbol
*sold
, Dsymbol
*snew
)
642 // The overloadset found via the new lookup rules is either
643 // equal or a subset of the overloadset found via the old
644 // lookup rules, so it suffices to compare the dimension to
645 // check for equality.
646 OverloadSet
*osold
= NULL
;
647 OverloadSet
*osnew
= NULL
;
648 if (sold
&& (osold
= sold
->isOverloadSet()) != NULL
&&
649 snew
&& (osnew
= snew
->isOverloadSet()) != NULL
&&
650 osold
->a
.dim
== osnew
->a
.dim
)
654 buf
.writestring("local import search method found ");
656 buf
.printf("%s %s (%d overloads)", sold
->kind(), sold
->toPrettyChars(), (int)osold
->a
.dim
);
658 buf
.printf("%s %s", sold
->kind(), sold
->toPrettyChars());
660 buf
.writestring("nothing");
661 buf
.writestring(" instead of ");
663 buf
.printf("%s %s (%d overloads)", snew
->kind(), snew
->toPrettyChars(), (int)osnew
->a
.dim
);
665 buf
.printf("%s %s", snew
->kind(), snew
->toPrettyChars());
667 buf
.writestring("nothing");
669 deprecation(loc
, "%s", buf
.peekString());
672 Dsymbol
*Scope::search_correct(Identifier
*ident
)
675 return NULL
; // don't do it for speculative compiles; too time consuming
677 return (Dsymbol
*)speller(ident
->toChars(), &scope_search_fp
, this, idchars
);
680 /************************************
681 * Maybe `ident` was a C or C++ name. Check for that,
682 * and suggest the D equivalent.
684 * ident = unknown identifier
686 * D identifier string if found, null if not
688 const char *Scope::search_correct_C(Identifier
*ident
)
691 if (ident
== Id::_NULL
)
693 else if (ident
== Id::_TRUE
)
695 else if (ident
== Id::_FALSE
)
697 else if (ident
== Id::_unsigned
)
701 return Token::toChars(tok
);