https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62015
Bug ID: 62015 Summary: ipa-cp-clone uses a clone that is too specialized for the call context Product: gcc Version: 4.10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: ipa Assignee: unassigned at gcc dot gnu.org Reporter: oremanj at mit dot edu In the C++ program below, interprocedural constant propagation cloning creates a clone of A::adjust() specialized for adjust(Side::Invalid, false). This clone is then used for an adjust(side, false) call when there is no way to prove side == Side::Invalid. This bug is present in gcc 4.8.2, is not present in 4.7.3, and is still present in a version compiled from today's SVN. Using an optimization level less than -O3 or passing -fno-ipa-cp-clone prevents the bug from manifesting. The onset of the bug was bisected to commit r193410. $ cat t.cc extern "C" int printf(const char *fmt, ...); struct Side { enum _Value { Left, Right, Invalid }; constexpr Side() : _value(Invalid) {} constexpr Side(_Value value) : _value(value) {} operator _Value() const { return (_Value)_value; } private: char _value; }; struct A { void init(); void adjust(Side side, bool final); void move(Side side); }; void A::init() { adjust(Side::Invalid, false); } __attribute__((noinline)) void A::adjust(Side side, bool final) { printf("adjust: side is %d, final %d\n", (int)side, final); } void A::move(Side side) { printf("move: side is %d\n", (int)side); adjust(side, false); adjust(side, true); } int main() { A t; t.move(Side::Left); } $ g++49 -v Using built-in specs. COLLECT_GCC=g++49 COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc49/gcc/x86_64-unknown-linux-gnu/4.10.0/lto-wrapper Target: x86_64-unknown-linux-gnu Configured with: ../gcc-trunk/configure --prefix=/usr/local --disable-nls --libdir=/usr/local/lib/gcc49 --libexecdir=/usr/local/libexec/gcc49 --program-suffix=49 --with-gmp=/usr/local --with-gxx-include-dir=/usr/local/lib/gcc49/include/c++/ --with-libiconv-prefix=/usr/local --with-system-zlib --disable-rpath --enable-languages=c,c++ --mandir=/usr/local/man --infodir=/usr/local/info/gcc49 --disable-initfini-array --disable-install-libiberty Thread model: posix gcc version 4.10.0 20140804 (experimental) (GCC) $ g++49 -Wall -Wextra -o t t.cc -std=c++11 -O3 $ ./t move: side is 0 adjust: side is 2, final 0 adjust: side is 0, final 1 The output should be 'side is 0' on all three lines.