Skip to content

[clang][bytecode] Expand subscript base if of pointer type #128511

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 25, 2025

Conversation

tbaederr
Copy link
Contributor

This is similar to what we do in the AddOffset instruction when adding an offset to a pointer.

This is similar to what we do in the AddOffset instruction when
adding an offset to a pointer.
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Feb 24, 2025
@llvmbot
Copy link
Member

llvmbot commented Feb 24, 2025

@llvm/pr-subscribers-clang

Author: Timm Baeder (tbaederr)

Changes

This is similar to what we do in the AddOffset instruction when adding an offset to a pointer.


Full diff: https://github.com/llvm/llvm-project/pull/128511.diff

4 Files Affected:

  • (modified) clang/lib/AST/ByteCode/Compiler.cpp (+11-1)
  • (modified) clang/lib/AST/ByteCode/Interp.h (+4-1)
  • (modified) clang/test/AST/ByteCode/arrays.cpp (+13)
  • (added) clang/test/AST/ByteCode/libcxx/pointer-subscript.cpp (+36)
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index b5745e516174d..74f5d6ebd9ca6 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -1674,6 +1674,7 @@ bool Compiler<Emitter>::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
   const Expr *LHS = E->getLHS();
   const Expr *RHS = E->getRHS();
   const Expr *Index = E->getIdx();
+  const Expr *Base = E->getBase();
 
   if (DiscardResult)
     return this->discard(LHS) && this->discard(RHS);
@@ -1682,8 +1683,17 @@ bool Compiler<Emitter>::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
   // side is the base.
   bool Success = true;
   for (const Expr *SubExpr : {LHS, RHS}) {
-    if (!this->visit(SubExpr))
+    if (!this->visit(SubExpr)) {
       Success = false;
+      continue;
+    }
+
+    // Expand the base if this is a subscript on a
+    // pointer expression.
+    if (SubExpr == Base && Base->getType()->isPointerType()) {
+      if (!this->emitExpandPtr(E))
+        Success = false;
+    }
   }
 
   if (!Success)
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index fa113aa0bb157..db35208a02941 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -2589,7 +2589,10 @@ inline bool NarrowPtr(InterpState &S, CodePtr OpPC) {
 
 inline bool ExpandPtr(InterpState &S, CodePtr OpPC) {
   const Pointer &Ptr = S.Stk.pop<Pointer>();
-  S.Stk.push<Pointer>(Ptr.expand());
+  if (Ptr.isBlockPointer())
+    S.Stk.push<Pointer>(Ptr.expand());
+  else
+    S.Stk.push<Pointer>(Ptr);
   return true;
 }
 
diff --git a/clang/test/AST/ByteCode/arrays.cpp b/clang/test/AST/ByteCode/arrays.cpp
index 9204179ad1a46..2ef0cf886b2dc 100644
--- a/clang/test/AST/ByteCode/arrays.cpp
+++ b/clang/test/AST/ByteCode/arrays.cpp
@@ -662,3 +662,16 @@ namespace InvalidIndex {
   }
   static_assert(foo(0) == 1, "");
 }
+
+namespace PointerSubscript {
+  template<typename T>
+  constexpr T foo() {
+    T ss[] = {{}, {}, {}};
+    T *s = &ss[0];
+
+    return s[2];
+  }
+  static_assert(foo<int>() == 0);
+  struct S{};
+  static_assert((foo<S>(), true));
+}
diff --git a/clang/test/AST/ByteCode/libcxx/pointer-subscript.cpp b/clang/test/AST/ByteCode/libcxx/pointer-subscript.cpp
new file mode 100644
index 0000000000000..68e25dcb17909
--- /dev/null
+++ b/clang/test/AST/ByteCode/libcxx/pointer-subscript.cpp
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -std=c++2c -fexperimental-new-constant-interpreter -verify=expected,both %s
+// RUN: %clang_cc1 -std=c++2c  -verify=ref,both %s
+
+// both-no-diagnostics
+
+namespace std {
+inline namespace __1 {
+template <class _Tp> class unique_ptr;
+template <class _Tp> class unique_ptr<_Tp[]> {
+public:
+  _Tp* __ptr_;
+
+public:
+  constexpr _Tp&
+  operator[](unsigned i) const {
+    return __ptr_[i];
+  };
+};
+} // namespace __1
+} // namespace std
+struct WithTrivialDtor {
+  int x = 6;
+  constexpr friend void operator==(WithTrivialDtor const &x,
+                                   WithTrivialDtor const &y) {
+    (void)(x.x == y.x);
+  }
+};
+constexpr bool test() {
+
+  WithTrivialDtor array[50];
+  std::unique_ptr<WithTrivialDtor[]> p(&array[0]);
+  (void)(p[1] == WithTrivialDtor());
+
+  return true;
+}
+static_assert(test());

@tbaederr tbaederr merged commit dfa3af9 into llvm:main Feb 25, 2025
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants