In an unevaluated contexts, consteval functions
should not be immediately evaluated.
Details
- Reviewers
aaron.ballman rsmith
Diff Detail
- Repository
- rG LLVM Github Monorepo
Unit Tests
Event Timeline
Note that I think this was partially implemented as part of https://reviews.llvm.org/D74130 - which has not progressed since October.
This PR implements P1937 only
clang/test/SemaCXX/cxx2a-consteval.cpp | ||
---|---|---|
603 | ||
608 | ||
612 | Here's an interesting test case: #include <typeinfo> struct S { virtual void f(); }; struct D : S { void f() override; }; consteval S *get_s() { return nullptr; } void func() { (void)typeid(*get_s()); } typeid still needs to evaluate its operand (due to the polymorphic return type of *get_s()), and so you should get a diagnostic about evaluating the side effects by calling get_s(). I think this then runs into https://eel.is/c++draft/expr.const#13.sentence-3 and we should diagnose? |
clang/test/SemaCXX/cxx2a-consteval.cpp | ||
---|---|---|
612 | Not sure! |
clang/test/SemaCXX/cxx2a-consteval.cpp | ||
---|---|---|
612 | Actually, I'm reading the wording again and I really don't know anymore. I played with a bunch of things in the code but the more I look at it the less I'm convinced an action is needed. |
clang/test/SemaCXX/cxx2a-consteval.cpp | ||
---|---|---|
612 | The changes to Sema::CheckForImmediateInvocation() to check for an unevaluated context and https://eel.is/c++draft/expr.const#13.sentence-3 that say an immediate invocation shall be a constant expression are what got me thinking about this code snippet in the first place. I was trying to decide whether isUnevaluatedContext() is correct or not because with typeid, it is potentially evaluated (so sometimes it's unevaluated). Interestingly, everyone comes up with a different answer: https://godbolt.org/z/TqjGh1he6 and I don't (yet) know who is correct. |
clang/test/SemaCXX/cxx2a-consteval.cpp | ||
---|---|---|
612 | There are a few different cases here and I don't think any compiler is getting them all right. struct S { void f(); }; struct T { virtual void f(); }; consteval S *null_s() { return nullptr; } consteval S *make_s() { return new S; } consteval T *null_t() { return nullptr; } consteval T *make_s() { return new T; } void func() { (void)typeid(*null_s()); // #1 (void)typeid(*make_s()); // #2 (void)typeid(*null_t()); // #3 (void)typeid(*make_t()); // #4 } Here, #3 and #4 pass an lvalue of polymorphic class type to typeid, so the arguments to those typeids are potentially evaluated. #1 and #2 pass an lvalue of non-polymorphic class type, so those arguments are unevaluated operands. So we have two immediate invocations: the null_t() call and the make_t() call. Lines #1 and #2 are valid because there's no immediate invocation to check. (Clang and GCC get this wrong and reject #2.) The way we handle typeid in general is to parse its operand as an unevaluated operand, and then later TransformToPotentiallyEvaluated if we find it's a glvalue of or pointer to polymorphic class type. If you find the above testcase isn't handled correctly, you may need to make some changes in TransformToPotentiallyEvaluated to trigger the proper rebuilding. (You might need to force it to transform CallExprs that refer to consteval functions even if nothing within them have changed, for example.) |
- Add tests for typeid
All the tests suggested by Richard pass as expected without having to
modify the implementation of type id itself!
clang/test/SemaCXX/cxx2a-consteval.cpp | ||
---|---|---|
612 | Thanks, this was super useful! I think clang gets everything right now - I added your scenarios as tests with the other typeid tests |
I have commit on your behalf in 131b4620ee7847102479f399ce3e35a3c1cb5461, thank you for the fix!
clang/www/cxx_status.html | ||
---|---|---|
1106 | I'm trying to evaluate our consteval support, and I am having trouble finding any unsuperceded part of P1073R3 that is not implemented in Clang14. Can you share what Delta you know of that has you considering this as 'partial'? Is it something in a different patch awaiting review? |
clang/www/cxx_status.html | ||
---|---|---|
1106 | This thing https://reviews.llvm.org/D74130 is what I believe the last bit of missing functionality. |
clang/www/cxx_status.html | ||
---|---|---|
1106 | Ah, thanks! |
Cleaning up the test a bit to not use relative locations, should be NFC.