Skip to content

Commit

Permalink
fix Issue 8339 - is(typeof(...)) is reporting true when it's false du…
Browse files Browse the repository at this point in the history
…e to nested function error
  • Loading branch information
9rnsr committed Aug 18, 2012
1 parent 5590585 commit a8be86a
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 13 deletions.
74 changes: 61 additions & 13 deletions src/declaration.c
Expand Up @@ -24,6 +24,51 @@
#include "statement.h"
#include "hdrgen.h"

AggregateDeclaration *isAggregate(Type *t); // from opover.c

void checkFrameAccess(Loc loc, Scope *sc, AggregateDeclaration *ad)
{
if (!ad->isnested)
return;

Dsymbol *s = sc->func;
if (s)
{
Dsymbol *sparent = ad->toParent2();
//printf("ad = %p %s [%s], parent:%p\n", ad, ad->toChars(), ad->loc.toChars(), ad->parent);
//printf("sparent = %p %s [%s], parent: %s\n", sparent, sparent->toChars(), sparent->loc.toChars(), sparent->parent->toChars());

while (s)
{
if (s == sparent) // hit!
{
// Is it better moving this check to AggregateDeclaration:semantic?
for (size_t i = 0; i < ad->fields.dim; i++)
{ VarDeclaration *vd = ad->fields[i]->isVarDeclaration();
if (vd)
if (AggregateDeclaration *ad2 = isAggregate(vd->type))
if (ad2->isStructDeclaration())
checkFrameAccess(loc, sc, ad2);
}
return;
}

if (FuncDeclaration *fd = s->isFuncDeclaration())
{
if (!fd->isThis() && !fd->isNested())
break;
}
if (AggregateDeclaration *ad2 = s->isAggregateDeclaration())
{
if (ad2->storage_class & STCstatic)
break;
}
s = s->toParent2();
}
}
error(loc, "cannot access frame pointer of %s", ad->toPrettyChars());
}

/********************************* Declaration ****************************/

Declaration::Declaration(Identifier *id)
Expand Down Expand Up @@ -1224,6 +1269,22 @@ void VarDeclaration::semantic(Scope *sc)
// Provide a default initializer
//printf("Providing default initializer for '%s'\n", toChars());
if (type->ty == Tstruct &&
((TypeStruct *)type)->sym->isnested)
{
/* Nested struct requires valid enclosing frame pointer.
* In StructLiteralExp::toElem(), it's calculated.
*/

checkFrameAccess(loc, sc, ((TypeStruct *)type)->sym);

Expression *e = type->defaultInitLiteral(loc);
Expression *e1 = new VarExp(loc, this);
e = new ConstructExp(loc, e1, e);
e = e->semantic(sc);
init = new ExpInitializer(loc, e);
goto Ldtor;
}
else if (type->ty == Tstruct &&
((TypeStruct *)type)->sym->zeroInit == 1)
{ /* If a struct is all zeros, as a special case
* set it's initializer to the integer 0.
Expand All @@ -1239,19 +1300,6 @@ void VarDeclaration::semantic(Scope *sc)
init = new ExpInitializer(loc, e);
goto Ldtor;
}
else if (type->ty == Tstruct &&
(((TypeStruct *)type)->sym->isnested))
{
/* Nested struct requires valid enclosing frame pointer.
* In StructLiteralExp::toElem(), it's calculated.
*/
Expression *e = type->defaultInitLiteral(loc);
Expression *e1 = new VarExp(loc, this);
e = new ConstructExp(loc, e1, e);
e = e->semantic(sc);
init = new ExpInitializer(loc, e);
goto Ldtor;
}
else if (type->ty == Ttypedef)
{ TypeTypedef *td = (TypeTypedef *)type;
if (td->sym->init)
Expand Down
98 changes: 98 additions & 0 deletions test/runnable/nested.d
Expand Up @@ -1702,6 +1702,101 @@ void test8194()
}
}

/*******************************************/
// 8339

template map8339a(fun...)
{
auto map8339a(Range)(Range r) {
struct Result {
this(double[] input) {}
}
return Result(r);
}
}
template map8339b(fun...)
{
auto map8339b(Range)(Range r) {
struct Result {
this(double[] input) { fun[0](input.length); }
}
return Result(r);
}
}
template map8339c(fun...)
{
auto map8339c(Range)(Range r) {
static struct Result {
this(double[] input) {}
}
return Result(r);
}
}
template map8339d(fun...)
{
auto map8339d(Range)(Range r) {
static struct Result {
this(double[] input) { fun[0](input.length); }
}
return Result(r);
}
}
void copy8339(T)(T x)
{
T xSaved;
}
void test8339a()
{
double[] x;
int n;

// Result has context pointer, so cannot copy
static assert (!is(typeof({ copy8339(map8339a!(a=>a)(x)); })));
static assert (!is(typeof({ copy8339(map8339a!(a=>n)(x)); })));

// same as
static assert (!is(typeof({ copy8339(map8339b!(a=>a)(x)); })));
static assert (!is(typeof({ copy8339(map8339b!(a=>n)(x)); })));

// fun is never instantiated
copy8339(map8339c!(a=>a)(x));
copy8339(map8339c!(a=>n)(x));

// static nested struct doesn't have contest pointer
copy8339(map8339d!(a=>a)(x));
//copy8339(map8339d!(a=>n)(x)); // too strict case

}

template filter8339(alias pred)
{
auto filter8339(R)(R r) {
struct Result {
R range;
this(R r) {}
auto front() { return pred(0); }
}
return Result(r);
}
}
void test8339b()
{
static makefilter() { int n; return filter8339!(a=>n)([]); }

auto r1 = makefilter();
static assert(!is(typeof({ filter8339!(a=>a)(r1); })));
}

void test8339c()
{
class C(X) { X x; }
class C1 { C!C1 x; }
alias C!C1 C2;

struct Pair { C1 t; C2 u; void func(){} }
Pair pair;
}

/*******************************************/

int main()
Expand Down Expand Up @@ -1771,6 +1866,9 @@ int main()

test5082();
test8194();
test8339a();
test8339b();
test8339c();

printf("Success\n");
return 0;
Expand Down

0 comments on commit a8be86a

Please sign in to comment.