c-common.c (decl_with_nonnull_addr_p): New function.
./: * c-common.c (decl_with_nonnull_addr_p): New function. (c_common_truthvalue_conversion): Call it. * c-typeck.c (build_binary_op): Likewise. * c-common.h (decl_with_nonnull_addr_p): Declare. cp/: * typeck.c (build_binary_op): Warn about comparing a non-weak address to NULL. testsuite/: * gcc.dg/Walways-true-1.c: New test. * gcc.dg/Walways-true-2.c: New test. * g++.dg/warn/Walways-true-1.C: New test. * g++.dg/warn/Walways-true-2.C: New test. From-SVN: r120493
This commit is contained in:
parent
97af925ba7
commit
b3c6d2ea00
11 changed files with 293 additions and 22 deletions
|
@ -1,3 +1,10 @@
|
|||
2007-01-05 Ian Lance Taylor <iant@google.com>
|
||||
|
||||
* c-common.c (decl_with_nonnull_addr_p): New function.
|
||||
(c_common_truthvalue_conversion): Call it.
|
||||
* c-typeck.c (build_binary_op): Likewise.
|
||||
* c-common.h (decl_with_nonnull_addr_p): Declare.
|
||||
|
||||
2007-01-05 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c/30360
|
||||
|
|
|
@ -2591,6 +2591,18 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
|
|||
return fold_build2 (resultcode, result_type, ptrop, intop);
|
||||
}
|
||||
|
||||
/* Return whether EXPR is a declaration whose address can never be
|
||||
NULL. */
|
||||
|
||||
bool
|
||||
decl_with_nonnull_addr_p (tree expr)
|
||||
{
|
||||
return (DECL_P (expr)
|
||||
&& (TREE_CODE (expr) == PARM_DECL
|
||||
|| TREE_CODE (expr) == LABEL_DECL
|
||||
|| !DECL_WEAK (expr)));
|
||||
}
|
||||
|
||||
/* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
|
||||
or for an `if' or `while' statement or ?..: exp. It should already
|
||||
have been validated to be of suitable type; otherwise, a bad
|
||||
|
@ -2656,23 +2668,22 @@ c_common_truthvalue_conversion (tree expr)
|
|||
case ADDR_EXPR:
|
||||
{
|
||||
tree inner = TREE_OPERAND (expr, 0);
|
||||
if (DECL_P (inner)
|
||||
&& (TREE_CODE (inner) == PARM_DECL
|
||||
|| TREE_CODE (inner) == LABEL_DECL
|
||||
|| !DECL_WEAK (inner)))
|
||||
if (decl_with_nonnull_addr_p (inner))
|
||||
{
|
||||
/* Common Ada/Pascal programmer's mistake. We always warn
|
||||
about this since it is so bad. */
|
||||
warning (OPT_Walways_true, "the address of %qD will always evaluate as %<true%>",
|
||||
/* Common Ada/Pascal programmer's mistake. */
|
||||
warning (OPT_Walways_true,
|
||||
"the address of %qD will always evaluate as %<true%>",
|
||||
inner);
|
||||
return truthvalue_true_node;
|
||||
}
|
||||
|
||||
/* If we are taking the address of an external decl, it might be
|
||||
zero if it is weak, so we cannot optimize. */
|
||||
if (DECL_P (inner)
|
||||
&& DECL_EXTERNAL (inner))
|
||||
break;
|
||||
/* If we still have a decl, it is possible for its address to
|
||||
be NULL, so we cannot optimize. */
|
||||
if (DECL_P (inner))
|
||||
{
|
||||
gcc_assert (DECL_WEAK (inner));
|
||||
break;
|
||||
}
|
||||
|
||||
if (TREE_SIDE_EFFECTS (inner))
|
||||
return build2 (COMPOUND_EXPR, truthvalue_type_node,
|
||||
|
|
|
@ -652,6 +652,7 @@ extern tree c_common_unsigned_type (tree);
|
|||
extern tree c_common_signed_type (tree);
|
||||
extern tree c_common_signed_or_unsigned_type (int, tree);
|
||||
extern tree c_build_bitfield_integer_type (unsigned HOST_WIDE_INT, int);
|
||||
extern bool decl_with_nonnull_addr_p (tree);
|
||||
extern tree c_common_truthvalue_conversion (tree);
|
||||
extern void c_apply_type_quals_to_decl (int, tree);
|
||||
extern tree c_sizeof_or_alignof_type (tree, bool, int);
|
||||
|
|
|
@ -8013,10 +8013,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
|
|||
else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
|
||||
{
|
||||
if (TREE_CODE (op0) == ADDR_EXPR
|
||||
&& DECL_P (TREE_OPERAND (op0, 0))
|
||||
&& (TREE_CODE (TREE_OPERAND (op0, 0)) == PARM_DECL
|
||||
|| TREE_CODE (TREE_OPERAND (op0, 0)) == LABEL_DECL
|
||||
|| !DECL_WEAK (TREE_OPERAND (op0, 0))))
|
||||
&& decl_with_nonnull_addr_p (TREE_OPERAND (op0, 0)))
|
||||
warning (OPT_Walways_true, "the address of %qD will never be NULL",
|
||||
TREE_OPERAND (op0, 0));
|
||||
result_type = type0;
|
||||
|
@ -8024,10 +8021,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
|
|||
else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
|
||||
{
|
||||
if (TREE_CODE (op1) == ADDR_EXPR
|
||||
&& DECL_P (TREE_OPERAND (op1, 0))
|
||||
&& (TREE_CODE (TREE_OPERAND (op1, 0)) == PARM_DECL
|
||||
|| TREE_CODE (TREE_OPERAND (op1, 0)) == LABEL_DECL
|
||||
|| !DECL_WEAK (TREE_OPERAND (op1, 0))))
|
||||
&& decl_with_nonnull_addr_p (TREE_OPERAND (op1, 0)))
|
||||
warning (OPT_Walways_true, "the address of %qD will never be NULL",
|
||||
TREE_OPERAND (op1, 0));
|
||||
result_type = type1;
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2007-01-05 Ian Lance Taylor <iant@google.com>
|
||||
|
||||
* typeck.c (build_binary_op): Warn about comparing a non-weak
|
||||
address to NULL.
|
||||
|
||||
2007-01-05 Douglas Gregor <doug.gregor@gmail.com>
|
||||
|
||||
* pt.c (tsubst): Propagate the need for structural equality checks
|
||||
|
|
|
@ -3334,10 +3334,22 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
|
|||
"comparison");
|
||||
else if ((code0 == POINTER_TYPE || TYPE_PTRMEM_P (type0))
|
||||
&& null_ptr_cst_p (op1))
|
||||
result_type = type0;
|
||||
{
|
||||
if (TREE_CODE (op0) == ADDR_EXPR
|
||||
&& decl_with_nonnull_addr_p (TREE_OPERAND (op0, 0)))
|
||||
warning (OPT_Walways_true, "the address of %qD will never be NULL",
|
||||
TREE_OPERAND (op0, 0));
|
||||
result_type = type0;
|
||||
}
|
||||
else if ((code1 == POINTER_TYPE || TYPE_PTRMEM_P (type1))
|
||||
&& null_ptr_cst_p (op0))
|
||||
result_type = type1;
|
||||
{
|
||||
if (TREE_CODE (op1) == ADDR_EXPR
|
||||
&& decl_with_nonnull_addr_p (TREE_OPERAND (op1, 0)))
|
||||
warning (OPT_Walways_true, "the address of %qD will never be NULL",
|
||||
TREE_OPERAND (op1, 0));
|
||||
result_type = type1;
|
||||
}
|
||||
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
|
||||
{
|
||||
result_type = type0;
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
2007-01-05 Ian Lance Taylor <iant@google.com>
|
||||
|
||||
* gcc.dg/Walways-true-1.c: New test.
|
||||
* gcc.dg/Walways-true-2.c: New test.
|
||||
* g++.dg/warn/Walways-true-1.C: New test.
|
||||
* g++.dg/warn/Walways-true-2.C: New test.
|
||||
|
||||
2007-01-05 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c/30360
|
||||
|
|
57
gcc/testsuite/g++.dg/warn/Walways-true-1.C
Normal file
57
gcc/testsuite/g++.dg/warn/Walways-true-1.C
Normal file
|
@ -0,0 +1,57 @@
|
|||
// Test -Walways-true for testing an address against NULL.
|
||||
// Origin: Ian Lance Taylor <iant@google.com>
|
||||
|
||||
// { dg-do compile}
|
||||
// { dg-options "-Walways-true" }
|
||||
|
||||
extern int foo (int);
|
||||
|
||||
int i;
|
||||
|
||||
void
|
||||
bar (int a)
|
||||
{
|
||||
lab:
|
||||
if (foo) // { dg-warning "always evaluate as" "correct warning" }
|
||||
foo (0);
|
||||
if (foo (1))
|
||||
;
|
||||
if (&i) // { dg-warning "always evaluate as" "correct warning" }
|
||||
foo (2);
|
||||
if (i)
|
||||
foo (3);
|
||||
if (&a) // { dg-warning "always evaluate as" "correct warning" }
|
||||
foo (4);
|
||||
if (a)
|
||||
foo (5);
|
||||
if (&&lab) // { dg-warning "always evaluate as" "correct warning" }
|
||||
foo (6);
|
||||
if (foo == 0) // { dg-warning "never be NULL" "correct warning" }
|
||||
foo (7);
|
||||
if (foo (1) == 0)
|
||||
foo (8);
|
||||
if (&i == 0) // { dg-warning "never be NULL" "correct warning" }
|
||||
foo (9);
|
||||
if (i == 0)
|
||||
foo (10);
|
||||
if (&a == 0) // { dg-warning "never be NULL" "correct warning" }
|
||||
foo (11);
|
||||
if (a == 0)
|
||||
foo (12);
|
||||
if (&&lab == 0) // { dg-warning "never be NULL" "correct warning" }
|
||||
foo (13);
|
||||
if (0 == foo) // { dg-warning "never be NULL" "correct warning" }
|
||||
foo (14);
|
||||
if (0 == foo (1))
|
||||
foo (15);
|
||||
if (0 == &i) // { dg-warning "never be NULL" "correct warning" }
|
||||
foo (16);
|
||||
if (0 == i)
|
||||
foo (17);
|
||||
if (0 == &a) // { dg-warning "never be NULL" "correct warning" }
|
||||
foo (18);
|
||||
if (0 == a)
|
||||
foo (19);
|
||||
if (0 == &&lab) // { dg-warning "never be NULL" "correct warning" }
|
||||
foo (20);
|
||||
}
|
60
gcc/testsuite/g++.dg/warn/Walways-true-2.C
Normal file
60
gcc/testsuite/g++.dg/warn/Walways-true-2.C
Normal file
|
@ -0,0 +1,60 @@
|
|||
// Make sure we don't assume that a weak symbol is always non-NULL.
|
||||
// This is just like Walways-true-1.C, except that it uses a weak
|
||||
// symbol.
|
||||
// Origin: Ian Lance Taylor <iant@google.com>
|
||||
|
||||
// { dg-do compile}
|
||||
// { dg-options "-Walways-true" }
|
||||
// { dg-require-weak "" }
|
||||
|
||||
extern int foo (int) __attribute__ ((weak));
|
||||
|
||||
int i __attribute__ ((weak));
|
||||
|
||||
void
|
||||
bar (int a)
|
||||
{
|
||||
lab:
|
||||
if (foo)
|
||||
foo (0);
|
||||
if (foo (1))
|
||||
;
|
||||
if (&i)
|
||||
foo (2);
|
||||
if (i)
|
||||
foo (3);
|
||||
if (&a) // { dg-warning "always evaluate as" "correct warning" }
|
||||
foo (4);
|
||||
if (a)
|
||||
foo (5);
|
||||
if (&&lab) // { dg-warning "always evaluate as" "correct warning" }
|
||||
foo (6);
|
||||
if (foo == 0)
|
||||
foo (7);
|
||||
if (foo (1) == 0)
|
||||
foo (8);
|
||||
if (&i == 0)
|
||||
foo (9);
|
||||
if (i == 0)
|
||||
foo (10);
|
||||
if (&a == 0) // { dg-warning "never be NULL" "correct warning" }
|
||||
foo (11);
|
||||
if (a == 0)
|
||||
foo (12);
|
||||
if (&&lab == 0) // { dg-warning "never be NULL" "correct warning" }
|
||||
foo (13);
|
||||
if (0 == foo)
|
||||
foo (14);
|
||||
if (0 == foo (1))
|
||||
foo (15);
|
||||
if (0 == &i)
|
||||
foo (16);
|
||||
if (0 == i)
|
||||
foo (17);
|
||||
if (0 == &a) // { dg-warning "never be NULL" "correct warning" }
|
||||
foo (18);
|
||||
if (0 == a)
|
||||
foo (19);
|
||||
if (0 == &&lab) // { dg-warning "never be NULL" "correct warning" }
|
||||
foo (20);
|
||||
}
|
57
gcc/testsuite/gcc.dg/Walways-true-1.c
Normal file
57
gcc/testsuite/gcc.dg/Walways-true-1.c
Normal file
|
@ -0,0 +1,57 @@
|
|||
/* Test -Walways-true for testing an address against NULL.
|
||||
Origin: Ian Lance Taylor <iant@google.com>. */
|
||||
|
||||
/* { dg-do compile} */
|
||||
/* { dg-options "-Walways-true" } */
|
||||
|
||||
extern int foo (int);
|
||||
|
||||
int i;
|
||||
|
||||
void
|
||||
bar (int a)
|
||||
{
|
||||
lab:
|
||||
if (foo) /* { dg-warning "always evaluate as" "correct warning" } */
|
||||
foo (0);
|
||||
if (foo (1))
|
||||
;
|
||||
if (&i) /* { dg-warning "always evaluate as" "correct warning" } */
|
||||
foo (2);
|
||||
if (i)
|
||||
foo (3);
|
||||
if (&a) /* { dg-warning "always evaluate as" "correct warning" } */
|
||||
foo (4);
|
||||
if (a)
|
||||
foo (5);
|
||||
if (&&lab) /* { dg-warning "always evaluate as" "correct warning" } */
|
||||
foo (6);
|
||||
if (foo == 0) /* { dg-warning "never be NULL" "correct warning" } */
|
||||
foo (7);
|
||||
if (foo (1) == 0)
|
||||
foo (8);
|
||||
if (&i == 0) /* { dg-warning "never be NULL" "correct warning" } */
|
||||
foo (9);
|
||||
if (i == 0)
|
||||
foo (10);
|
||||
if (&a == 0) /* { dg-warning "never be NULL" "correct warning" } */
|
||||
foo (11);
|
||||
if (a == 0)
|
||||
foo (12);
|
||||
if (&&lab == 0) /* { dg-warning "never be NULL" "correct warning" } */
|
||||
foo (13);
|
||||
if (0 == foo) /* { dg-warning "never be NULL" "correct warning" } */
|
||||
foo (14);
|
||||
if (0 == foo (1))
|
||||
foo (15);
|
||||
if (0 == &i) /* { dg-warning "never be NULL" "correct warning" } */
|
||||
foo (16);
|
||||
if (0 == i)
|
||||
foo (17);
|
||||
if (0 == &a) /* { dg-warning "never be NULL" "correct warning" } */
|
||||
foo (18);
|
||||
if (0 == a)
|
||||
foo (19);
|
||||
if (0 == &&lab) /* { dg-warning "never be NULL" "correct warning" } */
|
||||
foo (20);
|
||||
}
|
60
gcc/testsuite/gcc.dg/Walways-true-2.c
Normal file
60
gcc/testsuite/gcc.dg/Walways-true-2.c
Normal file
|
@ -0,0 +1,60 @@
|
|||
/* Make sure we don't assume that a weak symbol is always non-NULL.
|
||||
This is just like Walways-true-1.C, except that it uses a weak
|
||||
symbol.
|
||||
Origin: Ian Lance Taylor <iant@google.com>. */
|
||||
|
||||
/* { dg-do compile} */
|
||||
/* { dg-options "-Walways-true" } */
|
||||
/* { dg-require-weak "" } */
|
||||
|
||||
extern int foo (int) __attribute__ ((weak));
|
||||
|
||||
int i __attribute__ ((weak));
|
||||
|
||||
void
|
||||
bar (int a)
|
||||
{
|
||||
lab:
|
||||
if (foo)
|
||||
foo (0);
|
||||
if (foo (1))
|
||||
;
|
||||
if (&i)
|
||||
foo (2);
|
||||
if (i)
|
||||
foo (3);
|
||||
if (&a) /* { dg-warning "always evaluate as" "correct warning" } */
|
||||
foo (4);
|
||||
if (a)
|
||||
foo (5);
|
||||
if (&&lab) /* { dg-warning "always evaluate as" "correct warning" } */
|
||||
foo (6);
|
||||
if (foo == 0)
|
||||
foo (7);
|
||||
if (foo (1) == 0)
|
||||
foo (8);
|
||||
if (&i == 0)
|
||||
foo (9);
|
||||
if (i == 0)
|
||||
foo (10);
|
||||
if (&a == 0) /* { dg-warning "never be NULL" "correct warning" } */
|
||||
foo (11);
|
||||
if (a == 0)
|
||||
foo (12);
|
||||
if (&&lab == 0) /* { dg-warning "never be NULL" "correct warning" } */
|
||||
foo (13);
|
||||
if (0 == foo)
|
||||
foo (14);
|
||||
if (0 == foo (1))
|
||||
foo (15);
|
||||
if (0 == &i)
|
||||
foo (16);
|
||||
if (0 == i)
|
||||
foo (17);
|
||||
if (0 == &a) /* { dg-warning "never be NULL" "correct warning" } */
|
||||
foo (18);
|
||||
if (0 == a)
|
||||
foo (19);
|
||||
if (0 == &&lab) /* { dg-warning "never be NULL" "correct warning" } */
|
||||
foo (20);
|
||||
}
|
Loading…
Add table
Reference in a new issue