Bug 86953 - [8 Regression] compiler crashes with constexpr operator== and specific struct (cxx_eval_bit_field_ref, at cp/constexpr.c:2704)
Summary: [8 Regression] compiler crashes with constexpr operator== and specific struct...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 9.0
: P2 normal
Target Milestone: 9.0
Assignee: Not yet assigned to anyone
URL:
Keywords: ice-on-valid-code
Depends on: 81601 89285
Blocks: constexpr
  Show dependency treegraph
 
Reported: 2018-08-14 16:36 UTC by Rémi Ducceschi
Modified: 2021-05-14 10:57 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work: 5.4.0, 9.0
Known to fail:
Last reconfirmed: 2018-08-14 00:00:00


Attachments
preprocessed file of a small test case for the constexpr crash (89.93 KB, application/octet-stream)
2018-08-14 16:36 UTC, Rémi Ducceschi
Details
Small test case (354 bytes, text/plain)
2018-08-14 16:38 UTC, Rémi Ducceschi
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Rémi Ducceschi 2018-08-14 16:36:54 UTC
Created attachment 44538 [details]
preprocessed file of a small test case for the constexpr crash

Hello,

I've created a small test case that produces a compiler crash. You can find attached the preprocessed file (main.ii) made by running the following command, with `G++ 7.3.1 20180303 (Red Hat 7.3.1-5)` on a CentOS 7 (with the devtoolset-7 installed), but it seems to exist on the last version too (see https://wandbox.org/permlink/zGZWdHIrRNJKfh5Z):

g++ -O3 -Wall -Wextra -o main -save-temps -v main.cpp

I give at the end of the mail the output of the command.

You can find a run on the last G++ version (9) here: https://wandbox.org/permlink/zGZWdHIrRNJKfh5Z 

-----------------------
Here is the code:

#include <iostream>
struct Bugged {
    double x; bool isfreex; bool isfreey;
    constexpr bool operator==(const Bugged& other) const noexcept {
        return (x == other.x) && (isfreex == other.isfreex) && (isfreey == other.isfreey);
    }
};
int main () {
    std::cout << std::boolalpha << (Bugged{} == Bugged{}) << std::endl;
    return 0;
}
-----------------------

The bug only appears if I enable optimization (-02 or -O3), I guess constexpr optimization is not done otherwise.

The problem occurs on the operator==(). The compiler crashes because it can't compute the result of the constexpr. Note that if I change the struct so it doesn't hold booleans, but double instead, or if I remove any of the parentheses term in the operator== function, it doesn't crash.

Note that this code compiles on MSVC 2017 and on clang 6 (though it doesn't mean anything).

I search for a similar bug report but didn't find anything, sorry if this is a duplicate.

-----------------------
Below the output of the command:

Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,fortran,lto --prefix=/opt/rh/devtoolset-7/root/usr --mandir=/opt/rh/devtoolset-7/root/usr/share/man --infodir=/opt/rh/devtoolset-7/root/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --enable-plugin --with-linker-hash-style=gnu --enable-initfini-array --with-default-libstdcxx-abi=gcc4-compatible --with-isl=/builddir/build/BUILD/gcc-7.3.1-20180303/obj-x86_64-redhat-linux/isl-install --enable-libmpx --enable-gnu-indirect-function --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
Thread model: posix
gcc version 7.3.1 20180303 (Red Hat 7.3.1-5) (GCC) 
COLLECT_GCC_OPTIONS='-O3' '-Wall' '-Wextra' '-o' 'main' '-save-temps' '-v' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
 /opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/cc1plus -E -quiet -v -D_GNU_SOURCE main.cpp -mtune=generic -march=x86-64 -Wall -Wextra -O3 -fpch-preprocess -o main.ii
ignoring nonexistent directory "/opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/include-fixed"
ignoring nonexistent directory "/opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/../../../../x86_64-redhat-linux/include"
#include "..." search starts here:
#include <...> search starts here:
 /opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/../../../../include/c++/7
 /opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/../../../../include/c++/7/x86_64-redhat-linux
 /opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/../../../../include/c++/7/backward
 /opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/include
 /usr/local/include
 /opt/rh/devtoolset-7/root/usr/include
 /usr/include
End of search list.
COLLECT_GCC_OPTIONS='-O3' '-Wall' '-Wextra' '-o' 'main' '-save-temps' '-v' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
 /opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/cc1plus -fpreprocessed main.ii -quiet -dumpbase main.cpp -mtune=generic -march=x86-64 -auxbase main -O3 -Wall -Wextra -version -o main.s
GNU C++14 (GCC) version 7.3.1 20180303 (Red Hat 7.3.1-5) (x86_64-redhat-linux)
	compiled by GNU C version 7.3.1 20180303 (Red Hat 7.3.1-5), GMP version 6.0.0, MPFR version 3.1.1, MPC version 1.0.1, isl version isl-0.16.1-GMP

GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
GNU C++14 (GCC) version 7.3.1 20180303 (Red Hat 7.3.1-5) (x86_64-redhat-linux)
	compiled by GNU C version 7.3.1 20180303 (Red Hat 7.3.1-5), GMP version 6.0.0, MPFR version 3.1.1, MPC version 1.0.1, isl version isl-0.16.1-GMP

GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: d120f4d100e8519a845aa191e71919b8
main.cpp: In function âint main()â:
main.cpp:23:43:   in constexpr expansion of âBugged{}.Bugged::operator==(Bugged{})â
main.cpp:23:54: internal compiler error: in cxx_eval_bit_field_ref, at cp/constexpr.c:2565
  std::cout << std::boolalpha << (Bugged{} == Bugged{}) << std::endl;
                                                      ^
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://bugzilla.redhat.com/bugzilla> for instructions.
Preprocessed source stored into /tmp/ccVplEXc.out file, please attach this to your bugreport.
Comment 1 Rémi Ducceschi 2018-08-14 16:38:22 UTC
Created attachment 44539 [details]
Small test case
Comment 2 Marek Polacek 2018-08-14 16:46:52 UTC
Confirmed.  G++ 5 compiles it fine.
Comment 3 Marek Polacek 2018-08-14 17:42:03 UTC
struct B {
  double x;
  bool isfreex;
  bool isfreey;

  constexpr bool operator==(const B& other) const noexcept
  {
    return (x == other.x) && (isfreex == other.isfreex) && (isfreey == other.isfreey);
  }
	
  constexpr bool operator!=(const B& other) const noexcept { return !(*this == other); }
};

int
main ()
{
  bool b = B{} == B{};
}
Comment 4 Marek Polacek 2018-08-14 17:46:05 UTC
Started with r230365 -- Merge C++ delayed folding branch..
Comment 5 Jakub Jelinek 2018-08-24 15:25:55 UTC
Another reason why we badly need to finish PR81601.
The constexpr evaluator really can't cope well with these BIT_FIELD_REFs, they read multiple fields at once, or could also read some uninitialized bits in between and mask them off, etc.
So at minimum we'd need to disable these optimizations while folding constexpr declared functions and if the fields don't have INTEGRAL_TYPE or the bit field reference covers more than one field.
Comment 6 Jakub Jelinek 2018-10-26 10:13:46 UTC
GCC 6 branch is being closed
Comment 7 Jason Merrill 2019-02-21 23:12:21 UTC
The patch for 89285 seems to have fixed this on trunk.
Comment 8 Rémi Ducceschi 2019-04-16 13:42:38 UTC
It seems to be fixed on the last version available on wandbox.org (gcc HEAD 9.0.1 201904): https://wandbox.org/permlink/Tu4T8jEXDDtDw0OS

Though it doesn't work on any other versions (8.3.0...).
Any chance to see the fix in the 8 branch?

Anyway, thanks a lot :)
Comment 9 Jakub Jelinek 2019-04-16 19:07:14 UTC
Author: jakub
Date: Tue Apr 16 19:06:41 2019
New Revision: 270396

URL: https://gcc.gnu.org/viewcvs?rev=270396&root=gcc&view=rev
Log:
	PR c++/86953
	* g++.dg/cpp0x/constexpr-86953.C: New test.

Added:
    trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-86953.C
Modified:
    trunk/gcc/testsuite/ChangeLog
Comment 10 Richard Biener 2019-11-14 07:53:04 UTC
The GCC 7 branch is being closed, re-targeting to GCC 8.4.
Comment 11 Jakub Jelinek 2020-03-04 09:34:23 UTC
GCC 8.4.0 has been released, adjusting target milestone.
Comment 12 Jakub Jelinek 2021-05-14 10:57:27 UTC
The GCC 8 branch is being closed, fixed in GCC 9.1.