diff --git a/libcxx/include/__algorithm/any_of.h b/libcxx/include/__algorithm/any_of.h --- a/libcxx/include/__algorithm/any_of.h +++ b/libcxx/include/__algorithm/any_of.h @@ -16,10 +16,10 @@ # pragma GCC system_header #endif -_LIBCPP_BEGIN_NAMESPACE_STD +_LIBCPP_BEGIN_HIDE_FROM_ABI_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX20 bool any_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) { for (; __first != __last; ++__first) if (__pred(*__first)) @@ -27,6 +27,6 @@ return false; } -_LIBCPP_END_NAMESPACE_STD +_LIBCPP_END_HIDE_FROM_ABI_NAMESPACE_STD #endif // _LIBCPP___ALGORITHM_ANY_OF_H diff --git a/libcxx/include/__config b/libcxx/include/__config --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -650,6 +650,9 @@ # define _LIBCPP_END_NAMESPACE_STD }} # define _VSTD std +# define _LIBCPP_BEGIN_HIDE_FROM_ABI_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD inline namespace _LIBCPP_CONCAT(__, _LIBCPP_VERSION) _LIBCPP_HIDDEN { +# define _LIBCPP_END_HIDE_FROM_ABI_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD } + _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # if _LIBCPP_STD_VER > 14 diff --git a/libcxx/test/tools/clang_tidy_checks/hide_from_abi.cpp b/libcxx/test/tools/clang_tidy_checks/hide_from_abi.cpp --- a/libcxx/test/tools/clang_tidy_checks/hide_from_abi.cpp +++ b/libcxx/test/tools/clang_tidy_checks/hide_from_abi.cpp @@ -11,6 +11,27 @@ #include "hide_from_abi.hpp" +namespace { +bool is_hide_from_abi_namespace(std::string_view str) { + return str.size() == strlen("__MAMIPA") && str.starts_with("__"); +} + +AST_MATCHER(clang::Decl, isInHideFromABINamespace) { + auto context = Node.getDeclContext(); + if (context == nullptr || !context->isNamespace()) + return false; + + auto namespace_decl = cast(context); + while (!namespace_decl->isInline() || !is_hide_from_abi_namespace(namespace_decl->getName())) { + auto namespace_context = namespace_decl->getParent(); + if (!namespace_context->isNamespace()) + return false; + namespace_decl = cast(namespace_context); + } + return true; +} +} // namespace + namespace libcpp { hide_from_abi::hide_from_abi(llvm::StringRef name, clang::tidy::ClangTidyContext* context) : clang::tidy::ClangTidyCheck(name, context) {} @@ -35,15 +56,29 @@ hasAttr(clang::attr::AbiTag), cxxMethodDecl(), // We have explicitly instantiated classes and some of their methods don't have these attributes isDeleted(), - isConsteval())), + isConsteval(), + isInHideFromABINamespace())), isDefinition()) .bind("missing_hide_from_abi"), this); + + finder->addMatcher(cxxRecordDecl(isInHideFromABINamespace()).bind("struct_in_hide_from_abi_namespace"), this); + + finder->addMatcher(functionDecl(isInHideFromABINamespace(), hasAttr(clang::attr::AbiTag)) + .bind("function_marked_hide_from_abi_in_hide_from_abi_namespace"), + this); } void hide_from_abi::check(const clang::ast_matchers::MatchFinder::MatchResult& result) { if (const auto* call = result.Nodes.getNodeAs("missing_hide_from_abi"); call != nullptr) { diag(call->getBeginLoc(), "_LIBCPP_HIDE_FROM_ABI is missing"); + } else if (const auto* record = result.Nodes.getNodeAs("struct_in_hide_from_abi_namespace"); + record != nullptr) { + diag(record->getBeginLoc(), "structs should not be inside _LIBCPP_BEGIN_HIDE_FROM_ABI_NAMESPACE_STD"); + } else if (const auto* func = result.Nodes.getNodeAs( + "function_marked_hide_from_abi_in_hide_from_abi_namespace")) { + diag(func->getBeginLoc(), + "functions inside the hide-from-abi namespace should not be marked _LIBCPP_HIDE_FROM_ABI"); } } } // namespace libcpp