Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[libc++] Fix the behavior of throwing operator new under -fno-exceptions #69498

Merged
merged 15 commits into from
Jan 23, 2024

Commits on Dec 19, 2023

  1. [libc++] Fix the behavior of throwing operator new under -fno-excep…

    …tions
    
    In D144319, Clang tried to land a change that would cause some functions
    that are not supposed to return nullptr to optimize better. As reported
    in https://reviews.llvm.org/D144319#4203982, libc++ started seeing failures
    in its CI shortly after this change was landed.
    
    As explained in D146379, the reason for these failures is that libc++'s
    throwing `operator new` can in fact return nullptr when compiled with
    exceptions disabled. However, this contradicts the Standard, which
    clearly says that the throwing version of `operator new(size_t)`
    should never return nullptr. This is actually a long standing issue.
    I've previously seen a case where LTO would optimize incorrectly based
    on the assumption that `operator new` doesn't return nullptr, an
    assumption that was violated in that case because libc++.dylib was
    compiled with -fno-exceptions.
    
    Unfortunately, fixing this is kind of tricky. The Standard has a few
    requirements for the allocation functions, some of which are impossible
    to satisfy under -fno-exceptions:
    1. `operator new(size_t)` must never return nullptr
    2. `operator new(size_t, nothrow_t)` must call the throwing version
         and return nullptr on failure to allocate
    3. We can't throw exceptions when compiled with -fno-exceptions
    
    In the case where exceptions are enabled, things work nicely. `new(size_t)`
    throws and `new(size_t, nothrow_t)` uses a try-catch to return nullptr.
    However, when compiling the library with -fno-exceptions, we can't throw
    an exception from `new(size_t)`, and we can't catch anything from
    `new(size_t, nothrow_t)`. The only thing we can do from `new(size_t)`
    is actually abort the program, which does not make it possible for
    `new(size_t, nothrow_t)` to catch something and return nullptr.
    
    This patch makes the following changes:
    1. When compiled with -fno-exceptions, the throwing version of
       `operator new` will now abort on failure instead of returning
       nullptr on failure. This resolves the issue that the compiler
       could mis-compile based on the assumption that nullptr is never
       returned. This constitutes an API and ABI breaking change for
       folks compiling the library with -fno-exceptions (which is not
       the general public, who merely uses libc++ headers but use a
       shared library that has already been compiled). This should mostly
       impact vendors and other folks who compile libc++.dylib themselves.
    
    2. When the library is compiled with -fexceptions, the nothrow version
       of `operator new` has no change. When the library is compiled with
       -fno-exceptions, the nothrow version of `operator new` will now check
       whether the throwing version of `operator new` has been overridden.
       If it has not been overridden, then it will use an implementation
       equivalent to that of the throwing `operator new`, except it will
       return nullptr on failure to allocate (instead of terminating).
       However, if the throwing `operator new` has been overridden, it is
       now an error NOT to also override the nothrow `operator new`. Indeed,
       there is no way for us to implement a valid nothrow `operator new`
       without knowing the exact implementation of the throwing version.
    
    rdar://103958777
    
    Differential Revision: https://reviews.llvm.org/D150610
    ldionne committed Dec 19, 2023
    Configuration menu
    Copy the full SHA
    6f89b11 View commit details
    Browse the repository at this point in the history
  2. Improve diagnostic

    ldionne committed Dec 19, 2023
    Configuration menu
    Copy the full SHA
    1b5144f View commit details
    Browse the repository at this point in the history
  3. Configuration menu
    Copy the full SHA
    0f2b77f View commit details
    Browse the repository at this point in the history
  4. Configuration menu
    Copy the full SHA
    82d3e73 View commit details
    Browse the repository at this point in the history
  5. Configuration menu
    Copy the full SHA
    3980914 View commit details
    Browse the repository at this point in the history
  6. Fix formatting

    ldionne committed Dec 19, 2023
    Configuration menu
    Copy the full SHA
    e9863c3 View commit details
    Browse the repository at this point in the history

Commits on Jan 16, 2024

  1. Configuration menu
    Copy the full SHA
    f05c8a3 View commit details
    Browse the repository at this point in the history
  2. Configuration menu
    Copy the full SHA
    12e3239 View commit details
    Browse the repository at this point in the history
  3. Configuration menu
    Copy the full SHA
    170c592 View commit details
    Browse the repository at this point in the history

Commits on Jan 22, 2024

  1. Configuration menu
    Copy the full SHA
    14fe81e View commit details
    Browse the repository at this point in the history
  2. Move to src/

    ldionne committed Jan 22, 2024
    Configuration menu
    Copy the full SHA
    cf6209a View commit details
    Browse the repository at this point in the history
  3. Configuration menu
    Copy the full SHA
    64b2e5c View commit details
    Browse the repository at this point in the history
  4. Configuration menu
    Copy the full SHA
    f416bf0 View commit details
    Browse the repository at this point in the history
  5. Refactor

    ldionne committed Jan 22, 2024
    Configuration menu
    Copy the full SHA
    d1a0648 View commit details
    Browse the repository at this point in the history

Commits on Jan 23, 2024

  1. Fix test

    ldionne committed Jan 23, 2024
    Configuration menu
    Copy the full SHA
    609ba8d View commit details
    Browse the repository at this point in the history