-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[libc++] Allow the use of extensions in the implementation #79532
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
Conversation
@llvm/pr-subscribers-libcxx Author: Nikolas Klauser (philnik777) ChangesFull diff: https://github.com/llvm/llvm-project/pull/79532.diff 2 Files Affected:
diff --git a/libcxx/include/__config b/libcxx/include/__config
index 9fc608ee14320dc..aece8438e94207f 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -787,6 +787,23 @@ typedef __char32_t char32_t;
# define _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION _LIBCPP_ALWAYS_INLINE
# endif
+# ifdef _LIBCPP_COMPILER_CLANG_BASED
+# define _LIBCPP_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
+# define _LIBCPP_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
+# define _LIBCPP_CLANG_DIAGNOSTIC_IGNORED(str) _Pragma(_LIBCPP_TOSTRING(clang diagnostic ignored str))
+# define _LIBCPP_GCC_DIAGNOSTIC_IGNORED(str)
+# elif defined(_LIBCPP_COMPILER_GCC)
+# define _LIBCPP_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
+# define _LIBCPP_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
+# define _LIBCPP_CLANG_DIAGNOSTIC_IGNORED(str)
+# define _LIBCPP_GCC_DIAGNOSTIC_IGNORED(str) _Pragma(_LIBCPP_TOSTRING(GCC diagnostic ignored str))
+# else
+# define _LIBCPP_DIAGNOSTIC_PUSH
+# define _LIBCPP_DIAGNOSTIC_POP
+# define _LIBCPP_CLANG_DIAGNOSTIC_IGNORED(str)
+# define _LIBCPP_GCC_DIAGNOSTIC_IGNORED(str)
+# endif
+
# if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_FAST
# define _LIBCPP_HARDENING_SIG f
# elif _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_EXTENSIVE
@@ -881,14 +898,26 @@ typedef __char32_t char32_t;
// Inline namespaces are available in Clang/GCC/MSVC regardless of C++ dialect.
// clang-format off
-# define _LIBCPP_BEGIN_NAMESPACE_STD namespace _LIBCPP_TYPE_VISIBILITY_DEFAULT std { \
+# define _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_DIAGNOSTIC_PUSH \
+ _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++11-extensions") \
+ _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++14-extensions") \
+ _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++17-extensions") \
+ _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++20-extensions") \
+ _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++23-extensions") \
+ _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++26-extensions") \
+ _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++14-extensions") \
+ _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++17-extensions") \
+ _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++20-extensions") \
+ _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++23-extensions") \
+ _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++26-extensions") \
+ namespace _LIBCPP_TYPE_VISIBILITY_DEFAULT std { \
inline namespace _LIBCPP_ABI_NAMESPACE {
-# define _LIBCPP_END_NAMESPACE_STD }}
+# define _LIBCPP_END_NAMESPACE_STD }} _LIBCPP_DIAGNOSTIC_POP
# define _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM _LIBCPP_BEGIN_NAMESPACE_STD \
inline namespace __fs { namespace filesystem {
-# define _LIBCPP_END_NAMESPACE_FILESYSTEM _LIBCPP_END_NAMESPACE_STD }}
+# define _LIBCPP_END_NAMESPACE_FILESYSTEM }} _LIBCPP_END_NAMESPACE_STD
// clang-format on
# if __has_attribute(__enable_if__)
@@ -1322,23 +1351,6 @@ __sanitizer_verify_double_ended_contiguous_container(const void*, const void*, c
// the ABI inconsistent.
# endif
-# ifdef _LIBCPP_COMPILER_CLANG_BASED
-# define _LIBCPP_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
-# define _LIBCPP_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
-# define _LIBCPP_CLANG_DIAGNOSTIC_IGNORED(str) _Pragma(_LIBCPP_TOSTRING(clang diagnostic ignored str))
-# define _LIBCPP_GCC_DIAGNOSTIC_IGNORED(str)
-# elif defined(_LIBCPP_COMPILER_GCC)
-# define _LIBCPP_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
-# define _LIBCPP_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
-# define _LIBCPP_CLANG_DIAGNOSTIC_IGNORED(str)
-# define _LIBCPP_GCC_DIAGNOSTIC_IGNORED(str) _Pragma(_LIBCPP_TOSTRING(GCC diagnostic ignored str))
-# else
-# define _LIBCPP_DIAGNOSTIC_PUSH
-# define _LIBCPP_DIAGNOSTIC_POP
-# define _LIBCPP_CLANG_DIAGNOSTIC_IGNORED(str)
-# define _LIBCPP_GCC_DIAGNOSTIC_IGNORED(str)
-# endif
-
// c8rtomb() and mbrtoc8() were added in C++20 and C23. Support for these
// functions is gradually being added to existing C libraries. The conditions
// below check for known C library versions and conditions under which these
diff --git a/libcxx/include/tuple b/libcxx/include/tuple
index 0e5f0b4831b41e7..a2bacad183055f3 100644
--- a/libcxx/include/tuple
+++ b/libcxx/include/tuple
@@ -550,10 +550,6 @@ class _LIBCPP_TEMPLATE_VIS tuple {
public:
// [tuple.cnstr]
- _LIBCPP_DIAGNOSTIC_PUSH
- _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++20-extensions")
- _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++20-extensions")
-
// tuple() constructors (including allocator_arg_t variants)
template <template <class...> class _IsImpDefault = __is_implicitly_default_constructible,
template <class...> class _IsDefault = is_default_constructible,
@@ -835,8 +831,6 @@ public:
: __base_(allocator_arg_t(), __alloc, std::move(__p)) {}
# endif // _LIBCPP_STD_VER >= 23
- _LIBCPP_DIAGNOSTIC_POP
-
// [tuple.assign]
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 tuple&
operator=(_If<_And<is_copy_assignable<_Tp>...>::value, tuple, __nat> const& __tuple)
|
b134c7c
to
033ba90
Compare
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.
We discussed it multiple times and this is the end goal we've been driving towards. I think this has the potential to greatly simplify our implementation in places.
However, let's be reasonable and only use these extensions when they are actually useful -- in particular we shouldn't start reimplementing stuff using extensions just because we can, we should only do it when there's a tangible benefit. Let's use our judgement.
This is awesome! Is there a list of which extensions are available in which language modes -- or perhaps we should create one? It doesn't have to be exhaustive -- just listing some of the major, most clearly useful extensions with the minimum language standard where it can be used would be really useful, IMO (we can also have a checkbox saying whether there's already precedent for using the extension in the codebase, it might help rolling this out more gradually). |
b7e858c
to
470e009
Compare
Since we don't have a LLVM-18 release yet and presumably not a lot of usage except for users HEAD I feel this conclusion is premature. I really like to wait until after the release and see whether we get breakage before moving forward with this patch. |
We've had this in trunk for months now and nobody said anything. rc1 has been out for a week now and nobody said anything. If we caused any non-trivial breakage I'm pretty sure we would have heard about it by now. Everybody wants to start simplifying the code, and I don't think "but maybe" should stop us from doing so by now. |
470e009
to
dc770a3
Compare
@mordante @philnik777 I'd be fine to wait until after we have For what it's worth, I have been deploying LLVM 18 on a large code base internally and didn't see any issues around the use of these extensions, so I am not too concerned at this point. But I agree that a full point release would make sense before we actually merge this. |
dc770a3
to
fc36df2
Compare
Thanks for testing this. My main concern was never with users who we know about, but about the users we don't know about. |
fc36df2
to
d8aaa30
Compare
d8aaa30
to
806411c
Compare
Could you adjust the commit message to better describe which extensions we're enabling when? |
We're seeing major compile-time regressions (50%+) from this change in normal-looking code that uses libc++, using clang from head. My best guess is that we're now adding lots of diagnostics-overridden regions to most TUs, and querying them (when clang checks: should we emit diagnostic X) is inefficient. I will dig a bit into this. If this is not related to our use of modules (I need to check) then I think we should revert this and hopefully find a cheaper way. WDYT? |
(Sorry this is coming a week after the patch landed: internally we do basic correctness testing within days when we pull in the code, but only do performance testing for releases) |
If it is because of the diagnostic overrides, we should be able to go back to simply using the pragma system header. The diagnostic disabling is only really for our test suite (and people who enable -Wsystem-header, but they asking to see diagnostics). We should just be able to disable the warning entirely in the test suite. IDK Why we have it on when we allow the use of extensions. @philnik777 Can you say why you chose to go this route? |
Thanks! If we can avoid this entirely that seems ideal for everyone. We only see the regression in our modular builds. (Which unfortunately is our main mode). |
Is there a way to observe the issue or at least the structure that causes
the issue in the AST?
…On Thu, Mar 14, 2024 at 9:41 AM Sam McCall ***@***.***> wrote:
Thanks! If we can avoid this entirely that seems ideal for everyone.
We only see the regression in our modular builds. (Which unfortunately is
our main mode).
We use clang header modules, but I'd guess this isn't specific to that
mode.
libc++ has modules buildbots right? I'll see if I can scrape some timings
out of those, 50% might be possible to see through noise.
—
Reply to this email directly, view it on GitHub
<#79532 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAI7G2Z3X5BCHZFJO5O3J2LYYGSKBAVCNFSM6AAAAABCLMZLJGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSOJXGQ4DQOBYHE>
.
You are receiving this because your review was requested.Message ID:
***@***.***>
|
Actually, sorry I need to step back from this review. |
I'm pretty sure I've checked compile times before and after and didn't see any significant regression. While it's been a bit more than noise, it didn't seem significant enough to be worrisome, especially since should be able to offset that by simplifying the code.
I don't think we can revert. We're already depending on this in parts of the code base. IMO we should fix forward instead if this is actually a problem with this approach.
We're still using |
No worries @EricWF, thanks for your help. The regression is time spent in ASTReader::ReadPragmaDiagnosticMappings, which explains why it's modules-specific. here's the baseline and a ridiculously-wide screenshot of just that function (sorry I don't have a reasonable way to share the underlying data) |
My approximate understanding is that any query of diagnostic overrides ends up loading all the mappings (which is a bunch of work), and in order to understand the region they apply to it has to page in source-level information (since they are source-location based). @philnik777 thanks for the context!
(I would assume this is using libc++ textually rather than as modules, but just want to check)
Can you tell me how to check how much would break? (I know how to test llvm but not libcxx specifically).
It seems nice to enforce this, but if we can't revert and there isn't another obvious fix-forward, is it possible to live without this enforcement? Or move the pragmas out of libc++ proper and into the testsuite? |
Yes. I did not at all expect there to be a significant difference between normal header inclusion and clang modules.
You should be able to run the test suite with
I'd really like to avoid not enforcing this, since I expect there to be a significant amount of clean-up to pile up over a few months, maybe even making it almost prohibitive to revert. I also don't see a way to move the pragmas to the test suite. While it's not pretty, I think we could disable the pragmas when using clang modules with |
Yes, that solves the problems I know of. Would need other libc++ maintainers to weigh in on what the right tradeoff is here. |
…lvm#79532)" This reverts commit 4d323e4. The heavy use of push/pop directives causes a severe compile-time regression (>50%) when building code that uses libc++ via modules. See discussion on llvm#79532
We've talked about allowing extensions on discourse and in a libc++ monthly meeting and agreed to test it out in the LLVM 18 release. We've done that with the
tuple
constructor overload set (using conditionalexplicit
). Since we haven't heard about any breakages, it seems safe to do. This patch enables the use of extension from later C++ standards inside the versionedstd
namespaces. This should be good enough, since almost all of our code is inside that namespace. This approach also avoids the use of extensions inside the teststd
suite. That part of the code base should stay clean, since it's a test suite that is also used by other vendors to test their implementations.