https://github.com/marlus updated https://github.com/llvm/llvm-project/pull/207808
>From 379569598a352c60fa270eefe26d89e52fb5ad82 Mon Sep 17 00:00:00 2001 From: Cadanus da Costa <[email protected]> Date: Mon, 6 Jul 2026 14:27:08 -0400 Subject: [PATCH 1/2] [clang] Follow-up fixes for offsetof unsigned index change - Rename CastNoOverflow to CastAPToOffsetIndex for clarity - Add parentheses in overflow guard condition in InterpBuiltin.cpp - Improve comment explaining why 0x8000000000000000 is rejected Addresses post-merge review comments from shafik. --- clang/lib/AST/ByteCode/Compiler.cpp | 2 +- clang/lib/AST/ByteCode/Interp.h | 7 ++++--- clang/lib/AST/ByteCode/InterpBuiltin.cpp | 2 +- clang/lib/AST/ByteCode/Opcodes.td | 5 +++-- clang/test/Sema/offsetof-unsigned-index.c | 4 +++- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index b4468c94ff675..4e070d8237bbb 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -4001,7 +4001,7 @@ bool Compiler<Emitter>::VisitOffsetOfExpr(const OffsetOfExpr *E) { if (IndexT == PT_IntAP || IndexT == PT_IntAPS) { if (!this->visit(ArrayIndexExpr)) return false; - if (!this->emitCastNoOverflow(IndexT, E)) + if (!this->emitCastAPToOffsetIndex(IndexT, E)) return false; continue; } diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index d16a00414f45a..b70015aa67ab7 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -2893,10 +2893,11 @@ bool CastAPS(InterpState &S, uint32_t BitWidth) { return true; } -// Cast an AP integer to Sint64, failing constant evaluation if the value is -// negative or too large to fit (i.e. truncation would change the value). +// Cast an AP integer to Sint64 for use as an offsetof array index, failing +// constant evaluation if the value is negative or too large to fit in Sint64 +// (i.e. truncation would change the value). template <PrimType Name, class T = typename PrimConv<Name>::T> -bool CastNoOverflow(InterpState &S, CodePtr OpPC) { +bool CastAPToOffsetIndex(InterpState &S, CodePtr OpPC) { T Source = S.Stk.pop<T>(); APSInt Val = Source.toAPSInt(); if (Val.isNegative() || Val.getActiveBits() > 63) diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index 70717720c592d..57f3d793d4785 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -6824,7 +6824,7 @@ bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E, CurrentType = AT->getElementType(); CharUnits ElementSize = S.getASTContext().getTypeSizeInChars(CurrentType); int64_t ElemSize = ElementSize.getQuantity(); - if (Index != 0 && ElemSize > llvm::maxIntN(64) / Index) { + if ((Index != 0) && (ElemSize > (llvm::maxIntN(64) / Index))) { S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_offsetof_overflow) << S.Current->getRange(OpPC); diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td index 577c8523ab6c3..7b57849ebddb7 100644 --- a/clang/lib/AST/ByteCode/Opcodes.td +++ b/clang/lib/AST/ByteCode/Opcodes.td @@ -787,8 +787,9 @@ def APOnlyTypeClass : TypeClass { let Types = [IntAP, IntAPS]; } -// Cast from an AP integer type to Sint64, failing if the value doesn't fit. -def CastNoOverflow : Opcode { +// Cast from an AP integer type to Sint64 for use as an offsetof array index, +// failing if the value is negative or doesn't fit in Sint64. +def CastAPToOffsetIndex : Opcode { let Types = [APOnlyTypeClass]; let HasGroup = 1; } diff --git a/clang/test/Sema/offsetof-unsigned-index.c b/clang/test/Sema/offsetof-unsigned-index.c index 56396eb2a12e6..16d6989fe0a85 100644 --- a/clang/test/Sema/offsetof-unsigned-index.c +++ b/clang/test/Sema/offsetof-unsigned-index.c @@ -34,7 +34,9 @@ _Static_assert(__builtin_offsetof(struct BigStruct, data[(uint16_t)32768]) == 32 struct NegIdxStruct { int a; int x[1]; }; _Static_assert(__builtin_offsetof(struct NegIdxStruct, x[-1]) == 0, ""); // expected-error {{not an integral constant expression}} -// __uint128_t indices >= 0x8000000000000000 must be rejected. +// __uint128_t indices >= 0x8000000000000000 must be rejected: this value has +// bit 63 set, so getActiveBits() > 63, which our guard treats as too large +// for a signed 64-bit offset index. _Static_assert(__builtin_offsetof(struct NegIdxStruct, x[(__uint128_t)0x8000000000000000]) == 0, ""); // expected-error {{not an integral constant expression}} // Small __uint128_t values that fit in int64_t must work correctly. >From 72ba6b6258cb63cb425ea724ab07aef2fc98d876 Mon Sep 17 00:00:00 2001 From: Marlus Cadanus da Costa <[email protected]> Date: Wed, 8 Jul 2026 10:02:56 -0400 Subject: [PATCH 2/2] Fix parentheses in offsetof overflow guard per review feedback --- clang/lib/AST/ByteCode/InterpBuiltin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index 57f3d793d4785..766f89807706d 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -6824,7 +6824,7 @@ bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E, CurrentType = AT->getElementType(); CharUnits ElementSize = S.getASTContext().getTypeSizeInChars(CurrentType); int64_t ElemSize = ElementSize.getQuantity(); - if ((Index != 0) && (ElemSize > (llvm::maxIntN(64) / Index))) { + if (Index != 0 && ElemSize > (llvm::maxIntN(64) / Index)) { S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_offsetof_overflow) << S.Current->getRange(OpPC); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
