[TCWG CI] Regression caused by gcc: Enhance -Waddress to detect more suspicious 
expressions [PR102103].:
commit 4dc7ce6fb3917958d1a6036d8acf2953b9c1b868
Author: Martin Sebor <mse...@redhat.com>

    Enhance -Waddress to detect more suspicious expressions [PR102103].

Results regressed to
# reset_artifacts:
-10
# build_abe binutils:
-9
# build_abe stage1:
-5
# build_abe qemu:
-2
# linux_n_obj:
21397
# First few build errors in logs:
# 00:02:12 sound/core/oss/mixer_oss.c:1035:21: error: ‘slot’ is used 
uninitialized [-Werror=uninitialized]
# 00:02:15 make[3]: *** [scripts/Makefile.build:288: 
sound/core/oss/mixer_oss.o] Error 1
# 00:02:15 sound/core/oss/pcm_oss.c:108:29: error: ‘t’ is used uninitialized 
[-Werror=uninitialized]
# 00:02:15 sound/core/oss/pcm_oss.c:2475:34: error: ‘setup’ is used 
uninitialized [-Werror=uninitialized]
# 00:02:15 sound/core/oss/pcm_oss.c:2985:51: error: ‘template’ is used 
uninitialized [-Werror=uninitialized]
# 00:02:15 sound/core/seq/oss/seq_oss_init.c:350:35: error: ‘qinfo’ is used 
uninitialized [-Werror=uninitialized]
# 00:02:15 sound/core/seq/oss/seq_oss_init.c:370:35: error: ‘qinfo’ is used 
uninitialized [-Werror=uninitialized]
# 00:02:16 make[4]: *** [scripts/Makefile.build:288: 
sound/core/seq/oss/seq_oss_init.o] Error 1
# 00:02:22 make[3]: *** [scripts/Makefile.build:288: sound/core/oss/pcm_oss.o] 
Error 1
# 00:02:28 make[3]: *** [scripts/Makefile.build:571: sound/core/seq/oss] Error 2

from
# reset_artifacts:
-10
# build_abe binutils:
-9
# build_abe stage1:
-5
# build_abe qemu:
-2
# linux_n_obj:
21403

THIS IS THE END OF INTERESTING STUFF.  BELOW ARE LINKS TO BUILDS, REPRODUCTION 
INSTRUCTIONS, AND THE RAW COMMIT.

This commit has regressed these CI configurations:
 - tcwg_kernel/gnu-master-aarch64-next-allmodconfig

First_bad build: 
https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-master-aarch64-next-allmodconfig/27/artifact/artifacts/build-4dc7ce6fb3917958d1a6036d8acf2953b9c1b868/
Last_good build: 
https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-master-aarch64-next-allmodconfig/27/artifact/artifacts/build-f1710910087fb1f4a7706e9ce838163ffcbc50b4/
Baseline build: 
https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-master-aarch64-next-allmodconfig/27/artifact/artifacts/build-baseline/
Even more details: 
https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-master-aarch64-next-allmodconfig/27/artifact/artifacts/

Reproduce builds:
<cut>
mkdir investigate-gcc-4dc7ce6fb3917958d1a6036d8acf2953b9c1b868
cd investigate-gcc-4dc7ce6fb3917958d1a6036d8acf2953b9c1b868

# Fetch scripts
git clone https://git.linaro.org/toolchain/jenkins-scripts

# Fetch manifests and test.sh script
mkdir -p artifacts/manifests
curl -o artifacts/manifests/build-baseline.sh 
https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-master-aarch64-next-allmodconfig/27/artifact/artifacts/manifests/build-baseline.sh
 --fail
curl -o artifacts/manifests/build-parameters.sh 
https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-master-aarch64-next-allmodconfig/27/artifact/artifacts/manifests/build-parameters.sh
 --fail
curl -o artifacts/test.sh 
https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-master-aarch64-next-allmodconfig/27/artifact/artifacts/test.sh
 --fail
chmod +x artifacts/test.sh

# Reproduce the baseline build (build all pre-requisites)
./jenkins-scripts/tcwg_kernel-build.sh @@ artifacts/manifests/build-baseline.sh

# Save baseline build state (which is then restored in artifacts/test.sh)
mkdir -p ./bisect
rsync -a --del --delete-excluded --exclude /bisect/ --exclude /artifacts/ 
--exclude /gcc/ ./ ./bisect/baseline/

cd gcc

# Reproduce first_bad build
git checkout --detach 4dc7ce6fb3917958d1a6036d8acf2953b9c1b868
../artifacts/test.sh

# Reproduce last_good build
git checkout --detach f1710910087fb1f4a7706e9ce838163ffcbc50b4
../artifacts/test.sh

cd ..
</cut>

Full commit (up to 1000 lines):
<cut>
commit 4dc7ce6fb3917958d1a6036d8acf2953b9c1b868
Author: Martin Sebor <mse...@redhat.com>
Date:   Fri Oct 1 11:50:25 2021 -0600

    Enhance -Waddress to detect more suspicious expressions [PR102103].
    
    Resolves:
    PR c/102103 - missing warning comparing array address to null
    
    gcc/ChangeLog:
    
            PR c/102103
            * doc/invoke.texi (-Waddress): Update.
            * gengtype.c (write_types): Avoid -Waddress.
            * poly-int.h (POLY_SET_COEFF): Avoid using null.
    
    gcc/c-family/ChangeLog:
    
            PR c/102103
            * c-common.c (decl_with_nonnull_addr_p): Handle members.
            Check and perform warning suppression.
            (c_common_truthvalue_conversion): Enhance warning suppression.
    
    gcc/c/ChangeLog:
    
            PR c/102103
            * c-typeck.c (maybe_warn_for_null_address): New function.
            (build_binary_op): Call it.
    
    gcc/cp/ChangeLog:
    
            PR c/102103
            * typeck.c (warn_for_null_address): Enhance.
            (cp_build_binary_op): Call it also for member pointers.
    
    gcc/fortran/ChangeLog:
    
            PR c/102103
            * array.c: Remove an unnecessary test.
            * trans-array.c: Same.
    
    gcc/testsuite/ChangeLog:
    
            PR c/102103
            * g++.dg/cpp0x/constexpr-array-ptr10.C: Suppress a valid warning.
            * g++.dg/warn/Wreturn-local-addr-6.C: Correct a cast.
            * gcc.dg/Waddress.c: Expect a warning.
            * c-c++-common/Waddress-3.c: New test.
            * c-c++-common/Waddress-4.c: New test.
            * g++.dg/warn/Waddress-5.C: New test.
            * g++.dg/warn/Waddress-6.C: New test.
            * g++.dg/warn/pr101219.C: Expect a warning.
            * gcc.dg/Waddress-3.c: New test.
