Skip to content

Exceptions thrown inside the GCC-compiled libstdc++.so can't be caught by EDG-compiled code (terminate) #445

Description

@mborland

Issue Summary

With the C-generating back end, exception handling is lowered to EDG's own
runtime (libedgrt, lib_src/throw.c): handlers are a stack of frames rooted
at __curr_eh_stack_entry. libstdc++.so is compiled by GCC and throws with
the Itanium C++ ABI's __cxa_throw, which never looks at EDG's frames. So a
catch in EDG-compiled code never matches an exception thrown inside
libstdc++.so, and the program calls terminate(). The same exception thrown
from EDG-compiled code is caught normally.

Anything that throws from inside libstdc++.so is affected:

  • std::stoi and friends (std::invalid_argument)
  • std::vector::at and std::string::at, which call std::__throw_out_of_range_fmt in the .so
  • iostreams with exceptions enabled (std::__throw_ios_failure)
  • std::locale("name") (std::runtime_error)
  • presumably also std::filesystem and std::thread errors (not tested individually)

In Boost, this fails Boost.JSON's value, Boost.Regex's regex_regress and
Boost.Charconv's github_issue_122.

Reproducing Source Code

#include <stdexcept>
#include <string>

int main() {
  try {
    (void)std::stoi("x"); /* throws std::invalid_argument from libstdc++.so */
  } catch (const std::invalid_argument &) {
    return 0;
  }
  return 1;
}

Command-line Options

EDG_USE_SYSTEM_HEADERS=1 eccp --c++17 libstdcxx_throw.cpp -o libstdcxx_throw && ./libstdcxx_throw

Type of Issue

[Back End] There is a problem with the generated C code.

Additional Details

Expected: exit status 0 (g++ 15.3.1: 0).
Actual (linux-gcc-release and linux-gcc-debug): 3 of 3 runs:

C++ runtime abort: terminate() called by the exception handling mechanism

and Aborted, exit status 134. A throw std::runtime_error("x") written in
the program itself is caught. std::string("abc").at(10) aborts the same way.

The problem is in how EDG's runtime library works with libstdc++.so rather
than in the generated C as such; none of the issue types fits exactly.
libedgrt has no bridge for foreign exceptions: the only __cxa_* throw
routine it defines is __cxa_throw_bad_array_new_length
(lib_src/vec_newdel.c:1143). bases/docker/dev-env/gcc/edg_eccp_config:33
links -lstdc++ -lgcc_s -lpthread.

Possible directions (untested):

  • libedgrt could define the std::__throw_* helpers (__throw_out_of_range_fmt, __throw_length_error, __throw_invalid_argument, ...) to throw with EDG's mechanism. That would cover throws that start in header code compiled by EDG, such as vector::at, and possibly some inside the .so, depending on symbol interposition.
  • The runtime could catch foreign (Itanium) exceptions at the boundary and rethrow them through EDG's mechanism.

Backtraces of the Boost failures (gdb at the abort):

  • Boost.JSON value: __cxa_throw (libstdc++.so.6) ←
    std::__throw_ios_failure (libstdc++.so.6) ← std::basic_ios<char>::clear
    (libstdc++.so.6) ← boost::json::operator>>(std::istream &, value &)
  • Boost.Regex regex_regress: __cxa_throw ← std::__throw_out_of_range_fmt
    (libstdc++.so.6) ← std::vector<std::pair<size_t, size_t>>::_M_range_check
    ← at ← boost::basic_regex<char>::subexpression
  • Boost.Charconv github_issue_122: __cxa_throw ←
    std::__throw_runtime_error ← std::locale::facet::_S_create_c_locale ←
    std::locale::_Impl::_Impl (all libstdc++.so.6)

Environment: edgcpp/dev-env Docker image (Fedora 43, GCC 15.3.1) on
x86-64, boost branch at c36e03a67c. EDG_USE_SYSTEM_HEADERS=1 makes eccp
use GCC 15's headers (libstdc++) and pass --gnu_version=150301
(bases/docker/dev-env/gcc/edg_eccp_config).

Reproducing (Standard) Configuration(s)

linux-gcc-release

Reproducing (Non-standard) Configuration

No response

I acknowledge that:

  • I have checked open issues and existing discussions before filing this report.
  • The reproducing source code that I have provided does not depend on headers that I have not included with my submission.
  • I have reduced the reproducing source code to the best of my ability.
  • I have selected at least one standard configuration or uploaded a non-standard configuration dump.
  • I understand code shared via this form is NOT confidential.
  • I have permission to share the reproducing source code and grant permission for the project to use the source code (or derivatives of the source code) to create tests.
  • I agree that any tests created using the reproducing source code (or deriatives of it) will be licensed under project license unless I included a LICENSE.txt file in my .zip or .tar.gz upload. If I included a LICENSE.txt file, any tests created using the reproducing source code will be governed by the terms of the license I provided instead.

Activity

  1. added theissue type on Oct 30, 2026
  2. wchilders-nvidia commented on Oct 30, 2026

    @wchilders-nvidia
    Member

    This is less of a bug and more of a feature request for compatibility with the GNU exception implementation.

  3. changed the issue type fromtoon Oct 30, 2026
  4. mborland commented on Oct 30, 2026

    @mborland
    ContributorAuthor

    4. This is less of a bug and more of a feature request for compatibility with the GNU exception implementation.

    Labels have been updated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions