-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
Fix GCC 15 build errors with FMT_MODULE=ON #4347
Conversation
87f88bf
to
9381bba
Compare
Tried to make the linter happy, but not agreeing with it in std.h L278 |
There was a problem hiding this 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
include/fmt/std.h
Outdated
FMT_BEGIN_EXPORT | ||
template <typename Char> struct formatter<std::filesystem::path, Char> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Considering that clang and MSVC accept export on partial specializations, I don't think we should make this and similar changes until there is clarity which one is correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this is the relevant paper that made export of partial specializations ill-formed: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2615r0.html.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the correct fix is to remove FMT_EXPORT
without wrapping in FMT_BEGIN_EXPORT
/ FMT_END_EXPORT
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. I'll take your word for it as I'm not sure I'm qualified enough to be 100% certain it's not going to break anything. I didn't get anywhere trying to build the test-module.cc and only have a very minimal test project to test these changes with.
src/os.cc
Outdated
// Return type of read and write functions. | ||
# ifdef _WIN32 | ||
# define rwresult int | ||
# elif FMT_USE_FCNTL | ||
# define rwresult ssize_t | ||
# endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a way to fix this error:
In file included from /mnt/d/dev/libs/tools/fmt/src/fmt.cc:148:
/mnt/d/dev/libs/tools/fmt/src/os.cc:74:7: error: ‘using {anonymous}::rwresult = ssize_t’ exposes TU-local entity ‘{anonymous}’
74 | using rwresult = ssize_t;
| ^~~~~~~~
/mnt/d/dev/libs/tools/fmt/src/os.cc:62:1: note: ‘{anonymous}’ declared with internal linkage
62 | namespace {
| ^~~~~~~~~
When using using
, rwresult
becomes a TU-local type and has internal linkage because it's in anonymous namespace.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typedefs are just aliases and shouldn't have linkage of their own. And even if they had we wouldn't want to replace them with macros. Please revert.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding is that typedefs inherit the linkage of the type they refer to. This means that the name rwresult
has linkage because - in that case - it refers to ssize_t
, which is a fundamental type and therefore has linkage itself (see basic.link).
I initially thought of 2 ways to work around this (maybe there are other ways):
- take the
using rwresult = <type>
out of the anonymous namespace, but then this exposesrwresult
, which was hidden previously so I elected not to do that - use a macro which can be
#undef
ed hence not exposing therwresult
name
I'm happy to take rwresult
out of the anonymous namespace if you don't mind exposing rwresult
, unless there is a more elegant solution.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure gcc is correct here - it even seems to be inconsistent not just with other compilers but with itself since there are other TU-local symbols here like convert_rwcount
. I suggest reverting this change and possibly opening an issue in gcc to clarify why it complains for some symbols and not the other.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, indeed, it's weird that convert_rwcount
doesn't raise anything. Enquiry sent on gcc-help, I'll keep you posted.
@tkhyn do you plan to update the PR, addressing the review comments, or shall we close it for now? |
Yes I did intend to follow up, but didn't have the time to look into the While filing a GCC issue, I found this one. Which means you were right and GCC was incorrect in reporting an error with Push coming soon to revert the macro hack and remove the FMT_EXPORT statements. |
This fixes 'declaration of partial specialization in unbraced export-declaration' errors in GCC 15
LGTM but could you check that removing |
Clang + libstdc++ builds fine. Clang + libc++ builds were broken and still are ( However as mentioned earlier I didn't manage to build |
Merged, thanks! |
Hi again,
I'm not sure how far you want to support GCC 15 before it's released, but here are a few fixes in case
fmt
needs to be built as a module with it. I doesn't look like merging the changes now would have any adverse effect.Here are the steps to reproduce, with cmake 3.31.5 and GCC 15.0.1 20250205 (I couldn't build today's master for some reason) installed in /opt/gcc-dev:
before 'Fix partial specialization in unbraced export-declaration':
I couldn't find details or a reference in the C++ standard to fully understand the whys but my understanding is you can't directly
export
a partial template specialization. I think I got all the export blocks right but it would definitely warrant another checkbefore 'Fix TU-local entity exposition errors':
These 2 errors are related to the implementation of P1815, which aims at "forbidding exposure of internal-linkage constructs to other translation units" and may make its way into Clang at some stage.
Better suggestions welcome for the name of the previously unnamed struct instantiated in
div_small_pow10_infos
informat-inl.h
. As it's already indetails::dragonbox
its actual name doesn't matter much.I have checked it didn't break GCC 14, Clang 21 nor MSVC builds, whether
FMT_MODULE
is on or not.