c-common.c (decl_with_nonnull_addr_p): New function.
authorIan Lance Taylor <iant@google.com>
Fri, 5 Jan 2007 19:05:46 +0000 (19:05 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Fri, 5 Jan 2007 19:05:46 +0000 (19:05 +0000)
./: * 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

gcc/ChangeLog
gcc/c-common.c
gcc/c-common.h
gcc/c-typeck.c
gcc/cp/ChangeLog
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/warn/Walways-true-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/Walways-true-2.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/Walways-true-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Walways-true-2.c [new file with mode: 0644]

index c894c72..9292512 100644 (file)
@@ -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
index 2fd2a81..1794bd8 100644 (file)
@@ -2591,6 +2591,18 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
   return fold_build2 (resultcode, result_type, ptrop, intop);
 }
 \f
+/* 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,
index b2b10bd..86b4487 100644 (file)
@@ -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);
index 955bfd9..28d023d 100644 (file)
@@ -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;
index 79dce74..1f7945d 100644 (file)
@@ -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
index 6c05b9f..061241d 100644 (file)
@@ -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;
index 4636099..8856b7e 100644 (file)
@@ -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
diff --git a/gcc/testsuite/g++.dg/warn/Walways-true-1.C b/gcc/testsuite/g++.dg/warn/Walways-true-1.C
new file mode 100644 (file)
index 0000000..5102ca1
--- /dev/null
@@ -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);
+}
diff --git a/gcc/testsuite/g++.dg/warn/Walways-true-2.C b/gcc/testsuite/g++.dg/warn/Walways-true-2.C
new file mode 100644 (file)
index 0000000..5408566
--- /dev/null
@@ -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);
+}
diff --git a/gcc/testsuite/gcc.dg/Walways-true-1.c b/gcc/testsuite/gcc.dg/Walways-true-1.c
new file mode 100644 (file)
index 0000000..f531e8f
--- /dev/null
@@ -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);
+}
diff --git a/gcc/testsuite/gcc.dg/Walways-true-2.c b/gcc/testsuite/gcc.dg/Walways-true-2.c
new file mode 100644 (file)
index 0000000..cab897b
--- /dev/null
@@ -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);
+}