public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/95202] New: Assignment to a member is wrongly optimized away by g++ with -fstrict-aliasing
@ 2020-05-19 11:39 syomalina at gmail dot com
  2020-05-19 17:18 ` [Bug c++/95202] " rguenth at gcc dot gnu.org
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: syomalina at gmail dot com @ 2020-05-19 11:39 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95202

            Bug ID: 95202
           Summary: Assignment to a member is wrongly optimized away by
                    g++ with -fstrict-aliasing
           Product: gcc
           Version: 9.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: syomalina at gmail dot com
  Target Milestone: ---

Created attachment 48559
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=48559&action=edit
the preprocessed file (*.i*) that triggers the bug

The following code produces a wrong ERROR print with -fstrict-aliasing enabled.
It sounds like a commonly reported false-positive bug with aliasing rules
violation from the FAQ, but it's not (imho :-)), as no type-casting and memory
manipulations are involved. 

The problem could be related to the following bug:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93246, as "the symptoms" are quite
similar and type aliases are involved also here. But for the code below
-fno-ipa-sra doesn't help, only -fno-strict-aliasing does. 

The problem appears with GCC 9.2.0, 9.1.0. It doesn't appear with GCC 9.3 and
10.1. The reason I've thought it would be still useful to report the bug is: a
very fragile code constellation which allows to reproduce the problem. I've
marked in comments below what could be done to prevent the problem from
appearing. It looks like that even a slight change in the optimizer could
"hide" the problem back, what could have happened in the later versions of GCC.
So, it would be great to check what is the root cause of the problem, and if it
was actually fixed in later GCC versions. 

The code below models variable sized array allocated on stack. Then 2x
dimension  array is created with sizes 32 and 4 respectively. The bug happens
in this line:
outerArrItem.innerArray.setSize(innerArraySize);
body.numElements is not updated with the new size (4) for the inner array, and
following access to an element [0] of the inner array raises the error. 

// --------------------------------
#include <iostream>

template <typename T, uint32_t CAPACITY>
class VariableSizedArray
{
public:
    void setSize(uint32_t num) { body.numElements = num; }

    T& operator[](uint32_t idx)
    {
        if (idx >= CAPACITY or idx >= body.numElements)
        {
            raiseIndexErr("", 42, "ERROR: Invalid idx: ", idx, 42,
body.numElements);
        }
        return body.elems[idx];
    }

    // Changes in parameters make the problem to disappear
    static void raiseIndexErr(const char*, uint32_t, const char* error,
uint32_t idx, uint32_t, uint32_t num)
    {
        // If printf is used, problem disappears
        std::cerr << error << idx << "! Capacity: " << CAPACITY << ", number
elements: " << num << ::std::endl;
    }

    // private: // If private -- problem disappears
    struct Data
    {
        uint32_t numElements;
        T elems[CAPACITY];
    };
    using Body = Data; 
    Body body; // If Data is used directly here w/o "using", problem disappears
};

static constexpr int outerArraySize = 32;
static constexpr int innerArraySize = 4;

class InnerArrayItem
{
public:
    void use(){};
    uint8_t dummy[1]{}; // when removed or not an array, problem disappears
};

class OuterArrayItem
{
public:
    uint8_t dummy{0}; // When removed, problem disappears
    VariableSizedArray<InnerArrayItem, innerArraySize> innerArray{};
};

struct TestProblem
{
    // When parameter removed (its always 0) -- problem disappears
    static void run(const uint8_t index0)
    {
        VariableSizedArray<OuterArrayItem, outerArraySize> outerArray{};

        outerArray.setSize(outerArraySize);
        auto& outerArrItem = outerArray[index0];
        outerArrItem.innerArray.setSize(innerArraySize);

        // ERROR: invalid idx is reported for outerArray[0].innerArray[0]
access!
        outerArrItem.innerArray[index0].use();
    }
};

int main()
{
    TestProblem::run(0);
    std::cout << "Test finished." << std::endl;
    return 0;
}

/*
Execution results:

$ g++ --version # same happens for 9.1.0 as well
g++ (GCC) 9.2.0
Copyright (C) 2019 Free Software Foundation, Inc.

# Just -O1
$ rm gccBug; g++ -o gccBug -Wall -Werror -O1 TestGccBug.cpp && ./gccBug
Test finished.

# -O1 with -fstrict-aliasing
$ rm gccBug; g++ -o gccBug -Wall -Werror -O1 -fstrict-aliasing TestGccBug.cpp
&& ./gccBug 
ERROR: Invalid idx: 0! Capacity: 4, number elements: 0
Test finished.

# Just -O2
$ rm gccBug; g++ -o gccBug -Wall -Werror -O2 TestGccBug.cpp && ./gccBug
ERROR: Invalid idx: 0! Capacity: 4, number elements: 0
Test finished.

# Just -O3
$ rm gccBug; g++ -o gccBug -Wall -Werror -O3 TestGccBug.cpp && ./gccBug
ERROR: Invalid idx: 0! Capacity: 4, number elements: 0
Test finished.

# -O3 with -fno-ipa-sra as recommended in
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93246
$ rm gccBug; g++ -o gccBug -Wall -Werror -O3 -fno-ipa-sra TestGccBug.cpp &&
./gccBug
ERROR: Invalid idx: 0! Capacity: 4, number elements: 0
Test finished.

# -O3 with -fno-ipa-sra and -fno-strict-aliasing
$ rm gccBug; g++ -o gccBug -Wall -Werror -O3 -fno-ipa-sra -fno-strict-aliasing
TestGccBug.cpp && ./gccBug
Test finished.

# -O3 with -fno-strict-aliasing
$ rm gccBug; g++ -o gccBug -Wall -Werror -O3 -fno-strict-aliasing
TestGccBug.cpp && ./gccBug
Test finished.
*/

Verbose output of GCC compilation:

$ g++ -v -save-temps -o gccBug -Wall -Werror -Wextra -O3 TestGccBug.cpp
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/opt/gcc/x86_64/9.2.0a-1/libexec/gcc/x86_64-redhat-linux/9.2.0/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/opt/gcc/x86_64/9.2.0a-1
--exec-prefix=/opt/gcc/x86_64/9.2.0a-1 --bindir=/opt/gcc/x86_64/9.2.0a-1/bin
--sbindir=/opt/gcc/x86_64/9.2.0a-1/sbin
--sysconfdir=/opt/gcc/x86_64/9.2.0a-1/etc
--datadir=/opt/gcc/x86_64/9.2.0a-1/share
--includedir=/opt/gcc/x86_64/9.2.0a-1/include
--libdir=/opt/gcc/x86_64/9.2.0a-1/lib
--libexecdir=/opt/gcc/x86_64/9.2.0a-1/libexec --localstatedir=/var
--sharedstatedir=/var/lib --mandir=/opt/gcc/x86_64/9.2.0a-1/man
--infodir=/opt/gcc/x86_64/9.2.0a-1/info
--with-docdir=/opt/gcc/x86_64/9.2.0a-1/doc --enable-shared
--enable-languages=c,c++ --enable-threads=posix --enable-checking=release
--with-system-zlib --disable-libunwind-exceptions --enable-libssp --enable-lto
--with-gnu-ld --verbose --disable-gtktest --target=x86_64-redhat-linux
--build=x86_64-redhat-linux --host=x86_64-redhat-linux --enable-__cxa_atexit
--enable-pic
Thread model: posix
gcc version 9.2.0 (GCC) 
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-o' 'gccBug' '-Wall' '-Werror'
'-Wextra' '-O3' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
 /opt/gcc/x86_64/9.2.0a-1/libexec/gcc/x86_64-redhat-linux/9.2.0/cc1plus -E
-quiet -v -D_GNU_SOURCE TestGccBug.cpp -mtune=generic -march=x86-64 -Wall
-Werror -Wextra -O3 -fpch-preprocess -o TestGccBug.ii
ignoring nonexistent directory
"/opt/gcc/x86_64/9.2.0a-1/lib/gcc/x86_64-redhat-linux/9.2.0/../../../../x86_64-redhat-linux/include"
#include "..." search starts here:
#include <...> search starts here:

/opt/gcc/x86_64/9.2.0a-1/lib/gcc/x86_64-redhat-linux/9.2.0/../../../../include/c++/9.2.0

/opt/gcc/x86_64/9.2.0a-1/lib/gcc/x86_64-redhat-linux/9.2.0/../../../../include/c++/9.2.0/x86_64-redhat-linux

/opt/gcc/x86_64/9.2.0a-1/lib/gcc/x86_64-redhat-linux/9.2.0/../../../../include/c++/9.2.0/backward
 /opt/gcc/x86_64/9.2.0a-1/lib/gcc/x86_64-redhat-linux/9.2.0/include
 /usr/local/include
 /opt/gcc/x86_64/9.2.0a-1/include
 /opt/gcc/x86_64/9.2.0a-1/lib/gcc/x86_64-redhat-linux/9.2.0/include-fixed
 /usr/include
End of search list.
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-o' 'gccBug' '-Wall' '-Werror'
'-Wextra' '-O3' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
 /opt/gcc/x86_64/9.2.0a-1/libexec/gcc/x86_64-redhat-linux/9.2.0/cc1plus
-fpreprocessed TestGccBug.ii -quiet -dumpbase TestGccBug.cpp -mtune=generic
-march=x86-64 -auxbase TestGccBug -O3 -Wall -Werror -Wextra -version -o
TestGccBug.s
GNU C++14 (GCC) version 9.2.0 (x86_64-redhat-linux)
        compiled by GNU C version 9.2.0, GMP version 5.0.0, MPFR version 3.1.0,
MPC version 1.1.0, isl version none
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
GNU C++14 (GCC) version 9.2.0 (x86_64-redhat-linux)
        compiled by GNU C version 9.2.0, GMP version 5.0.0, MPFR version 3.1.0,
MPC version 1.1.0, isl version none
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 4b6a28fa973d06df756608f08fdba542
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-o' 'gccBug' '-Wall' '-Werror'
'-Wextra' '-O3' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
 as -v --64 -o TestGccBug.o TestGccBug.s
GNU assembler version 2.32 (x86_64-redhat-linux) using BFD version (GNU
Binutils) 2.32
COMPILER_PATH=/opt/gcc/x86_64/9.2.0a-1/libexec/gcc/x86_64-redhat-linux/9.2.0/:/opt/gcc/x86_64/9.2.0a-1/libexec/gcc/x86_64-redhat-linux/9.2.0/:/opt/gcc/x86_64/9.2.0a-1/libexec/gcc/x86_64-redhat-linux/:/opt/gcc/x86_64/9.2.0a-1/lib/gcc/x86_64-redhat-linux/9.2.0/:/opt/gcc/x86_64/9.2.0a-1/lib/gcc/x86_64-redhat-linux/
LIBRARY_PATH=/opt/gcc/x86_64/9.2.0a-1/lib/gcc/x86_64-redhat-linux/9.2.0/:/opt/gcc/x86_64/9.2.0a-1/lib/gcc/x86_64-redhat-linux/9.2.0/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/opt/gcc/x86_64/9.2.0a-1/lib/gcc/x86_64-redhat-linux/9.2.0/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-o' 'gccBug' '-Wall' '-Werror'
'-Wextra' '-O3' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
 /opt/gcc/x86_64/9.2.0a-1/libexec/gcc/x86_64-redhat-linux/9.2.0/collect2
-plugin
/opt/gcc/x86_64/9.2.0a-1/libexec/gcc/x86_64-redhat-linux/9.2.0/liblto_plugin.so
-plugin-opt=/opt/gcc/x86_64/9.2.0a-1/libexec/gcc/x86_64-redhat-linux/9.2.0/lto-wrapper
-plugin-opt=-fresolution=TestGccBug.res -plugin-opt=-pass-through=-lgcc_s
-plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc
-plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc
--eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o
gccBug /lib/../lib64/crt1.o /lib/../lib64/crti.o
/opt/gcc/x86_64/9.2.0a-1/lib/gcc/x86_64-redhat-linux/9.2.0/crtbegin.o
-L/opt/gcc/x86_64/9.2.0a-1/lib/gcc/x86_64-redhat-linux/9.2.0
-L/opt/gcc/x86_64/9.2.0a-1/lib/gcc/x86_64-redhat-linux/9.2.0/../../../../lib64
-L/lib/../lib64 -L/usr/lib/../lib64
-L/opt/gcc/x86_64/9.2.0a-1/lib/gcc/x86_64-redhat-linux/9.2.0/../../..
TestGccBug.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc
/opt/gcc/x86_64/9.2.0a-1/lib/gcc/x86_64-redhat-linux/9.2.0/crtend.o
/lib/../lib64/crtn.o
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-o' 'gccBug' '-Wall' '-Werror'
'-Wextra' '-O3' '-shared-libgcc' '-mtune=generic' '-march=x86-64'

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Bug c++/95202] Assignment to a member is wrongly optimized away by g++ with -fstrict-aliasing
  2020-05-19 11:39 [Bug c++/95202] New: Assignment to a member is wrongly optimized away by g++ with -fstrict-aliasing syomalina at gmail dot com
@ 2020-05-19 17:18 ` rguenth at gcc dot gnu.org
  2020-06-01 12:42 ` marxin at gcc dot gnu.org
  2021-09-19  9:25 ` pinskia at gcc dot gnu.org
  2 siblings, 0 replies; 4+ messages in thread
