Bug 81607 - [6 Regression] Conditional operator: "type mismatch in shift expression" error
Summary: [6 Regression] Conditional operator: "type mismatch in shift expression" error
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 8.0
: P3 normal
Target Milestone: 6.5
Assignee: Marek Polacek
URL:
Keywords: ice-checking, wrong-code
Depends on:
Blocks: yarpgen
  Show dependency treegraph
 
Reported: 2017-07-28 21:16 UTC by Dmitry Babokin
Modified: 2021-11-01 23:07 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2017-07-29 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Dmitry Babokin 2017-07-28 21:16:12 UTC
gcc trunk, rev250630, x86_64.

I see a lot of crashes involving conditional operator and struct field access. I see at least 7 different kind of crashes. They may be related, so I'm filing only this one for now to avoid spamming the bug tracker. After fixing this one, I'll proceed with others if they are not fixed.

> cat f.cpp
int a;
struct b {
  long c : 32;
} d;
char f = (903092 ? int(d.c) : 0) << a;

> g++ -c f.cpp
f.cpp: In function ‘void __static_initialization_and_destruction_0(int, int)’:
f.cpp:5:38: error: type mismatch in shift expression
 char f = (903092 ? int(d.c) : 0) << a;
                                      ^
int
long int
int
_4 = _2 << a.0_3;
f.cpp:5:38: internal compiler error: verify_gimple failed
0xf5e57d verify_gimple_in_seq(gimple*)
	../../gcc_svn_intel/gcc/tree-cfg.c:4975
0xd1d2ad gimplify_body(tree_node*, bool)
	../../gcc_svn_intel/gcc/gimplify.c:12589
0xd1d47c gimplify_function_tree(tree_node*)
	../../gcc_svn_intel/gcc/gimplify.c:12679
0xbb64b7 cgraph_node::analyze()
	../../gcc_svn_intel/gcc/cgraphunit.c:668
0xbb8b73 analyze_functions
	../../gcc_svn_intel/gcc/cgraphunit.c:1129
0xbb9a12 symbol_table::finalize_compilation_unit()
	../../gcc_svn_intel/gcc/cgraphunit.c:2607
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.
Comment 1 Marc Glisse 2017-07-29 06:20:14 UTC
The original dump has
(void) (f = (char) ((long int) d.c << a))

(using long instead of int) This happens only for a bitfield of size 32, not 31 or 33, we probably get confused about a NOP conversion somewhere along the way.
Comment 2 Richard Biener 2017-07-31 07:23:56 UTC
I will have a looksee.
Comment 3 Richard Biener 2017-07-31 08:20:45 UTC
0x000000000088d7d5 in cp_fold (x=<lshift_expr 0x7ffff69e6618>)
    at /tmp/trunk/gcc/cp/cp-gimplify.c:2251
2251                x = fold_build2_loc (loc, code, TREE_TYPE (x), op0, op1);
Value returned is $25 = (tree_node *) 0x7ffff69e6640
(gdb) p debug_generic_expr (op1)
a
$26 = void
(gdb) p debug_generic_expr (op0)
(long int) d.c
$27 = void
(gdb) p debug_generic_expr (x)
(1 ? (int) (long int) d.c : 0) << a
$28 = void

because we run into

