analyzer: const functions have no side effects [PR104576]
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. 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>
This commit is contained in:
parent
cb3afcd2a3
commit
5fbcbcaff7
@ -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;
|
||||
}
|
||||
|
134
gcc/testsuite/gcc.dg/analyzer/torture/uninit-pr63311.c
Normal file
134
gcc/testsuite/gcc.dg/analyzer/torture/uninit-pr63311.c
Normal file
@ -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;
|
||||
}
|
16
gcc/testsuite/gcc.dg/analyzer/uninit-pr104576.c
Normal file
16
gcc/testsuite/gcc.dg/analyzer/uninit-pr104576.c
Normal file
@ -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;
|
||||
}
|
39
gcc/testsuite/gfortran.dg/analyzer/uninit-pr63311.f90
Normal file
39
gcc/testsuite/gfortran.dg/analyzer/uninit-pr63311.f90
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user