From: rguenth at gcc dot gnu.org @ 2020-05-19 17:18 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95202

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |needs-bisection

--- Comment #1 from Richard Biener <rguenth at gcc dot gnu.org> ---
bisection might find the fix

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Bug c++/95202] Assignment to a member is wrongly optimized away by g++ with -fstrict-aliasing
  2020-05-19 11:39 [Bug c++/95202] New: Assignment to a member is wrongly optimized away by g++ with -fstrict-aliasing syomalina at gmail dot com
  2020-05-19 17:18 ` [Bug c++/95202] " rguenth at gcc dot gnu.org
@ 2020-06-01 12:42 ` marxin at gcc dot gnu.org
  2021-09-19  9:25 ` pinskia at gcc dot gnu.org
  2 siblings, 0 replies; 4+ messages in thread
From: marxin at gcc dot gnu.org @ 2020-06-01 12:42 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95202

Martin Liška <marxin at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |marxin at gcc dot gnu.org
   Last reconfirmed|                            |2020-06-01
             Status|UNCONFIRMED                 |NEW
           Keywords|needs-bisection             |
     Ever confirmed|0                           |1

--- Comment #2 from Martin Liška <marxin at gcc dot gnu.org> ---
> # -O1 with -fstrict-aliasing
> $ rm gccBug; g++ -o gccBug -Wall -Werror -O1 -fstrict-aliasing TestGccBug.cpp && ./gccBug 

This configuration fails on GCC 8 and 9 branches, started with:

$   r9-4245-gdc3221e1e3d3a39d(20 Nov 2018 09:31)(rguenther@suse.de): [took:
0.754s] result: FAILED (1)
ERROR: Invalid idx: 0! Capacity: 4, number elements: 0
re PR middle-end/83215 (C++: struct with char-array assumed to alias with
everything)

2018-11-20  Richard Biener  <rguenther@suse.de>

        PR middle-end/83215
        * alias.c (component_uses_parent_alias_set_from): Remove
        alias-set zero and TYPE_TYPELESS_STORAGE case both already
        handled in other ways.

        * g++.dg/tree-ssa/pr83215.C: New testcase.

From-SVN: r266305

and is gone since:

  r10-5940-g6b8df3e421b56bb7(14 Jan 2020 09:47)(rguenther@suse.de): [took:
0.822s] result: OK
Test finished.
PR middle-end/93246 - missing alias subsets

Starting with the introduction of TYPE_TYPELESS_STORAGE the situation
of having a alias-set zero aggregate field became more common which
prevents recording alias-sets of fields of said aggregate as subset
of the outer aggregate.  component_uses_parent_alias_set_from in the
past fended off some of the issues with that but the alias oracles
use of the alias set of the base of an access path never appropriately
handled it.

The following makes it so that alias-sets of fields of alias-set zero
aggregate fields are still recorded as subset of the container.

2020-01-14  Richard Biener  <rguenther@suse.de>

        PR middle-end/93246
        * alias.c (record_component_aliases): Take superset to record
        into, recurse for alias-set zero fields.
        (record_component_aliases): New oveerload wrapping around the above.

        * g++.dg/torture/pr93246.C: New testcase.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Bug c++/95202] Assignment to a member is wrongly optimized away by g++ with -fstrict-aliasing
  2020-05-19 11:39 [Bug c++/95202] New: Assignment to a member is wrongly optimized away by g++ with -fstrict-aliasing syomalina at gmail dot com
  2020-05-19 17:18 ` [Bug c++/95202] " rguenth at gcc dot gnu.org
  2020-06-01 12:42 ` marxin at gcc dot gnu.org
@ 2021-09-19  9:25 ` pinskia at gcc dot gnu.org
  2 siblings, 0 replies; 4+ messages in thread
From: pinskia at gcc dot gnu.org @ 2021-09-19  9:25 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95202

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Resolution|---                         |DUPLICATE
             Status|NEW                         |RESOLVED

--- Comment #3 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
So this is a dup of bug 93246.

*** This bug has been marked as a duplicate of bug 93246 ***

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2021-09-19  9:25 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-19 11:39 [Bug c++/95202] New: Assignment to a member is wrongly optimized away by g++ with -fstrict-aliasing syomalina at gmail dot com
2020-05-19 17:18 ` [Bug c++/95202] " rguenth at gcc dot gnu.org
2020-06-01 12:42 ` marxin at gcc dot gnu.org
2021-09-19  9:25 ` pinskia at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).