static tree
cp_fold (tree x)
{
...
    case VEC_COND_EXPR:
    case COND_EXPR:
...
      /* A COND_EXPR might have incompatible types in branches if one or both
         arms are bitfields.  If folding exposed such a branch, fix it up.  */
      if (TREE_CODE (x) != code)
        if (tree type = is_bitfield_expr_with_lowered_type (x))
          x = fold_convert (type, x);

and fold (int) (long int) d.c to (long int) d.c here.

C++ FE bug.

Not sure why this isn't simply the following as we surely have to preserve
the type of the COND_EXPR when folding.

Index: gcc/cp/cp-gimplify.c
===================================================================
--- gcc/cp/cp-gimplify.c        (revision 250725)
+++ gcc/cp/cp-gimplify.c        (working copy)
@@ -2314,8 +2314,7 @@ cp_fold (tree x)
       /* A COND_EXPR might have incompatible types in branches if one or both
         arms are bitfields.  If folding exposed such a branch, fix it up.  */
       if (TREE_CODE (x) != code)
-       if (tree type = is_bitfield_expr_with_lowered_type (x))
-         x = fold_convert (type, x);
+       x = fold_convert (TREE_TYPE (org_x), x);
 
       break;
 

Leaving to C++ folks.
Comment 4 Marek Polacek 2017-07-31 08:35:11 UTC
Started with r234384.
Comment 5 Marek Polacek 2017-07-31 08:41:13 UTC
cp_genericize_r does this fix-up too, and so has to cp_fold, but apparently what's in cp_fold isn't enough.
Comment 6 Marek Polacek 2017-07-31 09:32:42 UTC
Actually I think richi's fix is the right one.  Let me test.
Comment 7 rguenther@suse.de 2017-07-31 09:41:47 UTC
On Mon, 31 Jul 2017, mpolacek at gcc dot gnu.org wrote:

> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81607
> 
> --- Comment #6 from Marek Polacek <mpolacek at gcc dot gnu.org> ---
> Actually I think richi's fix is the right one.  Let me test.

Note for aggregate types fold_const might just ICE so I'm not 100% sure
we don't need some more guards on it.  Like if type != expected-type or 
so?
Comment 8 Marek Polacek 2017-07-31 09:44:09 UTC
I'm actually testing this

--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -2314,9 +2314,9 @@ cp_fold (tree x)
 
       /* A COND_EXPR might have incompatible types in branches if one or both
     arms are bitfields.  If folding exposed such a branch, fix it up.  */
-      if (TREE_CODE (x) != code)
-   if (tree type = is_bitfield_expr_with_lowered_type (x))
-     x = fold_convert (type, x);
+      if (TREE_CODE (x) != code
+     && !useless_type_conversion_p (TREE_TYPE (org_x), TREE_TYPE (x)))
+   x = fold_convert (TREE_TYPE (org_x), x);
 
       break;
 
so I hope that case is covered.  We'll see.
Comment 9 rguenther@suse.de 2017-07-31 09:47:11 UTC
On Mon, 31 Jul 2017, mpolacek at gcc dot gnu.org wrote:

> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81607
> 
> --- Comment #8 from Marek Polacek <mpolacek at gcc dot gnu.org> ---
> I'm actually testing this
> 
> --- a/gcc/cp/cp-gimplify.c
> +++ b/gcc/cp/cp-gimplify.c
> @@ -2314,9 +2314,9 @@ cp_fold (tree x)
> 
>        /* A COND_EXPR might have incompatible types in branches if one or both
>      arms are bitfields.  If folding exposed such a branch, fix it up.  */
> -      if (TREE_CODE (x) != code)
> -   if (tree type = is_bitfield_expr_with_lowered_type (x))
> -     x = fold_convert (type, x);
> +      if (TREE_CODE (x) != code
> +     && !useless_type_conversion_p (TREE_TYPE (org_x), TREE_TYPE (x)))
> +   x = fold_convert (TREE_TYPE (org_x), x);
> 
>        break;
> 
> so I hope that case is covered.  We'll see.

Yeah, hopefully the FE doesn't mess up types for aggregates ;)

useless_type_conversion_p should be fine in the gimplify hook.
Comment 10 Marek Polacek 2017-08-08 08:56:15 UTC
Author: mpolacek
Date: Tue Aug  8 08:55:43 2017
New Revision: 250948

URL: https://gcc.gnu.org/viewcvs?rev=250948&root=gcc&view=rev
Log:
	PR c++/81607
	* cp-gimplify.c (cp_fold): If folding exposed a branch of
	a COND_EXPR, convert it to the original type of the COND_EXPR, if
	they differ.		   

	* g++.dg/other/bitfield6.C: New test.

Added:
    trunk/gcc/testsuite/g++.dg/other/bitfield6.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/cp-gimplify.c
    trunk/gcc/testsuite/ChangeLog
Comment 11 Marek Polacek 2017-08-08 09:10:34 UTC
Fixed on trunk so far.
Comment 12 Dmitry Babokin 2017-08-08 22:28:51 UTC
The fix helped all fails that I see (with all 7 different symptoms). Thanks!
Comment 13 Marek Polacek 2017-08-25 16:32:22 UTC
Author: mpolacek
Date: Fri Aug 25 16:31:50 2017
New Revision: 251358

URL: https://gcc.gnu.org/viewcvs?rev=251358&root=gcc&view=rev
Log:
	PR c++/81607
	* cp-gimplify.c (cp_fold): If folding exposed a branch of
	a COND_EXPR, convert it to the original type of the COND_EXPR, if
	they differ.

Added:
    branches/gcc-7-branch/gcc/testsuite/g++.dg/other/bitfield6.C
Modified:
    branches/gcc-7-branch/gcc/cp/ChangeLog
    branches/gcc-7-branch/gcc/cp/cp-gimplify.c
Comment 14 Marek Polacek 2017-08-25 16:32:43 UTC
Fixed.
Comment 15 Aldy Hernandez 2017-09-13 16:39:31 UTC
Author: aldyh
Date: Wed Sep 13 16:39:00 2017
New Revision: 252338

URL: https://gcc.gnu.org/viewcvs?rev=252338&root=gcc&view=rev
Log:
	PR c++/81607
	* cp-gimplify.c (cp_fold): If folding exposed a branch of
	a COND_EXPR, convert it to the original type of the COND_EXPR, if
	they differ.		   

	* g++.dg/other/bitfield6.C: New test.

Added:
    branches/range-gen2/gcc/testsuite/g++.dg/other/bitfield6.C
Modified:
    branches/range-gen2/gcc/cp/ChangeLog
    branches/range-gen2/gcc/cp/cp-gimplify.c
    branches/range-gen2/gcc/testsuite/ChangeLog