[prev in list] [next in list] [prev in thread] [next in thread] 

List:       gcc-bugs
Subject:    [Bug c++/70018] New: Possible issue around IPO and C++ inline functions
From:       "sanjoy at playingwithpointers dot com" <gcc-bugzilla () gcc ! gnu ! org>
Date:       2016-02-29 19:20:01
Message-ID: bug-70018-4 () http ! gcc ! gnu ! org/bugzilla/
[Download RAW message or body]

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

            Bug ID: 70018
           Summary: Possible issue around IPO and C++ inline functions
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: sanjoy at playingwithpointers dot com
  Target Milestone: ---

I don't grok gcc internals so I cannot write a terribly well-informed
bug report, but GCC 5.3.0 seems to miscompile
https://github.com/sanjoy/comdat-ipo

This was discussed on llvm-dev:
http://lists.llvm.org/pipermail/llvm-dev/2016-February/095833.html and
the thread contains a description of the underlying cause for
LLVM/Clang.

The TL;DR is that for C++ inline functions (and other functions with
similar linkage rules), you can override a more-refined function
implementation with a less-refined one at link time, and that can
retroactively invalidate earlier transforms, where "refined" in this
case means "undefined in fewer situations".

E.g. if we have (this is very similar to the reproducer above minus
some mechanical details):

inline void foo(int* ptr) {
  100 / ptr[0];
}

void bar(int* ptr) {
  *ptr = 40;
  foo(ptr):
  *ptr = 50;
}

=>

inline void foo(int* ptr) {
  // 100 / ptr[0]; removed, dead code
}

void bar(int* ptr) {
  *ptr = 40;
  foo(ptr):
  *ptr = 50;
}

=>

inline void foo(int* ptr) {
  // 100 / ptr[0]; removed, dead code
}

void bar(int* ptr) {
  // *ptr = 40; dead store, since foo does not read memory
  foo(ptr):
  *ptr = 50;
}

we've miscompiled if *ptr == 0 on entry to bar, and foo is replaced
with the original definition at link time.=
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic