Commit ef3ddd4f by Mark Mitchell Committed by Mark Mitchell

typeck.c (cp_build_binary_op): Move warnings about use of NULL in arithmetic…

typeck.c (cp_build_binary_op): Move warnings about use of NULL in arithmetic earlier and allow comparisions of...

2009-07-02  Mark Mitchell  <mark@codesourcery.com>

	* typeck.c (cp_build_binary_op): Move warnings about use of NULL
	in arithmetic earlier and allow comparisions of NULL with
	pointers-to-members.

2009-07-02  Mark Mitchell  <mark@codesourcery.com>

	* g++.dg/warn/null4.C: Extend.

From-SVN: r149190
parent 2b110bfc
2009-07-02 Mark Mitchell <mark@codesourcery.com>
* typeck.c (cp_build_binary_op): Move warnings about use of NULL
in arithmetic earlier and allow comparisions of NULL with
pointers-to-members.
2009-07-02 Jason Merrill <jason@redhat.com> 2009-07-02 Jason Merrill <jason@redhat.com>
Use hash tables for template specialization lookup. Use hash tables for template specialization lookup.
......
...@@ -3419,7 +3419,6 @@ cp_build_binary_op (location_t location, ...@@ -3419,7 +3419,6 @@ cp_build_binary_op (location_t location,
/* If an error was already reported for one of the arguments, /* If an error was already reported for one of the arguments,
avoid reporting another error. */ avoid reporting another error. */
if (code0 == ERROR_MARK || code1 == ERROR_MARK) if (code0 == ERROR_MARK || code1 == ERROR_MARK)
return error_mark_node; return error_mark_node;
...@@ -3430,6 +3429,25 @@ cp_build_binary_op (location_t location, ...@@ -3430,6 +3429,25 @@ cp_build_binary_op (location_t location,
return error_mark_node; return error_mark_node;
} }
/* Issue warnings about peculiar, but valid, uses of NULL. */
if ((orig_op0 == null_node || orig_op1 == null_node)
/* It's reasonable to use pointer values as operands of &&
and ||, so NULL is no exception. */
&& code != TRUTH_ANDIF_EXPR && code != TRUTH_ORIF_EXPR
&& ( /* Both are NULL (or 0) and the operation was not a
comparison or a pointer subtraction. */
(null_ptr_cst_p (orig_op0) && null_ptr_cst_p (orig_op1)
&& code != EQ_EXPR && code != NE_EXPR && code != MINUS_EXPR)
/* Or if one of OP0 or OP1 is neither a pointer nor NULL. */
|| (!null_ptr_cst_p (orig_op0)
&& !TYPE_PTR_P (type0) && !TYPE_PTR_TO_MEMBER_P (type0))
|| (!null_ptr_cst_p (orig_op1)
&& !TYPE_PTR_P (type1) && !TYPE_PTR_TO_MEMBER_P (type1)))
&& (complain & tf_warning))
/* Some sort of arithmetic operation involving NULL was
performed. */
warning (OPT_Wpointer_arith, "NULL used in arithmetic");
switch (code) switch (code)
{ {
case MINUS_EXPR: case MINUS_EXPR:
...@@ -4031,25 +4049,6 @@ cp_build_binary_op (location_t location, ...@@ -4031,25 +4049,6 @@ cp_build_binary_op (location_t location,
} }
} }
/* Issue warnings about peculiar, but valid, uses of NULL. */
if ((orig_op0 == null_node || orig_op1 == null_node)
/* It's reasonable to use pointer values as operands of &&
and ||, so NULL is no exception. */
&& code != TRUTH_ANDIF_EXPR && code != TRUTH_ORIF_EXPR
&& ( /* Both are NULL (or 0) and the operation was not a comparison. */
(null_ptr_cst_p (orig_op0) && null_ptr_cst_p (orig_op1)
&& code != EQ_EXPR && code != NE_EXPR)
/* Or if one of OP0 or OP1 is neither a pointer nor NULL. */
|| (!null_ptr_cst_p (orig_op0) && TREE_CODE (TREE_TYPE (op0)) != POINTER_TYPE)
|| (!null_ptr_cst_p (orig_op1) && TREE_CODE (TREE_TYPE (op1)) != POINTER_TYPE))
&& (complain & tf_warning))
/* Some sort of arithmetic operation involving NULL was
performed. Note that pointer-difference and pointer-addition
have already been handled above, and so we don't end up here in
that case. */
warning (OPT_Wpointer_arith, "NULL used in arithmetic");
/* If CONVERTED is zero, both args will be converted to type RESULT_TYPE. /* If CONVERTED is zero, both args will be converted to type RESULT_TYPE.
Then the expression will be built. Then the expression will be built.
It will be given type FINAL_TYPE if that is nonzero; It will be given type FINAL_TYPE if that is nonzero;
......
2009-07-02 Mark Mitchell <mark@codesourcery.com>
* g++.dg/warn/null4.C: Extend.
2009-07-02 Jason Merrill <jason@redhat.com> 2009-07-02 Jason Merrill <jason@redhat.com>
* g++.dg/template/spec8.C: Fix. * g++.dg/template/spec8.C: Fix.
......
...@@ -11,9 +11,22 @@ int foo (void) ...@@ -11,9 +11,22 @@ int foo (void)
if (NULL < NULL) return -1; // { dg-warning "NULL used in arithmetic" } if (NULL < NULL) return -1; // { dg-warning "NULL used in arithmetic" }
if (NULL >= 0) return -1; // { dg-warning "NULL used in arithmetic" } if (NULL >= 0) return -1; // { dg-warning "NULL used in arithmetic" }
if (NULL <= 0) return -1; // { dg-warning "NULL used in arithmetic" } if (NULL <= 0) return -1; // { dg-warning "NULL used in arithmetic" }
// Adding to the NULL pointer, which has no specific type, should
// result in a warning; the type of the resulting expression is
// actually "int", not a pointer type.
if (NULL + 1) return -1; // { dg-warning "NULL used in arithmetic" }
if (1 + NULL) return -1; // { dg-warning "NULL used in arithmetic" }
return 0; return 0;
} }
int *ip;
struct S {};
typedef int S::*SPD;
typedef void (S::*SPF)(void);
SPD spd;
SPF spf;
int bar (void) int bar (void)
{ {
if (NULL) return -1; if (NULL) return -1;
...@@ -25,5 +38,18 @@ int bar (void) ...@@ -25,5 +38,18 @@ int bar (void)
if (NULL != NULL) return -1; if (NULL != NULL) return -1;
if (NULL == 0) return -1; if (NULL == 0) return -1;
if (NULL != 0) return -1; if (NULL != 0) return -1;
// Subtraction of pointers is vaild, so using NULL is OK.
if (ip - NULL) return -1;
if (NULL - NULL) return -1;
// Comparing NULL with a pointer-to-member is OK.
if (NULL == spd) return -1;
if (spd == NULL) return -1;
if (NULL != spd) return -1;
if (spd != NULL) return -1;
if (NULL == spf) return -1;
if (spf == NULL) return -1;
if (NULL != spf) return -1;
if (spf != NULL) return -1;
return 0; return 0;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment