Bug 7184 – parse error on *(x)++

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
Other
OS
All
Creation time
2011-12-29T16:27:58Z
Last change time
2023-07-14T09:48:28Z
Keywords
bootcamp, pull, spec
Assigned to
No Owner
Creator
timon.gehr

Comments

Comment #0 by timon.gehr — 2011-12-29T16:27:58Z
void main(){ int[2] y; int *x = y.ptr; *(x)++=0; } Error: expression expected, not '=' Error: C style cast illegal, use cast(x)++0 Error: found '0' when expecting ';' following statement The code should compile. Workaround if parentheses are a result of code generation: void main(){ int[2] y; int *x = y.ptr; *(*&x)++=0; }
Comment #1 by razvan.nitu1305 — 2017-11-02T10:01:49Z
Issuing an error is the correct behavior. As you can see in the grammar [1], *(x)++ is parsed the following way: *UnaryExpression. If a parenthesis is encountered, then the parser expects a type : (type).identifier/templateInstance. Since none of the above is actually encountered, the parser presumes you tried to do a C style cast. Note that dropping the useless parens or doing *((x))++ works since the parser then knows that the outermost () hold a primary expression. The behavior is according to the spec, so I will close this as invalid. [1] https://dlang.org/spec/grammar.html#UnaryExpression
Comment #2 by dfj1esp02 — 2017-11-02T16:35:34Z
Is the grammar ordered? It expects braces through PowExpression: https://dlang.org/spec/grammar.html#PowExpression
Comment #3 by simen.kjaras — 2017-11-03T08:01:41Z
(In reply to RazvanN from comment #1) > The behavior is according to the spec, so I will close this as invalid. It's perfectly possible for the spec to be in error (there's even the spec keyword in Bugzilla). In this case, the code looks perfectly sensible for someone who doesn't know the spec in detail, and getting a compiler error like this is not expected. Could the spec in this case be amended to allow the example code to compile, without breaking code elsewhere? I don't know. If you know it's impossible, please explain why, and close this bug again.
Comment #4 by razvan.nitu1305 — 2017-11-03T09:50:15Z
(In reply to Simen Kjaeraas from comment #3) > (In reply to RazvanN from comment #1) > > The behavior is according to the spec, so I will close this as invalid. > > It's perfectly possible for the spec to be in error (there's even the spec > keyword in Bugzilla). In this case, the code looks perfectly sensible for > someone who doesn't know the spec in detail, and getting a compiler error > like this is not expected. > > Could the spec in this case be amended to allow the example code to compile, > without breaking code elsewhere? I don't know. If you know it's impossible, > please explain why, and close this bug again. It's not that it is impossible, rather that it requires much effort to allow a redundant use of ().
Comment #5 by dfj1esp02 — 2017-11-03T12:31:33Z
Ah, so the problem is that in expression (a[b]).c it's undecidable if the braced expression should be parsed as type or value.
Comment #6 by simen.kjaras — 2017-11-03T14:47:45Z
You're at least partly right, though (a[b]).c does work. The smallest example of this bug is probably this: unittest { (a)++; } That should of course fail to compile as well, but for other reasons. This should compile: unittest { int a; (a)++; } Are there any cases where this is valid with 'a' being a type? No. The compiler even complains about exactly that: "C style cast illegal, use cast(a)++0". ++(T), where T has overloaded static opUnary, should and does work, but the postfix version does not, because the lowering doesn't make sense. Another example of where this bug shows up is with call expressions: void foo(int n) {} unittest { (foo)(3); } (parameter added because the compiler gives up and spews other errors when getting empty parentheses) For comparison, (a)++ compiles and runs with expected semantics in C#, C++ and Javascript. It seems to me that this is in fact not a spec error, but that the parser is misbehaving when reporting this error. It gives up when it sees that the next character after (a) is not a period[0], while the grammar seems to support a test for PowExpression, to find that (a) is a PrimaryExpression on the form (Expression), and continue down that route. The error message is printed long before the parser knows that the stuff inside the parentheses is a type. [0]: https://github.com/dlang/dmd/blob/1fa67d062b8d755b11722ea112af63cb34cc06b7/src/ddmd/parse.d#L7959
Comment #7 by simen.kjaras — 2017-11-03T18:16:05Z
Unsurprisingly, the function call variant is somewhat unfixable. (T)(a+b) is a very common cast in C, and looks a lot like a function call where T is a function. Even (T)(1,2,3) is valid C. It would probably be possible to make this an error at a later point - when we know that the content of the parentheses does evaluate to a type. Anyways, PR: https://github.com/dlang/dmd/pull/7281
Comment #8 by timon.gehr — 2017-11-04T02:36:23Z
(In reply to RazvanN from comment #1) > Issuing an error is the correct behavior. As you can see in the grammar [1], > *(x)++ is parsed the following way: *UnaryExpression. If a parenthesis is > encountered, then the parser expects a type : > (type).identifier/templateInstance. That is the bug. The grammar allows the derivation UnaryExpression \ PowExpression \ PostfixExpression \ PostfixExpression ++ \ ( PrimaryExpression ) \ ... \ Identifier Aside: It is a bad idea to try and distinguish types from non-types in the parser, because it just can't. I guess this grew out of the way the parser and semantic analysis were developed. It's not a very good design. > Since none of the above is actually encountered, the parser presumes you > tried to do a C style cast. Note that dropping the useless parens The parens were not useless, they just became useless because I created a reduced test case. > or doing > *((x))++ works since the parser then knows that the outermost () hold a > primary expression. > ... That's a workaround. > The behavior is according to the spec, Certainly not. The spec is also bad though. Types should be part of the expression grammar. > so I will close this as invalid. It's not invalid. > > [1] https://dlang.org/spec/grammar.html#UnaryExpression
Comment #9 by timon.gehr — 2017-11-04T02:38:00Z
(In reply to timon.gehr from comment #8) > (In reply to RazvanN from comment #1) > > Issuing an error is the correct behavior. As you can see in the grammar [1], > > *(x)++ is parsed the following way: *UnaryExpression. If a parenthesis is > > encountered, then the parser expects a type : > > (type).identifier/templateInstance. > > That is the bug. The grammar allows the derivation > > UnaryExpression > \ > PowExpression > \ > PostfixExpression > \ > PostfixExpression ++ > \ > ( PrimaryExpression ) > \ > ... > \ > Identifier > Should have been: UnaryExpression \ PowExpression \ PostfixExpression \ PostfixExpression ++ \ PrimaryExpression \ ( Expression ) \ ... \ Identifier
Comment #10 by razvan.nitu1305 — 2017-11-06T14:10:17Z
(In reply to timon.gehr from comment #9) > (In reply to timon.gehr from comment #8) > > (In reply to RazvanN from comment #1) > > > Issuing an error is the correct behavior. As you can see in the grammar [1], > > > *(x)++ is parsed the following way: *UnaryExpression. If a parenthesis is > > > encountered, then the parser expects a type : > > > (type).identifier/templateInstance. > > > > That is the bug. The grammar allows the derivation > > > > UnaryExpression > > \ > > PowExpression > > \ > > PostfixExpression > > \ > > PostfixExpression ++ > > \ > > ( PrimaryExpression ) > > \ > > ... > > \ > > Identifier > > > > Should have been: > > UnaryExpression > \ > PowExpression > \ > PostfixExpression > \ > PostfixExpression ++ > \ > PrimaryExpression > \ > ( Expression ) > \ > ... > \ > Identifier That is correct. I looked at the code which tests that the content of the parentheses is a type and at the UnaryExpression expression grammar so I presumed that you cannot have the given construct. I understand now that indeed this is not acceptable behavior. Thanks
Comment #11 by greensunny12 — 2018-05-05T15:42:49Z
Comment #12 by razvan.nitu1305 — 2022-10-24T13:30:29Z
*** Issue 15463 has been marked as a duplicate of this issue. ***
Comment #13 by dlang-bot — 2023-07-13T19:36:06Z
@ntrel created dlang/dmd pull request #15410 "Fix Issue 7184 - parse error on *(x)++" fixing this issue: - Fix Issue 7184 - parse error on *(x)++ https://github.com/dlang/dmd/pull/15410
Comment #14 by dlang-bot — 2023-07-14T09:48:28Z
dlang/dmd pull request #15410 "Fix Issue 7184 - parse error on *(x)++" was merged into master: - 50e5492929f4afe27177824371407094d93029dc by Nick Treleaven: Fix Issue 7184 - parse error on *(x)++ https://github.com/dlang/dmd/pull/15410