Skip to content

Commit

Permalink
2nd fix for Issue 9124 - Object variable of variadic template struct …
Browse files Browse the repository at this point in the history
…needs explicit "this" in certain situations
  • Loading branch information
9rnsr committed Dec 13, 2012
1 parent 2284bb9 commit 69307c2
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 52 deletions.
77 changes: 42 additions & 35 deletions src/template.c
Expand Up @@ -167,6 +167,38 @@ Dsymbol *getDsymbol(Object *oarg)
return sa;
}

/***********************
* Try to get value from manifest constant
*/

Expression *getValue(Expression *e)
{
if (e && e->op == TOKvar)
{
VarDeclaration *v = ((VarExp *)e)->var->isVarDeclaration();
if (v && v->storage_class & STCmanifest)
{ ExpInitializer *ei = v->init->isExpInitializer();
if (ei)
e = ei->exp;
}
}
return e;
}
Expression *getValue(Dsymbol *&s)
{
Expression *e = NULL;
if (s)
{
VarDeclaration *v = s->isVarDeclaration();
if (v && v->storage_class & STCmanifest)
{ ExpInitializer *ei = v->init->isExpInitializer();
if (ei)
e = ei->exp, s = NULL;
}
}
return e;
}

/******************************
* If o1 matches o2, return 1.
* Else, return 0.
Expand All @@ -176,10 +208,10 @@ int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc)
{
Type *t1 = isType(o1);
Type *t2 = isType(o2);
Expression *e1 = isExpression(o1);
Expression *e2 = isExpression(o2);
Dsymbol *s1 = isDsymbol(o1);
Dsymbol *s2 = isDsymbol(o2);
Expression *e1 = s1 ? getValue(s1) : getValue(isExpression(o1));
Expression *e2 = s2 ? getValue(s2) : getValue(isExpression(o2));
Tuple *u1 = isTuple(o1);
Tuple *u2 = isTuple(o2);

Expand All @@ -190,24 +222,9 @@ int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc)
* we'll do that another day.
*/

if (s1)
{
VarDeclaration *v1 = s1->isVarDeclaration();
if (v1 && v1->storage_class & STCmanifest)
{ ExpInitializer *ei1 = v1->init->isExpInitializer();
if (ei1)
e1 = ei1->exp, s1 = NULL;
}
}
if (s2)
{
VarDeclaration *v2 = s2->isVarDeclaration();
if (v2 && v2->storage_class & STCmanifest)
{ ExpInitializer *ei2 = v2->init->isExpInitializer();
if (ei2)
e2 = ei2->exp, s2 = NULL;
}
}
/* Manifest constants should be compared by their values,
* at least in template arguments.
*/

if (t1)
{
Expand Down Expand Up @@ -241,25 +258,14 @@ int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc)
if (e1 && e2)
{
printf("match %d\n", e1->equals(e2));
e1->print();
e2->print();
e1->type->print();
e2->type->print();
printf("\te1 = %p %s %s %s\n", e1, e1->type->toChars(), Token::toChars(e1->op), e1->toChars());
printf("\te2 = %p %s %s %s\n", e2, e2->type->toChars(), Token::toChars(e2->op), e2->toChars());
}
#endif
if (!e2)
goto Lnomatch;
if (!e1->equals(e2))
{ // e2 might be a enum variable symbol, then optimize and re-try
if (!(e2->isConst() && e1->op == TOKvar))
goto Lnomatch;
VarDeclaration *v = ((VarExp *)e1)->var->isVarDeclaration();
if (!(v && (v->storage_class & STCmanifest)))
goto Lnomatch;
e1 = e1->optimize(WANTvalue);
if (!e1->equals(e2))
goto Lnomatch;
}
goto Lnomatch;
}
else if (s1)
{
Expand Down Expand Up @@ -5216,7 +5222,7 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
Expression *ea = isExpression(o);
Dsymbol *sa = isDsymbol(o);

//printf("1: (*tiargs)[%d] = %p, %p, %p, ea=%p, ta=%p\n", j, o, isDsymbol(o), isTuple(o), ea, ta);
//printf("1: (*tiargs)[%d] = %p, s=%p, v=%p, ea=%p, ta=%p\n", j, o, isDsymbol(o), isTuple(o), ea, ta);
if (ta)
{
//printf("type %s\n", ta->toChars());
Expand All @@ -5225,6 +5231,7 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
if (ea)
{
ea = ea->semantic(sc);
//printf("-> ea = %s %s\n", Token::toChars(ea->op), ea->toChars());
/* This test is to skip substituting a const var with
* its initializer. The problem is the initializer won't
* match with an 'alias' parameter. Instead, do the
Expand Down
61 changes: 44 additions & 17 deletions test/runnable/template9.d
Expand Up @@ -1797,45 +1797,71 @@ void test9100()
(new C9100()).test();
}

/**********************************/
// 9101

class Node9101
{
template ForwardCtorNoId()
{
this() {} // default constructor
void foo() { 0 = 1; } // wrong code
}
}
enum x9101 = __traits(compiles, Node9101.ForwardCtorNoId!());

/**********************************/
// 9124

struct Foo9124(N...)
struct Foo9124a(N...)
{
enum SIZE = N[0];
private int _val;

public void opAssign (T) (T other)
if (is(T unused == Foo9124!(_N), _N...))
if (is(T unused == Foo9124a!(_N), _N...))
{
_val = other._val; // compile error
// this._val = other._val; // explicit this make it work
this._val = other._val; // explicit this make it work
}

public auto opUnary (string op) () if (op == "~") {
Foo9124!(SIZE) result = this;
Foo9124a!(SIZE) result = this;
return result;
}
}

void test9124()
void test9124a()
{
Foo9124!(28) a;
Foo9124!(28) b = ~a;
Foo9124a!(28) a;
Foo9124a!(28) b = ~a;
}

/**********************************/
// 9101
// --------

class Node9101
template Foo9124b(T, U, string OP)
{
template ForwardCtorNoId()
{
this() {} // default constructor
void foo() { 0 = 1; } // wrong code
enum N = T.SIZE;
alias Foo9124b = Foo9124b!(false, true, N);
}
struct Foo9124b(bool S, bool L, N...)
{
enum SIZE = 5;
long[1] _a = 0;
void someFunction() const {
auto data1 = _a; // Does not compile
auto data2 = this._a; // <--- Compiles
}
auto opBinary(string op, T)(T) {
Foo9124b!(typeof(this), T, op) test;
}
}
enum x9101 = __traits(compiles, Node9101.ForwardCtorNoId!());
void test9124b()
{
auto p = Foo9124b!(false, false, 5)();
auto q = Foo9124b!(false, false, 5)();
p|q;
p&q;
}

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

Expand Down Expand Up @@ -1906,7 +1932,8 @@ int main()
test9038();
test9076();
test9100();
test9124();
test9124a();
test9124b();

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

0 comments on commit 69307c2

Please sign in to comment.