This is an archive of the discontinued LLVM Phabricator instance.

[lldb] Show fix-it applied even if expression didn't evaluate succesfully
ClosedPublic

Authored by augusto2112 on Sep 16 2021, 12:29 PM.

Details

Summary

If we applied a fix-it before evaluating an expression and that
expression didn't evaluate correctly, we should still tell users about
the fix-it we applied since that may be the reason why it didn't work
correctly.

Diff Detail

Event Timeline

augusto2112 requested review of this revision.Sep 16 2021, 12:29 PM
augusto2112 created this revision.
Herald added a project: Restricted Project. · View Herald TranscriptSep 16 2021, 12:29 PM
teemperor requested changes to this revision.Sep 16 2021, 1:18 PM
teemperor added a subscriber: teemperor.

Could you add a test for that? The usual test fixit in Clang is ./-> mixup, e.g.

(lldb) expr struct Foo { int i; }; Foo *f; f.i ; unknown_identifier_for_fatal_error
(int) $0 = 0
  Fix-it applied, fixed expression was: 
    struct Foo { int i; }; Foo *f; f->i ; unknown_identifier_for_fatal_error
...

I think this patch also needs to update UserExpression::Evaluate which, IIRC, is clearing the fixed expression when it fails to parse.

The direction of the patch is IMHO fine. One thing that would be nice is to see if we could maybe preserve the Fix-It diagnostics from the original expression. If we just return whatever the fixed expression fails with then it's not clear why the compiler actually generated a Fix-It. But that's more of a nice-to-have I think.

This revision now requires changes to proceed.Sep 16 2021, 1:18 PM

Could you add a test for that? The usual test fixit in Clang is ./-> mixup, e.g.

(lldb) expr struct Foo { int i; }; Foo *f; f.i ; unknown_identifier_for_fatal_error
(int) $0 = 0
  Fix-it applied, fixed expression was: 
    struct Foo { int i; }; Foo *f; f->i ; unknown_identifier_for_fatal_error
...

Added!

I think this patch also needs to update UserExpression::Evaluate which, IIRC, is clearing the fixed expression when it fails to parse.

I think that makes sense... If we fail to parse the fix-it we silently ignore it and don't need to tell the user about it.

The direction of the patch is IMHO fine. One thing that would be nice is to see if we could maybe preserve the Fix-It diagnostics from the original expression.

What do you mean by this? If we could preserve the original expression.

If we just return whatever the fixed expression fails with then it's not clear why the compiler actually generated a Fix-It. But that's more of a nice-to-have I think.

You can see in the test I added, fixing foo.bar to foo->bar where foo won't execute correctly, but it's still nice for the user to see that the Fix-it was applied.

teemperor accepted this revision.Sep 23 2021, 10:07 AM

My bad, I thought you wanted to print the fix-its if the 'fixed' expression failed to *parse* again, but this is about non-parsing errors. Ignore my other points, they were suggestions how to implemented what I thought this is about.

LGTM now. Just have some nits about the test but those don't need another round of review. Thanks for fixing this!

lldb/test/API/commands/expression/fixits/TestFixIts.py
86

Trailing white space here.

96

I think you meant ret_val.GetOutput() here as message gets printed if result != eReturnStatusFailed?

I anyway think you can just minimize everything from line 94 onwards with the normal expect routine:

self.expect("expression -- null_pointer.first", error=True, substrs=[
    "Fix-it applied, fixed expression was:", "null_pointer->first"])
This revision is now accepted and ready to land.Sep 23 2021, 10:07 AM