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

None

>From ccea1fcbd2a848e679bca4d75a67b51795b468c5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com>
Date: Thu, 17 Jul 2025 17:04:18 +0200
Subject: [PATCH] [clang][bytecode] Diagnose dereferencing a null pointer

---
 clang/lib/AST/ByteCode/Compiler.cpp |  3 +++
 clang/lib/AST/ByteCode/Interp.h     | 11 +++++++++++
 clang/lib/AST/ByteCode/Opcodes.td   |  1 +
 clang/test/AST/ByteCode/complex.cpp |  5 ++---
 clang/test/AST/ByteCode/cxx11.cpp   |  5 ++---
 clang/test/AST/ByteCode/records.cpp |  6 ++----
 clang/test/CXX/drs/cwg14xx.cpp      |  8 ++++++++
 7 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/clang/lib/AST/ByteCode/Compiler.cpp 
b/clang/lib/AST/ByteCode/Compiler.cpp
index ea473730350b6..8fa3c91bcf329 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -6375,6 +6375,9 @@ bool Compiler<Emitter>::VisitUnaryOperator(const 
UnaryOperator *E) {
     if (!this->visit(SubExpr))
       return false;
 
+    if (!this->emitCheckNull(E))
+      return false;
+
     if (classifyPrim(SubExpr) == PT_Ptr)
       return this->emitNarrowPtr(E);
     return true;
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index ce0ebdd8321b7..c0e084ce554a6 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -1885,6 +1885,17 @@ inline bool Dump(InterpState &S, CodePtr OpPC) {
   return true;
 }
 
+inline bool CheckNull(InterpState &S, CodePtr OpPC) {
+  const auto &Ptr = S.Stk.peek<Pointer>();
+  if (Ptr.isZero()) {
+    S.FFDiag(S.Current->getSource(OpPC),
+             diag::note_constexpr_dereferencing_null);
+    return false;
+  }
+
+  return true;
+}
+
 inline bool VirtBaseHelper(InterpState &S, CodePtr OpPC, const RecordDecl 
*Decl,
                            const Pointer &Ptr) {
   Pointer Base = Ptr;
diff --git a/clang/lib/AST/ByteCode/Opcodes.td 
b/clang/lib/AST/ByteCode/Opcodes.td
index 804853d29512e..80703ad72d954 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -865,6 +865,7 @@ def CheckNewTypeMismatchArray : Opcode {
 
 def IsConstantContext: Opcode;
 def CheckAllocations : Opcode;
+def CheckNull : Opcode;
 
 def BitCastTypeClass : TypeClass {
   let Types = [Uint8, Sint8, Uint16, Sint16, Uint32, Sint32, Uint64, Sint64,
diff --git a/clang/test/AST/ByteCode/complex.cpp 
b/clang/test/AST/ByteCode/complex.cpp
index 959d759005ef4..be10b3cfa53da 100644
--- a/clang/test/AST/ByteCode/complex.cpp
+++ b/clang/test/AST/ByteCode/complex.cpp
@@ -396,10 +396,9 @@ namespace ComplexConstexpr {
                                     // both-note {{cannot refer to element 3 
of array of 2 elements}}
   constexpr _Complex float *p = 0;
   constexpr float pr = __real *p; // both-error {{constant expr}} \
-                                  // expected-note {{read of dereferenced null 
pointer}} \
-                                  // ref-note {{dereferencing a null pointer}}
+                                  // both-note {{dereferencing a null pointer}}
   constexpr float pi = __imag *p; // both-error {{constant expr}} \
-                                  // ref-note {{dereferencing a null pointer}}
+                                  // both-note {{dereferencing a null pointer}}
   constexpr const _Complex double *q = &test3 + 1;
   constexpr double qr = __real *q; // ref-error {{constant expr}} \
                                    // ref-note {{cannot access real component 
of pointer past the end}}
diff --git a/clang/test/AST/ByteCode/cxx11.cpp 
b/clang/test/AST/ByteCode/cxx11.cpp
index 55554220b0a8a..378702f9b3620 100644
--- a/clang/test/AST/ByteCode/cxx11.cpp
+++ b/clang/test/AST/ByteCode/cxx11.cpp
@@ -39,9 +39,8 @@ struct S {
 constexpr S s = { 5 };
 constexpr const int *p = &s.m + 1;
 
-constexpr const int *np2 = &(*(int(*)[4])nullptr)[0];
-// ref-error@-1 {{constexpr variable 'np2' must be initialized by a constant 
expression}} \
-// ref-note@-1  {{dereferencing a null pointer is not allowed in a constant 
expression}}
+constexpr const int *np2 = &(*(int(*)[4])nullptr)[0]; // both-error 
{{constexpr variable 'np2' must be initialized by a constant expression}} \
+                                                      // both-note  
{{dereferencing a null pointer is not allowed in a constant expression}}
 
 constexpr int preDec(int x) { // both-error {{never produces a constant 
expression}}
   return --x;                 // both-note {{subexpression}}
