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

Add class name output to formatter for std::exception #3076

Merged
merged 1 commit into from
Sep 10, 2022

Conversation

phprus
Copy link
Contributor

@phprus phprus commented Sep 2, 2022

Discussion:
#3062 (comment)

@phprus phprus marked this pull request as draft September 3, 2022 08:49
@phprus phprus marked this pull request as ready for review September 3, 2022 09:30
@phprus
Copy link
Contributor Author

phprus commented Sep 3, 2022

Rebased and fixed bug related to GCC < 5.

@phprus
Copy link
Contributor Author

phprus commented Sep 3, 2022

cc @Baardi, @zach2good

@Baardi
Copy link
Contributor

Baardi commented Sep 3, 2022

I think this type of formatting looks good for exceptions, considering how important the exception type is, e.g. when logging errors.
It also looks consistent with the c# way of formatting exceptions, except for the callstack, which wouldn't be possible to include anways. Not that c++/fmtlib necessarily have to follow other languages on everything.

bilde
c# with string.Format on the left, c++ with fmtlib to the right

I guess the main issues would be that it locks support to the main compilers + and that the output isn't completely consistent, which I guess would violate the point below.

ref:
bilde

Copy link
Contributor

@vitaut vitaut left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR!

Comment on lines 489 to 497
FMT_CONSTEXPR_CHAR_TRAITS bool starts_with(
basic_string_view<Char> sv) const noexcept {
return size_ >= sv.size_ &&
std::char_traits<Char>::compare(data_, sv.data_, sv.size_) == 0;
}
FMT_CONSTEXPR_CHAR_TRAITS bool starts_with(Char c) const noexcept {
return size_ >= 1 && std::char_traits<Char>::eq(*data_, c);
}
FMT_CONSTEXPR_CHAR_TRAITS bool starts_with(const Char* s) const {
return starts_with(basic_string_view<Char>(s));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you move this to a separate PR and add unit tests?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR #3080

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vitaut
Rebased after merge #3080

@vitaut
Copy link
Contributor

vitaut commented Sep 4, 2022

I guess the main issues would be that it locks support to the main compilers + and that the output isn't completely consistent, which I guess would violate the point below.

Hmm, that's a good point.

@phprus
Copy link
Contributor Author

phprus commented Sep 4, 2022

@vitaut
Visual Studio ABI and Itanium ABI will show human-readable names.
Other ABIs will show compiler-specific (mangled) names. But other ABIs are rare.

@vitaut
Copy link
Contributor

vitaut commented Sep 6, 2022

I think we should keep the default format independent of ABI. Let's make type output an opt-in via a separate specifier (maybe t?)

@phprus
Copy link
Contributor Author

phprus commented Sep 7, 2022

Like range format specifications:
Spec: {:t:OtherStringSpec}, Out: exception_class: exception message
or
Spec: {::OtherStringSpec} or {::} or {}, Out: exception message
?

@phprus
Copy link
Contributor Author

phprus commented Sep 7, 2022

@vitaut
Implemented.

@Baardi
Copy link
Contributor

Baardi commented Sep 9, 2022

I think we should keep the default format independent of ABI. Let's make type output an opt-in via a separate specifier (maybe t?)

I like the idea. It makes sense to format the content of an item by default, which I guess would be the .what() on exceptions.
And for exceptions it also makes sense to provide and easy way to format the type, considering how important it is.
While I think in general it would be better to provide the type by default in exception-formatting, it makes sense to drop it, as there's no standardized way to format the type.

Btw @phprus, with the current PR, it still formats the whole typeinfo.name(), even if it's not one of the "big 3" compilers.
Is there any way to avoid specifying the type-formatter if it's not a "supported ABI"? The reason I wonder, is because the user would then be free to specify a better formatter himself

@vitaut
Copy link
Contributor

vitaut commented Sep 9, 2022

Please don't use : in format specs because it will interfere with ranges. I think t should be a presentation type specifier like s for strings. We don't really need to combine it with other presentation specifiers.

@phprus
Copy link
Contributor Author

phprus commented Sep 9, 2022

@Baardi
I think the formatter should always be defined.
typeinfo.name() will return the mangled name for any ABI. I think that if the rules for demangling the name are not known, then it is better to output it unchanged.

@Baardi
Copy link
Contributor

Baardi commented Sep 9, 2022

@Baardi I think the formatter should always be defined. typeinfo.name() will return the mangled name for any ABI. I think that if the rules for demangling the name are not known, then it is better to output it unchanged.

Good point. There's argument both ways. I guess that not specifying the formatter could lead to unexpected exceptions etc,, when trying to write cross-platform code, which would be a good argument for always speciyfing it. And I guess "important" platforms could always create PR's adding proper formatting, if they're not happy with the current way it is formatted.

Anyways, regardless of whether this gets merged or not.
Thanks @vitaut for creating an excellent formatting library, and thanks @phprus for implementing my idea, it would've taken significantly more time for me to create a PR.

@phprus
Copy link
Contributor Author

phprus commented Sep 9, 2022

@vitaut
Implemented.

Copy link
Contributor

@vitaut vitaut left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly looks good. A few comments/questions inline.

@@ -28,6 +31,16 @@
# endif
#endif

#if FMT_HAS_INCLUDE(<cxxabi.h>) || defined(__GLIBCXX__)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need __GLIBCXX__ check? Isn't FMT_HAS_INCLUDE enough?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GCC 4 does not support FMT_HAS_INCLUDE, but it does support demangling.
It is possible to check for the presence of libstdc++ instead of gcc version, since all libstdc++ support demangling.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a comment that the __GLIBCXX__ is for gcc 4 here then?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -28,6 +31,16 @@
# endif
#endif

#if FMT_HAS_INCLUDE(<cxxabi.h>) || defined(__GLIBCXX__)
# include <cxxabi.h>
# ifndef __GABIXX_CXXABI_H__
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is __GABIXX_CXXABI_H__ check for?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For Android.
See comment from Boost:

// For some archtectures (mips, mips64, x86, x86_64) cxxabi.h in Android NDK is implemented by gabi++ library
// (https://android.googlesource.com/platform/ndk/+/master/sources/cxx-stl/gabi++/), which does not implement
// abi::__cxa_demangle(). We detect this implementation by checking the include guard here.

https://github.com/boostorg/core/blob/162a4e1d24d1cab4f24cbca9489203d891f352e6/include/boost/core/demangle.hpp#L33-L35

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a comment here too?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.
And I renamed FMT_HAS_CXXABI_H to FMT_HAS_ABI_CXA_DEMANGLE.

include/fmt/std.h Outdated Show resolved Hide resolved
include/fmt/std.h Outdated Show resolved Hide resolved
@phprus phprus force-pushed the std-exception-1 branch 2 times, most recently from d30bf69 to 3ed02f7 Compare September 10, 2022 13:12
@vitaut vitaut merged commit 21c2137 into fmtlib:master Sep 10, 2022
@vitaut
Copy link
Contributor

vitaut commented Sep 10, 2022

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants