Author: Timm Bäder
Date: 2024-02-21T17:18:22+01:00
New Revision: ffcdf47bc443b36754c36bd6e1a77b4163657a00

URL: 
https://github.com/llvm/llvm-project/commit/ffcdf47bc443b36754c36bd6e1a77b4163657a00
DIFF: 
https://github.com/llvm/llvm-project/commit/ffcdf47bc443b36754c36bd6e1a77b4163657a00.diff

LOG: [clang][Interp] Allow adding an offset to a function pointer

Pretty sure this isn't doing anything, but it fixes a test and
is generally the right thing to do.
Fixing the behavior will come later.

Added: 
    clang/test/AST/Interp/pointer-addition.c

Modified: 
    clang/lib/AST/Interp/ByteCodeExprGen.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp 
b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index d11d05dd709d5e..0b08309e4e6e02 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -1403,12 +1403,11 @@ bool 
ByteCodeExprGen<Emitter>::VisitPointerCompoundAssignOperator(
 
   if (!LT || !RT)
     return false;
-  assert(*LT == PT_Ptr);
 
   if (!visit(LHS))
     return false;
 
-  if (!this->emitLoadPtr(LHS))
+  if (!this->emitLoad(*LT, LHS))
     return false;
 
   if (!visit(RHS))
@@ -2828,7 +2827,7 @@ bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const 
UnaryOperator *E) {
     if (!this->visit(SubExpr))
       return false;
 
-    if (T == PT_Ptr) {
+    if (T == PT_Ptr || T == PT_FnPtr) {
       if (!this->emitIncPtr(E))
         return false;
 
@@ -2846,7 +2845,7 @@ bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const 
UnaryOperator *E) {
     if (!this->visit(SubExpr))
       return false;
 
-    if (T == PT_Ptr) {
+    if (T == PT_Ptr || T == PT_FnPtr) {
       if (!this->emitDecPtr(E))
         return false;
 
@@ -2864,7 +2863,7 @@ bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const 
UnaryOperator *E) {
     if (!this->visit(SubExpr))
       return false;
 
-    if (T == PT_Ptr) {
+    if (T == PT_Ptr || T == PT_FnPtr) {
       if (!this->emitLoadPtr(E))
         return false;
       if (!this->emitConstUint8(1, E))
@@ -2903,7 +2902,7 @@ bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const 
UnaryOperator *E) {
     if (!this->visit(SubExpr))
       return false;
 
-    if (T == PT_Ptr) {
+    if (T == PT_Ptr || T == PT_FnPtr) {
       if (!this->emitLoadPtr(E))
         return false;
       if (!this->emitConstUint8(1, E))

diff  --git a/clang/test/AST/Interp/pointer-addition.c 
b/clang/test/AST/Interp/pointer-addition.c
new file mode 100644
index 00000000000000..80ab670e8bface
--- /dev/null
+++ b/clang/test/AST/Interp/pointer-addition.c
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 %s -fsyntax-only -verify=gnu,expected -pedantic -Wextra 
-std=c11 -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 %s -fsyntax-only -triple i686-unknown-unknown 
-verify=gnu,expected -pedantic -Wextra -std=c11 
-fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 %s -fsyntax-only -triple x86_64-unknown-unknown 
-verify=gnu,expected -pedantic -Wextra -std=c11 
-fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 %s -fsyntax-only -verify -pedantic -Wextra -Wno-gnu 
-std=c11 -fexperimental-new-constant-interpreter
+
+typedef __INTPTR_TYPE__ intptr_t;
+typedef struct S S; // expected-note 4 {{forward declaration of 'struct S'}}
+extern _Atomic(S*) e;
+void a(S* b, void* c) {
+  void (*fp)(int) = 0;
+  b++;       // expected-error {{arithmetic on a pointer to an incomplete 
type}}
+  b += 1;    // expected-error {{arithmetic on a pointer to an incomplete 
type}}
+  c++;       // gnu-warning {{arithmetic on a pointer to void is a GNU 
extension}}
+  c += 1;    // gnu-warning {{arithmetic on a pointer to void is a GNU 
extension}}
+  c--;       // gnu-warning {{arithmetic on a pointer to void is a GNU 
extension}}
+  c -= 1;    // gnu-warning {{arithmetic on a pointer to void is a GNU 
extension}}
+  (void) c[1]; // gnu-warning {{subscript of a pointer to void is a GNU 
extension}}
+  b = 1+b;   // expected-error {{arithmetic on a pointer to an incomplete 
type}}
+  /* The next couple tests are only pedantic warnings in gcc */
+  void (*d)(S*,void*) = a;
+  d += 1;    // gnu-warning {{arithmetic on a pointer to the function type 
'void (S *, void *)' (aka 'void (struct S *, void *)') is a GNU extension}}
+  d++;       // gnu-warning {{arithmetic on a pointer to the function type 
'void (S *, void *)' (aka 'void (struct S *, void *)') is a GNU extension}}
+  d--;       // gnu-warning {{arithmetic on a pointer to the function type 
'void (S *, void *)' (aka 'void (struct S *, void *)') is a GNU extension}}
+  d -= 1;    // gnu-warning {{arithmetic on a pointer to the function type 
'void (S *, void *)' (aka 'void (struct S *, void *)') is a GNU extension}}
+  (void)(1 + d); // gnu-warning {{arithmetic on a pointer to the function type 
'void (S *, void *)' (aka 'void (struct S *, void *)') is a GNU extension}}
+  e++;       // expected-error {{arithmetic on a pointer to an incomplete 
type}}
+  intptr_t i = (intptr_t)b;
+  char *f = (char*)0 + i; // gnu-warning {{arithmetic on a null pointer 
treated as a cast from integer to pointer is a GNU extension}}
+  // Cases that don't match the GNU inttoptr idiom get a 
diff erent warning.
+  f = (char*)0 - i; // expected-warning {{performing pointer arithmetic on a 
null pointer has undefined behavior}}
+  int *g = (int*)0 + i; // expected-warning {{performing pointer arithmetic on 
a null pointer has undefined behavior}}
+}


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to