[clang] [clang][bytecode] Don't set OnePastEnd bit for array elements (PR #136422)

Timm Baeder via cfe-commits cfe-commits at lists.llvm.org
Sat Apr 19 03:28:10 PDT 2025


https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/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.

>From 9e3abaa3711d1845c6b6669ba002570445d29116 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Sat, 19 Apr 2025 12:08:13 +0200
Subject: [PATCH] [clang][bytecode] Don't set OnePastEnd bit for array elements

If we refer to arr[N], don't set the OnePastEnd bit of the APValue,
since that is already encoded in the array index.
---
 clang/lib/AST/ByteCode/Pointer.cpp |  9 +++++----
 clang/test/AST/ByteCode/arrays.cpp | 10 ++++++++++
 2 files changed, 15 insertions(+), 4 deletions(-)

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])'}}
+}



More information about the cfe-commits mailing list