Skip to content

Commit c43f828

Browse files
authored
[Clang] Be less strict about diagnosing null pointer dereference. (#149648)
In #143667, we made constant evaluation fail on `*null_ptr`, as this is UB. However, `&(*(foo*)0)` seems to be a common pattern, which made #143667 too disruptive. So instead of failing the evaluation, we note the UB, which let clang recovers when checking for constant initialization. Fixes #149500
1 parent 1fcf49a commit c43f828

File tree

4 files changed

+16
-8
lines changed

4 files changed

+16
-8
lines changed

clang/lib/AST/ExprConstant.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9346,9 +9346,13 @@ bool LValueExprEvaluator::VisitUnaryDeref(const UnaryOperator *E) {
93469346
// [C++26][expr.unary.op]
93479347
// If the operand points to an object or function, the result
93489348
// denotes that object or function; otherwise, the behavior is undefined.
9349-
return Success &&
9350-
(!E->getType().getNonReferenceType()->isObjectType() ||
9351-
findCompleteObject(Info, E, AK_Dereference, Result, E->getType()));
9349+
// Because &(*(type*)0) is a common pattern, we do not fail the evaluation
9350+
// immediately.
9351+
if (!Success || !E->getType().getNonReferenceType()->isObjectType())
9352+
return Success;
9353+
return bool(findCompleteObject(Info, E, AK_Dereference, Result,
9354+
E->getType())) ||
9355+
Info.noteUndefinedBehavior();
93529356
}
93539357

93549358
bool LValueExprEvaluator::VisitUnaryReal(const UnaryOperator *E) {

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@ struct s {
5151
};
5252

5353
EVAL_EXPR(19, ((int)&*(char*)10 == 10 ? 1 : -1));
54-
// ref-error@-1 {{expression is not an integer constant expression}} \
55-
// ref-note@-1 {{dereferencing a null pointer}}
5654

5755
#ifndef NEW_INTERP
5856
EVAL_EXPR(20, __builtin_constant_p(*((int*) 10)));

clang/test/Sema/const-eval.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,6 @@ struct s {
4141
};
4242

4343
EVAL_EXPR(19, ((int)&*(char*)10 == 10 ? 1 : -1));
44-
// expected-error@-1 {{not an integer constant expression}} \
45-
// expected-note@-1 {{dereferencing a null pointer is not allowed in a constant expression}}
46-
4744

4845
EVAL_EXPR(20, __builtin_constant_p(*((int*) 10)));
4946

@@ -153,3 +150,7 @@ struct PR35214_X {
153150
int PR35214_x;
154151
int PR35214_y = ((struct PR35214_X *)&PR35214_x)->arr[1]; // expected-error {{not a compile-time constant}}
155152
int *PR35214_z = &((struct PR35214_X *)&PR35214_x)->arr[1]; // ok, &PR35214_x + 2
153+
154+
155+
int * GH149500_p = &(*(int *)0x400);
156+
static const void *GH149500_q = &(*(const struct sysrq_key_op *)0);

clang/test/SemaCXX/constant-expression-cxx14.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1445,3 +1445,8 @@ static_assert(test_member_null(), "");
14451445

14461446
}
14471447
}
1448+
1449+
namespace GH149500 {
1450+
unsigned int * p = &(*(unsigned int *)0x400);
1451+
static const void *q = &(*(const struct sysrq_key_op *)0);
1452+
}

0 commit comments

Comments
 (0)