diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -481,16 +481,21 @@ // 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(E->IgnoreParenCasts())) - if (UO->getOpcode() == UO_Deref && - UO->getSubExpr()->IgnoreParenCasts()-> - isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull) && + const auto *UO = dyn_cast(E->IgnoreParenCasts()); + if (UO && UO->getOpcode() == UO_Deref) { + const LangAS AS = + UO->getSubExpr()->getType()->getPointeeType().getAddressSpace(); + bool isTargetAS = isTargetAddressSpace(AS); + if ((!isTargetAS || (isTargetAS && 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)); + } } } diff --git a/clang/test/Sema/exprs.c b/clang/test/Sema/exprs.c --- a/clang/test/Sema/exprs.c +++ b/clang/test/Sema/exprs.c @@ -179,17 +179,27 @@ 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 x3 = *(int __attribute__((address_space(0))) *)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 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) {