From 1093dbe73f2414f4c03706e99888e0764b42fa65 Mon Sep 17 00:00:00 2001 From: k-hara Date: Sat, 6 Jul 2013 14:30:00 +0900 Subject: [PATCH] fix Issue 7538 - All kinds of property functions should be called before getting their types inside typeof --- src/expression.c | 105 +++++++++++++++++++++++++++ src/expression.h | 1 + src/mtype.c | 7 +- test/runnable/property2.d | 146 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 254 insertions(+), 5 deletions(-) diff --git a/src/expression.c b/src/expression.c index 4dfaffa785dd..c633d98c6694 100644 --- a/src/expression.c +++ b/src/expression.c @@ -543,6 +543,111 @@ void checkPropertyCall(Expression *e, Expression *emsg) } } +/****************************** + * If e1 is a property function (template), resolve it. + */ + +Expression *resolvePropertiesOnly(Scope *sc, Expression *e1) +{ + OverloadSet *os; + FuncDeclaration *fd; + TemplateDeclaration *td; + + if (e1->op == TOKdotexp) + { + DotExp *de = (DotExp *)e1; + if (de->e2->op == TOKoverloadset) + { + os = ((OverExp *)de->e2)->vars; + goto Los; + } + } + else if (e1->op == TOKoverloadset) + { + os = ((OverExp *)e1)->vars; + Los: + assert(os); + for (size_t i = 0; i < os->a.dim; i++) + { + Dsymbol *s = os->a[i]; + fd = s->isFuncDeclaration(); + td = s->isTemplateDeclaration(); + if (fd) + { + if (((TypeFunction *)fd->type)->isproperty) + return resolveProperties(sc, e1); + } + else if (td && td->onemember && + (fd = td->onemember->isFuncDeclaration()) != NULL) + { + if (((TypeFunction *)fd->type)->isproperty || + (fd->storage_class2 & STCproperty) || + (td->scope->stc & STCproperty)) + { + return resolveProperties(sc, e1); + } + } + } + } + else if (e1->op == TOKdotti) + { + DotTemplateInstanceExp* dti = (DotTemplateInstanceExp *)e1; + td = dti->ti->tempdecl; + if (td) + goto Ltd; + } + else if (e1->op == TOKdottd) + { + td = ((DotTemplateExp *)e1)->td; + goto Ltd; + } + else if (e1->op == TOKimport) + { + Dsymbol *s = ((ScopeExp *)e1)->sds; + td = s->isTemplateDeclaration(); + if (td) + goto Ltd; + TemplateInstance *ti = s->isTemplateInstance(); + if (ti && !ti->semanticRun) + { + td = ti->tempdecl; + if (td) + goto Ltd; + } + } + else if (e1->op == TOKtemplate) + { + td = ((TemplateExp *)e1)->td; + Ltd: + assert(td); + if (td->onemember && + (fd = td->onemember->isFuncDeclaration()) != NULL) + { + if (((TypeFunction *)fd->type)->isproperty || + (fd->storage_class2 & STCproperty) || + (td->scope->stc & STCproperty)) + { + return resolveProperties(sc, e1); + } + } + } + else if (e1->op == TOKdotvar && e1->type->ty == Tfunction) + { + DotVarExp *dve = (DotVarExp *)e1; + fd = dve->var->isFuncDeclaration(); + goto Lfd; + } + else if (e1->op == TOKvar && e1->type->ty == Tfunction) + { + fd = ((VarExp *)e1)->var->isFuncDeclaration(); + Lfd: + assert(fd); + if (((TypeFunction *)fd->type)->isproperty) + return resolveProperties(sc, e1); + } + return e1; +} + /****************************** * Find symbol in accordance with the UFCS name look up rule diff --git a/src/expression.h b/src/expression.h index 5938cc1cd616..a99409df0969 100644 --- a/src/expression.h +++ b/src/expression.h @@ -68,6 +68,7 @@ void initPrecedence(); typedef int (*apply_fp_t)(Expression *, void *); Expression *resolveProperties(Scope *sc, Expression *e); +Expression *resolvePropertiesOnly(Scope *sc, Expression *e1); void accessCheck(Loc loc, Scope *sc, Expression *e, Declaration *d); Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Dsymbol *d); Dsymbol *search_function(ScopeDsymbol *ad, Identifier *funcid); diff --git a/src/mtype.c b/src/mtype.c index b23db1a24def..eed2478d13e3 100644 --- a/src/mtype.c +++ b/src/mtype.c @@ -6992,13 +6992,10 @@ void TypeTypeof::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol if (global.gag) global.speculativeGag = global.gag; exp = exp->semantic(sc2); - global.speculativeGag = oldspecgag; - #if DMDV2 - if (exp->type && exp->type->ty == Tfunction && - ((TypeFunction *)exp->type)->isproperty) - exp = resolveProperties(sc2, exp); + exp = resolvePropertiesOnly(sc2, exp); #endif + global.speculativeGag = oldspecgag; sc2->pop(); if (exp->op == TOKtype) { diff --git a/test/runnable/property2.d b/test/runnable/property2.d index c795b09b40b0..929ff99c2212 100644 --- a/test/runnable/property2.d +++ b/test/runnable/property2.d @@ -312,6 +312,151 @@ void test7275() } } +/*****************************************/ +// 7538 + +void test7538() +{ + struct P + { + @property long pr() { return 1; } + @property void pr(int) {} + + @property long a1()() { return 1; } + @property void a1()(int) {} + template a2() { @property long a2() { return 1; } } + template a2() { @property void a2(int) {} } + template a3() { long a3() @property { return 1; } } + template a3() { void a3(int) @property {} } + + static + { + @property long b1()() { return 1; } + @property void b1()(int) {} + template b2() { @property long b2() { return 1; } } + template b2() { @property void b2(int) {} } + template b3() { long b3() @property { return 1; } } + template b3() { void b3(int) @property {} } + } + + @property long c1(T)() { return 1; } + @property long c1(T)(int) { return 1; } + template c2(T) { @property long c2() { return 1; } } + template c2(T) { @property void c2(int) {} } + template c3(T) { long c3() @property { return 1; } } + template c3(T) { void c3(int) @property {} } + + static + { + @property long d1(T)() { return 1; } + @property void d1(T)(int) {} + template d2(T) { @property long d2() { return 1; } } + template d2(T) { @property void d2(int) {} } + template d3(T) { long d3() @property { return 1; } } + template d3(T) { void d3(int) @property {} } + } + + void test() + { + // TOKvar + static assert(is(typeof(pr) == long)); + + // TOKtemplate + static assert(is(typeof(b1) == long)); + static assert(is(typeof(b2) == long)); + static assert(is(typeof(b3) == long)); + + // TOKimport + static assert(is(typeof(d1!int) == long)); + static assert(is(typeof(d2!int) == long)); + static assert(is(typeof(d3!int) == long)); + } + } + P p; + { + // TOKdotvar + static assert(is(typeof(p.pr) == long)); + + // TOKdottd + static assert(is(typeof(p.a1) == long)); + static assert(is(typeof(p.a2) == long)); + static assert(is(typeof(p.a3) == long)); + + // TOKimport + static assert(is(typeof(P.b1) == long)); + static assert(is(typeof(P.b2) == long)); + static assert(is(typeof(P.b3) == long)); + + // TOKdotti; + static assert(is(typeof(p.c1!int) == long)); + static assert(is(typeof(p.c2!int) == long)); + static assert(is(typeof(p.c3!int) == long)); + } + + struct F + { + long fn() { return 1; } + void fn(int) {} + + long a1()() { return 1; } + void a1()(int) {} + template a2() { long a2() { return 1; } } + template a2() { void a2(int) {} } + + static + { + long b1()() { return 1; } + void b1()(int) {} + template b2() { long b2() { return 1; } } + template b2() { void b2(int) {} } + } + + long c1(T)() { return 1; } + long c1(T)(int) { return 1; } + template c2(T) { long c2() { return 1; } } + template c2(T) { void c2(int) {} } + + static + { + long d1(T)() { return 1; } + void d1(T)(int) {} + template d2(T) { long d2() { return 1; } } + template d2(T) { void d2(int) {} } + } + + void test() + { + // TOKvar + static assert( is(typeof(fn) == function)); + + // TOKtemplate + static assert(!is(typeof(b1) == long)); + static assert(!is(typeof(b2) == long)); + + // TOKimport + static assert(!is(typeof(d1!int) == long)); + static assert(!is(typeof(d2!int) == long)); + } + } + F f; + { + // TOKdotvar + static assert(is( typeof(f.fn) == function)); + + // TOKdottd + static assert(!is(typeof(f.a1) == long)); + static assert(!is(typeof(f.a2) == long)); + + // TOKimport + static assert(!is(typeof(F.b1) == long)); + static assert(!is(typeof(F.b2) == long)); + + // TOKdotti; + static assert(!is(typeof(f.c1!int) == long)); + static assert(!is(typeof(f.c2!int) == long)); + } +} + /*****************************************/ // 8251 @@ -451,6 +596,7 @@ int main() test7174(); test7274(); test7275(); + test7538(); test8251(); test10103(); test10197();