Skip to content

Commit 1d66c36

Browse files
committed
Fix issue 21284: report "no property" error at identifier location
The "no property `X` for type `Y`" error for enum member access was reported at the location of the enum type expression instead of the invalid identifier, e.g. across: auto x = E . three; it reported the error on the "E" line instead of the "three" line. - Add identLoc to DotIdExp, set by the parser from the identifier's own token location. - Thread identLoc through dotExp() and use it (falling back to the previous location when unset) when reporting the "no property" error for TypeEnum. - Add fail_compilation test diag21284.d. Based on the diagnosis and approach explored in #22740 by Jay-Lokhande. Fixes https://issues.dlang.org/show_bug.cgi?id=21284
1 parent 078e406 commit 1d66c36

6 files changed

Lines changed: 31 additions & 9 deletions

File tree

compiler/include/dmd/expression.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -688,8 +688,9 @@ class DotIdExp final : public UnaExp
688688
d_bool noderef; // true if the result of the expression will never be dereferenced
689689
d_bool wantsym; // do not replace Symbol with its initializer during semantic()
690690
d_bool arrow; // ImportC: if -> instead of .
691+
Loc identLoc; // location of `ident` itself (may differ from `loc`, e.g. across multiple lines)
691692

692-
static DotIdExp *create(Loc loc, Expression *e, Identifier *ident);
693+
static DotIdExp *create(Loc loc, Expression *e, Identifier *ident, Loc identLoc = Loc());
693694
void accept(Visitor *v) override { v->visit(this); }
694695
};
695696

compiler/src/dmd/expression.d

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2191,16 +2191,18 @@ extern (C++) final class DotIdExp : UnaExp
21912191
bool noderef; // true if the result of the expression will never be dereferenced
21922192
bool wantsym; // do not replace Symbol with its initializer during semantic()
21932193
bool arrow; // ImportC: if -> instead of .
2194+
Loc identLoc; // location of `ident` itself (may differ from `loc`, e.g. across multiple lines)
21942195

2195-
extern (D) this(Loc loc, Expression e, Identifier ident) @safe
2196+
extern (D) this(Loc loc, Expression e, Identifier ident, Loc identLoc = Loc.init) @safe
21962197
{
21972198
super(loc, EXP.dotIdentifier, e);
21982199
this.ident = ident;
2200+
this.identLoc = identLoc.isValid() ? identLoc : loc;
21992201
}
22002202

2201-
static DotIdExp create(Loc loc, Expression e, Identifier ident) @safe
2203+
static DotIdExp create(Loc loc, Expression e, Identifier ident, Loc identLoc = Loc.init) @safe
22022204
{
2203-
return new DotIdExp(loc, e, ident);
2205+
return new DotIdExp(loc, e, ident, identLoc);
22042206
}
22052207

22062208
override void accept(Visitor v)

compiler/src/dmd/expressionsem.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16528,7 +16528,7 @@ Expression dotIdSemanticProp(DotIdExp exp, Scope* sc, bool gag)
1652816528

1652916529
const flag = cast(DotExpFlag) (exp.noderef * DotExpFlag.noDeref | gag * DotExpFlag.gag);
1653016530

16531-
Expression e = dotExp(exp.e1.type, sc, exp.e1, exp.ident, flag);
16531+
Expression e = dotExp(exp.e1.type, sc, exp.e1, exp.ident, flag, exp.identLoc);
1653216532
if (e)
1653316533
{
1653416534
e = e.expressionSemantic(sc);

compiler/src/dmd/parse.d

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9371,6 +9371,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
93719371
if (token.value == TOK.identifier)
93729372
{
93739373
Identifier id = token.ident;
9374+
const identLoc = token.loc;
93749375

93759376
nextToken();
93769377
if (token.value == TOK.not && peekNext() != TOK.is_ && peekNext() != TOK.in_)
@@ -9379,7 +9380,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
93799380
e = new AST.DotTemplateInstanceExp(loc, e, id, tiargs);
93809381
}
93819382
else
9382-
e = new AST.DotIdExp(loc, e, id);
9383+
e = new AST.DotIdExp(loc, e, id, identLoc);
93839384
continue;
93849385
}
93859386
if (token.value == TOK.new_)

compiler/src/dmd/typesem.d

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6194,7 +6194,7 @@ void resolve(Type mt, Loc loc, Scope* sc, out Expression pe, out Type pt, out Ds
61946194
* Returns:
61956195
* resulting expression with e.ident resolved
61966196
*/
6197-
Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag flag)
6197+
Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag flag, Loc identLoc = Loc.init)
61986198
{
61996199
enum LOGDOTEXP = false;
62006200
if (LOGDOTEXP)
@@ -7045,11 +7045,12 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag
70457045
Expression res = mt.sym.getMemtype(Loc.initial).dotExp(sc, e, ident, DotExpFlag.gag);
70467046
if (!(flag & 1) && !res)
70477047
{
7048+
const errLoc = identLoc.isValid() ? identLoc : e.loc;
70487049
if (auto ns = mt.sym.search_correct(ident))
7049-
eSink.error(e.loc, "no property `%s` for type `%s`. Did you mean `%s.%s` ?", ident.toErrMsg(), mt.toErrMsg(), mt.toErrMsg(),
7050+
eSink.error(errLoc, "no property `%s` for type `%s`. Did you mean `%s.%s` ?", ident.toErrMsg(), mt.toErrMsg(), mt.toErrMsg(),
70507051
ns.toErrMsg());
70517052
else
7052-
eSink.error(e.loc, "no property `%s` for type `%s`", ident.toErrMsg(),
7053+
eSink.error(errLoc, "no property `%s` for type `%s`", ident.toErrMsg(),
70537054
mt.toErrMsg());
70547055

70557056
eSink.errorSupplemental(mt.sym.loc, "%s `%s` defined here",
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
TEST_OUTPUT:
3+
---
4+
fail_compilation/diag21284.d(16): Error: no property `three` for type `E`
5+
fail_compilation/diag21284.d(9): enum `E` defined here
6+
---
7+
*/
8+
// https://issues.dlang.org/show_bug.cgi?id=21284 (github issue)
9+
enum E { one, two }
10+
11+
void test21284()
12+
{
13+
auto x =
14+
E
15+
.
16+
three;
17+
}

0 commit comments

Comments
 (0)