Compiler error: constexpr with bitfields.

Bug #1791425 reported by Marcin Bienkowski
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
gcc-defaults
Fix Released
Medium
gcc-7 (Ubuntu)
New
Undecided
Unassigned
gcc-8 (Ubuntu)
New
Undecided
Unassigned

Bug Description

GCC crashes when trying to compile the following program.

$> cat prog.cpp

struct Boolean {
   bool is_true : 1;
 constexpr explicit Boolean () : is_true(true) { }
 constexpr explicit Boolean (bool init) : is_true(init) {
  if (is_true != Boolean().is_true)
   is_true = false;
 }
};

int main() { Boolean x(false); }

$> g++ -O2 prog.cpp
prog.cpp: In function ‘int main()’:
prog.cpp:10:29: in constexpr expansion of ‘x.Boolean::Boolean(0)’
prog.cpp:10:29: internal compiler error: in cxx_eval_bit_field_ref, at cp/constexpr.c:2570
 int main() { Boolean x(false); }
                             ^
Please submit a full bug report,
with preprocessed source if appropriate.
See <file:///usr/share/doc/gcc-7/README.Bugs> for instructions.

Note that -O2 is required for reproducing the bug (otherwise, constexpr does not seem to be evaluated in the compile time). The program might seem a bit convoluted, but this is the minimum non-working example I was able to construct from a real-life scenario. The problem does not occur if line

bool is_true : 1;

is changed to

bool is_true;

-- Marcin.

ProblemType: Bug
DistroRelease: Ubuntu 18.04
Package: g++ 4:7.3.0-3ubuntu2
ProcVersionSignature: Ubuntu 4.15.0-33.36-generic 4.15.18
Uname: Linux 4.15.0-33-generic x86_64
NonfreeKernelModules: nvidia_modeset nvidia
ApportVersion: 2.20.9-0ubuntu7.2
Architecture: amd64
CurrentDesktop: GNOME
Date: Sat Sep 8 12:51:21 2018
InstallationDate: Installed on 2014-12-10 (1367 days ago)
InstallationMedia: Ubuntu 14.10 "Utopic Unicorn" - Release amd64 (20141022.1)
SourcePackage: gcc-defaults
UpgradeStatus: Upgraded to bionic on 2018-08-13 (26 days ago)

Revision history for this message
In , Remi-ducceschi (remi-ducceschi) wrote :
Download full text (5.3 KiB)

Created attachment 44538
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"
i...

Read more...

Revision history for this message
In , Remi-ducceschi (remi-ducceschi) wrote :

Created attachment 44539
Small test case

Revision history for this message
In , Mpolacek (mpolacek) wrote :

Confirmed. G++ 5 compiles it fine.

Revision history for this message
In , Mpolacek (mpolacek) wrote :

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{};
}

Revision history for this message
In , Mpolacek (mpolacek) wrote :

Started with r230365 -- Merge C++ delayed folding branch..

Revision history for this message
In , Jakub-gcc (jakub-gcc) wrote :

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.

Revision history for this message
Marcin Bienkowski (marcin.bienkowski) wrote :
Revision history for this message
Juhani Numminen (jsonic) wrote :

Reassigned to gcc-7, which is the source package of the actual compiler, while gcc-defaults only provides metapackages.

affects: gcc-defaults (Ubuntu) → gcc-7 (Ubuntu)
Revision history for this message
In , Jakub-gcc (jakub-gcc) wrote :

GCC 6 branch is being closed

Changed in gcc-defaults:
importance: Unknown → Medium
status: Unknown → Confirmed
Revision history for this message
In , Jason-gcc (jason-gcc) wrote :

The patch for 89285 seems to have fixed this on trunk.

Revision history for this message
In , Remi-ducceschi (remi-ducceschi) wrote :

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 :)

Revision history for this message
In , Jakub-gcc (jakub-gcc) wrote :

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

Revision history for this message
In , Rguenth (rguenth) wrote :

The GCC 7 branch is being closed, re-targeting to GCC 8.4.

Revision history for this message
In , Jakub-gcc (jakub-gcc) wrote :

GCC 8.4.0 has been released, adjusting target milestone.

Revision history for this message
In , Jakub-gcc (jakub-gcc) wrote :

The GCC 8 branch is being closed, fixed in GCC 9.1.

Changed in gcc-defaults:
status: Confirmed → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.