diff mbox series

[committed] analyzer: const functions have no side effects [PR104576]

Message ID 20220217024333.1126644-1-dmalcolm@redhat.com
State New
Headers show
Series [committed] analyzer: const functions have no side effects [PR104576] | expand

Commit Message

David Malcolm Feb. 17, 2022, 2:43 a.m. UTC
PR analyzer/104576 tracks that we issue a false positive from
-Wanalyzer-use-of-uninitialized-value for the reproducers of PR 63311
when optimization is disabled.

The root cause is that the analyzer was considering that a call to
__builtin_sinf could have side-effects.

This patch fixes things by generalizing the handling for "pure"
functions to also consider "const" functions.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to trunk as r12-7270-g5fbcbcaff7248604e04b39464f4fbd64fbf6e43b.

gcc/analyzer/ChangeLog:
	PR analyzer/104576
	* region-model.cc: Include "calls.h".
	(region_model::on_call_pre): Use flags_from_decl_or_type to
	generalize check for DECL_PURE_P to also check for ECF_CONST.

gcc/testsuite/ChangeLog:
	PR analyzer/104576
	* gcc.dg/analyzer/torture/uninit-pr63311.c: New test.
	* gcc.dg/analyzer/uninit-pr104576.c: New test.
	* gfortran.dg/analyzer/uninit-pr63311.f90: New test.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/analyzer/region-model.cc                  |   6 +-
 .../gcc.dg/analyzer/torture/uninit-pr63311.c  | 134 ++++++++++++++++++
 .../gcc.dg/analyzer/uninit-pr104576.c         |  16 +++
 .../gfortran.dg/analyzer/uninit-pr63311.f90   |  39 +++++
 4 files changed, 193 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/torture/uninit-pr63311.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/uninit-pr104576.c
 create mode 100644 gcc/testsuite/gfortran.dg/analyzer/uninit-pr63311.f90
diff mbox series

Patch

diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index 69e8fa7d1e3..d4d7816e0d5 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -72,6 +72,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "tree-phinodes.h"
 #include "tree-ssa-operands.h"
 #include "ssa-iterators.h"
+#include "calls.h"
 
 #if ENABLE_ANALYZER
 
