[Diagnostics] Teach -Wnull-dereference about address_space attribute

Summary:
Clang should not warn for:

> test.c:2:12: warning: indirection of non-volatile null pointer will be deleted,
>       not trap [-Wnull-dereference]
>     return *(int __attribute__((address_space(256))) *) 0;
>            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Solves PR42292.

Reviewers: aaron.ballman, rsmith

Reviewed By: aaron.ballman

Subscribers: cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D69664
This commit is contained in:
Dávid Bolvanský 2019-11-07 20:47:09 +01:00
parent b95bb0847a
commit 01b10bc7b1
2 changed files with 29 additions and 14 deletions

View File

@ -481,16 +481,21 @@ static void CheckForNullPointerDereference(Sema &S, Expr *E) {
// optimizer will delete, so warn about it. People sometimes try to use this
// to get a deterministic trap and are surprised by clang's behavior. This
// only handles the pattern "*null", which is a very syntactic check.
if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E->IgnoreParenCasts()))
if (UO->getOpcode() == UO_Deref &&
UO->getSubExpr()->IgnoreParenCasts()->
isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull) &&
const auto *UO = dyn_cast<UnaryOperator>(E->IgnoreParenCasts());
if (UO && UO->getOpcode() == UO_Deref) {
const LangAS AS =
UO->getSubExpr()->getType()->getPointeeType().getAddressSpace();
if ((!isTargetAddressSpace(AS) ||
(isTargetAddressSpace(AS) && toTargetAddressSpace(AS) == 0)) &&
UO->getSubExpr()->IgnoreParenCasts()->isNullPointerConstant(
S.Context, Expr::NPC_ValueDependentIsNotNull) &&
!UO->getType().isVolatileQualified()) {
S.DiagRuntimeBehavior(UO->getOperatorLoc(), UO,
S.PDiag(diag::warn_indirection_through_null)
<< UO->getSubExpr()->getSourceRange());
S.DiagRuntimeBehavior(UO->getOperatorLoc(), UO,
S.PDiag(diag::note_indirection_through_null));
S.DiagRuntimeBehavior(UO->getOperatorLoc(), UO,
S.PDiag(diag::warn_indirection_through_null)
<< UO->getSubExpr()->getSourceRange());
S.DiagRuntimeBehavior(UO->getOperatorLoc(), UO,
S.PDiag(diag::note_indirection_through_null));
}
}
}

View File

@ -179,17 +179,27 @@ void test18(int b) {
test18_e(); // expected-error {{too few arguments to function call, expected at least 2, have 0}}
}
typedef int __attribute__((address_space(256))) int_AS256;
// PR7569
void test19() {
*(int*)0 = 0; // expected-warning {{indirection of non-volatile null pointer}} \
*(int *)0 = 0; // expected-warning {{indirection of non-volatile null pointer}} \
// expected-note {{consider using __builtin_trap}}
*(volatile int*)0 = 0; // Ok.
*(volatile int *)0 = 0; // Ok.
*(int __attribute__((address_space(256))) *)0 = 0; // Ok.
*(int __attribute__((address_space(0))) *)0 = 0; // expected-warning {{indirection of non-volatile null pointer}} \
// expected-note {{consider using __builtin_trap}}
*(int_AS256 *)0 = 0; // Ok.
// rdar://9269271
int x = *(int*)0; // expected-warning {{indirection of non-volatile null pointer}} \
int x = *(int *)0; // expected-warning {{indirection of non-volatile null pointer}} \
// expected-note {{consider using __builtin_trap}}
int x2 = *(volatile int*)0; // Ok.
int *p = &(*(int*)0); // Ok;
int x2 = *(volatile int *)0; // Ok.
int x3 = *(int __attribute__((address_space(0))) *)0; // expected-warning {{indirection of non-volatile null pointer}} \
// expected-note {{consider using __builtin_trap}}
int x4 = *(int_AS256 *)0; // Ok.
int *p = &(*(int *)0); // Ok.
int_AS256 *p1 = &(*(int __attribute__((address_space(256))) *)0); // Ok.
int __attribute__((address_space(0))) *p2 = &(*(int __attribute__((address_space(0))) *)0); // Ok.
}
int test20(int x) {