Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix issue_8684 by bailing early in parseArguments #10529

Merged
merged 1 commit into from Nov 4, 2019

Conversation

benjones
Copy link
Contributor

@benjones benjones commented Nov 1, 2019

This does make the error messages better for the code from the bug report:

int foo(int n, int m)
{
    int x = foo( 5, m;
    for (int q=0; q<10; ++q){
       ++q;
    }
    return  2;
}

goes from a bunch of lines down to bad.d(3): Error: found ; when expecting , or )

Not sure if this was the best way to approach or implement a fix, so open to feedback.

@dlang-bot
Copy link
Contributor

dlang-bot commented Nov 1, 2019

Thanks for your pull request and interest in making D better, @benjones! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please verify that your PR follows this checklist:

  • My PR is fully covered with tests (you can see the coverage diff by visiting the details link of the codecov check)
  • My PR is as minimal as possible (smaller, focused PRs are easier to review than big ones)
  • I have provided a detailed rationale explaining my changes
  • New or modified functions have Ddoc comments (with Params: and Returns:)

Please see CONTRIBUTING.md for more information.


If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment.

Bugzilla references

Auto-close Bugzilla Severity Description
8684 normal Missing ')' in argument list creates a sea of error messages

Testing this PR locally

If you don't have a local development environment setup, you can use Digger to test this PR:

dub fetch digger
dub run digger -- build "master + dmd#10529"

src/dmd/parse.d Outdated Show resolved Hide resolved
src/dmd/parse.d Outdated Show resolved Hide resolved
src/dmd/parse.d Outdated Show resolved Hide resolved
@WalterBright
Copy link
Member

Seems like most of the generated errors are from check(endtok). This suggests a more general solution of suppressing that if any errors occurred in the lexing process.

@benjones
Copy link
Contributor Author

benjones commented Nov 1, 2019

The big list of errors came from staying in the while loop and calling check(comma) and trying to parse arguments a bunch of times. The check(endtok) only basically affects whether we correctly parse what comes after a malformed arglist.

I agree there's probably something more general to do with the loop + check(comma) that could be used for for + foreach.

Does the benefit of better diagnostics outweigh the cost of extra checks when parsing?

fail_compilation/ice11967.d(12): Error: found `g` when expecting `,` or `)`
fail_compilation/ice11967.d(12): Error: found `g` when expecting `,` or `]`
fail_compilation/ice11967.d(12): Error: no identifier for declarator `g`
fail_compilation/ice11967.d(12): Error: declaration expected, not `{`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd recommend also adding a more obvious test case.

@benjones
Copy link
Contributor Author

benjones commented Nov 3, 2019

Good idea @rainers . That changes the behavior, but I think still gives pretty good diagnostics and is simpler code. The test case output that changed previously was unrelated and is improved slightly from before, but is a bit longer than my first attempt which I think is fine.

I added the test case from the bug report.

src/dmd/parse.d Outdated
while (token.value != endtok && token.value != TOK.endOfFile)
{
auto arg = parseAssignExp();
arguments.push(arg);
if (token.value == endtok)
if (token.value == endtok || token.value != TOK.comma || errorCount != errorsBefore)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should not check the error count, as an error from an inner expression can be completely unrelated and might have been recovered from.

src/dmd/parse.d Outdated
while (token.value != endtok && token.value != TOK.endOfFile)
{
auto arg = parseAssignExp();
arguments.push(arg);
if (token.value == endtok)
if (token.value == endtok || token.value != TOK.comma)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As endtok is never a comma, the first part of the condition is unnecessary now. The braces below can also be omitted.
Other than that, LGTM.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it worth checking for endTok before the loop and switching to while(true)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A trailing comma is optional, so the check in the while condition should be kept.

added test example, simplified logic per @rainers suggestion
Copy link
Member

@rainers rainers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks

@dlang-bot dlang-bot merged commit a0a68bc into dlang:master Nov 4, 2019
@benjones benjones deleted the Issue_8684 branch May 19, 2020 21:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants