<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/155453>155453</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Bytecode Interpreter: Representing negative pointer offsets
</td>
</tr>
<tr>
<th>Labels</th>
<td>
clang:frontend,
clang:bytecode
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
tbaederr
</td>
</tr>
</table>
<pre>
In `test/AST/ByteCode/const-eval.c`, we have this test:
```c
#define EVAL_EXPR(testno, expr) enum { test##testno = (expr) }; struct check_positive##testno { int a[test##testno]; };
int x;
EVAL_EXPR(48, &x != &x - 1 ? 1 : -1)
```
which uses a negative offset on `&x`. If we add:
```diff
diff --git i/clang/lib/AST/ExprConstant.cpp w/clang/lib/AST/ExprConstant.cpp
index d5c5c827e6fc..9cd6498b56ec 100644
--- i/clang/lib/AST/ExprConstant.cpp
+++ w/clang/lib/AST/ExprConstant.cpp
@@ -14852,6 +14852,10 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E,
if (!EvaluatePointer(E->getRHS(), RHSValue, Info) || !LHSOK)
return false;
+
+ llvm::errs() << "LHS: " << LHSValue.toString(Info.Ctx, E->getLHS()->getType()) << '\n';
+ llvm::errs() << "RHS: " << RHSValue.toString(Info.Ctx, E->getRHS()->getType()) << '\n';
+
// Reject differing bases from the normal codepath; we special-case
// comparisons to null.
if (!HasSameBase(LHSValue, RHSValue)) {
```
we can see that the current interpreter correctly saves the negative offset:
```console
LHS: &x
RHS: &x + -1
```
however, we currently save `Pointer::Offset` as a `uint64_t`, so we don't get this right.
If we apply
```diff
diff --git i/clang/lib/AST/ByteCode/Interp.h w/clang/lib/AST/ByteCode/Interp.h
index 92e60b6b88e6..fc008ab26452 100644
--- i/clang/lib/AST/ByteCode/Interp.h
+++ w/clang/lib/AST/ByteCode/Interp.h
@@ -1079,6 +1079,12 @@ inline bool CmpHelperEQ<Pointer>(InterpState &S, CodePtr OpPC, CompareFn Fn) {
const Pointer &RHS = S.Stk.pop<Pointer>();
const Pointer &LHS = S.Stk.pop<Pointer>();
+
+ llvm::errs() << LHS << " / " << RHS << '\n';
+ llvm::errs() << LHS.toDiagnosticString(S.getASTContext()) << " / " << RHS.toDiagnosticString(S.getASTContext()) << '\n';
+
+
+
if (LHS.isZero() && RHS.isZero()) {
S.Stk.push<BoolT>(BoolT::from(Fn(ComparisonCategoryResult::Equal)));
return true;
``` we get the following output:
```console
(Block) 0x7dd20e47b150 {rootptr(0), 0, 8} / (Block) 0x7dd20e47b150 {rootptr(0), 28, 8}
&x / &x + 1
```
That looks almost correct, however, that's just a coincidence. The offset underflows to -1, to which we then add `sizeof(InitMapPtr)`, which happens to be 32. And `32 - 4 = 28`. If we change the example to use `-7` instead, we get a different result that's clearly wrong:
```console
(Block) 0x7d53cfc7b150 {rootptr(0), 0, 8} / (Block) 0x7d53cfc7b150 {rootptr(0), 4, 8}
&x / &x
```
In this case, the two pointers also compare equal.
Even if we change `Pointer::Offset` to a `int64_t`, we still run into weird errors because that value doesn't just represent the value that was added verbatim but we e.g. multiply it by the element size and/or add the size of the `InitMapPtr`.
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJycV9Fy4joS_RrlpQuXkbExDzwAEyqpzdbMQurW1r5MyXIbPCMkryQH2K_fatkGkpvcyZ1UCttY3epWnz6nEc7VO404Z-mSpV_uROv3xs59IbBEa-8KU57njxpYFnt0nvH1YvvM-Hp59rgyJTK-lkY7P8IXoSLJspjxFRwR9uIFwe9rB8EuWbB4QW_Dv6QHnpRY1Rrh_o_F0_f7f3_bMJ7TYm3IB54ay_gMULcHYNNl54cnjCfdImDJF2A8Hxay6ReWLMF520oPco_y5_fGuNrXL_jabrqEWnsQLF2-dcrS4KTzxeIFrTt1t7dhTnIKkfHsBIyPu0CyE4xgDCxZh88FjMaMz27TZvHiuK_lHlqHDgRo3AmKDkxVOfRgwjmTJ5bFEcBjRScpyrI_vhtXZV1VLF7QBUajXe2hplIooXeMr1VdXCp1f2rsikoktI9k08DxkwtD9iWeoExlKnM-xaySUTSTZTaZ5UWaoYRxHGeTCYsXo9Ho0xGE4i-7_78TDZvEbBLDaDzJU874KgPGl8PDOIb-_f2LUK0geB4aYWtn9LLWwp6_NmiFN5bxnJY86spQ1ehKxQwwhtdLgfHFPeMrFi-grghsjI8H_99MrT0GdyOW3O_Qbx62YcmM_G0etn8I1SLdd3sQRFdsSrgZPz1sv_6jgwd0fxZ9azVUQjnsANefU_ikFUq9HAgJyQKtdd1OwJIVS8glf3rYEuoY58OXT30IkTdbb2s645xCiVb-RGENcT8NcffPz-cGh0RudpiydKXpknw-qM2fgtp8MqjNbwY1nCjja8bXsMEfKD1QoyDtBoWg5qusOYDfI2hjD0KBNCU2wu-p-Y8IrkFZCzWSwuEbh_ICKwfegG6VioYlF4w8CLcVB1ySOc-fbqBwhUWXx3T5liEQpNDgkOhT-BCkbK1F7SEArrHo0YI01qL06gxOvKDrknlNKG9Z12hnFOVzgUp2YvFic32ijiLeeh0Sixd7c8QXAnsg9z6efm8iraEZAhK-drtnMQiiOZbFba19Nvnue31whryUhgrnYYe-Uwpb7_aeDrMnvqZR598jvRt5egxnFu0_ZJp31l6ob8Yxi4usyHPMoqiScZyLgmeTlH-O-t73_Wv2-8BuIMB4OrvwX3c_5gP91VqRqBbGKFgdmgdUDdr7f7FkdanRfWg5crv1wiNVfktloR2_eQtfm2-r7pmgjmsNa30FK0DPlb0_Mt88bIMcb6Ot_xk1pnm7HcE9-cj66dPWrynxr7in8znQEDXvGxL6S177hefImy-12GnjfC0vLLaNdugX2-eV0R5P_h2yei-O3_X1HvHdfl7oiOKt3X_QmiEPnjGehb1vv7-pcF-I1u1Zsloao567OvS3dC5EoIznBIz8qrQr4XFn7HmDrlW-W3n_31aozv8VBb3aedsOYjc0OXV-xwgIlVHKHIm1Teub9mNCo9iUkT8ph_g0LUse42RajNOYUrLG-MaTUse9OAcWytn0S1-Qv2fN88E8bB1oc33lz7f0-Uw0roz56UCog3F-4G7yckOsRPeMTx38aJ0HAdLUWtYlaokRPO8vY2KrS7SVMscgQDRlruimGy2PJBuoaWok4nX1_9BUod9r_0_RfKNEZsOYHiz2ommwE7MCIeERLHSwTTiMYBI6k-dhIu14We6F3oVtAE_i0Cgk29YFIRhNqYa1dh5F2csFlVP0EkwyZgM6rvlKhcKqMxyt0btP1zhNZCV_u8a_sp58VOI3xX3UnXaFSSEUEcEfDTQdf1HJnemHBgSkXog6Irt_QU0tej3Rj3XUm05HX8soDSq-Vgpsq2k2IFWtbQlorbEOCpSCqhLGCBpaSXLRdaIbMGaxseioJBR2tySsPpJwlyWW8IK2EL4-QNF62hCjXQSHVvm6UWeoPRTnDgkKD-SIAAdCl4yvjQ0opLfhW1OFe5bFN2DMYjqOu3KelLNkJu5wPp6mGeezPBnf7efTPJf5BHlezIoqG6fVBNO0jEWaFQJxIu_qOY95Guc8G0-T6XgcxZnM8qmsUllls1mRsUmMB1GriDg9MnZ3VzvX4nycppM0uVOiQOXCz1_OOykO5KY9UhL00-LmRXH2KIMuc_q1bOfkdFS0O8cmsaqdd9dtfO0Vzpe9BTxeZzeatjbD0RO7Xea2HjV9p7u71qr53vvGESDC_Lmr_b4tIknsuw4y1V1GjTU_AqesQ36O8XWf4suc_z8AAP__Gqis2g">