Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 105 additions & 0 deletions src/expression.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/expression.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
7 changes: 2 additions & 5 deletions src/mtype.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
146 changes: 146 additions & 0 deletions test/runnable/property2.d
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -451,6 +596,7 @@ int main()
test7174();
test7274();
test7275();
test7538();
test8251();
test10103();
test10197();
Expand Down