@@ -1271,13 +1272,14 @@  region_model::on_call_pre (const gcall *call, region_model_context *ctxt,
 	 in region-model-impl-calls.cc.
 	 Having them split out into separate functions makes it easier
 	 to put breakpoints on the handling of specific functions.  */
+      int callee_fndecl_flags = flags_from_decl_or_type (callee_fndecl);
 
       if (fndecl_built_in_p (callee_fndecl, BUILT_IN_NORMAL)
 	  && gimple_builtin_call_types_compatible_p (call, callee_fndecl))
 	switch (DECL_UNCHECKED_FUNCTION_CODE (callee_fndecl))
 	  {
 	  default:
-	    if (!DECL_PURE_P (callee_fndecl))
+	    if (!(callee_fndecl_flags & (ECF_CONST | ECF_PURE)))
 	      unknown_side_effects = true;
 	    break;
 	  case BUILT_IN_ALLOCA:
@@ -1433,7 +1435,7 @@  region_model::on_call_pre (const gcall *call, region_model_context *ctxt,
 	  /* Handle in "on_call_post".  */
 	}
       else if (!fndecl_has_gimple_body_p (callee_fndecl)
-	       && !DECL_PURE_P (callee_fndecl)
+	       && (!(callee_fndecl_flags & (ECF_CONST | ECF_PURE)))
 	       && !fndecl_built_in_p (callee_fndecl))
 	unknown_side_effects = true;
     }
diff --git a/gcc/testsuite/gcc.dg/analyzer/torture/uninit-pr63311.c b/gcc/testsuite/gcc.dg/analyzer/torture/uninit-pr63311.c
new file mode 100644
index 00000000000..a73289cb83f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/torture/uninit-pr63311.c
@@ -0,0 +1,134 @@ 
+/* { dg-additional-options "-Wno-analyzer-too-complex" } */
+
+int foo ()
+{
+  static volatile int v = 42;
+  int __result_foo;
+
+  __result_foo = (int) v;
+  return __result_foo;
+}
+
+void test (int * restrict n, int * restrict flag)
+{
+  int i;
+  int j;
+  int k;
+  double t;
+  int tt;
+  double v;
+
+  if (*flag)
+    {
+      t = 4.2e+1;
+      tt = foo ();
+    }
+  L_1: ;
+  v = 0.0;
+  {
+    int D_3353;
+
+    D_3353 = *n;
+    i = 1;
+    if (i <= D_3353)
+      {
+        while (1)
+          {
+            {
+              int D_3369;
+
+              v = 0.0;
+              if (*flag)
+                {
+                  if (tt == i)
+                    {
+                      {
+                        double M_0;
+
+                        M_0 = v;
+                        if (t > M_0 || (int) (M_0 != M_0))
+                          {
+                            M_0 = t;
+                          }
+                        v = M_0;
+                      }
+                    }
+                  L_5:;
+                }
+              L_4:;
+              {
+                int D_3359;
+
+                D_3359 = *n;
+                j = 1;
+                if (j <= D_3359)
+                  {
+                    while (1)
+                      {
+                        {
+                          int D_3368;
+
+                          {
+                            int D_3362;
+
+                            D_3362 = *n;
+                            k = 1;
+                            if (k <= D_3362)
+                              {
+                                while (1)
+                                  {
+                                    {
+                                      int D_3367;
+
+                                      {
+                                        double D_3366;
+                                        double M_1;
+
+                                        M_1 = v;
+                                        D_3366 = (double) __builtin_sinf ((float) (j * k));
+                                        if (D_3366 > M_1 || (int) (M_1 != M_1))
+                                          {
+                                            M_1 = D_3366;
+                                          }
+                                        v = M_1;
+                                      }
+                                      L_8:;
+                                      D_3367 = k == D_3362;
+                                      k = k + 1;
+                                      if (D_3367) goto L_9;
+                                    }
+                                  }
+                              }
+                            L_9:;
+                          }
+                          L_6:;
+                          D_3368 = j == D_3359;
+                          j = j + 1;
+                          if (D_3368) goto L_7;
+                        }
+                      }
+                  }
+                L_7:;
+              }
+              L_2:;
+              D_3369 = i == D_3353;
+              i = i + 1;
+              if (D_3369) goto L_3;
+            }
+          }
+      }
+    L_3:;
+  }
+}
+
+
+int main ()
+{
+  int flag;
+  int n;
+
+  n = 4;
+  flag = 0;
+  test (&n, &flag);
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/uninit-pr104576.c b/gcc/testsuite/gcc.dg/analyzer/uninit-pr104576.c
new file mode 100644
index 00000000000..0b59acdb6e7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/uninit-pr104576.c
@@ -0,0 +1,16 @@ 
+float
+test_1 (int *flag, float theta)
+{
+  float t;
+  float f;
+
+  if (*flag)
+    t = 2.0f;
+
+  f = __builtin_sinf (theta);
+  
+  if (*flag)
+    f *= t;
+
+  return f;
+}
diff --git a/gcc/testsuite/gfortran.dg/analyzer/uninit-pr63311.f90 b/gcc/testsuite/gfortran.dg/analyzer/uninit-pr63311.f90
new file mode 100644
index 00000000000..34cc25da01d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/analyzer/uninit-pr63311.f90
@@ -0,0 +1,39 @@ 
+! { dg-additional-options "-O0" }
+
+MODULE M1
+  IMPLICIT NONE
+CONTAINS
+  INTEGER FUNCTION foo()
+     INTEGER, VOLATILE :: v=42
+     foo=v
+  END FUNCTION
+  SUBROUTINE test(n,flag)
+    INTEGER :: n,i,j,k,l,tt
+    LOGICAL :: flag
+    REAL(KIND=8) :: v,t
+    IF (flag) THEN
+      t=42
+      tt=foo()
+    ENDIF
+    v=0
+    DO i=1,n
+       v=0
+       IF (flag) THEN
+          IF (tt==i) v=MAX(v,t)
+       ENDIF
+       DO j=1,n
+        DO k=1,n
+            v=MAX(v,sin(REAL(j*k)))
+         ENDDO
+       ENDDO
+    ENDDO
+  END SUBROUTINE
+END MODULE M1
+
+USE M1
+INTEGER :: n
+LOGICAL :: flag
+n=4
+flag=.FALSE.
+CALL test(n,flag)
+END