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
11 #include "root/dsystem.h" // strlen()
12 #include "root/root.h"
13 #include "root/rmem.h"
14 #include "root/speller.h"
18 #include "identifier.h"
22 #include "declaration.h"
23 #include "statement.h"
24 #include "aggregate.h"
29 Scope
*Scope::freelist
= NULL
;
31 void allocFieldinit(Scope
*sc
, size_t dim
)
33 sc
->fieldinit
= (unsigned *)mem
.xcalloc(sizeof(unsigned), dim
);
34 sc
->fieldinit_dim
= dim
;
37 void freeFieldinit(Scope
*sc
)
40 mem
.xfree(sc
->fieldinit
);
42 sc
->fieldinit_dim
= 0;
50 freelist
= s
->enclosing
;
51 //printf("freelist %p\n", s);
52 assert(s
->flags
& SCOPEfree
);
53 s
->flags
&= ~SCOPEfree
;
64 //printf("Scope::Scope() %p\n", this);
66 this->scopesym
= NULL
;
68 this->enclosing
= NULL
;
76 this->scontinue
= NULL
;
79 this->aligndecl
= NULL
;
82 this->linkage
= LINKd
;
83 this->cppmangle
= CPPMANGLEdefault
;
84 this->inlining
= PINLINEdefault
;
85 this->protection
= Prot(PROTpublic
);
86 this->explicitProtection
= 0;
95 this->fieldinit
= NULL
;
96 this->fieldinit_dim
= 0;
99 this->anchorCounts
= NULL
;
100 this->prevAnchor
= NULL
;
101 this->userAttribDecl
= NULL
;
106 Scope
*sc
= Scope::alloc();
107 *sc
= *this; // memcpy
109 /* Bugzilla 11777: The copied scope should not inherit fieldinit.
111 sc
->fieldinit
= NULL
;
116 Scope
*Scope::createGlobal(Module
*_module
)
118 Scope
*sc
= Scope::alloc();
119 *sc
= Scope(); // memset
121 sc
->aligndecl
= NULL
;
123 sc
->inlining
= PINLINEdefault
;
124 sc
->protection
= Prot(PROTpublic
);
126 sc
->_module
= _module
;
131 sc
->scopesym
= new ScopeDsymbol();
132 sc
->scopesym
->symtab
= new DsymbolTable();
134 // Add top level package as member of this global scope
135 Dsymbol
*m
= _module
;
138 m
->addMember(NULL
, sc
->scopesym
);
139 m
->parent
= NULL
; // got changed by addMember()
141 // Create the module scope underneath the global scope
142 sc
= sc
->push(_module
);
143 sc
->parent
= _module
;
151 //printf("Scope::push(this = %p) new = %p\n", this, s);
152 assert(!(flags
& SCOPEfree
));
158 s
->fieldinit
= saveFieldInit();
159 s
->flags
= (flags
& (SCOPEcontract
| SCOPEdebug
| SCOPEctfe
| SCOPEcompile
| SCOPEconstraint
|
160 SCOPEnoaccesscheck
| SCOPEignoresymbolvisibility
));
167 Scope
*Scope::push(ScopeDsymbol
*ss
)
169 //printf("Scope::push(%s)\n", ss->toChars());
177 //printf("Scope::pop() %p nofree = %d\n", this, nofree);
178 Scope
*enc
= enclosing
;
182 enclosing
->callSuper
|= callSuper
;
185 if (enclosing
->fieldinit
)
187 assert(fieldinit
!= enclosing
->fieldinit
);
188 size_t dim
= fieldinit_dim
;
189 for (size_t i
= 0; i
< dim
; i
++)
190 enclosing
->fieldinit
[i
] |= fieldinit
[i
];
198 enclosing
= freelist
;
206 Scope
*Scope::startCTFE()
208 Scope
*sc
= this->push();
209 sc
->flags
= this->flags
| SCOPEctfe
;
213 Scope
*Scope::endCTFE()
215 assert(flags
& SCOPEctfe
);
219 void Scope::mergeCallSuper(Loc loc
, unsigned cs
)
221 // This does a primitive flow analysis to support the restrictions
222 // regarding when and how constructors can appear.
223 // It merges the results of two paths.
224 // The two paths are callSuper and cs; the result is merged into callSuper.
228 // Have ALL branches called a constructor?
229 int aAll
= (cs
& (CSXthis_ctor
| CSXsuper_ctor
)) != 0;
230 int bAll
= (callSuper
& (CSXthis_ctor
| CSXsuper_ctor
)) != 0;
232 // Have ANY branches called a constructor?
233 bool aAny
= (cs
& CSXany_ctor
) != 0;
234 bool bAny
= (callSuper
& CSXany_ctor
) != 0;
236 // Have any branches returned?
237 bool aRet
= (cs
& CSXreturn
) != 0;
238 bool bRet
= (callSuper
& CSXreturn
) != 0;
240 // Have any branches halted?
241 bool aHalt
= (cs
& CSXhalt
) != 0;
242 bool bHalt
= (callSuper
& CSXhalt
) != 0;
250 else if ((!aHalt
&& aRet
&& !aAny
&& bAny
) ||
251 (!bHalt
&& bRet
&& !bAny
&& aAny
))
253 // If one has returned without a constructor call, there must be never
254 // have been ctor calls in the other.
257 else if (aHalt
|| (aRet
&& aAll
))
259 // If one branch has called a ctor and then exited, anything the
260 // other branch has done is OK (except returning without a
261 // ctor call, but we already checked that).
262 callSuper
|= cs
& (CSXany_ctor
| CSXlabel
);
264 else if (bHalt
|| (bRet
&& bAll
))
266 callSuper
= cs
| (callSuper
& (CSXany_ctor
| CSXlabel
));
270 // Both branches must have called ctors, or both not.
272 // If one returned without a ctor, we must remember that
273 // (Don't bother if we've already found an error)
274 if (ok
&& aRet
&& !aAny
)
275 callSuper
|= CSXreturn
;
276 callSuper
|= cs
& (CSXany_ctor
| CSXlabel
);
279 error(loc
, "one path skips constructor");
283 unsigned *Scope::saveFieldInit()
286 if (fieldinit
) // copy
288 size_t dim
= fieldinit_dim
;
289 fi
= (unsigned *)mem
.xmalloc(sizeof(unsigned) * dim
);
290 for (size_t i
= 0; i
< dim
; i
++)
291 fi
[i
] = fieldinit
[i
];
296 static bool mergeFieldInit(unsigned &fieldInit
, unsigned fi
, bool mustInit
)
300 // Have any branches returned?
301 bool aRet
= (fi
& CSXreturn
) != 0;
302 bool bRet
= (fieldInit
& CSXreturn
) != 0;
304 // Have any branches halted?
305 bool aHalt
= (fi
& CSXhalt
) != 0;
306 bool bHalt
= (fieldInit
& CSXhalt
) != 0;
315 else if (!aHalt
&& aRet
)
317 ok
= !mustInit
|| (fi
& CSXthis_ctor
);
318 fieldInit
= fieldInit
;
320 else if (!bHalt
&& bRet
)
322 ok
= !mustInit
|| (fieldInit
& CSXthis_ctor
);
327 ok
= !mustInit
|| (fieldInit
& CSXthis_ctor
);
328 fieldInit
= fieldInit
;
332 ok
= !mustInit
|| (fi
& CSXthis_ctor
);
337 ok
= !mustInit
|| !((fieldInit
^ fi
) & CSXthis_ctor
);
346 void Scope::mergeFieldInit(Loc loc
, unsigned *fies
)
348 if (fieldinit
&& fies
)
350 FuncDeclaration
*f
= func
;
351 if (fes
) f
= fes
->func
;
352 AggregateDeclaration
*ad
= f
->isMember2();
355 for (size_t i
= 0; i
< ad
->fields
.dim
; i
++)
357 VarDeclaration
*v
= ad
->fields
[i
];
358 bool mustInit
= (v
->storage_class
& STCnodefaultctor
||
359 v
->type
->needsNested());
361 if (!::mergeFieldInit(fieldinit
[i
], fies
[i
], mustInit
))
363 ::error(loc
, "one path skips field %s", ad
->fields
[i
]->toChars());
369 Module
*Scope::instantiatingModule()
371 // TODO: in speculative context, returning 'module' is correct?
372 return minst
? minst
: _module
;
375 static Dsymbol
*searchScopes(Scope
*scope
, Loc loc
, Identifier
*ident
, Dsymbol
**pscopesym
, int flags
)
377 for (Scope
*sc
= scope
; sc
; sc
= sc
->enclosing
)
379 assert(sc
!= sc
->enclosing
);
382 //printf("\tlooking in scopesym '%s', kind = '%s', flags = x%x\n", sc->scopesym->toChars(), sc->scopesym->kind(), flags);
384 if (sc
->scopesym
->isModule())
385 flags
|= SearchUnqualifiedModule
; // tell Module.search() that SearchLocalsOnly is to be obeyed
387 if (Dsymbol
*s
= sc
->scopesym
->search(loc
, ident
, flags
))
389 if (!(flags
& (SearchImportsOnly
| IgnoreErrors
)) &&
390 ident
== Id::length
&& sc
->scopesym
->isArrayScopeSymbol() &&
391 sc
->enclosing
&& sc
->enclosing
->search(loc
, ident
, NULL
, flags
))
393 warning(s
->loc
, "array 'length' hides other 'length' name in outer scope");
396 *pscopesym
= sc
->scopesym
;
399 // Stop when we hit a module, but keep going if that is not just under the global scope
400 if (sc
->scopesym
->isModule() && !(sc
->enclosing
&& !sc
->enclosing
->enclosing
))
406 /************************************
407 * Perform unqualified name lookup by following the chain of scopes up
411 * loc = location to use for error messages
412 * ident = name to look up
413 * pscopesym = if supplied and name is found, set to scope that ident was found in
414 * flags = modify search based on flags
417 * symbol if found, null if not
419 Dsymbol
*Scope::search(Loc loc
, Identifier
*ident
, Dsymbol
**pscopesym
, int flags
)
421 // This function is called only for unqualified lookup
422 assert(!(flags
& (SearchLocalsOnly
| SearchImportsOnly
)));
424 /* If ident is "start at module scope", only look at module scope
426 if (ident
== Id::empty
)
428 // Look for module scope
429 for (Scope
*sc
= this; sc
; sc
= sc
->enclosing
)
431 assert(sc
!= sc
->enclosing
);
435 if (Dsymbol
*s
= sc
->scopesym
->isModule())
438 *pscopesym
= sc
->scopesym
;
445 if (this->flags
& SCOPEignoresymbolvisibility
)
446 flags
|= IgnoreSymbolVisibility
;
448 Dsymbol
*sold
= NULL
;
449 if (global
.params
.bug10378
|| global
.params
.check10378
)
451 sold
= searchScopes(this, loc
, ident
, pscopesym
, flags
| IgnoreSymbolVisibility
);
452 if (!global
.params
.check10378
)
455 if (ident
== Id::dollar
) // Bugzilla 15825
461 // First look in local scopes
462 Dsymbol
*s
= searchScopes(this, loc
, ident
, pscopesym
, flags
| SearchLocalsOnly
);
465 // Second look in imported modules
466 s
= searchScopes(this, loc
, ident
, pscopesym
, flags
| SearchImportsOnly
);
467 /** Still find private symbols, so that symbols that weren't access
468 * checked by the compiler remain usable. Once the deprecation is over,
469 * this should be moved to search_correct instead.
471 if (!s
&& !(flags
& IgnoreSymbolVisibility
))
473 s
= searchScopes(this, loc
, ident
, pscopesym
, flags
| SearchLocalsOnly
| IgnoreSymbolVisibility
);
475 s
= searchScopes(this, loc
, ident
, pscopesym
, flags
| SearchImportsOnly
| IgnoreSymbolVisibility
);
477 if (s
&& !(flags
& IgnoreErrors
))
478 ::deprecation(loc
, "%s is not visible from module %s", s
->toPrettyChars(), _module
->toChars());
482 if (global
.params
.check10378
)
486 deprecation10378(loc
, sold
, snew
);
487 if (global
.params
.bug10378
)
493 Dsymbol
*Scope::insert(Dsymbol
*s
)
495 if (VarDeclaration
*vd
= s
->isVarDeclaration())
498 vd
->lastVar
= lastVar
;
501 else if (WithScopeSymbol
*ss
= s
->isWithScopeSymbol())
503 if (VarDeclaration
*vd
= ss
->withstate
->wthis
)
506 vd
->lastVar
= lastVar
;
511 for (Scope
*sc
= this; sc
; sc
= sc
->enclosing
)
513 //printf("\tsc = %p\n", sc);
516 //printf("\t\tsc->scopesym = %p\n", sc->scopesym);
517 if (!sc
->scopesym
->symtab
)
518 sc
->scopesym
->symtab
= new DsymbolTable();
519 return sc
->scopesym
->symtabInsert(s
);
526 /********************************************
527 * Search enclosing scopes for ClassDeclaration.
530 ClassDeclaration
*Scope::getClassScope()
532 for (Scope
*sc
= this; sc
; sc
= sc
->enclosing
)
537 ClassDeclaration
*cd
= sc
->scopesym
->isClassDeclaration();
544 /********************************************
545 * Search enclosing scopes for ClassDeclaration.
548 AggregateDeclaration
*Scope::getStructClassScope()
550 for (Scope
*sc
= this; sc
; sc
= sc
->enclosing
)
555 AggregateDeclaration
*ad
= sc
->scopesym
->isClassDeclaration();
558 ad
= sc
->scopesym
->isStructDeclaration();
565 /*******************************************
566 * For TemplateDeclarations, we need to remember the Scope
567 * where it was declared. So mark the Scope as not
571 void Scope::setNoFree()
575 //printf("Scope::setNoFree(this = %p)\n", this);
576 for (Scope
*sc
= this; sc
; sc
= sc
->enclosing
)
578 //printf("\tsc = %p\n", sc);
581 assert(!(flags
& SCOPEfree
));
582 //assert(sc != sc->enclosing);
583 //assert(!sc->enclosing || sc != sc->enclosing->enclosing);
589 structalign_t
Scope::alignment()
592 return aligndecl
->getAlignment(this);
594 return STRUCTALIGN_DEFAULT
;
597 /************************************************
598 * Given the failed search attempt, try to find
599 * one with a close spelling.
602 void *scope_search_fp(void *arg
, const char *seed
, int* cost
)
604 //printf("scope_search_fp('%s')\n", seed);
606 /* If not in the lexer's string table, it certainly isn't in the symbol table.
607 * Doing this first is a lot faster.
609 size_t len
= strlen(seed
);
612 Identifier
*id
= Identifier::lookup(seed
, len
);
616 Scope
*sc
= (Scope
*)arg
;
617 Module::clearCache();
618 Dsymbol
*scopesym
= NULL
;
619 Dsymbol
*s
= sc
->search(Loc(), id
, &scopesym
, IgnoreErrors
);
622 for (*cost
= 0; sc
; sc
= sc
->enclosing
, (*cost
)++)
623 if (sc
->scopesym
== scopesym
)
625 if (scopesym
!= s
->parent
)
627 (*cost
)++; // got to the symbol through an import
628 if (s
->prot().kind
== PROTprivate
)
635 void Scope::deprecation10378(Loc loc
, Dsymbol
*sold
, Dsymbol
*snew
)
639 // The overloadset found via the new lookup rules is either
640 // equal or a subset of the overloadset found via the old
641 // lookup rules, so it suffices to compare the dimension to
642 // check for equality.
643 OverloadSet
*osold
= NULL
;
644 OverloadSet
*osnew
= NULL
;
645 if (sold
&& (osold
= sold
->isOverloadSet()) != NULL
&&
646 snew
&& (osnew
= snew
->isOverloadSet()) != NULL
&&
647 osold
->a
.dim
== osnew
->a
.dim
)
651 buf
.writestring("local import search method found ");
653 buf
.printf("%s %s (%d overloads)", sold
->kind(), sold
->toPrettyChars(), (int)osold
->a
.dim
);
655 buf
.printf("%s %s", sold
->kind(), sold
->toPrettyChars());
657 buf
.writestring("nothing");
658 buf
.writestring(" instead of ");
660 buf
.printf("%s %s (%d overloads)", snew
->kind(), snew
->toPrettyChars(), (int)osnew
->a
.dim
);
662 buf
.printf("%s %s", snew
->kind(), snew
->toPrettyChars());
664 buf
.writestring("nothing");
666 deprecation(loc
, "%s", buf
.peekString());
669 Dsymbol
*Scope::search_correct(Identifier
*ident
)
672 return NULL
; // don't do it for speculative compiles; too time consuming
674 return (Dsymbol
*)speller(ident
->toChars(), &scope_search_fp
, this, idchars
);
677 /************************************
678 * Maybe `ident` was a C or C++ name. Check for that,
679 * and suggest the D equivalent.
681 * ident = unknown identifier
683 * D identifier string if found, null if not
685 const char *Scope::search_correct_C(Identifier
*ident
)
688 if (ident
== Id::_NULL
)
690 else if (ident
== Id::_TRUE
)
692 else if (ident
== Id::_FALSE
)
694 else if (ident
== Id::_unsigned
)
698 return Token::toChars(tok
);