mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-03-21 03:21:52 +01:00
First merge of 2.064 beta.
This corresponds to DMD commit a913ce4bc59a94a022a27e390fc841f4aededffb. Doesn't build Phobos yet.
This commit is contained in:
committed by
Kai Nacke
parent
c400d180d2
commit
cb341586e3
169
dmd2/scope.c
169
dmd2/scope.c
@@ -21,6 +21,7 @@
|
||||
#include "dsymbol.h"
|
||||
#include "scope.h"
|
||||
#include "declaration.h"
|
||||
#include "statement.h"
|
||||
#include "aggregate.h"
|
||||
#include "module.h"
|
||||
#include "id.h"
|
||||
@@ -50,6 +51,7 @@ Scope::Scope()
|
||||
|
||||
//printf("Scope::Scope() %p\n", this);
|
||||
this->module = NULL;
|
||||
this->instantiatingModule = NULL;
|
||||
this->scopesym = NULL;
|
||||
this->sd = NULL;
|
||||
this->enclosing = NULL;
|
||||
@@ -74,12 +76,11 @@ Scope::Scope()
|
||||
this->inunion = 0;
|
||||
this->nofree = 0;
|
||||
this->noctor = 0;
|
||||
this->noaccesscheck = 0;
|
||||
this->needctfe = 0;
|
||||
this->intypeof = 0;
|
||||
this->speculative = 0;
|
||||
this->parameterSpecialization = 0;
|
||||
this->callSuper = 0;
|
||||
this->fieldinit = NULL;
|
||||
this->fieldinit_dim = 0;
|
||||
this->flags = 0;
|
||||
this->lastdc = NULL;
|
||||
this->lastoffset = 0;
|
||||
@@ -92,6 +93,7 @@ Scope::Scope(Scope *enclosing)
|
||||
//printf("Scope::Scope(enclosing = %p) %p\n", enclosing, this);
|
||||
assert(!(enclosing->flags & SCOPEfree));
|
||||
this->module = enclosing->module;
|
||||
this->instantiatingModule = enclosing->instantiatingModule;
|
||||
this->func = enclosing->func;
|
||||
this->parent = enclosing->parent;
|
||||
this->scopesym = NULL;
|
||||
@@ -125,13 +127,12 @@ Scope::Scope(Scope *enclosing)
|
||||
this->inunion = enclosing->inunion;
|
||||
this->nofree = 0;
|
||||
this->noctor = enclosing->noctor;
|
||||
this->noaccesscheck = enclosing->noaccesscheck;
|
||||
this->needctfe = enclosing->needctfe;
|
||||
this->intypeof = enclosing->intypeof;
|
||||
this->speculative = enclosing->speculative;
|
||||
this->parameterSpecialization = enclosing->parameterSpecialization;
|
||||
this->callSuper = enclosing->callSuper;
|
||||
this->flags = (enclosing->flags & (SCOPEcontract | SCOPEdebug));
|
||||
this->fieldinit = enclosing->saveFieldInit();
|
||||
this->fieldinit_dim = enclosing->fieldinit_dim;
|
||||
this->flags = (enclosing->flags & (SCOPEcontract | SCOPEdebug | SCOPEctfe));
|
||||
this->lastdc = NULL;
|
||||
this->lastoffset = 0;
|
||||
this->docbuf = enclosing->docbuf;
|
||||
@@ -183,7 +184,17 @@ Scope *Scope::pop()
|
||||
Scope *enc = enclosing;
|
||||
|
||||
if (enclosing)
|
||||
{
|
||||
enclosing->callSuper |= callSuper;
|
||||
if (enclosing->fieldinit && fieldinit)
|
||||
{
|
||||
size_t dim = fieldinit_dim;
|
||||
for (size_t i = 0; i < dim; i++)
|
||||
enclosing->fieldinit[i] |= fieldinit[i];
|
||||
delete[] fieldinit;
|
||||
fieldinit = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nofree)
|
||||
{ enclosing = freelist;
|
||||
@@ -194,6 +205,19 @@ Scope *Scope::pop()
|
||||
return enc;
|
||||
}
|
||||
|
||||
Scope *Scope::startCTFE()
|
||||
{
|
||||
Scope *sc = this->push();
|
||||
sc->flags = this->flags | SCOPEctfe;
|
||||
return sc;
|
||||
}
|
||||
|
||||
Scope *Scope::endCTFE()
|
||||
{
|
||||
assert(flags & SCOPEctfe);
|
||||
return pop();
|
||||
}
|
||||
|
||||
void Scope::mergeCallSuper(Loc loc, unsigned cs)
|
||||
{
|
||||
// This does a primitive flow analysis to support the restrictions
|
||||
@@ -247,6 +271,131 @@ void Scope::mergeCallSuper(Loc loc, unsigned cs)
|
||||
}
|
||||
}
|
||||
|
||||
unsigned *Scope::saveFieldInit()
|
||||
{
|
||||
unsigned *fi = NULL;
|
||||
if (fieldinit) // copy
|
||||
{
|
||||
size_t dim = fieldinit_dim;
|
||||
fi = new unsigned[dim];
|
||||
fi[0] = dim;
|
||||
for (size_t i = 0; i < dim; i++)
|
||||
fi[i] = fieldinit[i];
|
||||
}
|
||||
return fi;
|
||||
}
|
||||
|
||||
bool mergeFieldInit(Loc loc, unsigned &fieldInit, unsigned fi, bool mustInit)
|
||||
{
|
||||
if (fi != fieldInit)
|
||||
{
|
||||
|
||||
// Have any branches returned?
|
||||
bool aRet = (fi & CSXreturn) != 0;
|
||||
bool bRet = (fieldInit & CSXreturn) != 0;
|
||||
|
||||
bool ok;
|
||||
|
||||
if (aRet)
|
||||
{
|
||||
ok = !mustInit || (fi & CSXthis_ctor);
|
||||
fieldInit = fieldInit;
|
||||
}
|
||||
else if (bRet)
|
||||
{
|
||||
ok = !mustInit || (fieldInit & CSXthis_ctor);
|
||||
fieldInit = fi;
|
||||
}
|
||||
else
|
||||
{
|
||||
ok = !mustInit || !((fieldInit ^ fi) & CSXthis_ctor);
|
||||
fieldInit |= fi;
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
#if 0
|
||||
// This does a primitive flow analysis to support the restrictions
|
||||
// regarding when and how constructors can appear.
|
||||
// It merges the results of two paths.
|
||||
// The two paths are fieldInit and fi; the result is merged into fieldInit.
|
||||
|
||||
if (fi != fieldInit)
|
||||
{ // Have ALL branches called a constructor?
|
||||
int aAll = (fi & CSXthis_ctor) != 0;
|
||||
int bAll = (fieldInit & CSXthis_ctor) != 0;
|
||||
|
||||
// Have ANY branches called a constructor?
|
||||
bool aAny = (fi & CSXany_ctor) != 0;
|
||||
bool bAny = (fieldInit & CSXany_ctor) != 0;
|
||||
|
||||
// Have any branches returned?
|
||||
bool aRet = (fi & CSXreturn) != 0;
|
||||
bool bRet = (fieldInit & CSXreturn) != 0;
|
||||
|
||||
bool ok = true;
|
||||
|
||||
printf("L%d fieldInit = x%x, fi = x%x\n", __LINE__, fieldInit, fi);
|
||||
|
||||
// If one has returned without a constructor call, there must be never
|
||||
// have been ctor calls in the other.
|
||||
if ( (aRet && !aAny && bAny) ||
|
||||
(bRet && !bAny && aAny))
|
||||
{ ok = false;
|
||||
printf("L%d\n", __LINE__);
|
||||
}
|
||||
// If one branch has called a ctor and then exited, anything the
|
||||
// other branch has done is OK (except returning without a
|
||||
// ctor call, but we already checked that).
|
||||
else if (aRet && aAll)
|
||||
{
|
||||
//fieldInit |= fi & (CSXany_ctor | CSXlabel);
|
||||
printf("L%d -> fieldInit = x%x\n", __LINE__, fieldInit);
|
||||
}
|
||||
else if (bRet && bAll)
|
||||
{
|
||||
fieldInit = fi;// | (fieldInit & (CSXany_ctor | CSXlabel));
|
||||
printf("L%d -> fieldInit = x%x\n", __LINE__, fieldInit);
|
||||
}
|
||||
else
|
||||
{ // Both branches must have called ctors, or both not.
|
||||
ok = (aAll == bAll);
|
||||
// If one returned without a ctor, we must remember that
|
||||
// (Don't bother if we've already found an error)
|
||||
if (ok && aRet && !aAny)
|
||||
fieldInit |= CSXreturn;
|
||||
fieldInit |= fi & (CSXany_ctor | CSXlabel);
|
||||
printf("L%d ok = %d, fieldInit = x%x, fi = x%x\n", __LINE__, ok, fieldInit, fi);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void Scope::mergeFieldInit(Loc loc, unsigned *fies)
|
||||
{
|
||||
if (fieldinit && fies)
|
||||
{
|
||||
FuncDeclaration *f = func;
|
||||
if (fes) f = fes->func;
|
||||
AggregateDeclaration *ad = f->isAggregateMember2();
|
||||
assert(ad);
|
||||
|
||||
for (size_t i = 0; i < ad->fields.dim; i++)
|
||||
{
|
||||
VarDeclaration *v = ad->fields[i];
|
||||
bool mustInit = (v->storage_class & STCnodefaultctor ||
|
||||
v->type->needsNested());
|
||||
|
||||
if (!::mergeFieldInit(loc, fieldinit[i], fies[i], mustInit))
|
||||
{
|
||||
::error(loc, "one path skips field %s", ad->fields[i]->toChars());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Dsymbol *Scope::search(Loc loc, Identifier *ident, Dsymbol **pscopesym)
|
||||
{ Dsymbol *s;
|
||||
Scope *sc;
|
||||
@@ -282,8 +431,7 @@ Dsymbol *Scope::search(Loc loc, Identifier *ident, Dsymbol **pscopesym)
|
||||
s = sc->scopesym->search(loc, ident, 0);
|
||||
if (s)
|
||||
{
|
||||
if (global.params.Dversion > 1 &&
|
||||
ident == Id::length &&
|
||||
if (ident == Id::length &&
|
||||
sc->scopesym->isArrayScopeSymbol() &&
|
||||
sc->enclosing &&
|
||||
sc->enclosing->search(loc, ident, NULL))
|
||||
@@ -414,9 +562,8 @@ void *scope_search_fp(void *arg, const char *seed)
|
||||
assert(id);
|
||||
|
||||
Scope *sc = (Scope *)arg;
|
||||
Module::clearCache();
|
||||
Dsymbol *s = sc->search(Loc(), id, NULL);
|
||||
return s;
|
||||
return (void*)s;
|
||||
}
|
||||
|
||||
Dsymbol *Scope::search_correct(Identifier *ident)
|
||||
|
||||
Reference in New Issue
Block a user