diff options
author | Chris Lattner <sabre@nondot.org> | 2010-07-07 06:14:23 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2010-07-07 06:14:23 +0000 |
commit | 8b5dec3002bd3e17061a8bf1fc35ba82912ec768 (patch) | |
tree | 8cf91f9f1d87ea40a35b7761f0f4018e8ffa0e32 | |
parent | 0f2b692bb10be35fdc60d0a72a847bdd73124670 (diff) |
implement PR7569, warning about assignment to null, which
people seem to write when they want a deterministic trap.
Suggest instead that they use a volatile pointer or
__builtin_trap.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107756 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 11 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 17 | ||||
-rw-r--r-- | test/Analysis/misc-ps.m | 2 | ||||
-rw-r--r-- | test/Sema/exprs.c | 8 |
4 files changed, 31 insertions, 7 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 136dfb5ad0..f88a0ae664 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -21,12 +21,6 @@ def ext_expr_not_ice : Extension< "expression is not integer constant expression " "(but is allowed as an extension)">; -def ext_null_pointer_expr_not_ice : Extension< - "null pointer expression is not an integer constant expression " - "(but is allowed as an extension)">; - - - // Semantic analysis of constant literals. def ext_predef_outside_function : Warning< "predefined identifier is only valid inside function">; @@ -2095,6 +2089,11 @@ def err_typecheck_unary_expr : Error< "invalid argument type %0 to unary expression">; def err_typecheck_indirection_requires_pointer : Error< "indirection requires pointer operand (%0 invalid)">; +def warn_indirection_through_null : Warning< + "indirection of non-volatile null pointer will be deleted, not trap">; +def note_indirection_through_null : Note< + "consider using __builtin_trap() or qualifying pointer with 'volatile'">; + def err_indirection_requires_nonfragile_object : Error< "indirection cannot be to an interface in non-fragile ABI (%0 invalid)">; def err_direct_interface_unsupported : Error< diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 8b7c689ae2..342c522442 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -5892,6 +5892,23 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS, RHS, AA_Assigning)) return QualType(); + + // Check to see if the destination operand is a dereferenced null pointer. If + // so, and if not volatile-qualified, this is undefined behavior that the + // 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 = whatever", which is a very syntactic + // check. + if (UnaryOperator *UO = dyn_cast<UnaryOperator>(LHS->IgnoreParenCasts())) + if (UO->getOpcode() == UnaryOperator::Deref && + UO->getSubExpr()->IgnoreParenCasts()-> + isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull) && + !UO->getType().isVolatileQualified()) { + Diag(UO->getOperatorLoc(), diag::warn_indirection_through_null) + << UO->getSubExpr()->getSourceRange(); + Diag(UO->getOperatorLoc(), diag::note_indirection_through_null); + } + // C99 6.5.16p3: The type of an assignment expression is the type of the // left operand unless the left operand has qualified type, in which case // it is the unqualified version of the type of the left operand. diff --git a/test/Analysis/misc-ps.m b/test/Analysis/misc-ps.m index 253450cc42..b1d47e214e 100644 --- a/test/Analysis/misc-ps.m +++ b/test/Analysis/misc-ps.m @@ -582,7 +582,7 @@ void pr4781(unsigned long *raw1) { - (id) foo { if (self) return self; - *((int *) 0x0) = 0xDEADBEEF; // no-warning + *((volatile int *) 0x0) = 0xDEADBEEF; // no-warning return self; } @end diff --git a/test/Sema/exprs.c b/test/Sema/exprs.c index dbb6e80aa6..b22b5220f2 100644 --- a/test/Sema/exprs.c +++ b/test/Sema/exprs.c @@ -134,3 +134,11 @@ void test18(int b) { test18_a(b, b); // expected-error {{too many arguments to function call, expected 1, have 2}} test18_a(); // expected-error {{too few arguments to function call, expected 1, have 0}} } + +// PR7569 +void test19() { + *(int*)0 = 0; // expected-warning {{indirection of non-volatile null pointer}} \ + // expected-note {{consider using __builtin_trap}} + *(volatile int*)0 = 0; // Ok. +} + |