diff --git a/clang/test/AST/ByteCode/records.cpp 
b/clang/test/AST/ByteCode/records.cpp
index 774fed6189d64..5ca3e2d12e2df 100644
--- a/clang/test/AST/ByteCode/records.cpp
+++ b/clang/test/AST/ByteCode/records.cpp
@@ -1660,11 +1660,9 @@ namespace NullptrCast {
   constexpr A *na = nullptr;
   constexpr B *nb = nullptr;
   constexpr A &ra = *nb; // both-error {{constant expression}} \
-                         // ref-note {{dereferencing a null pointer}} \
-                         // expected-note {{cannot access base class of null 
pointer}}
+                         // both-note {{dereferencing a null pointer}}
   constexpr B &rb = (B&)*na; // both-error {{constant expression}} \
-                             // ref-note {{dereferencing a null pointer}} \
-                             // expected-note {{cannot access derived class of 
null pointer}}
+                             // both-note {{dereferencing a null pointer}}
   constexpr bool test() {
     auto a = (A*)(B*)nullptr;
 
diff --git a/clang/test/CXX/drs/cwg14xx.cpp b/clang/test/CXX/drs/cwg14xx.cpp
index 8d39018d8926c..047df171afffa 100644
--- a/clang/test/CXX/drs/cwg14xx.cpp
+++ b/clang/test/CXX/drs/cwg14xx.cpp
@@ -6,6 +6,14 @@
 // RUN: %clang_cc1 -std=c++23 %s 
-verify=expected,since-cxx11,since-cxx14,since-cxx20 -fexceptions 
-fcxx-exceptions -pedantic-errors
 // RUN: %clang_cc1 -std=c++2c %s 
-verify=expected,since-cxx11,since-cxx14,since-cxx20 -fexceptions 
-fcxx-exceptions -pedantic-errors
 
+// RUN: %clang_cc1 -std=c++98 %s -verify=expected -fexceptions 
-fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx11-17,since-cxx11, 
-fexceptions -fcxx-exceptions -pedantic-errors 
-fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -std=c++14 %s 
-verify=expected,cxx14-17,cxx11-17,since-cxx11,since-cxx14 -fexceptions 
-fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -std=c++17 %s 
-verify=expected,cxx14-17,cxx11-17,since-cxx11,since-cxx14 -fexceptions 
-fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -std=c++20 %s 
-verify=expected,since-cxx11,since-cxx14,since-cxx20 -fexceptions 
-fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -std=c++23 %s 
-verify=expected,since-cxx11,since-cxx14,since-cxx20 -fexceptions 
-fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -std=c++2c %s 
-verify=expected,since-cxx11,since-cxx14,since-cxx20 -fexceptions 
-fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter
+
 namespace cwg1413 { // cwg1413: 12
   template<int> struct Check {
     typedef int type;

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

Reply via email to