---
 gcc/c-family/c-common.c                            |  29 +++--
 gcc/c/c-typeck.c                                   | 140 ++++++++++++++++-----
 gcc/cp/typeck.c                                    |  94 ++++++++++++--
 gcc/doc/invoke.texi                                |  48 +++++--
 gcc/fortran/array.c                                |   2 +-
 gcc/fortran/trans-array.c                          |   1 -
 gcc/gengtype.c                                     |   4 +-
 gcc/poly-int.h                                     |   4 +-
 gcc/testsuite/c-c++-common/Waddress-3.c            | 125 ++++++++++++++++++
 gcc/testsuite/c-c++-common/Waddress-4.c            | 106 ++++++++++++++++
 gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr10.C |   5 +-
 gcc/testsuite/g++.dg/warn/Waddress-5.C             | 115 +++++++++++++++++
 gcc/testsuite/g++.dg/warn/Waddress-6.C             |  79 ++++++++++++
 gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C   |   4 +-
 gcc/testsuite/g++.dg/warn/pr101219.C               |   4 +-
 gcc/testsuite/gcc.dg/Waddress-3.c                  |  35 ++++++
 gcc/testsuite/gcc.dg/Waddress.c                    |   2 +-
 17 files changed, 722 insertions(+), 75 deletions(-)

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 5845c675e85..9d19e352725 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -3393,14 +3393,16 @@ c_wrap_maybe_const (tree expr, bool non_const)
   return expr;
 }
 
