-
Notifications
You must be signed in to change notification settings - Fork 14.5k
[clang][bytecode] Diagnose dereferencing a null pointer #149330
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
Conversation
@llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) ChangesFull diff: https://github.com/llvm/llvm-project/pull/149330.diff 7 Files Affected:
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;
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks.
(Note that this does not cover the case of forming a reference to a one-past-the-end object, which is covered by the same wording, but if you don't already do that, it can be a separate pr.
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/88/builds/14108 Here is the relevant piece of the build log for the reference
|
No description provided.