This is an archive of the discontinued LLVM Phabricator instance.

[clang][Interp] Implement pointer (de)ref operations and DeclRefExprs
ClosedPublic

Authored by tbaeder on Aug 18 2022, 1:27 AM.

Details

Summary

I wanted to do only pointers here, but they are impossible to test without having some support for DeclRefExprs.

This also implements assignments because that was broken when implementing DeclRefExprs. Assignments were handled through LValueToRValue casts before.

Diff Detail

Event Timeline

tbaeder created this revision.Aug 18 2022, 1:27 AM
Herald added a project: Restricted Project. · View Herald TranscriptAug 18 2022, 1:27 AM
tbaeder requested review of this revision.Aug 18 2022, 1:27 AM
Herald added a project: Restricted Project. · View Herald TranscriptAug 18 2022, 1:27 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript
tbaeder added inline comments.Aug 18 2022, 3:18 AM
clang/lib/AST/Interp/ByteCodeExprGen.cpp
649

Handling the deref like this breaks assigning, e.g. int m = 10; int *p = &m; *p = 12; doesn't work. The LHS of the assignment ends up being *p, so just an int.

tbaeder updated this revision to Diff 453610.Aug 18 2022, 3:35 AM
tbaeder updated this revision to Diff 453617.Aug 18 2022, 4:00 AM
tbaeder updated this revision to Diff 453618.
tbaeder updated this revision to Diff 453619.Aug 18 2022, 4:15 AM
tbaeder updated this revision to Diff 453624.Aug 18 2022, 5:13 AM

Just the 1 question for my info, Tests seem pretty complete for what is being looked at, but I'm hopeful someone else will take a look at this too. @shafik or @tahonermann want to take a pass so aaron doesn't have to?

clang/lib/AST/Interp/ByteCodeExprGen.cpp
219

Can you explain what this is doing for me?

tbaeder added inline comments.Aug 18 2022, 6:21 AM
clang/lib/AST/Interp/ByteCodeExprGen.cpp
219

The Store operation pops the value to store from the stack, but leaves the pointer it stores the value to on the stack (it only peek()s the pointer). So after the emitStore, there's still the pointer we stored to on the stack, and we need to get rid of it if DiscardResult is true (that's the case for a simple i = 5; on a single line). Otherwise, we leave it no the stack for the caller to read from.

This mostly makes sense to me but I will let @tahonermann review it as well.

clang/test/AST/Interp/literals.cpp
41

What are these functions testing?

tbaeder added inline comments.Aug 18 2022, 10:44 PM
clang/test/AST/Interp/literals.cpp
41

Functions take a slightly different code path where actual bytecode is generated instead of the expression directly evaluated, so the functions test that this codepath works as well.

tahonermann added inline comments.Aug 19 2022, 8:13 AM
clang/lib/AST/Interp/ByteCodeExprGen.cpp
619–620

I don't love that the Visit() calls are now repeated for most of the operations, but I don't have a better suggestion. I see that Visit() must not be called for `UO_Deref since dereference() will perform the visitation. I guess that case could be pulled out of the switch, but that isn't necessarily better. Consider this an unactionable comment.

673

Perhaps add:

else {
  assert(0 && "Unhandled declaration kind");
}
clang/test/AST/Interp/cxx20.cpp
3

Is -DREFERENCE needed here? I don't see REFERENCE referenced in the test. From the other test, I gather that it is intended to annotate differences from the "reference" implementation.

12

Perhaps add:

//static_assert(getMinux5() == -5, "");  TODO
clang/test/AST/Interp/literals.cpp
43

Perhaps add:

//static_assert(*getIntPointer() == 10, ""); TODO
47

Perhaps add:

//static_assert(gimme(5) == 5, ""); TODO
tbaeder marked 3 inline comments as done.Aug 19 2022, 9:24 AM
tbaeder added inline comments.
clang/test/AST/Interp/cxx20.cpp
3

Yes, exactly. I'll switch this one to use -verify=ref as well.

tbaeder updated this revision to Diff 454045.Aug 19 2022, 9:25 AM
tahonermann added inline comments.Aug 19 2022, 12:01 PM
clang/test/AST/Interp/cxx20.cpp
3

Cool! I didn't know about -verify=ref!

clang/test/AST/Interp/literals.cpp
45

Should be == 10 for the second case.

tbaeder updated this revision to Diff 454164.Aug 19 2022, 9:56 PM
tbaeder marked 5 inline comments as done.Aug 19 2022, 10:04 PM
tbaeder added inline comments.
clang/lib/AST/Interp/ByteCodeExprGen.cpp
673

We actually hit this path for non-constexpr-conforming functions, so asserting doesn't work:

constexpr void foo(int a) {
  constexpr int b = a;
}

The initializer for b goes through evaluteAsInitializer() before the function foo is ever registered, so the parameter is not known. This is diagnosed by the current interpreter as well:

array.cpp:13:17: error: constexpr variable 'b' must be initialized by a constant expression
  constexpr int b = a;
                ^   ~
array.cpp:13:21: note: function parameter 'a' with unknown value cannot be used in a constant expression
  constexpr int b = a;
                    ^
array.cpp:12:24: note: declared here
constexpr void foo(int a) {
                       ^

Would be a good future test case, but right now the error message for the new interpreter is just "constexpr variable 'b' must be initialized by a constant expression".

tbaeder marked an inline comment as done.Aug 19 2022, 10:04 PM
tahonermann added inline comments.Aug 23 2022, 9:02 AM
clang/lib/AST/Interp/ByteCodeExprGen.cpp
673

I see, interesting.

I imagine future work will be needed to support references to lambda/block captures, data members, and such? And the answer to those right now is, we're not there yet?

tbaeder added inline comments.Aug 23 2022, 9:07 AM
clang/lib/AST/Interp/ByteCodeExprGen.cpp
673

Yes, almost nothing works right now. :)

tahonermann accepted this revision.Aug 23 2022, 10:59 AM

Thanks, Timm. The changes look reasonable to me, so I'll accept. Given my unfamiliarity with this code though, it would be great if someone else also gave it a nod.

This revision is now accepted and ready to land.Aug 23 2022, 10:59 AM
erichkeane accepted this revision.Aug 23 2022, 11:02 AM

I'm happy as well.

This revision was landed with ongoing or failed builds.Aug 25 2022, 5:22 AM
This revision was automatically updated to reflect the committed changes.