-/* Return whether EXPR is a declaration whose address can never be
-   NULL.  */
+/* Return whether EXPR is a declaration whose address can never be NULL.
+   The address of the first struct member could be NULL only if it were
+   accessed through a NULL pointer, and such an access would be invalid.  */
 
 bool
 decl_with_nonnull_addr_p (const_tree expr)
 {
   return (DECL_P (expr)
-         && (TREE_CODE (expr) == PARM_DECL
+         && (TREE_CODE (expr) == FIELD_DECL
+             || TREE_CODE (expr) == PARM_DECL
              || TREE_CODE (expr) == LABEL_DECL
              || !DECL_WEAK (expr)));
 }
@@ -3488,13 +3490,17 @@ c_common_truthvalue_conversion (location_t location, 
tree expr)
     case ADDR_EXPR:
       {
        tree inner = TREE_OPERAND (expr, 0);
-       if (decl_with_nonnull_addr_p (inner))
+       if (decl_with_nonnull_addr_p (inner)
+           /* Check both EXPR and INNER for suppression.  */
+           && !warning_suppressed_p (expr, OPT_Waddress)
+           && !warning_suppressed_p (inner, OPT_Waddress))
          {
-           /* Common Ada programmer's mistake.  */
+           /* Common Ada programmer's mistake.  */
            warning_at (location,
                        OPT_Waddress,
                        "the address of %qD will always evaluate as %<true%>",
                        inner);
+           suppress_warning (inner, OPT_Waddress);
            return truthvalue_true_node;
          }
        break;
@@ -3627,8 +3633,17 @@ c_common_truthvalue_conversion (location_t location, 
tree expr)
          break;
        /* If this isn't narrowing the argument, we can ignore it.  */
        if (TYPE_PRECISION (totype) >= TYPE_PRECISION (fromtype))
-         return c_common_truthvalue_conversion (location,
-                                                TREE_OPERAND (expr, 0));
+         {
+           tree op0 = TREE_OPERAND (expr, 0);
+           if ((TREE_CODE (fromtype) == POINTER_TYPE
+                && TREE_CODE (totype) == INTEGER_TYPE)
+               || warning_suppressed_p (expr, OPT_Waddress))
+             /* Suppress -Waddress for casts to intptr_t, propagating
+                any suppression from the enclosing expression to its
+                operand.  */
+             suppress_warning (op0, OPT_Waddress);
+           return c_common_truthvalue_conversion (location, op0);
+         }
       }
       break;
 
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index c74f876e667..33963d7555a 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -11554,6 +11554,110 @@ build_vec_cmp (tree_code code, tree type,
   return build3 (VEC_COND_EXPR, type, cmp, minus_one_vec, zero_vec);
 }
 
+/* Possibly warn about an address of OP never being NULL in a comparison
+   operation CODE involving null.  */
+
+static void
+maybe_warn_for_null_address (location_t loc, tree op, tree_code code)
+{
+  if (!warn_address || warning_suppressed_p (op, OPT_Waddress))
+    return;
+
+  if (TREE_CODE (op) == NOP_EXPR)
+    {
+      /* Allow casts to intptr_t to suppress the warning.  */
+      tree type = TREE_TYPE (op);
+      if (TREE_CODE (type) == INTEGER_TYPE)
+       return;
+      op = TREE_OPERAND (op, 0);
+    }
+
+  if (TREE_CODE (op) == POINTER_PLUS_EXPR)
+    {
+      /* Allow a cast to void* to suppress the warning.  */
+      tree type = TREE_TYPE (TREE_TYPE (op));
+      if (VOID_TYPE_P (type))
+       return;
+
+      /* Adding any value to a null pointer, including zero, is undefined
+        in C.  This includes the expression &p[0] where p is the null
+        pointer, although &p[0] will have been folded to p by this point
+        and so not diagnosed.  */
+      if (code == EQ_EXPR)
+       warning_at (loc, OPT_Waddress,
+                   "the comparison will always evaluate as %<false%> "
+                   "for the pointer operand in %qE must not be NULL",
+                   op);
+      else
+       warning_at (loc, OPT_Waddress,
+                   "the comparison will always evaluate as %<true%> "
+                   "for the pointer operand in %qE must not be NULL",
+                   op);
+
+      return;
+    }
+
+  if (TREE_CODE (op) != ADDR_EXPR)
+    return;
+
+  op = TREE_OPERAND (op, 0);
+
+  if (TREE_CODE (op) == IMAGPART_EXPR
+      || TREE_CODE (op) == REALPART_EXPR)
+    {
+      /* The address of either complex part may not be null.  */
+      if (code == EQ_EXPR)
+       warning_at (loc, OPT_Waddress,
+                   "the comparison will always evaluate as %<false%> "
+                   "for the address of %qE will never be NULL",
+                   op);
+      else
+       warning_at (loc, OPT_Waddress,
+                   "the comparison will always evaluate as %<true%> "
+                   "for the address of %qE will never be NULL",
+                   op);
+      return;
+    }
+
+  /* Set to true in the loop below if OP dereferences is operand.
+     In such a case the ultimate target need not be a decl for
+     the null [in]equality test to be constant.  */
+  bool deref = false;
+
+  /* Get the outermost array or object, or member.  */
+  while (handled_component_p (op))
+    {
+      if (TREE_CODE (op) == COMPONENT_REF)
+       {
+         /* Get the member (its address is never null).  */
+         op = TREE_OPERAND (op, 1);
+         break;
+       }
+
+      /* Get the outer array/object to refer to in the warning.  */
+      op = TREE_OPERAND (op, 0);
+      deref = true;
+    }
+
+  if ((!deref && !decl_with_nonnull_addr_p (op))
+      || from_macro_expansion_at (loc))
+    return;
+
+  if (code == EQ_EXPR)
+    warning_at (loc, OPT_Waddress,
+               "the comparison will always evaluate as %<false%> "
+               "for the address of %qE will never be NULL",
+               op);
+  else
+    warning_at (loc, OPT_Waddress,
+               "the comparison will always evaluate as %<true%> "
+               "for the address of %qE will never be NULL",
+               op);
+
+  if (DECL_P (op))
+    inform (DECL_SOURCE_LOCATION (op), "%qD declared here", op);
+}
+
 /* Build a binary-operation expression without default conversions.
    CODE is the kind of expression to build.
    LOCATION is the operator's location.
@@ -12189,44 +12293,12 @@ build_binary_op (location_t location, enum tree_code 
code,
        short_compare = 1;
       else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
        {
-         if (TREE_CODE (op0) == ADDR_EXPR
-             && decl_with_nonnull_addr_p (TREE_OPERAND (op0, 0))
-             && !from_macro_expansion_at (location))
-           {
-             if (code == EQ_EXPR)
-               warning_at (location,
-                           OPT_Waddress,
-                           "the comparison will always evaluate as %<false%> "
-                           "for the address of %qD will never be NULL",
-                           TREE_OPERAND (op0, 0));
-             else
-               warning_at (location,
-                           OPT_Waddress,
-                           "the comparison will always evaluate as %<true%> "
-                           "for the address of %qD will never be NULL",
-                           TREE_OPERAND (op0, 0));
-           }
+         maybe_warn_for_null_address (location, op0, code);
          result_type = type0;
        }
       else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
        {
-         if (TREE_CODE (op1) == ADDR_EXPR
-             && decl_with_nonnull_addr_p (TREE_OPERAND (op1, 0))
-             && !from_macro_expansion_at (location))
-           {
-             if (code == EQ_EXPR)
-               warning_at (location,
-                           OPT_Waddress,
-                           "the comparison will always evaluate as %<false%> "
-                           "for the address of %qD will never be NULL",
-                           TREE_OPERAND (op1, 0));
-             else
-               warning_at (location,
-                           OPT_Waddress,
-                           "the comparison will always evaluate as %<true%> "
-                           "for the address of %qD will never be NULL",
-                           TREE_OPERAND (op1, 0));
-           }
+         maybe_warn_for_null_address (location, op1, code);
          result_type = type1;
        }
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index cd130f16a66..e880d34dcfe 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -4603,25 +4603,93 @@ warn_for_null_address (location_t location, tree op, 
tsubst_flags_t complain)
       || warning_suppressed_p (op, OPT_Waddress))
     return;
 
+  if (TREE_CODE (op) == NON_DEPENDENT_EXPR)
+    op = TREE_OPERAND (op, 0);
+
   tree cop = fold_for_warn (op);
 
-  if (TREE_CODE (cop) == ADDR_EXPR
-      && decl_with_nonnull_addr_p (TREE_OPERAND (cop, 0))
-      && !warning_suppressed_p (cop, OPT_Waddress))
-    warning_at (location, OPT_Waddress, "the address of %qD will never "
-               "be NULL", TREE_OPERAND (cop, 0));
+  if (TREE_CODE (cop) == NON_LVALUE_EXPR)
+    /* Unwrap the expression for C++ 98.  */
+    cop = TREE_OPERAND (cop, 0);
 
-  if (CONVERT_EXPR_P (op)
+  if (TREE_CODE (cop) == PTRMEM_CST)
+    {
+      /* The address of a nonstatic data member is never null.  */
+      warning_at (location, OPT_Waddress,
+                 "the address %qE will never be NULL",
+                 cop);
+      return;
+    }
+
+  if (TREE_CODE (cop) == NOP_EXPR)
+    {
+      /* Allow casts to intptr_t to suppress the warning.  */
+      tree type = TREE_TYPE (cop);
+      if (TREE_CODE (type) == INTEGER_TYPE)
+       return;
+
+      STRIP_NOPS (cop);
+    }
+
+  bool warned = false;
+  if (TREE_CODE (cop) == ADDR_EXPR)
+    {
+      cop = TREE_OPERAND (cop, 0);
+
+      /* Set to true in the loop below if OP dereferences its operand.
+        In such a case the ultimate target need not be a decl for
+        the null [in]equality test to be necessarily constant.  */
+      bool deref = false;
+
+      /* Get the outermost array or object, or member.  */
+      while (handled_component_p (cop))
+       {
+         if (TREE_CODE (cop) == COMPONENT_REF)
+           {
+             /* Get the member (its address is never null).  */
+             cop = TREE_OPERAND (cop, 1);
+             break;
+           }
+
+         /* Get the outer array/object to refer to in the warning.  */
+         cop = TREE_OPERAND (cop, 0);
+         deref = true;
+       }
+
+      if ((!deref && !decl_with_nonnull_addr_p (cop))
+         || from_macro_expansion_at (location)
+         || warning_suppressed_p (cop, OPT_Waddress))
+       return;
+
+      warned = warning_at (location, OPT_Waddress,
+                          "the address of %qD will never be NULL", cop);
+      op = cop;
+    }
+  else if (TREE_CODE (cop) == POINTER_PLUS_EXPR)
+    {
+      /* Adding zero to the null pointer is well-defined in C++.  When
+        the offset is unknown (i.e., not a constant) warn anyway since
+        it's less likely that the pointer operand is null than not.  */
+      tree off = TREE_OPERAND (cop, 1);
+      if (!integer_zerop (off)
+         && !warning_suppressed_p (cop, OPT_Waddress))
+       warning_at (location, OPT_Waddress, "comparing the result of pointer "
+                   "addition %qE and NULL", cop);
+      return;
+    }
+  else if (CONVERT_EXPR_P (op)
       && TYPE_REF_P (TREE_TYPE (TREE_OPERAND (op, 0))))
     {
-      tree inner_op = op;
-      STRIP_NOPS (inner_op);
+      STRIP_NOPS (op);
 
-      if (DECL_P (inner_op))
-       warning_at (location, OPT_Waddress,
-                   "the compiler can assume that the address of "
-                   "%qD will never be NULL", inner_op);
+      if (DECL_P (op))
+       warned = warning_at (location, OPT_Waddress,
+                            "the compiler can assume that the address of "
+                            "%qD will never be NULL", op);
     }
+
+  if (warned && DECL_P (op))
+    inform (DECL_SOURCE_LOCATION (op), "%qD declared here", op);
 }
 
 /* Warn about [expr.arith.conv]/2: If one operand is of enumeration type and
@@ -5411,6 +5479,8 @@ cp_build_binary_op (const op_location_t &location,
              op1 = cp_convert (TREE_TYPE (op0), op1, complain);
            }
          result_type = TREE_TYPE (op0);
+
+         warn_for_null_address (location, orig_op0, complain);
        }
       else if (TYPE_PTRMEMFUNC_P (type1) && null_ptr_cst_p (orig_op0))
        return cp_build_binary_op (location, code, op1, op0, complain);
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 5f39b208049..d35114c0727 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -8551,17 +8551,43 @@ by @option{-Wall}.
 @item -Waddress
 @opindex Waddress
 @opindex Wno-address
-Warn about suspicious uses of memory addresses. These include using
-the address of a function in a conditional expression, such as
-@code{void func(void); if (func)}, and comparisons against the memory
-address of a string literal, such as @code{if (x == "abc")}.  Such
-uses typically indicate a programmer error: the address of a function
-always evaluates to true, so their use in a conditional usually
-indicate that the programmer forgot the parentheses in a function
-call; and comparisons against string literals result in unspecified
-behavior and are not portable in C, so they usually indicate that the
-programmer intended to use @code{strcmp}.  This warning is enabled by
-@option{-Wall}.
+Warn about suspicious uses of address expressions. These include comparing
+the address of a function or a declared object to the null pointer constant
+such as in
+@smallexample
+void f (void);
+void g (void)
+@{
+  if (!func)   // warning: expression evaluates to false
+    abort ();
+@}
+@end smallexample
+comparisons of a pointer to a string literal, such as in
+@smallexample
+void f (const char *x)
+@{
+  if (x == "abc")   // warning: expression evaluates to false
+    puts ("equal");
+@}
+@end smallexample
+and tests of the results of pointer addition or subtraction for equality
+to null, such as in
+@smallexample
+void f (const int *p, int i)
+@{
+  return p + i == NULL;
+@}
+@end smallexample
+Such uses typically indicate a programmer error: the address of most
+functions and objects necessarily evaluates to true (the exception are
+weak symbols), so their use in a conditional might indicate missing
+parentheses in a function call or a missing dereference in an array
+expression.  The subset of the warning for object pointers can be
+suppressed by casting the pointer operand to an integer type such
+as @code{inptr_t} or @code{uinptr_t}.
+Comparisons against string literals result in unspecified behavior
+and are not portable, and suggest the intent was to call @code{strcmp}.
+@option{-Waddress} warning is enabled by @option{-Wall}.
 
 @item -Wno-address-of-packed-member
 @opindex Waddress-of-packed-member
diff --git a/gcc/fortran/array.c b/gcc/fortran/array.c
index a4d1cb4c72d..6552eaf3b0c 100644
--- a/gcc/fortran/array.c
+++ b/gcc/fortran/array.c
@@ -2581,7 +2581,7 @@ gfc_array_dimen_size (gfc_expr *array, int dimen, mpz_t 
*result)
            }
        }
 
-      if (array->shape && array->shape[dimen])
+      if (array->shape)
        {
          mpz_init_set (*result, array->shape[dimen]);
          return true;
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index b8061f37772..e2f59e0823c 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -5104,7 +5104,6 @@ set_loop_bounds (gfc_loopinfo *loop)
 
          if (info->shape)
            {
-             gcc_assert (info->shape[dim]);
              /* The frontend has worked out the size for us.  */
              if (!loopspec[n]
                  || !specinfo->shape
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index 31d4bf4e5d0..a77cfd92bfa 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -3685,8 +3685,8 @@ write_types (outf_p output_header, type_p structures,
        output_mangled_typename (output_header, s);
        oprintf (output_header, "(X) do { \\\n");
        oprintf (output_header,
-                "  if (X != NULL) gt_%sx_%s (X);\\\n", wtd->prefix,
-                s_id_for_tag);
+                "  if ((intptr_t)(X) != 0) gt_%sx_%s (X);\\\n",
+                wtd->prefix, s_id_for_tag);
        oprintf (output_header, "  } while (0)\n");
 
        for (opt = s->u.s.opt; opt; opt = opt->next)
diff --git a/gcc/poly-int.h b/gcc/poly-int.h
index f47f9e436a8..94e7b701f64 100644
--- a/gcc/poly-int.h
+++ b/gcc/poly-int.h
@@ -324,10 +324,10 @@ struct poly_result<T1, T2, 2>
    routine can take the address of RES rather than the address of
    a temporary.
 
-   The dummy comparison against a null C * is just a way of checking
+   The dummy self-comparison against C * is just a way of checking
    that C gives the right type.  */
 #define POLY_SET_COEFF(C, RES, I, VALUE) \
-  ((void) (&(RES).coeffs[0] == (C *) 0), \
+  ((void) (&(RES).coeffs[0] == (C *) (void *) &(RES).coeffs[0]), \
    wi::int_traits<C>::precision_type == wi::FLEXIBLE_PRECISION \
    ? (void) ((RES).coeffs[I] = VALUE) \
    : (void) ((RES).coeffs[I].~C (), new (&(RES).coeffs[I]) C (VALUE)))
diff --git a/gcc/testsuite/c-c++-common/Waddress-3.c 
b/gcc/testsuite/c-c++-common/Waddress-3.c
new file mode 100644
index 00000000000..9a13a444045
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Waddress-3.c
@@ -0,0 +1,125 @@
+/* PR c/102103 - missing warning comparing array address to null
+   { dg-do compile }
+   { dg-options "-Wall" } */
+
+typedef __INTPTR_TYPE__  intptr_t;
+typedef __UINTPTR_TYPE__ uintptr_t;
+
+#ifndef __cplusplus
+#  define bool _Bool
+#endif
+
+struct S { void *p, *a1[2], *a2[2][2]; } s, *p;
+
+extern const void *a1[2];
+extern void *a2[2][2], *ax[];
+
+void T (bool);
+
+void test_array_eq_0 (int i)
+{
+  // Verify that casts intptr_t suppress the warning.
+  T ((intptr_t)a1 == 0);
+  T ((uintptr_t)a1 == 0);
+  T (a1 == 0);          // { dg-warning "-Waddress" }
+  T (0 == &a1);         // { dg-warning "-Waddress" }
+  // Verify that casts to other pointer types don't suppress it.
+  T ((void *)a1 == 0);  // { dg-warning "-Waddress" }
+  T ((char *)a1 == 0);  // { dg-warning "-Waddress" }
+  T (a1[0] == 0);
+  T (0 == (intptr_t)&a1[0]);
+  T (0 == &a1[0]);      // { dg-warning "-Waddress" }
+  T (a1[i] == 0);
+  T (0 == (uintptr_t)&a1[i]);
+  T (0 == &a1[i]);      // { dg-warning "-Waddress" }
+
+  T ((intptr_t)a2 == 0);
+  T (a2 == 0);          // { dg-warning "-Waddress" }
+  T (0 == &a2);         // { dg-warning "-Waddress" }
+  T (a2[0] == 0);       // { dg-warning "-Waddress" }
+  T (0 == &a1[0]);      // { dg-warning "-Waddress" }
+  T (a2[i] == 0);       // { dg-warning "-Waddress" }
+  T (0 == &a2[i]);      // { dg-warning "-Waddress" }
+  T (a2[0][0] == 0);
+  T (0 == &a2[0][0]);   // { dg-warning "-Waddress" }
+  T (&ax == 0);         // { dg-warning "-Waddress" }
+  T (0 == &ax);         // { dg-warning "-Waddress" }
+  T (&ax[0] == 0);      // { dg-warning "-Waddress" }
+  T (0 == ax[0]);
+}
+
+
+void test_array_neq_0 (int i)
+{
+  // Verify that casts to intptr_t suppress the warning.
+  T ((uintptr_t)a1);
+
+  T (a1);               // { dg-warning "-Waddress" }
+  T ((void *)a1);       // { dg-warning "-Waddress" }
+  T (&a1 != 0);         // { dg-warning "-Waddress" }
+  T (a1[0]);
+  T (&a1[0] != 0);      // { dg-warning "-Waddress" }
+  T (a1[i]);
+  T (&a1[i] != 0);      // { dg-warning "-Waddress" }
+
+  T ((intptr_t)a2);
+  T (a2);               // { dg-warning "-Waddress" }
+  T ((void *)a2);       // { dg-warning "-Waddress" }
+  T ((char *)a2);       // { dg-warning "-Waddress" }
+  T (&a2 != 0);         // { dg-warning "-Waddress" }
+  T (a2[0]);            // { dg-warning "-Waddress" }
+  T (&a1[0] != 0);      // { dg-warning "-Waddress" }
+  T (a2[i]);            // { dg-warning "-Waddress" }
+  T (&a2[i] != 0);      // { dg-warning "-Waddress" }
+  T (a2[0][0]);
+  T (&a2[0][0] != 0);   // { dg-warning "-Waddress" }
+}
+
+
+void test_member_array_eq_0 (int i)
+{
+  // Verify that casts to intptr_t suppress the warning.
+  T ((intptr_t)s.a1 == 0);
+  T (s.a1 == 0);        // { dg-warning "-Waddress" }
+  T (0 == &a1);         // { dg-warning "-Waddress" }
+  T (s.a1[0] == 0);
+  T ((void*)s.a1);      // { dg-warning "-Waddress" }
+  T (0 == &a1[0]);      // { dg-warning "-Waddress" }
+  T (s.a1[i] == 0);
+  T (0 == &a1[i]);      // { dg-warning "-Waddress" }
+
+  T ((uintptr_t)s.a2 == 0);
+  T (s.a2 == 0);        // { dg-warning "-Waddress" }
+  T (0 == &a2);         // { dg-warning "-Waddress" }
+  T ((void *)s.a2 == 0);// { dg-warning "-Waddress" }
+  T (s.a2[0] == 0);     // { dg-warning "-Waddress" }
+  T (0 == &a1[0]);      // { dg-warning "-Waddress" }
+  T (s.a2[i] == 0);     // { dg-warning "-Waddress" }
+  T (0 == &a2[i]);      // { dg-warning "-Waddress" }
+  T (s.a2[0][0] == 0);
+  T (0 == &a2[0][0]); // { dg-warning "-Waddress" }
+}
+
+
+void test_member_array_neq_0 (int i)
+{
+  // Verify that casts to intptr_t suppress the warning.
+  T ((uintptr_t)s.a1);
+  T (s.a1);             // { dg-warning "-Waddress" }
+  T (&s.a1 != 0);       // { dg-warning "-Waddress" }
+  T ((void *)&s.a1[0]); // { dg-warning "-Waddress" }
+  T (s.a1[0]);
+  T (&s.a1[0] != 0);    // { dg-warning "-Waddress" }
+  T (s.a1[i]);
+  T (&s.a1[i] != 0);    // { dg-warning "-Waddress" }
+
+  T ((intptr_t)s.a2);
+  T (s.a2);             // { dg-warning "-Waddress" }
+  T (&s.a2 != 0);       // { dg-warning "-Waddress" }
+  T (s.a2[0]);          // { dg-warning "-Waddress" }
+  T (&s.a1[0] != 0);    // { dg-warning "-Waddress" }
+  T (s.a2[i]);          // { dg-warning "-Waddress" }
+  T (&s.a2[i] != 0);    // { dg-warning "-Waddress" }
+  T (s.a2[0][0]);
+  T (&s.a2[0][0] != 0); // { dg-warning "-Waddress" }
+}
diff --git a/gcc/testsuite/c-c++-common/Waddress-4.c 
b/gcc/testsuite/c-c++-common/Waddress-4.c
new file mode 100644
index 00000000000..489a0cd717c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Waddress-4.c
@@ -0,0 +1,106 @@
+/* PR c/102103 - missing warning comparing array address to null
+   { dg-do compile }
+   { dg-options "-Wall" } */
+
+typedef __INTPTR_TYPE__ intptr_t;
+typedef __INTPTR_TYPE__ uintptr_t;
+
+extern char *ax[], *a2[][2];
+
+void T (int);
+
+void test_ax_plus_eq_0 (int i)
+{
+  // Verify that casts to intptr_t suppress the warning.
+  T ((intptr_t)(ax + 0) == 0);
+  T ((uintptr_t)(ax + 1) == 0);
+
+  T (ax + 0 == 0);      // { dg-warning "-Waddress" }
+  T (&ax[0] == 0);      // { dg-warning "-Waddress" }
+  T (ax - 1 == 0);      // { dg-warning "-Waddress" }
+  T (0 == &ax[-1]);     // { dg-warning "-Waddress" }
+  T ((void *)(&ax[0] + 2) == 0);  // { dg-warning "-Waddress" }
+  T (&ax[0] + 2 == 0);  // { dg-warning "-Waddress" }
+  T (ax + 3 == 0);      // { dg-warning "-Waddress" }
+  T (0 == &ax[-4]);     // { dg-warning "-Waddress" }
+  T (ax - i == 0);      // { dg-warning "-Waddress" }
+  T (&ax[i] == 0);      // { dg-warning "-Waddress" }
+  T (0 == &ax[1] + i);  // { dg-warning "-Waddress" }
+}
+
+void test_a2_plus_eq_0 (int i)
+{
+  // Verify that casts to intptr_t suppress the warning.
+  T ((intptr_t)(a2 + 0) == 0);
+  T ((uintptr_t)(a2 + 1) == 0);
+
+  T (a2 + 0 == 0);      // { dg-warning "-Waddress" }
+  // Verify that a cast to another pointer type doesn't suppress it.
+  T ((void*)(a2 + 0) == 0);       // { dg-warning "-Waddress" }
+  T ((char*)a2 + 1 == 0);         // { dg-warning "-Waddress" }
+  T (&a2[0] == 0);      // { dg-warning "-Waddress" }
+  T (a2 - 1 == 0);      // { dg-warning "-Waddress" }
+  T (0 == &a2[-1]);     // { dg-warning "-Waddress" }
+  T (a2 + 2 == 0);      // { dg-warning "-Waddress" }
+  T (0 == &a2[-2]);     // { dg-warning "-Waddress" }
+  T (a2 - i == 0);      // { dg-warning "-Waddress" }
+  T (&a2[i] == 0);      // { dg-warning "-Waddress" }
+}
+
+// Exercise a pointer.
+void test_p_plus_eq_0 (int *p, int i)
+{
+  /* P + 0 and equivalently &P[0] are invalid for a null P but they're
+     folded to p before the warning has a chance to trigger.  */
+  T (p + 0 == 0);       // { dg-warning "-Waddress" "pr102555" { xfail *-*-* } 
}
+  T (&p[0] == 0);       // { dg-warning "-Waddress" "pr102555" { xfail *-*-* } 
}
+
+  T (p - 1 == 0);       // { dg-warning "-Waddress" }
+  T (0 == &p[-1]);      // { dg-warning "-Waddress" }
+  T (p + 2 == 0);       // { dg-warning "-Waddress" }
+  T (0 == &p[-2]);      // { dg-warning "-Waddress" }
+  T (p - i == 0);       // { dg-warning "-Waddress" }
+  T (&p[i] == 0);       // { dg-warning "-Waddress" }
+}
+
+// Exercise pointer to array.
+void test_pa_plus_eq_0 (int (*p)[], int (*p2)[][2], int i)
+{
+  // The array pointer may be null.
+  T (*p == 0);
+  /* &**P is equivalent to *P and might be the result od macro expansion.
+     Verify it doesn't cause a warning.  */
+  T (&**p == 0);
+
+  /* *P + 0 is invalid but folded to *P before the warning has a chance
+     to trigger.  */
+  T (*p + 0 == 0);      // { dg-warning "-Waddress" "pr102555" { xfail *-*-* } 
}
+
+  T (&(*p)[0] == 0);    // { dg-warning "-Waddress" }
+  T (*p - 1 == 0);      // { dg-warning "-Waddress" }
+  T (0 == &(*p)[-1]);   // { dg-warning "-Waddress" }
+  T (*p + 2 == 0);      // { dg-warning "-Waddress" }
+  T (0 == &(*p)[-2]);   // { dg-warning "-Waddress" }
+  T (*p - i == 0);      // { dg-warning "-Waddress" }
+  T (&(*p)[i] == 0);    // { dg-warning "-Waddress" }
+
+
+  /* Similar to the above but for a pointer to a two-dimensional array,
+     referring to the higher-level element (i.e., an array itself).  */
+  T (*p2 == 0);
+  T (**p2 == 0);         // { dg-warning "-Waddress" "pr102555" { xfail *-*-* 
} }
+  T (&**p2 == 0);        // { dg-warning "-Waddress" "pr102555" { xfail *-*-* 
} }
+  T (&***p2 == 0);       // { dg-warning "-Waddress" "pr102555" { xfail *-*-* 
} }
+  T (&**p2 == 0);
+
+  T (*p2 + 0 == 0);      // { dg-warning "-Waddress" "pr102555" { xfail *-*-* 
} }
+  T (&(*p2)[0] == 0);    // { dg-warning "-Waddress" }
+  T (&(*p2)[0][1] == 0); // { dg-warning "-Waddress" }
+  T (*p2 - 1 == 0);      // { dg-warning "-Waddress" }
+  T (0 == &(*p2)[-1]);   // { dg-warning "-Waddress" }
+  T (0 == &(*p2)[1][2]); // { dg-warning "-Waddress" }
+  T (*p2 + 2 == 0);      // { dg-warning "-Waddress" }
+  T (0 == &(*p2)[-2]);   // { dg-warning "-Waddress" }
+  T (*p2 - i == 0);      // { dg-warning "-Waddress" }
+  T (&(*p2)[i] == 0);    // { dg-warning "-Waddress" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr10.C 
b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr10.C
index 5224bb14234..63295230d51 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr10.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr10.C
@@ -85,8 +85,11 @@ extern __attribute__ ((weak)) int i;
 constexpr int *p1 = &i + 1;
 
 #pragma GCC diagnostic push
