aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2010-07-07 06:14:23 +0000
committerChris Lattner <sabre@nondot.org>2010-07-07 06:14:23 +0000
commit8b5dec3002bd3e17061a8bf1fc35ba82912ec768 (patch)
tree8cf91f9f1d87ea40a35b7761f0f4018e8ffa0e32
parent0f2b692bb10be35fdc60d0a72a847bdd73124670 (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.td11
-rw-r--r--lib/Sema/SemaExpr.cpp17
-rw-r--r--test/Analysis/misc-ps.m2
-rw-r--r--test/Sema/exprs.c8
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.
+}
+