Skip to content

Commit 9710a19

Browse files
committed
fix(statementsem): correctly resolve opDispatch in WithStatement
Signed-off-by: royalpinto007 <[email protected]>
1 parent 6523a70 commit 9710a19

File tree

2 files changed

+62
-21
lines changed

2 files changed

+62
-21
lines changed

compiler/src/dmd/statementsem.d

+24-21
Original file line numberDiff line numberDiff line change
@@ -3150,7 +3150,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
31503150
void visitWith(WithStatement ws)
31513151
{
31523152
/* https://dlang.org/spec/statement.html#with-statement
3153-
*/
3153+
*/
31543154

31553155
ScopeDsymbol sym;
31563156
Initializer _init;
@@ -3160,8 +3160,10 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
31603160
ws.exp = resolveProperties(sc, ws.exp);
31613161
ws.exp = ws.exp.optimize(WANTvalue);
31623162
ws.exp = checkGC(sc, ws.exp);
3163+
31633164
if (ws.exp.op == EXP.error)
31643165
return setError();
3166+
31653167
if (ws.exp.op == EXP.scope_)
31663168
{
31673169
sym = new WithScopeSymbol(ws);
@@ -3183,19 +3185,19 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
31833185
else
31843186
{
31853187
Type texp = ws.exp.type;
3186-
Type t = texp.toBasetype();
3188+
if (!texp)
3189+
{
3190+
error(ws.loc, "Expression has no type.");
3191+
return setError();
3192+
}
31873193

3188-
Expression olde = ws.exp;
3189-
if (t.ty == Tpointer)
3194+
Type t = texp.toBasetype();
3195+
if (!t)
31903196
{
3191-
ws.exp = new PtrExp(ws.loc, ws.exp);
3192-
ws.exp = ws.exp.expressionSemantic(sc);
3193-
texp = ws.exp.type;
3194-
t = texp.toBasetype();
3197+
error(ws.loc, "Unable to resolve base type.");
3198+
return setError();
31953199
}
31963200

3197-
assert(t);
3198-
t = t.toBasetype();
31993201
if (t.isClassHandle())
32003202
{
32013203
_init = new ExpInitializer(ws.loc, ws.exp);
@@ -3212,14 +3214,14 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
32123214
if (!ws.exp.isLvalue())
32133215
{
32143216
/* Re-write to
3215-
* {
3216-
* auto __withtmp = exp
3217-
* with(__withtmp)
3218-
* {
3219-
* ...
3220-
* }
3221-
* }
3222-
*/
3217+
* {
3218+
* auto __withtmp = exp
3219+
* with(__withtmp)
3220+
* {
3221+
* ...
3222+
* }
3223+
* }
3224+
*/
32233225
auto tmp = copyToTemp(0, "__withtmp", ws.exp);
32243226
tmp.dsymbolSemantic(sc);
32253227
auto es = new ExpStatement(ws.loc, tmp);
@@ -3233,9 +3235,9 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
32333235
ws.wthis = new VarDeclaration(ws.loc, e.type, Id.withSym, _init);
32343236
ws.wthis.storage_class |= STC.temp;
32353237
ws.wthis.dsymbolSemantic(sc);
3238+
32363239
sym = new WithScopeSymbol(ws);
3237-
// Need to set the scope to make use of resolveAliasThis
3238-
sym.setScope(sc);
3240+
sym.setScope(sc); // Enable resolveAliasThis
32393241
sym.parent = sc.scopesym;
32403242
sym.endlinnum = ws.endloc.linnum;
32413243
}
@@ -3248,7 +3250,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
32483250
}
32493251
else
32503252
{
3251-
error(ws.loc, "`with` expression types must be enums or aggregates or pointers to them, not `%s`", olde.type.toChars());
3253+
error(ws.loc, "`with` expression types must be enums, structs, or classes, not `%s`", t.toChars());
32523254
return setError();
32533255
}
32543256
}
@@ -3260,6 +3262,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
32603262
sc.insert(sym);
32613263
ws._body = ws._body.statementSemantic(sc);
32623264
sc.pop();
3265+
32633266
if (ws._body && ws._body.isErrorStatement())
32643267
{
32653268
result = ws._body;
+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
TEST_OUTPUT:
3+
---
4+
fail_compilation/test20274.d(28): Error: function expected before `()`, not `(*__withSym).opDispatch()` of type `void`
5+
fail_compilation/test20274.d(35): Error: undefined identifier `foo`
6+
---
7+
*/
8+
9+
// https://issues.dlang.org/show_bug.cgi?id=20274
10+
11+
struct A {
12+
void opDispatch(string name, A...)(A a) {
13+
}
14+
}
15+
16+
struct B {
17+
void opDispatch(string name, T)(T a) {
18+
}
19+
}
20+
21+
void main()
22+
{
23+
A a;
24+
a.foo(2); // ok
25+
26+
with (a)
27+
{
28+
foo(2); // fails
29+
}
30+
31+
B b;
32+
b.foo(3); // ok
33+
34+
with(b) {
35+
foo(3); // fails
36+
}
37+
38+
}

0 commit comments

Comments
 (0)