Author: Timm Baeder Date: 2025-04-19T16:48:49+02:00 New Revision: 6196b4ee8c47dc4a2267b7c704d1811e68c7f1c1
URL: https://github.com/llvm/llvm-project/commit/6196b4ee8c47dc4a2267b7c704d1811e68c7f1c1 DIFF: https://github.com/llvm/llvm-project/commit/6196b4ee8c47dc4a2267b7c704d1811e68c7f1c1.diff LOG: [clang][bytecode] Don't set OnePastEnd bit for array elements (#136422) If we refer to arr[N], don't set the OnePastEnd bit of the APValue, since that is already encoded in the array index. Added: Modified: clang/lib/AST/ByteCode/Pointer.cpp clang/test/AST/ByteCode/arrays.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp index 686ec381d232a..059503cae3561 100644 --- a/clang/lib/AST/ByteCode/Pointer.cpp +++ b/clang/lib/AST/ByteCode/Pointer.cpp @@ -223,6 +223,7 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const { UsePath = false; // Build the path into the object. + bool OnePastEnd = isOnePastEnd(); Pointer Ptr = *this; while (Ptr.isField() || Ptr.isArrayElement()) { @@ -251,9 +252,10 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const { Ptr = Ptr.expand(); const Descriptor *Desc = Ptr.getFieldDesc(); unsigned Index; - if (Ptr.isOnePastEnd()) + if (Ptr.isOnePastEnd()) { Index = Ptr.getArray().getNumElems(); - else + OnePastEnd = false; + } else Index = Ptr.getIndex(); QualType ElemType = Desc->getElemQualType(); @@ -304,8 +306,7 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const { std::reverse(Path.begin(), Path.end()); if (UsePath) - return APValue(Base, Offset, Path, - /*IsOnePastEnd=*/!isElementPastEnd() && isOnePastEnd()); + return APValue(Base, Offset, Path, OnePastEnd); return APValue(Base, Offset, APValue::NoLValuePath()); } diff --git a/clang/test/AST/ByteCode/arrays.cpp b/clang/test/AST/ByteCode/arrays.cpp index e50839e0f0877..934c3a3e7aff1 100644 --- a/clang/test/AST/ByteCode/arrays.cpp +++ b/clang/test/AST/ByteCode/arrays.cpp @@ -761,3 +761,13 @@ namespace PointerSubscript { struct S{}; static_assert((foo<S>(), true)); } + +namespace OnePastEndDiag { + + constexpr int a(const int *b) { + return *b; // both-note {{read of dereferenced one-past-the-end pointer}} + } + constexpr int foo[] = {1,2}; + constexpr int k = a(foo + 2); // both-error {{must be initialized by a constant expression}} \ + // both-note {{in call to 'a(&foo[2])'}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits