]> granicus.if.org Git - clang/commitdiff
implement PR7569, warning about assignment to null, which
authorChris Lattner <sabre@nondot.org>
Wed, 7 Jul 2010 06:14:23 +0000 (06:14 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 7 Jul 2010 06:14:23 +0000 (06:14 +0000)
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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaExpr.cpp
test/Analysis/misc-ps.m
test/Sema/exprs.c

index 136dfb5ad06f61bd43230f4bce0e47f7c05aee27..f88a0ae66415c6fd8f51cb4e429548d07e3fa3a9 100644 (file)
@@ -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<
index 8b7c689ae23106e4800bedb6db51d19ed13459be..342c522442d2c5509156cfaa347f8414be861d1f 100644 (file)
@@ -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.
index 253450cc42afdadfc094c095a79e441d59339fbf..b1d47e214ef79247cfaab8c7b3067889e0d3e2e6 100644 (file)
@@ -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
index dbb6e80aa6d571fba2ed8e1f7426c667986f41a1..b22b5220f2859ea7c7d6dfdc0c7d3cec17b8ef91 100644 (file)
@@ -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.
+}
+