[clang] [clang][Interp] Fix variables refering to their own address (PR #70587)

Timm Baeder via cfe-commits cfe-commits at lists.llvm.org
Sun Oct 29 01:15:15 PDT 2023


https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/70587

This was a combination of issues:
  1) We can subtract pointers that don't point into arrays.
  2) In C, everything is possible.

>From 01d5cccfc4cd3813fb57e17af3c7b395bc0c9646 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Sun, 29 Oct 2023 09:12:00 +0100
Subject: [PATCH] [clang][Interp] Fix variables refering to their own address

This was a combination of issues:
  1) We can subtract pointers that don't point into arrays.
  2) In C, everything is possible.
---
 clang/lib/AST/Interp/Interp.h      |  4 ++--
 clang/test/AST/Interp/c.c          |  4 ++++
 clang/test/AST/Interp/literals.cpp | 15 +++++++++++++++
 3 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 7dd415d6e460536..c5ee720d5a29ddd 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -1453,7 +1453,7 @@ bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset,
       DiagInvalidOffset();
   }
 
-  if (Invalid && !Ptr.isDummy())
+  if (Invalid && !Ptr.isDummy() && S.getLangOpts().CPlusPlus)
     return false;
 
   // Offset is valid - compute it on unsigned.
@@ -1531,7 +1531,7 @@ inline bool SubPtr(InterpState &S, CodePtr OpPC) {
   const Pointer &LHS = S.Stk.pop<Pointer>();
   const Pointer &RHS = S.Stk.pop<Pointer>();
 
-  if (!Pointer::hasSameArray(LHS, RHS)) {
+  if (!Pointer::hasSameBase(LHS, RHS) && S.getLangOpts().CPlusPlus) {
     // TODO: Diagnose.
     return false;
   }
diff --git a/clang/test/AST/Interp/c.c b/clang/test/AST/Interp/c.c
index 6bfcded0a78646c..2bc3d906bcc5ef9 100644
--- a/clang/test/AST/Interp/c.c
+++ b/clang/test/AST/Interp/c.c
@@ -4,6 +4,7 @@
 // RUN: %clang_cc1 -pedantic -verify=pedantic-ref -std=c11 %s
 
 typedef __INTPTR_TYPE__ intptr_t;
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
 
 _Static_assert(1, "");
 _Static_assert(0 != 1, "");
@@ -81,3 +82,6 @@ const intptr_t L = (intptr_t)(&(yy->y)); // expected-error {{not a compile-time
                                          // pedantic-expected-error {{not a compile-time constant}} \
                                          // ref-error {{not a compile-time constant}} \
                                          // pedantic-ref-error {{not a compile-time constant}}
+const ptrdiff_t m = &m + 137 - &m;
+_Static_assert(m == 137, ""); // pedantic-ref-warning {{GNU extension}} \
+                              // pedantic-expected-warning {{GNU extension}}
diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp
index ba24955d14503be..92b467da3e8847b 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -7,6 +7,7 @@
 #define INT_MAX __INT_MAX__
 
 typedef __INTPTR_TYPE__ intptr_t;
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
 
 
 static_assert(true, "");
@@ -198,6 +199,20 @@ namespace PointerComparison {
                                  // ref-note {{comparison between '&s.b' and 'nullptr' has unspecified value}}
 
   constexpr bool v7 = qv <= (void*)&s.b; // ok
+
+  constexpr ptrdiff_t m = &m - &m;
+  static_assert(m == 0, "");
+
+  constexpr ptrdiff_t m2 = (&m2 + 1) - (&m2 + 1);
+  static_assert(m2 == 0, "");
+
+  constexpr long m3 = (&m3 + 1) - (&m3);
+  static_assert(m3 == 1, "");
+
+  constexpr long m4 = &m4 + 2 - &m4; // ref-error {{must be initialized by a constant expression}} \
+                                     // ref-note {{cannot refer to element 2 of non-array object}} \
+                                     // expected-error {{must be initialized by a constant expression}} \
+                                     // expected-note {{cannot refer to element 2 of non-array object}}
 }
 
 namespace SizeOf {



More information about the cfe-commits mailing list