analyzer: prevent ICE on isnan (PR 93290)
authorDavid Malcolm <dmalcolm@redhat.com>
Thu, 16 Jan 2020 14:46:30 +0000 (09:46 -0500)
committerDavid Malcolm <dmalcolm@redhat.com>
Fri, 17 Jan 2020 21:41:34 +0000 (16:41 -0500)
PR analyzer/93290 reports an ICE on calls to isnan().
The root cause is that an UNORDERED_EXPR is passed
to region_model::eval_condition_without_cm, and there's
a stray gcc_unreachable () in the case where we're comparing
an svalue against itself.

I attempted a more involved patch that properly handled NaN in general
but it seems I've baked the assumption of reflexivity too deeply into
the constraint_manager code.

For now, this patch avoids the ICE and documents the limitation.

gcc/analyzer/ChangeLog:
PR analyzer/93290
* region-model.cc (region_model::eval_condition_without_cm): Avoid
gcc_unreachable for unexpected operations for the case where
we're comparing an svalue against itself.

gcc/ChangeLog
* doc/analyzer.texi (Limitations): Add note about NaN.

gcc/testsuite/ChangeLog:
PR analyzer/93290
* gcc.dg/analyzer/pr93290.c: New test.

gcc/ChangeLog
gcc/analyzer/ChangeLog
gcc/analyzer/region-model.cc
gcc/doc/analyzer.texi
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/analyzer/pr93290.c [new file with mode: 0644]

index 7986c68e53353a0f4a76a8b7220f8a0ec274d8f0..d837e95509ad9cd615c3b82dbf6135527a1bea9f 100644 (file)
@@ -1,3 +1,7 @@
+2020-01-17  David Malcolm  <dmalcolm@redhat.com>
+
+       * doc/analyzer.texi (Limitations): Add note about NaN.
+
 2020-01-17  Mihail-Calin Ionescu <mihail.ionescu@arm.com>
            Sudakshina Das  <sudi.das@arm.com>
 
index e809018421650ae62ec2f34aeb2efdffad3a7bdb..3e6e21b27408c65c38fada2828304dcd994c0a97 100644 (file)
@@ -1,3 +1,10 @@
+2020-01-17  David Malcolm  <dmalcolm@redhat.com>
+
+       PR analyzer/93290
+       * region-model.cc (region_model::eval_condition_without_cm): Avoid
+       gcc_unreachable for unexpected operations for the case where
+       we're comparing an svalue against itself.
+
 2020-01-17  David Malcolm  <dmalcolm@redhat.com>
 
        PR analyzer/93281
index f67572e2d456974f12f408fcee005eb1e3ae4e36..1e0be312e03f0a079414cfc3bfc8fa7c95e27751 100644 (file)
@@ -5189,13 +5189,11 @@ region_model::eval_condition_without_cm (svalue_id lhs_sid,
     {
       if (lhs == rhs)
        {
-         /* If we have the same svalue, then we have equality.
+         /* If we have the same svalue, then we have equality
+            (apart from NaN-handling).
             TODO: should this definitely be the case for poisoned values?  */
          switch (op)
            {
-           default:
-             gcc_unreachable ();
-
            case EQ_EXPR:
            case GE_EXPR:
            case LE_EXPR:
@@ -5205,6 +5203,10 @@ region_model::eval_condition_without_cm (svalue_id lhs_sid,
            case GT_EXPR:
            case LT_EXPR:
              return tristate::TS_FALSE;
+
+           default:
+             /* For other ops, use the logic below.  */
+             break;
            }
        }
 
index b4e9b01da2efa4290bdd8f48746a58999d944ff9..81acdd8998bd805a631e65272ce707036eeb70aa 100644 (file)
@@ -388,6 +388,9 @@ The implementation of call summaries is currently very simplistic.
 @item
 Lack of function pointer analysis
 @item
+The constraint-handling code assumes reflexivity in some places
+(that values are equal to themselves), which is not the case for NaN.
+@item
 The region model code creates lots of little mutable objects at each
 @code{region_model} (and thus per @code{exploded_node}) rather than
 sharing immutable objects and having the mutable state in the
index d3a89a3ac72c79ab9c75ce41ccebbc36932af80b..95e4e344ee058913c55c73ad70cfab9e93447c60 100644 (file)
@@ -1,3 +1,8 @@
+2020-01-17  David Malcolm  <dmalcolm@redhat.com>
+
+       PR analyzer/93290
+       * gcc.dg/analyzer/pr93290.c: New test.
+
 2020-01-17  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/92542
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr93290.c b/gcc/testsuite/gcc.dg/analyzer/pr93290.c
new file mode 100644 (file)
index 0000000..fa35629
--- /dev/null
@@ -0,0 +1,9 @@
+#include <math.h>
+
+int test_1 (void)
+{
+  float foo = 42.;
+  if (isnan (foo))
+    return 1;
+  return 0;
+}