[clang] 177f9ab - [clang][Interp] Check pointer inc/dec ops for initialization

Timm Bäder via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 15 04:04:42 PDT 2023


Author: Timm Bäder
Date: 2023-09-15T13:04:04+02:00
New Revision: 177f9ab2fbd868fb9cc7d5504e56a241e8e79329

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

LOG: [clang][Interp] Check pointer inc/dec ops for initialization

Differential Revision: https://reviews.llvm.org/D158702

Added: 
    

Modified: 
    clang/lib/AST/Interp/Interp.h
    clang/test/AST/Interp/literals.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index b109f2bda17bfb1..37d3dd0da6568af 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -1441,9 +1441,9 @@ bool SubOffset(InterpState &S, CodePtr OpPC) {
 }
 
 template <ArithOp Op>
-static inline bool IncDecPtrHelper(InterpState &S, CodePtr OpPC) {
+static inline bool IncDecPtrHelper(InterpState &S, CodePtr OpPC,
+                                   const Pointer &Ptr) {
   using OneT = Integral<8, false>;
-  const Pointer &Ptr = S.Stk.pop<Pointer>();
 
   // Get the current value on the stack.
   S.Stk.push<Pointer>(Ptr.deref<Pointer>());
@@ -1460,11 +1460,21 @@ static inline bool IncDecPtrHelper(InterpState &S, CodePtr OpPC) {
 }
 
 static inline bool IncPtr(InterpState &S, CodePtr OpPC) {
-  return IncDecPtrHelper<ArithOp::Add>(S, OpPC);
+  const Pointer &Ptr = S.Stk.pop<Pointer>();
+
+  if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
+    return false;
+
+  return IncDecPtrHelper<ArithOp::Add>(S, OpPC, Ptr);
 }
 
 static inline bool DecPtr(InterpState &S, CodePtr OpPC) {
-  return IncDecPtrHelper<ArithOp::Sub>(S, OpPC);
+  const Pointer &Ptr = S.Stk.pop<Pointer>();
+
+  if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
+    return false;
+
+  return IncDecPtrHelper<ArithOp::Sub>(S, OpPC, Ptr);
 }
 
 /// 1) Pops a Pointer from the stack.

diff  --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp
index dae1d5af6f7ae38..1a12413f3f0fa8e 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -509,36 +509,72 @@ namespace IncDec {
   }
   static_assert(incBool(), "");
 
-  template<typename T, bool Inc>
+  /// FIXME: The diagnostics for pre-inc/dec of pointers doesn't match the
+  /// current interpreter. But they are stil OK.
+  template<typename T, bool Inc, bool Pre>
   constexpr int uninit() {
     T a;
-    if constexpr (Inc)
-      ++a; // ref-note 2{{increment of uninitialized}} \
-           // expected-note 2{{increment of uninitialized}}
-    else
-      --a; // ref-note 2{{decrement of uninitialized}} \
-           // expected-note 2{{decrement of uninitialized}}
+    if constexpr (Inc) {
+      if (Pre)
+        ++a; // ref-note 3{{increment of uninitialized}} \
+             // expected-note 2{{increment of uninitialized}} \
+             // expected-note {{read of uninitialized}}
+      else
+        a++; // ref-note 2{{increment of uninitialized}} \
+             // expected-note 2{{increment of uninitialized}}
+    } else {
+      if (Pre)
+        --a; // ref-note 3{{decrement of uninitialized}} \
+             // expected-note 2{{decrement of uninitialized}} \
+             // expected-note {{read of uninitialized}}
+      else
+        a--; // ref-note 2{{decrement of uninitialized}} \
+             // expected-note 2{{decrement of uninitialized}}
+    }
     return 1;
   }
-  static_assert(uninit<int, true>(), ""); // ref-error {{not an integral constant expression}} \
-                                          // ref-note {{in call to 'uninit<int, true>()'}} \
-                                          // expected-error {{not an integral constant expression}} \
-                                          // expected-note {{in call to 'uninit()'}}
-
-  static_assert(uninit<int, false>(), ""); // ref-error {{not an integral constant expression}} \
-                                           // ref-note {{in call to 'uninit<int, false>()'}} \
-                                           // expected-error {{not an integral constant expression}} \
-                                           // expected-note {{in call to 'uninit()'}}
-
-  static_assert(uninit<float, true>(), ""); // ref-error {{not an integral constant expression}} \
-                                            // ref-note {{in call to 'uninit<float, true>()'}} \
-                                            // expected-error {{not an integral constant expression}} \
-                                            // expected-note {{in call to 'uninit()'}}
-
-  static_assert(uninit<float, false>(), ""); // ref-error {{not an integral constant expression}} \
-                                             // ref-note {{in call to 'uninit<float, false>()'}} \
-                                             // expected-error {{not an integral constant expression}} \
-                                             // expected-note {{in call to 'uninit()'}}
+  static_assert(uninit<int, true, true>(), ""); // ref-error {{not an integral constant expression}} \
+                                                // ref-note {{in call to 'uninit<int, true, true>()'}} \
+                                                // expected-error {{not an integral constant expression}} \
+                                                // expected-note {{in call to 'uninit()'}}
+  static_assert(uninit<int, false, true>(), ""); // ref-error {{not an integral constant expression}} \
+                                                 // ref-note {{in call to 'uninit<int, false, true>()'}} \
+                                                 // expected-error {{not an integral constant expression}} \
+                                                 // expected-note {{in call to 'uninit()'}}
+
+  static_assert(uninit<float, true, true>(), ""); // ref-error {{not an integral constant expression}} \
+                                                  // ref-note {{in call to 'uninit<float, true, true>()'}} \
+                                                  // expected-error {{not an integral constant expression}} \
+                                                  // expected-note {{in call to 'uninit()'}}
+  static_assert(uninit<float, false, true>(), ""); // ref-error {{not an integral constant expression}} \
+                                                   // ref-note {{in call to 'uninit<float, false, true>()'}} \
+                                                   // expected-error {{not an integral constant expression}} \
+                                                   // expected-note {{in call to 'uninit()'}}
+  static_assert(uninit<float, true, false>(), ""); // ref-error {{not an integral constant expression}} \
+                                                   // ref-note {{in call to 'uninit<float, true, false>()'}} \
+                                                   // expected-error {{not an integral constant expression}} \
+                                                   // expected-note {{in call to 'uninit()'}}
+  static_assert(uninit<float, false, false>(), ""); // ref-error {{not an integral constant expression}} \
+                                                    // ref-note {{in call to 'uninit<float, false, false>()'}} \
+                                                    // expected-error {{not an integral constant expression}} \
+                                                    // expected-note {{in call to 'uninit()'}}
+
+  static_assert(uninit<int*, true, true>(), ""); // ref-error {{not an integral constant expression}} \
+                                                 // ref-note {{in call to 'uninit<int *, true, true>()'}} \
+                                                 // expected-error {{not an integral constant expression}} \
+                                                 // expected-note {{in call to 'uninit()'}}
+  static_assert(uninit<int*, false, true>(), ""); // ref-error {{not an integral constant expression}} \
+                                                  // ref-note {{in call to 'uninit<int *, false, true>()'}} \
+                                                  // expected-error {{not an integral constant expression}} \
+                                                  // expected-note {{in call to 'uninit()'}}
+  static_assert(uninit<int*, true, false>(), ""); // ref-error {{not an integral constant expression}} \
+                                                  // ref-note {{in call to 'uninit<int *, true, false>()'}} \
+                                                  // expected-error {{not an integral constant expression}} \
+                                                  // expected-note {{in call to 'uninit()'}}
+  static_assert(uninit<int*, false, false>(), ""); // ref-error {{not an integral constant expression}} \
+                                                   // ref-note {{in call to 'uninit<int *, false, false>()'}} \
+                                                   // expected-error {{not an integral constant expression}} \
+                                                   // expected-note {{in call to 'uninit()'}}
 
   constexpr int OverFlow() { // ref-error {{never produces a constant expression}} \
                              // expected-error {{never produces a constant expression}}


        


More information about the cfe-commits mailing list