Bug 93631 - [11/12/13/14 Regression] ICE on an invalid strcmp call in gimple_call_arg, at gimple.h:3258
Summary: [11/12/13/14 Regression] ICE on an invalid strcmp call in gimple_call_arg, at...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 10.0
: P2 normal
Target Milestone: 11.5
Assignee: Not yet assigned to anyone
URL:
Keywords: ice-on-invalid-code, needs-bisection
Depends on:
Blocks:
 
Reported: 2020-02-08 04:41 UTC by Yongheng Chen
Modified: 2024-03-11 08:36 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 7.3.0, 8.3.0, 9.2.0
Last reconfirmed: 2020-02-10 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Yongheng Chen 2020-02-08 04:41:55 UTC
POC:
---
---

Run command:
---
gcc -o poc poc.c
---

Gcc version:
---
gcc (GCC) 10.0.1 20200208 (experimental)
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
---

Stack dump:
---
internal compiler error: in gimple_ca
ll_arg, at gimple.h:3258
    1 | int f2 ( int x [ strcmp ( ) ] , int b ) { return c - b ;
      |     ^~
0x696d12 gimple_call_arg
        ../../gcc/gimple.h:3258
0x69ae3a gimple_call_arg
        ../../gcc/tree.h:3799
0x69ae3a gimple_call_arg
        ../../gcc/gimple.h:3266
0x69ae3a gimple_fold_builtin_string_compare
        ../../gcc/gimple-fold.c:2382
0xafbc7d gimple_fold_builtin
        ../../gcc/gimple-fold.c:3966
0xafbc7d gimple_fold_call
        ../../gcc/gimple-fold.c:4481
0xafd2f3 fold_stmt_1
        ../../gcc/gimple-fold.c:5152
0x169fc97 lower_stmt
        ../../gcc/gimple-low.c:388
0x169f7f2 lower_sequence
        ../../gcc/gimple-low.c:217
0x169f7f2 lower_gimple_bind
        ../../gcc/gimple-low.c:474
0x16a08f9 lower_function_body
        ../../gcc/gimple-low.c:110
0x16a08f9 execute
        ../../gcc/gimple-low.c:195
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
---
Comment 1 Yongheng Chen 2020-02-08 04:43:12 UTC
POC:
---
int f2 ( int x [ strcmp ( ) ] , int b ) { return c - b ;
 }
 int ( * f1 ( int a , enum E2 { E = -2 , F , G , H }
 b ) ) ( int c , int b ) { if ( a != b ) return f2 ;
 return 0 ;
 }
 int main ( ) { int ( * ( * p ) ( int a , int b ) ) ( int c , int d ) = f1 ;
 return ( * ( * p ) ( 0 , 2 ) ) ( 2 , 2 ) ;
 }
---
Comment 2 Richard Biener 2020-02-10 08:06:23 UTC
Confirmed.  As said elsewhere the real issue lies in the C FE having this kind of prototypes marked with BUILT-IN.
Comment 3 Richard Biener 2020-02-17 12:34:43 UTC
smaller "invalid" testcase (why don't we diagnose it?):

int f2 ( int x [ strcmp ( ) ] , int b ) { return x[0] - b ; } 

it's interesting that if I declare strcmp to avoid an implicit declaration
warning with the following it stops to ICE...

int strcmp();

so somehow the FEs decl merging for an implicit declaration coming from
the argument list is "broken" and doesn't avoid pre-empting the built-in
declaration?

While I have a patch to paper over the issue in the middle-end it would
be nice to avoid the issue in the frontend.  The middle-end patch would do
the following, using the canonical built-in declaration for argument
verification.  Similar issues exist for target builtins since we also
have a target specific folder.  Not sure how the FE deals with user-provided
"bogus" implementations of those (and whether they ever exist in non
__builtin_ obfuscated variants).

diff --git a/gcc/gimple.c b/gcc/gimple.c
index 324e706d508..d64c2a77ea3 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -2698,6 +2698,11 @@ gimple_builtin_call_types_compatible_p (const gimple *stmt, tree fndecl)
 {
   gcc_checking_assert (DECL_BUILT_IN_CLASS (fndecl) != NOT_BUILT_IN);
 
+  /* Use the decl we are actually expecting for comparison, not a possibly
+     bogus one from the user the C frontend is happily marking as builtin.  */
+  if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
+    fndecl = builtin_decl_explicit (DECL_FUNCTION_CODE (fndecl));
+
   tree ret = gimple_call_lhs (stmt);
   if (ret
       && !useless_type_conversion_p (TREE_TYPE (ret),


CCing C FE folks.
Comment 4 Martin Sebor 2020-02-17 23:26:18 UTC
Both test cases are diagnosed with two instances of -Wimplicit-function-declaration, the smaller of the two with:

$ gcc -S pr93631.c
pr93631.c:1:18: warning: implicit declaration of function ‘strcmp’ [-Wimplicit-function-declaration]
    1 | int f2 ( int x [ strcmp ( ) ] , int b ) { return x[0] - b ; }
      |                  ^~~~~~
pr93631.c:1:18: warning: too few arguments to built-in function ‘strcmp’ expecting 2 [-Wbuiltin-declaration-mismatch]
during GIMPLE pass: lower
pr93631.c: In function ‘f2’:
pr93631.c:1:5: internal compiler error: in gimple_call_arg, at gimple.h:3258
    1 | int f2 ( int x [ strcmp ( ) ] , int b ) { return x[0] - b ; }
      |     ^~

The second warning has started to be issued with r266194 but it doesn't prevent the call from being treated as a built-in (the function only prevents that for errors, not for warning).  There are a couple more checks later on for incompatible built-in calls that look like should catch this but don't.  Changing the convert_arguments() function in the C front-end that issues the second warning to treat this case as an error (while still only issuing a warning) avoids the GIMPLE ICE but then causes another ICE later on:

$ gcc -S -Wall -Wextra -Wpedantic t.c
t.c:1:18: warning: implicit declaration of function ‘strcmp’ [-Wimplicit-function-declaration]
    1 | int f2 ( int x [ strcmp ( ) ] , int b ) { return x[0] - b ; }
      |                  ^~~~~~
t.c:1:18: warning: too few arguments to built-in function ‘strcmp’ expecting 2 [-Wbuiltin-declaration-mismatch]
t.c: In function ‘f2’:
t.c:1:14: warning: unused parameter ‘x’ [-Wunused-parameter]
    1 | int f2 ( int x [ strcmp ( ) ] , int b ) { return x[0] - b ; }
      |          ~~~~^~~~~~~~~~~~~~~~
t.c:1:1: warning: control reaches end of non-void function [-Wreturn-type]
    1 | int f2 ( int x [ strcmp ( ) ] , int b ) { return x[0] - b ; }
      | ^~~
during RTL pass: expand
t.c:1:5: internal compiler error: in adjust_one_expanded_partition_var, at cfgexpand.c:1463
    1 | int f2 ( int x [ strcmp ( ) ] , int b ) { return x[0] - b ; }
      |     ^~
0xb06387 adjust_one_expanded_partition_var
	/src/gcc/trunk/gcc/cfgexpand.c:1463
0xb184b4 execute
	/src/gcc/trunk/gcc/cfgexpand.c:6457
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <https://gcc.gnu.org/bugs/> for instructions.



For reference, bisection of the reported ICE points to r243832:

commit d17680f342ef5407303d8c76f8faa0762f83c3f7
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Wed Dec 21 01:07:49 2016 +0100

    re PR c/77767 (Side-effect from VLA array parameters lost)
    
            PR c/77767
            * c-decl.c (grokdeclarator): If *expr is non-NULL, append expression
            to *expr instead of overwriting it.
    
            * gcc.c-torture/execute/pr77767.c: New test.
    
    From-SVN: r243832
Comment 5 Richard Biener 2020-02-18 08:12:54 UTC
Just to add as a data point, gimple_builtin_call_types_compatible_p was originally added to catch indirect calls turned into direct calls of
builtins but with wrongly typed args like from

 void (*fn)(int) = (void (*)(int))&memcpy;
 fn (1);

it was _not_ designed to cope with a function decl that claims to be
BUILT_IN_MEMCPY but whose TYPE_ARG_TYPES are not compatible with what
we'd expect from a memcpy declaration.  It is the frontends business
to make sure the middle-end is not seeing a DECL_FUNCTION_CODE when
the types do not match the canonical function declaration.

The patch from comment#3 is a hack trying to work around FEs brokeness.

But it's the frontends that need fixing.  Finally.  Please.  Iff then
as hackish as comment#3 but please within the FE like in merge_decls
at the end do

if (DECL_FUNCTION_CODE (...)
    && !decls_compatible_p (builtin_decl_explicit (...), ...)))
  DECL_BUILT_IN_CLASS (..) = BUILT_IN_NONE;

and possibly clear the decl from builtin_decl_implicit iff we ever
populated that with user decls.
Comment 6 Jakub Jelinek 2020-03-04 09:49:48 UTC
GCC 8.4.0 has been released, adjusting target milestone.
Comment 7 Jakub Jelinek 2021-05-14 09:52:51 UTC
GCC 8 branch is being closed.
Comment 8 Richard Biener 2021-06-01 08:16:18 UTC
GCC 9.4 is being released, retargeting bugs to GCC 9.5.
Comment 9 Richard Biener 2022-05-27 09:42:04 UTC
GCC 9 branch is being closed
Comment 10 Richard Biener 2022-06-01 13:14:45 UTC
I can't reproduce with GCC 10+
Comment 11 Jakub Jelinek 2022-06-28 10:39:39 UTC
GCC 10.4 is being released, retargeting bugs to GCC 10.5.
Comment 12 Richard Biener 2023-07-07 10:36:43 UTC
GCC 10 branch is being closed.
Comment 13 Jeffrey A. Law 2024-03-10 21:37:43 UTC
Per c#10.
Comment 14 Jakub Jelinek 2024-03-11 08:36:53 UTC
Seems r12-8017-g71770a0ea920641c53912f725f5abd4413b38fd5 fixed this.