| 1 |
// Copyright (c) 1999-2010 by Digital Mars |
|---|
| 2 |
// All Rights Reserved |
|---|
| 3 |
// written by Walter Bright |
|---|
| 4 |
// http://www.digitalmars.com |
|---|
| 5 |
// License for redistribution is by either the Artistic License |
|---|
| 6 |
// in artistic.txt, or the GNU General Public License in gnu.txt. |
|---|
| 7 |
// See the included readme.txt for details. |
|---|
| 8 |
|
|---|
| 9 |
#include <stdio.h> |
|---|
| 10 |
#include <assert.h> |
|---|
| 11 |
|
|---|
| 12 |
#include "root.h" |
|---|
| 13 |
#include "speller.h" |
|---|
| 14 |
|
|---|
| 15 |
#include "mars.h" |
|---|
| 16 |
#include "init.h" |
|---|
| 17 |
#include "identifier.h" |
|---|
| 18 |
#include "scope.h" |
|---|
| 19 |
#include "attrib.h" |
|---|
| 20 |
#include "dsymbol.h" |
|---|
| 21 |
#include "declaration.h" |
|---|
| 22 |
#include "aggregate.h" |
|---|
| 23 |
#include "module.h" |
|---|
| 24 |
#include "id.h" |
|---|
| 25 |
#include "lexer.h" |
|---|
| 26 |
|
|---|
| 27 |
Scope *Scope::freelist = NULL; |
|---|
| 28 |
|
|---|
| 29 |
void *Scope::operator new(size_t size) |
|---|
| 30 |
{ |
|---|
| 31 |
if (freelist) |
|---|
| 32 |
{ |
|---|
| 33 |
Scope *s = freelist; |
|---|
| 34 |
freelist = s->enclosing; |
|---|
| 35 |
//printf("freelist %p\n", s); |
|---|
| 36 |
assert(s->flags & SCOPEfree); |
|---|
| 37 |
s->flags &= ~SCOPEfree; |
|---|
| 38 |
return s; |
|---|
| 39 |
} |
|---|
| 40 |
|
|---|
| 41 |
void *p = ::operator new(size); |
|---|
| 42 |
//printf("new %p\n", p); |
|---|
| 43 |
return p; |
|---|
| 44 |
} |
|---|
| 45 |
|
|---|
| 46 |
Scope::Scope() |
|---|
| 47 |
{ // Create root scope |
|---|
| 48 |
|
|---|
| 49 |
//printf("Scope::Scope() %p\n", this); |
|---|
| 50 |
this->module = NULL; |
|---|
| 51 |
this->scopesym = NULL; |
|---|
| 52 |
this->sd = NULL; |
|---|
| 53 |
this->enclosing = NULL; |
|---|
| 54 |
this->parent = NULL; |
|---|
| 55 |
this->sw = NULL; |
|---|
| 56 |
this->tf = NULL; |
|---|
| 57 |
this->tinst = NULL; |
|---|
| 58 |
this->sbreak = NULL; |
|---|
| 59 |
this->scontinue = NULL; |
|---|
| 60 |
this->fes = NULL; |
|---|
| 61 |
this->structalign = global.structalign; |
|---|
| 62 |
this->func = NULL; |
|---|
| 63 |
this->slabel = NULL; |
|---|
| 64 |
this->linkage = LINKd; |
|---|
| 65 |
this->protection = PROTpublic; |
|---|
| 66 |
this->explicitProtection = 0; |
|---|
| 67 |
this->stc = 0; |
|---|
| 68 |
this->offset = 0; |
|---|
| 69 |
this->inunion = 0; |
|---|
| 70 |
this->incontract = 0; |
|---|
| 71 |
this->nofree = 0; |
|---|
| 72 |
this->noctor = 0; |
|---|
| 73 |
this->noaccesscheck = 0; |
|---|
| 74 |
this->mustsemantic = 0; |
|---|
| 75 |
this->intypeof = 0; |
|---|
| 76 |
this->parameterSpecialization = 0; |
|---|
| 77 |
this->callSuper = 0; |
|---|
| 78 |
this->flags = 0; |
|---|
| 79 |
this->anonAgg = NULL; |
|---|
| 80 |
this->lastdc = NULL; |
|---|
| 81 |
this->lastoffset = 0; |
|---|
| 82 |
this->docbuf = NULL; |
|---|
| 83 |
} |
|---|
| 84 |
|
|---|
| 85 |
Scope::Scope(Scope *enclosing) |
|---|
| 86 |
{ |
|---|
| 87 |
//printf("Scope::Scope(enclosing = %p) %p\n", enclosing, this); |
|---|
| 88 |
assert(!(enclosing->flags & SCOPEfree)); |
|---|
| 89 |
this->module = enclosing->module; |
|---|
| 90 |
this->func = enclosing->func; |
|---|
| 91 |
this->parent = enclosing->parent; |
|---|
| 92 |
this->scopesym = NULL; |
|---|
| 93 |
this->sd = NULL; |
|---|
| 94 |
this->sw = enclosing->sw; |
|---|
| 95 |
this->tf = enclosing->tf; |
|---|
| 96 |
this->tinst = enclosing->tinst; |
|---|
| 97 |
this->sbreak = enclosing->sbreak; |
|---|
| 98 |
this->scontinue = enclosing->scontinue; |
|---|
| 99 |
this->fes = enclosing->fes; |
|---|
| 100 |
this->structalign = enclosing->structalign; |
|---|
| 101 |
this->enclosing = enclosing; |
|---|
| 102 |
#ifdef DEBUG |
|---|
| 103 |
if (enclosing->enclosing) |
|---|
| 104 |
assert(!(enclosing->enclosing->flags & SCOPEfree)); |
|---|
| 105 |
if (this == enclosing->enclosing) |
|---|
| 106 |
{ |
|---|
| 107 |
printf("this = %p, enclosing = %p, enclosing->enclosing = %p\n", this, enclosing, enclosing->enclosing); |
|---|
| 108 |
} |
|---|
| 109 |
assert(this != enclosing->enclosing); |
|---|
| 110 |
#endif |
|---|
| 111 |
this->slabel = NULL; |
|---|
| 112 |
this->linkage = enclosing->linkage; |
|---|
| 113 |
this->protection = enclosing->protection; |
|---|
| 114 |
this->explicitProtection = enclosing->explicitProtection; |
|---|
| 115 |
this->stc = enclosing->stc; |
|---|
| 116 |
this->offset = 0; |
|---|
| 117 |
this->inunion = enclosing->inunion; |
|---|
| 118 |
this->incontract = enclosing->incontract; |
|---|
| 119 |
this->nofree = 0; |
|---|
| 120 |
this->noctor = enclosing->noctor; |
|---|
| 121 |
this->noaccesscheck = enclosing->noaccesscheck; |
|---|
| 122 |
this->mustsemantic = enclosing->mustsemantic; |
|---|
| 123 |
this->intypeof = enclosing->intypeof; |
|---|
| 124 |
this->parameterSpecialization = enclosing->parameterSpecialization; |
|---|
| 125 |
this->callSuper = enclosing->callSuper; |
|---|
| 126 |
this->flags = 0; |
|---|
| 127 |
this->anonAgg = NULL; |
|---|
| 128 |
this->lastdc = NULL; |
|---|
| 129 |
this->lastoffset = 0; |
|---|
| 130 |
this->docbuf = enclosing->docbuf; |
|---|
| 131 |
assert(this != enclosing); |
|---|
| 132 |
} |
|---|
| 133 |
|
|---|
| 134 |
Scope *Scope::createGlobal(Module *module) |
|---|
| 135 |
{ |
|---|
| 136 |
Scope *sc; |
|---|
| 137 |
|
|---|
| 138 |
sc = new Scope(); |
|---|
| 139 |
sc->module = module; |
|---|
| 140 |
sc->scopesym = new ScopeDsymbol(); |
|---|
| 141 |
sc->scopesym->symtab = new DsymbolTable(); |
|---|
| 142 |
|
|---|
| 143 |
// Add top level package as member of this global scope |
|---|
| 144 |
Dsymbol *m = module; |
|---|
| 145 |
while (m->parent) |
|---|
| 146 |
m = m->parent; |
|---|
| 147 |
m->addMember(NULL, sc->scopesym, 1); |
|---|
| 148 |
m->parent = NULL; // got changed by addMember() |
|---|
| 149 |
|
|---|
| 150 |
// Create the module scope underneath the global scope |
|---|
| 151 |
sc = sc->push(module); |
|---|
| 152 |
sc->parent = module; |
|---|
| 153 |
return sc; |
|---|
| 154 |
} |
|---|
| 155 |
|
|---|
| 156 |
Scope *Scope::push() |
|---|
| 157 |
{ |
|---|
| 158 |
//printf("Scope::push()\n"); |
|---|
| 159 |
Scope *s = new Scope(this); |
|---|
| 160 |
assert(this != s); |
|---|
| 161 |
return s; |
|---|
| 162 |
} |
|---|
| 163 |
|
|---|
| 164 |
Scope *Scope::push(ScopeDsymbol *ss) |
|---|
| 165 |
{ |
|---|
| 166 |
//printf("Scope::push(%s)\n", ss->toChars()); |
|---|
| 167 |
Scope *s = push(); |
|---|
| 168 |
s->scopesym = ss; |
|---|
| 169 |
return s; |
|---|
| 170 |
} |
|---|
| 171 |
|
|---|
| 172 |
Scope *Scope::pop() |
|---|
| 173 |
{ |
|---|
| 174 |
//printf("Scope::pop() %p nofree = %d\n", this, nofree); |
|---|
| 175 |
Scope *enc = enclosing; |
|---|
| 176 |
|
|---|
| 177 |
if (enclosing) |
|---|
| 178 |
enclosing->callSuper |= callSuper; |
|---|
| 179 |
|
|---|
| 180 |
if (!nofree) |
|---|
| 181 |
{ enclosing = freelist; |
|---|
| 182 |
freelist = this; |
|---|
| 183 |
flags |= SCOPEfree; |
|---|
| 184 |
} |
|---|
| 185 |
|
|---|
| 186 |
return enc; |
|---|
| 187 |
} |
|---|
| 188 |
|
|---|
| 189 |
void Scope::mergeCallSuper(Loc loc, unsigned cs) |
|---|
| 190 |
{ |
|---|
| 191 |
// This does a primitive flow analysis to support the restrictions |
|---|
| 192 |
// regarding when and how constructors can appear. |
|---|
| 193 |
// It merges the results of two paths. |
|---|
| 194 |
// The two paths are callSuper and cs; the result is merged into callSuper. |
|---|
| 195 |
|
|---|
| 196 |
if (cs != callSuper) |
|---|
| 197 |
{ int a; |
|---|
| 198 |
int b; |
|---|
| 199 |
|
|---|
| 200 |
callSuper |= cs & (CSXany_ctor | CSXlabel); |
|---|
| 201 |
if (cs & CSXreturn) |
|---|
| 202 |
{ |
|---|
| 203 |
} |
|---|
| 204 |
else if (callSuper & CSXreturn) |
|---|
| 205 |
{ |
|---|
| 206 |
callSuper = cs | (callSuper & (CSXany_ctor | CSXlabel)); |
|---|
| 207 |
} |
|---|
| 208 |
else |
|---|
| 209 |
{ |
|---|
| 210 |
a = (cs & (CSXthis_ctor | CSXsuper_ctor)) != 0; |
|---|
| 211 |
b = (callSuper & (CSXthis_ctor | CSXsuper_ctor)) != 0; |
|---|
| 212 |
if (a != b) |
|---|
| 213 |
error(loc, "one path skips constructor"); |
|---|
| 214 |
callSuper |= cs; |
|---|
| 215 |
} |
|---|
| 216 |
} |
|---|
| 217 |
} |
|---|
| 218 |
|
|---|
| 219 |
Dsymbol *Scope::search(Loc loc, Identifier *ident, Dsymbol **pscopesym) |
|---|
| 220 |
{ Dsymbol *s; |
|---|
| 221 |
Scope *sc; |
|---|
| 222 |
|
|---|
| 223 |
//printf("Scope::search(%p, '%s')\n", this, ident->toChars()); |
|---|
| 224 |
if (ident == Id::empty) |
|---|
| 225 |
{ |
|---|
| 226 |
// Look for module scope |
|---|
| 227 |
for (sc = this; sc; sc = sc->enclosing) |
|---|
| 228 |
{ |
|---|
| 229 |
assert(sc != sc->enclosing); |
|---|
| 230 |
if (sc->scopesym) |
|---|
| 231 |
{ |
|---|
| 232 |
s = sc->scopesym->isModule(); |
|---|
| 233 |
if (s) |
|---|
| 234 |
{ |
|---|
| 235 |
//printf("\tfound %s.%s\n", s->parent ? s->parent->toChars() : "", s->toChars()); |
|---|
| 236 |
if (pscopesym) |
|---|
| 237 |
*pscopesym = sc->scopesym; |
|---|
| 238 |
return s; |
|---|
| 239 |
} |
|---|
| 240 |
} |
|---|
| 241 |
} |
|---|
| 242 |
return NULL; |
|---|
| 243 |
} |
|---|
| 244 |
|
|---|
| 245 |
for (sc = this; sc; sc = sc->enclosing) |
|---|
| 246 |
{ |
|---|
| 247 |
assert(sc != sc->enclosing); |
|---|
| 248 |
if (sc->scopesym) |
|---|
| 249 |
{ |
|---|
| 250 |
//printf("\tlooking in scopesym '%s', kind = '%s'\n", sc->scopesym->toChars(), sc->scopesym->kind()); |
|---|
| 251 |
s = sc->scopesym->search(loc, ident, 0); |
|---|
| 252 |
if (s) |
|---|
| 253 |
{ |
|---|
| 254 |
if ((global.params.warnings || |
|---|
| 255 |
global.params.Dversion > 1) && |
|---|
| 256 |
ident == Id::length && |
|---|
| 257 |
sc->scopesym->isArrayScopeSymbol() && |
|---|
| 258 |
sc->enclosing && |
|---|
| 259 |
sc->enclosing->search(loc, ident, NULL)) |
|---|
| 260 |
{ |
|---|
| 261 |
warning(s->loc, "array 'length' hides other 'length' name in outer scope"); |
|---|
| 262 |
} |
|---|
| 263 |
|
|---|
| 264 |
//printf("\tfound %s.%s, kind = '%s'\n", s->parent ? s->parent->toChars() : "", s->toChars(), s->kind()); |
|---|
| 265 |
if (pscopesym) |
|---|
| 266 |
*pscopesym = sc->scopesym; |
|---|
| 267 |
return s; |
|---|
| 268 |
} |
|---|
| 269 |
} |
|---|
| 270 |
} |
|---|
| 271 |
|
|---|
| 272 |
return NULL; |
|---|
| 273 |
} |
|---|
| 274 |
|
|---|
| 275 |
Dsymbol *Scope::insert(Dsymbol *s) |
|---|
| 276 |
{ Scope *sc; |
|---|
| 277 |
|
|---|
| 278 |
for (sc = this; sc; sc = sc->enclosing) |
|---|
| 279 |
{ |
|---|
| 280 |
//printf("\tsc = %p\n", sc); |
|---|
| 281 |
if (sc->scopesym) |
|---|
| 282 |
{ |
|---|
| 283 |
//printf("\t\tsc->scopesym = %p\n", sc->scopesym); |
|---|
| 284 |
if (!sc->scopesym->symtab) |
|---|
| 285 |
sc->scopesym->symtab = new DsymbolTable(); |
|---|
| 286 |
return sc->scopesym->symtabInsert(s); |
|---|
| 287 |
} |
|---|
| 288 |
} |
|---|
| 289 |
assert(0); |
|---|
| 290 |
return NULL; |
|---|
| 291 |
} |
|---|
| 292 |
|
|---|
| 293 |
/******************************************** |
|---|
| 294 |
* Search enclosing scopes for ClassDeclaration. |
|---|
| 295 |
*/ |
|---|
| 296 |
|
|---|
| 297 |
ClassDeclaration *Scope::getClassScope() |
|---|
| 298 |
{ Scope *sc; |
|---|
| 299 |
|
|---|
| 300 |
for (sc = this; sc; sc = sc->enclosing) |
|---|
| 301 |
{ |
|---|
| 302 |
ClassDeclaration *cd; |
|---|
| 303 |
|
|---|
| 304 |
if (sc->scopesym) |
|---|
| 305 |
{ |
|---|
| 306 |
cd = sc->scopesym->isClassDeclaration(); |
|---|
| 307 |
if (cd) |
|---|
| 308 |
return cd; |
|---|
| 309 |
} |
|---|
| 310 |
} |
|---|
| 311 |
return NULL; |
|---|
| 312 |
} |
|---|
| 313 |
|
|---|
| 314 |
/******************************************** |
|---|
| 315 |
* Search enclosing scopes for ClassDeclaration. |
|---|
| 316 |
*/ |
|---|
| 317 |
|
|---|
| 318 |
AggregateDeclaration *Scope::getStructClassScope() |
|---|
| 319 |
{ Scope *sc; |
|---|
| 320 |
|
|---|
| 321 |
for (sc = this; sc; sc = sc->enclosing) |
|---|
| 322 |
{ |
|---|
| 323 |
AggregateDeclaration *ad; |
|---|
| 324 |
|
|---|
| 325 |
if (sc->scopesym) |
|---|
| 326 |
{ |
|---|
| 327 |
ad = sc->scopesym->isClassDeclaration(); |
|---|
| 328 |
if (ad) |
|---|
| 329 |
return ad; |
|---|
| 330 |
else |
|---|
| 331 |
{ ad = sc->scopesym->isStructDeclaration(); |
|---|
| 332 |
if (ad) |
|---|
| 333 |
return ad; |
|---|
| 334 |
} |
|---|
| 335 |
} |
|---|
| 336 |
} |
|---|
| 337 |
return NULL; |
|---|
| 338 |
} |
|---|
| 339 |
|
|---|
| 340 |
/******************************************* |
|---|
| 341 |
* For TemplateDeclarations, we need to remember the Scope |
|---|
| 342 |
* where it was declared. So mark the Scope as not |
|---|
| 343 |
* to be free'd. |
|---|
| 344 |
*/ |
|---|
| 345 |
|
|---|
| 346 |
void Scope::setNoFree() |
|---|
| 347 |
{ Scope *sc; |
|---|
| 348 |
//int i = 0; |
|---|
| 349 |
|
|---|
| 350 |
//printf("Scope::setNoFree(this = %p)\n", this); |
|---|
| 351 |
for (sc = this; sc; sc = sc->enclosing) |
|---|
| 352 |
{ |
|---|
| 353 |
//printf("\tsc = %p\n", sc); |
|---|
| 354 |
sc->nofree = 1; |
|---|
| 355 |
|
|---|
| 356 |
assert(!(flags & SCOPEfree)); |
|---|
| 357 |
//assert(sc != sc->enclosing); |
|---|
| 358 |
//assert(!sc->enclosing || sc != sc->enclosing->enclosing); |
|---|
| 359 |
//if (++i == 10) |
|---|
| 360 |
//assert(0); |
|---|
| 361 |
} |
|---|
| 362 |
} |
|---|
| 363 |
|
|---|
| 364 |
|
|---|
| 365 |
/************************************************ |
|---|
| 366 |
* Given the failed search attempt, try to find |
|---|
| 367 |
* one with a close spelling. |
|---|
| 368 |
*/ |
|---|
| 369 |
|
|---|
| 370 |
void *scope_search_fp(void *arg, const char *seed) |
|---|
| 371 |
{ |
|---|
| 372 |
//printf("scope_search_fp('%s')\n", seed); |
|---|
| 373 |
|
|---|
| 374 |
/* If not in the lexer's string table, it certainly isn't in the symbol table. |
|---|
| 375 |
* Doing this first is a lot faster. |
|---|
| 376 |
*/ |
|---|
| 377 |
size_t len = strlen(seed); |
|---|
| 378 |
if (!len) |
|---|
| 379 |
return NULL; |
|---|
| 380 |
StringValue *sv = Lexer::stringtable.lookup(seed, len); |
|---|
| 381 |
if (!sv) |
|---|
| 382 |
return NULL; |
|---|
| 383 |
Identifier *id = (Identifier *)sv->ptrvalue; |
|---|
| 384 |
assert(id); |
|---|
| 385 |
|
|---|
| 386 |
Scope *sc = (Scope *)arg; |
|---|
| 387 |
Module::clearCache(); |
|---|
| 388 |
Dsymbol *s = sc->search(0, id, NULL); |
|---|
| 389 |
return s; |
|---|
| 390 |
} |
|---|
| 391 |
|
|---|
| 392 |
Dsymbol *Scope::search_correct(Identifier *ident) |
|---|
| 393 |
{ |
|---|
| 394 |
if (global.gag) |
|---|
| 395 |
return NULL; // don't do it for speculative compiles; too time consuming |
|---|
| 396 |
|
|---|
| 397 |
return (Dsymbol *)speller(ident->toChars(), &scope_search_fp, this, idchars); |
|---|
| 398 |
} |
|---|