+// Suppress warning: ordered comparison of pointer with integer zero.
 #pragma GCC diagnostic ignored "-Wextra"
-// Suppress warning: ordered comparison of pointer with integer zero
+// Also suppress -Waddress for comparisons of constant addresses to
+// to null.
+#pragma GCC diagnostic ignored "-Waddress"
 
 constexpr bool b0  = p1;        // { dg-error "not a constant expression" }
 constexpr bool b1  = p1 == 0;   // { dg-error "not a constant expression" }
diff --git a/gcc/testsuite/g++.dg/warn/Waddress-5.C 
b/gcc/testsuite/g++.dg/warn/Waddress-5.C
new file mode 100644
index 00000000000..b1ad38a8112
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Waddress-5.C
@@ -0,0 +1,115 @@
+/* PR c/102103 - missing warning comparing array address to null
+   { dg-do compile }
+   { dg-options "-Wall" } */
+
+#if __cplusplus < 201103L
+# define nullptr __null
+#endif
+
+struct A
+{
+  void f ();
+  virtual void vf ();
+  virtual void pvf () = 0;
+
+  void sf ();
+
+  int *p;
+  int a[2];
+};
+
+void T (bool);
+
+void warn_memptr_if ()
+{
+  // Exercise warnings for addresses of nonstatic member functions.
+  if (&A::f == 0)         // { dg-warning "the address '&A::f'" }
+    T (0);
+
+  if (&A::vf)             // { dg-warning "-Waddress" }
+    T (0);
+
+  if (&A::pvf != 0)       // { dg-warning "-Waddress" }
+    T (0);
+
+  // Exercise warnings for addresses of static member functions.
+  if (&A::sf == 0)        // { dg-warning "-Waddress" }
+    T (0);
+
+  if (&A::sf)             // { dg-warning "-Waddress" }
+    T (0);
+
+  // Exercise warnings for addresses of nonstatic data members.
+  if (&A::p == 0)         // { dg-warning "the address '&A::p'" }
+    T (0);
+
+  if (&A::a == nullptr)   // { dg-warning "-Waddress" }
+    T (0);
+}
+
+void warn_memptr_bool ()
+{
+  // Exercise warnings for addresses of nonstatic member functions.
+  T (&A::f == 0);         // { dg-warning "-Waddress" }
+  T (&A::vf);             // { dg-warning "-Waddress" }
+  T (&A::pvf != 0);       // { dg-warning "-Waddress" }
+
+  // Exercise warnings for addresses of static member functions.
+  T (&A::sf == 0);        // { dg-warning "-Waddress" }
+  T (&A::sf);             // { dg-warning "-Waddress" }
+
+  // Exercise warnings for addresses of nonstatic data members.
+  T (&A::p == 0);         // { dg-warning "-Waddress" }
+  T (&A::a == nullptr);   // { dg-warning "-Waddress" }
+}
+
+
+/* Verify that no warnings are issued for a dependent expression in
+   a template.  */
+
+template <int>
+struct B
+{
+  // This is why.
+  struct F { void* operator& () const { return 0; } } f;
+};
+
+template <class Type, int N>
+void nowarn_dependent (Type targ)
+{
+  T (&Type::x == 0);
+  T (&targ == 0);
+
+  Type tarr[1];
+  T (&tarr[0] == nullptr);
+
+  T (&B<N>::f == 0);
+
+  /* Like in the case above, the address-of operator could be a member
+     of B<N>::vf that returns zero.  */
+  T (&B<N>::vf);
+  T (&B<N>::pvf != 0);
+  T (&B<N>::p == 0);
+  T (&B<N>::a == 0);
+}
+
+
+/* Verify that in an uninstantiated template warnings are not issued
+   for dependent expressions but are issued otherwise.  */
+
+template <class Type>
+void warn_non_dependent (Type targ, Type *tptr, int i)
+{
+  /* The address of a pointer to a dependent type cannot be null but
+     the warning doesn't have a chance to see it.  */
+  T (&tptr == 0);       // { dg-warning "-Waddress" "pr102378" { xfail *-*-* } 
}
+  T (&i == 0);          // { dg-warning "-Waddress" }
+
+  int iarr[1];
+  T (&iarr == 0);       // { dg-warning "-Waddress" }
+  T (&*iarr != 0);      // { dg-warning "-Waddress" "pr102378" { xfail *-*-* } 
}
+  T (&iarr[0] == 0);    // { dg-warning "-Waddress" }
+
+  Type tarr[1];
+  T (&tarr == nullptr);   // { dg-warning "-Waddress" "pr102378" { xfail *-*-* 
} }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Waddress-6.C 
b/gcc/testsuite/g++.dg/warn/Waddress-6.C
new file mode 100644
index 00000000000..c22a83a0dd7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Waddress-6.C
@@ -0,0 +1,79 @@
+/* PR c/102103 - missing warning comparing array address to null
+   { dg-do compile }
+   Verify -Waddress for member arrays of structs and notes.
+   { dg-options "-Wall" } */
+
+#if __cplusplus < 201103L
+# define nullptr __null
+#endif
+
+void T (bool);
+
+struct A
+{
+  int n;
+  int ia[];                   // { dg-message "'A::ia' declared here" }
+};
+
+struct B
+{
+  A a[3];                     // { dg-message "'B::a' declared here" }
+};
+
+struct C
+{
+  B b[3];                     // { dg-message "'C::b' declared here" }
+};
+
+struct D
+{
+  C c[3];                     // { dg-message "'D::c' declared here" }
+};
+
+
+void test_waddress_1d ()
+{
+  D d[2];                     // { dg-message "'d' declared here" }
+
+  T (d);                      // { dg-warning "address of 'd'" }
+  T (d == nullptr);           // { dg-warning "address of 'd'" }
+  T (&d);                     // { dg-warning "address of 'd'" }
+  T (d->c);                   // { dg-warning "address of 'D::c'" }
+  T (d->c != nullptr);        // { dg-warning "address of 'D::c'" }
+  T (d->c->b);                // { dg-warning "address of 'C::b'" }
+  T (d->c[1].b->a);           // { dg-warning "address of 'B::a'" }
+  T (d->c->b[2].a->ia);       // { dg-warning "address of 'A::ia'" }
+
+  if (d->c->b[2].a[1].ia)     // { dg-warning "address of 'A::ia'" }
+    T (0);
+
+  if (bool b = d->c->b[1].a)  // { dg-warning "address of 'B::a'" }
+    T (b);
+
+  /* The following is represented as a declaration of P followed
+     by an if statement and so it isn't diagnosed.  It's not clear
+     that it should be since the pointer is then used.
+       void *p = d->c->b[2].a;
+       if (p) ...
+  */
+  if (void *p = d->c->b[2].a) // { dg-warning "address of 'A::ia'" "" { xfail 
*-*-* } }
+    T (p);
+}
+
+
+void test_waddress_2d (int i)
+{
+  D d[2][3];                  // { dg-message "'d' declared here" }
+
+  T (d);                      // { dg-warning "address of 'd'" }
+  T (d == nullptr);           // { dg-warning "address of 'd'" }
+  T (&d);                     // { dg-warning "address of 'd'" }
+  T (*d);                     // { dg-warning "address of 'd'" }
+  T (d[1] != nullptr);        // { dg-warning "address of 'd'" }
+  T (&d[1]->c);               // { dg-warning "address of 'D::c'" }
+  T (d[1]->c);                // { dg-warning "address of 'D::c'" }
+  T (d[1]->c == nullptr);     // { dg-warning "address of 'D::c'" }
+  T (d[i]->c[1].b);           // { dg-warning "address of 'C::b'" }
+  T ((*(d + i))->c->b->a);    // { dg-warning "address of 'B::a'" }
+  T (d[1][2].c->b->a->ia);    // { dg-warning "address of 'A::ia'" }
+}
</cut>
_______________________________________________
linaro-toolchain mailing list
linaro-toolchain@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/linaro-toolchain

Reply via email to