As outlined in the PR, this fixes one ICE.  The code in question here
tries to determine whether OP can be derived as non-NULL.  In case the
function has the nonnull attribute that applies to all the arguments,
we want to see whether OP is in this argument list.  But nonnull only
appertains to pointers.  Some ssa_names don't have a type so check for
that first instead of segv before looking at its tree code.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2015-08-14  Marek Polacek  <pola...@redhat.com>

        PR middle-end/67133
        * gimple.c (infer_nonnull_range_by_attribute): Handle null TREE_TYPE.

        * g++.dg/torture/pr67133.C: New test.

diff --git gcc/gimple.c gcc/gimple.c
index cca328a..1482eb4 100644
--- gcc/gimple.c
+++ gcc/gimple.c
@@ -2678,14 +2678,16 @@ infer_nonnull_range_by_attribute (gimple stmt, tree op)
          if (attrs == NULL_TREE)
            return false;
 
-         /* If "nonnull" applies to all the arguments, then ARG
+         /* If "nonnull" applies to all the arguments, then OP
             is non-null if it's in the argument list.  */
          if (TREE_VALUE (attrs) == NULL_TREE)
            {
              for (unsigned int i = 0; i < gimple_call_num_args (stmt); i++)
                {
-                 if (POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (stmt, i)))
-                     && operand_equal_p (op, gimple_call_arg (stmt, i), 0))
+                 tree arg = gimple_call_arg (stmt, i);
+                 if (TREE_TYPE (arg) != NULL_TREE
+                     && POINTER_TYPE_P (TREE_TYPE (arg))
+                     && operand_equal_p (op, arg, 0))
                    return true;
                }
              return false;
diff --git gcc/testsuite/g++.dg/torture/pr67133.C 
gcc/testsuite/g++.dg/torture/pr67133.C
index e69de29..0f23572 100644
--- gcc/testsuite/g++.dg/torture/pr67133.C
+++ gcc/testsuite/g++.dg/torture/pr67133.C
@@ -0,0 +1,46 @@
+// { dg-do compile }
+// { dg-additional-options "-fisolate-erroneous-paths-attribute" }
+
+class A;
+struct B {
+  typedef A type;
+};
+template <typename> struct I : B {};
+class C {
+public:
+  C(char *);
+  int size();
+};
+template <typename> struct D;
+template <typename _Tp, typename = D<_Tp>> class F {
+  class G {
+    template <typename> static _Tp *__test();
+    typedef int _Del;
+
+  public:
+    typedef decltype(__test<_Del>()) type;
+  };
+
+public:
+  typename I<_Tp>::type operator*() {
+    typename G::type a = 0;
+    return *a;
+  }
+};
+class H {
+  F<A> Out;
+  H();
+};
+void fn1(void *, void *, int) __attribute__((__nonnull__));
+class A {
+  int OutBufEnd, OutBufCur;
+
+public:
+  void operator<<(C p1) {
+    int b, c = p1.size();
+    if (OutBufEnd)
+      fn1(&OutBufCur, &b, c);
+  }
+};
+char* a;
+H::H() { *Out << a; }

        Marek

Reply via email to