This is an archive of the discontinued LLVM Phabricator instance.

[clang][ExprConstant] Fix display of syntactically-invalid note for member function calls
ClosedPublic

Authored by hazohelet on May 30 2023, 8:30 AM.

Details

Summary

This patch changes the display of member function calls in constexpr evaluator diagnostics from arrow operator to dot operator.
This avoids the syntactical invalidness in notes previously caused by the display of & operator
(lack of parentheses and reference of rvalue)

Fixes https://github.com/llvm/llvm-project/issues/57081

Diff Detail

Event Timeline

hazohelet created this revision.May 30 2023, 8:30 AM
Herald added a project: Restricted Project. · View Herald TranscriptMay 30 2023, 8:30 AM
hazohelet requested review of this revision.May 30 2023, 8:30 AM
Herald added a project: Restricted Project. · View Herald TranscriptMay 30 2023, 8:30 AM
erichkeane added inline comments.May 30 2023, 8:59 AM
clang/test/SemaCXX/constant-expression-cxx11.cpp
994

So I think this is just trading 1 'wrong' for another. We should be looking to see if we can figure out whether this is called with an arrow or not. I don't have a good way of doing that unfortunately, but perhaps Aaron has an idea?

Thanks for the feedback.

clang/test/SemaCXX/constant-expression-cxx11.cpp
994

I believe there might be a slight misunderstanding.
The note generated for the sptr->f() will be sobj.f(), and not sptr.f(), so I think this patch does not introduce something wrong here.
Note: BEFORE this patch, invalid code &sobj->f() is generated for this line.
link: https://godbolt.org/z/vPWjdeqcK

That said, I think it would be ideal to distinguish sptr and sobj here, but I am unsure whether we can achieve it without incurring additional memory footprint.

erichkeane added inline comments.May 30 2023, 10:22 AM
clang/test/SemaCXX/constant-expression-cxx11.cpp
994

Ah, I see, less bad then I think. I'm on the fence here, this seems like it is still not great messaging. GCC manages to maintain the sptr here, which I wish we could do (though they have an odder way of printing it all the same: https://godbolt.org/z/Kn3Mn75rh).

I think I want to see what Aaron says when he gets back next week.

Can you show the output for an example where the -> notation is correct, e.h. https://godbolt.org/z/6a5oExjME ?

I suppose the patch doesn't change this much, but the current way that's displayed (&{*new Foo#0}->zomg()) is... questionable.

Can you show the output for an example where the -> notation is correct, e.h. https://godbolt.org/z/6a5oExjME ?

I suppose the patch doesn't change this much, but the current way that's displayed (&{*new Foo#0}->zomg()) is... questionable.

The output for that code becomes

source.cpp:20:12: note: in call to '{*new Foo#0}.zomg()'
        F->zomg();
           ^
source.cpp:28:17: note: in call to 's.heh()'
static_assert(s.heh());
                ^

, which I think is still not good.
But, at least (*new Foo).zomg() would be syntactically valid. I'll check the reason for the use of curly bracket and #number notations.

I think the proper message here can be obtained by letting the stack frame keep the syntactical structure of the function call, although it introduces additional memory footprint.

  • Add const Expr * new field to CallStackFrame in order to save the syntactical structure of the member function call
  • Generate proper message using that new field
  • Fallback to the conventional value-based printing when handling destructors because it is not explicitly written by the user
tbaeder added inline comments.May 31 2023, 8:39 PM
clang/lib/AST/ExprConstant.cpp
1927–1949
1935

Address comments from @tbaeder

  • Change dyn_cast_or_null to dyn_cast_if_present
hazohelet marked 2 inline comments as done.May 31 2023, 11:48 PM
hazohelet added inline comments.
clang/lib/AST/ExprConstant.cpp
1935

Thank you. I fixed them.

The only additional test I could come up with is one where the -> is in the middle of an lvalue designator, like:

struct A {
  constexpr int foo() { (void)(1/0); return 1;}
};

struct B {
  A aa;
  A *a = &aa;
};

struct C {
  B b;
};

struct D {
  C cc;
  C *c = &cc;
};

constexpr D d{};
static_assert(d.c->b.a->foo() == 1);

but this is printed correctly. The rest of the output LGTM but I'll wait for some of the others to maybe chime in.

clang/lib/AST/ExprConstant.cpp
1933

Did you clang-format these changes? The two if/else body here seems indented 4 spaces instead of 2.

clang/test/SemaCXX/constant-expression-cxx11.cpp
995
996
clang/test/SemaCXX/constexpr-frame-describe.cpp
6
12
hazohelet updated this revision to Diff 527363.Jun 1 2023, 4:52 AM

Address comments from @tbaeder

  • Add new suggested test case
  • NFC stylistic changes in test cases
hazohelet marked 5 inline comments as done.Jun 1 2023, 5:04 AM
hazohelet added inline comments.
clang/lib/AST/ExprConstant.cpp
1933

Yes, I did run git clang-format before uploading. clang-format forces 4 spaces here even when I write 2 spaces.
Precommit CI's clang-format also seems to say nothing about the indentation here.
(Link: https://buildkite.com/llvm-project/premerge-checks/builds/155642#018875b6-df57-4c32-8f54-203e79d4a428)
So I think this might be an internal bug of clang-format.

@aaron.ballman I would like to hear what's your take on this approach.

cjdb accepted this revision.Jun 13 2023, 11:56 AM

This patch seems like a win to me.

clang/docs/ReleaseNotes.rst
356

I like that we're referencing bugs in our release notes now :)

This revision is now accepted and ready to land.Jun 13 2023, 11:56 AM
shafik added a subscriber: shafik.Jun 21 2023, 8:34 PM
shafik added inline comments.
clang/lib/AST/ExprConstant.cpp
984–986

Let's fix the missing one while here.

1929
1936–1937
16312–16313
hazohelet updated this revision to Diff 533964.Jun 23 2023, 7:52 AM

Address review comment NFC

  • make some arguments conform to bugprone-argument-comments
  • edit release note text
hazohelet marked 4 inline comments as done.Jun 23 2023, 7:53 AM
hazohelet added inline comments.
clang/lib/AST/ExprConstant.cpp
984–986

Thanks for all the fix.