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

Support formatting nested exceptions #3385

Closed
Krzmbrzl opened this issue Apr 14, 2023 · 3 comments
Closed

Support formatting nested exceptions #3385

Krzmbrzl opened this issue Apr 14, 2023 · 3 comments

Comments

@Krzmbrzl
Copy link

As far as I can tell, support for formatting regular exceptions has been added via #3062 and this was then extended by #3076.
However, this implementation is currently missing support for nested exceptions (see e.g. https://cplusplus.com/reference/exception/nested_exception/ and https://riptutorial.com/cplusplus/example/18879/nested-exception).

When dealing with nested exceptions, simply calling what() only reveals the message of the topmost exception, but all messages from the nested exceptions (which are typically more interesting) are ignored. In order to print all messages, something along the line of this is typically used (source)

// recursively print exception whats:
void print_what (const std::exception& e) {
    std::cerr << e.what() << '\n';
    try {
        std::rethrow_if_nested(e);
    } catch (const std::exception& nested) {
        std::cerr << "nested: ";
        print_what(nested);
    }
}

It'd be great if formatting an exception with this library would also print the messages of the nested exceptions in order to save users the hassle of having to take care of this themselves.

However, since implementing this requires rethrowing, I guess this is incompatible with builds that disable exceptions altogether (which, as I understand it, is a support case for this library). I guess there has to be some preprocessor magic to remove this feature in builds without exceptions.

Godbolt: https://godbolt.org/z/Yc3KsY193 (currently fails to compile as apparently the version of fmt that is used doesn't support exceptions yet)

@Skylion007
Copy link

However, since implementing this requires rethrowing, I guess this is incompatible with builds that disable exceptions altogether (which, as I understand it, is a support case for this library). I guess there has to be some preprocessor magic to remove this feature in builds without exceptions.

it actually doesn't require rethrowing necessarily, but it may require RTTI otherwise. (Dynamic cast to nested exception and then get the exception ptr of the nested exception).

@ShawnZhong
Copy link
Contributor

I can successfully get an exception_ptr from a nested exception, but there is not much you can do with it other than calling rethrow_exception on it.

If you are comfortable with casting exception_ptr to a std::exception * (which is definitely UB), then the following code snippet would work:

void print_exception(const std::exception &e) {
  fmt::print("{}\n", e.what());
  if (auto nep = dynamic_cast<const std::nested_exception *>(&e)) {
    auto ptr = nep->nested_ptr();
    print_exception(**(std::exception **)(&ptr));
  }
}

@vitaut
Copy link
Contributor

vitaut commented Jul 2, 2023

Closing since it is possible to do this via the usual extension API but a PR to add this to the existing formatter would be welcome too.

@vitaut vitaut closed this as completed Jul 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants