Skip to content

Commit fed6db4

Browse files
authored
[clang][bytecode] Diagnose dereferencing a null pointer (llvm#149330)
1 parent 5753be4 commit fed6db4

File tree

8 files changed

+31
-10
lines changed

8 files changed

+31
-10
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6375,6 +6375,9 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
63756375
if (!this->visit(SubExpr))
63766376
return false;
63776377

6378+
if (!this->emitCheckNull(E))
6379+
return false;
6380+
63786381
if (classifyPrim(SubExpr) == PT_Ptr)
63796382
return this->emitNarrowPtr(E);
63806383
return true;

clang/lib/AST/ByteCode/Interp.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1885,6 +1885,16 @@ inline bool Dump(InterpState &S, CodePtr OpPC) {
18851885
return true;
18861886
}
18871887

1888+
inline bool CheckNull(InterpState &S, CodePtr OpPC) {
1889+
const auto &Ptr = S.Stk.peek<Pointer>();
1890+
if (Ptr.isZero()) {
1891+
S.FFDiag(S.Current->getSource(OpPC),
1892+
diag::note_constexpr_dereferencing_null);
1893+
return S.noteUndefinedBehavior();
1894+
}
1895+
return true;
1896+
}
1897+
18881898
inline bool VirtBaseHelper(InterpState &S, CodePtr OpPC, const RecordDecl *Decl,
18891899
const Pointer &Ptr) {
18901900
Pointer Base = Ptr;

clang/lib/AST/ByteCode/Opcodes.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -865,6 +865,7 @@ def CheckNewTypeMismatchArray : Opcode {
865865

866866
def IsConstantContext: Opcode;
867867
def CheckAllocations : Opcode;
868+
def CheckNull : Opcode;
868869

869870
def BitCastTypeClass : TypeClass {
870871
let Types = [Uint8, Sint8, Uint16, Sint16, Uint32, Sint32, Uint64, Sint64,

clang/test/AST/ByteCode/complex.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -396,10 +396,9 @@ namespace ComplexConstexpr {
396396
// both-note {{cannot refer to element 3 of array of 2 elements}}
397397
constexpr _Complex float *p = 0;
398398
constexpr float pr = __real *p; // both-error {{constant expr}} \
399-
// expected-note {{read of dereferenced null pointer}} \
400-
// ref-note {{dereferencing a null pointer}}
399+
// both-note {{dereferencing a null pointer}}
401400
constexpr float pi = __imag *p; // both-error {{constant expr}} \
402-
// ref-note {{dereferencing a null pointer}}
401+
// both-note {{dereferencing a null pointer}}
403402
constexpr const _Complex double *q = &test3 + 1;
404403
constexpr double qr = __real *q; // ref-error {{constant expr}} \
405404
// ref-note {{cannot access real component of pointer past the end}}

clang/test/AST/ByteCode/const-eval.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,9 @@ typedef __INTPTR_TYPE__ intptr_t;
180180
const intptr_t A = (intptr_t)(((int*) 0) + 1);
181181
const intptr_t B = (intptr_t)(((char*)0) + 3);
182182
_Static_assert(A > B, "");
183+
int * GH149500_p = &(*(int *)0x400);
184+
static const void *GH149500_q = &(*(const struct sysrq_key_op *)0);
185+
183186
#else
184187
#error :(
185188
#endif

clang/test/AST/ByteCode/cxx11.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,8 @@ struct S {
3939
constexpr S s = { 5 };
4040
constexpr const int *p = &s.m + 1;
4141

42-
constexpr const int *np2 = &(*(int(*)[4])nullptr)[0];
43-
// ref-error@-1 {{constexpr variable 'np2' must be initialized by a constant expression}} \
44-
// ref-note@-1 {{dereferencing a null pointer is not allowed in a constant expression}}
42+
constexpr const int *np2 = &(*(int(*)[4])nullptr)[0]; // both-error {{constexpr variable 'np2' must be initialized by a constant expression}} \
43+
// both-note {{dereferencing a null pointer is not allowed in a constant expression}}
4544

4645
constexpr int preDec(int x) { // both-error {{never produces a constant expression}}
4746
return --x; // both-note {{subexpression}}

clang/test/AST/ByteCode/records.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1660,11 +1660,9 @@ namespace NullptrCast {
16601660
constexpr A *na = nullptr;
16611661
constexpr B *nb = nullptr;
16621662
constexpr A &ra = *nb; // both-error {{constant expression}} \
1663-
// ref-note {{dereferencing a null pointer}} \
1664-
// expected-note {{cannot access base class of null pointer}}
1663+
// both-note {{dereferencing a null pointer}}
16651664
constexpr B &rb = (B&)*na; // both-error {{constant expression}} \
1666-
// ref-note {{dereferencing a null pointer}} \
1667-
// expected-note {{cannot access derived class of null pointer}}
1665+
// both-note {{dereferencing a null pointer}}
16681666
constexpr bool test() {
16691667
auto a = (A*)(B*)nullptr;
16701668

clang/test/CXX/drs/cwg14xx.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@
66
// RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx11,since-cxx14,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors
77
// RUN: %clang_cc1 -std=c++2c %s -verify=expected,since-cxx11,since-cxx14,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors
88

9+
// RUN: %clang_cc1 -std=c++98 %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter
10+
// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx11-17,since-cxx11, -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter
11+
// 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
12+
// 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
13+
// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx11,since-cxx14,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter
14+
// RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx11,since-cxx14,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter
15+
// RUN: %clang_cc1 -std=c++2c %s -verify=expected,since-cxx11,since-cxx14,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter
16+
917
namespace cwg1413 { // cwg1413: 12
1018
template<int> struct Check {
1119
typedef int type;

0 commit comments

Comments
 (0)