diff --git a/libcxx/.clang-format b/libcxx/.clang-format --- a/libcxx/.clang-format +++ b/libcxx/.clang-format @@ -30,7 +30,6 @@ '_LIBCPP_DEPRECATED_IN_CXX20', '_LIBCPP_DEPRECATED', '_LIBCPP_DISABLE_EXTENTSION_WARNING', - '_LIBCPP_ENUM_VIS', '_LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION', '_LIBCPP_EXPORTED_FROM_ABI', '_LIBCPP_EXTERN_TEMPLATE_TYPE_VIS', diff --git a/libcxx/docs/DesignDocs/VisibilityMacros.rst b/libcxx/docs/DesignDocs/VisibilityMacros.rst --- a/libcxx/docs/DesignDocs/VisibilityMacros.rst +++ b/libcxx/docs/DesignDocs/VisibilityMacros.rst @@ -14,6 +14,13 @@ both the library and the headers. These macros work by changing the visibility and inlining characteristics of the symbols they are applied to. +The std namespace also has visibility attributes applied to avoid having to +add visibility macros in as many places. Namespace std has default +type_visibility to export RTTI and other type-specific information. Note that +type_visibility is only supported by Clang, so this doesn't replace +type-specific attributes. The only exception are enums, which GCC always gives +default visibility, thus removing the need for any annotations. + Visibility Macros ================= @@ -72,19 +79,6 @@ **Windows Behavior**: DLLs do not support dllimport/export on class templates. The macro has an empty definition on this platform. - -**_LIBCPP_ENUM_VIS** - Mark the typeinfo of an enum as having default visibility. This attribute - should be applied to all enum declarations. - - **Windows Behavior**: DLLs do not support importing or exporting enumeration - typeinfo. The macro has an empty definition on this platform. - - **GCC Behavior**: GCC un-hides the typeinfo for enumerations by default, even - if `-fvisibility=hidden` is specified. Additionally applying a visibility - attribute to an enum class results in a warning. The macro has an empty - definition with GCC. - **_LIBCPP_EXTERN_TEMPLATE_TYPE_VIS** Mark the member functions, typeinfo, and vtable of the type named in an extern template declaration as being exported by the libc++ library. diff --git a/libcxx/docs/ReleaseNotes/18.rst b/libcxx/docs/ReleaseNotes/18.rst --- a/libcxx/docs/ReleaseNotes/18.rst +++ b/libcxx/docs/ReleaseNotes/18.rst @@ -77,5 +77,13 @@ - The symbol of a non-visible function part of ``std::system_error`` was removed. This is not a breaking change as the private function ``__init`` was never referenced internally outside of the dylib +- This release of libc++ added missing visibility annotations on some types in the library. Users compiling with + ``-fvisbility=hidden`` may notice that additional type infos from libc++ are being exported from their ABI. This is + the correct behavior in almost all cases since exporting the RTTI is required for these types to work properly with + dynamic_cast, exceptions and other mechanisms across binaries. However, if you intend to use libc++ purely as an + internal implementation detail (i.e. you use libc++ as a static archive and never export libc++ symbols from your ABI) + and you notice changes to your exported symbols list, then this means that you were not properly preventing libc++ + symbols from being part of your ABI. + Build System Changes -------------------- diff --git a/libcxx/include/__charconv/chars_format.h b/libcxx/include/__charconv/chars_format.h --- a/libcxx/include/__charconv/chars_format.h +++ b/libcxx/include/__charconv/chars_format.h @@ -21,7 +21,7 @@ #if _LIBCPP_STD_VER >= 17 -enum class _LIBCPP_ENUM_VIS chars_format { scientific = 0x1, fixed = 0x2, hex = 0x4, general = fixed | scientific }; +enum class chars_format { scientific = 0x1, fixed = 0x2, hex = 0x4, general = fixed | scientific }; inline _LIBCPP_HIDE_FROM_ABI constexpr chars_format operator~(chars_format __x) { return chars_format(~std::__to_underlying(__x)); diff --git a/libcxx/include/__compare/ordering.h b/libcxx/include/__compare/ordering.h --- a/libcxx/include/__compare/ordering.h +++ b/libcxx/include/__compare/ordering.h @@ -22,13 +22,13 @@ #if _LIBCPP_STD_VER >= 20 // exposition only -enum class _LIBCPP_ENUM_VIS _OrdResult : signed char { +enum class _OrdResult : signed char { __less = -1, __equiv = 0, __greater = 1 }; -enum class _LIBCPP_ENUM_VIS _NCmpResult : signed char { +enum class _NCmpResult : signed char { __unordered = -127 }; diff --git a/libcxx/include/__config b/libcxx/include/__config --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -685,7 +685,7 @@ # define _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS # define _LIBCPP_TEMPLATE_VIS # define _LIBCPP_TEMPLATE_DATA_VIS -# define _LIBCPP_ENUM_VIS +# define _LIBCPP_TYPE_VISIBILITY_DEFAULT # else @@ -713,20 +713,17 @@ # define _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS # endif -# if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) -# if __has_attribute(__type_visibility__) -# define _LIBCPP_TEMPLATE_VIS __attribute__((__type_visibility__("default"))) -# else -# define _LIBCPP_TEMPLATE_VIS __attribute__((__visibility__("default"))) -# endif +// GCC doesn't support the type_visibility attribute, so we have to keep the visibility attribute on templates +# if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) && !__has_attribute(__type_visibility__) +# define _LIBCPP_TEMPLATE_VIS __attribute__((__visibility__("default"))) # else # define _LIBCPP_TEMPLATE_VIS # endif # if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) && __has_attribute(__type_visibility__) -# define _LIBCPP_ENUM_VIS __attribute__((__type_visibility__("default"))) +# define _LIBCPP_TYPE_VISIBILITY_DEFAULT __attribute__((__type_visibility__("default"))) # else -# define _LIBCPP_ENUM_VIS +# define _LIBCPP_TYPE_VISIBILITY_DEFAULT # endif # endif // defined(_LIBCPP_OBJECT_FORMAT_COFF) @@ -800,7 +797,8 @@ // Inline namespaces are available in Clang/GCC/MSVC regardless of C++ dialect. // clang-format off -# define _LIBCPP_BEGIN_NAMESPACE_STD namespace std { inline namespace _LIBCPP_ABI_NAMESPACE { +# define _LIBCPP_BEGIN_NAMESPACE_STD namespace _LIBCPP_TYPE_VISIBILITY_DEFAULT std { \ + inline namespace _LIBCPP_ABI_NAMESPACE { # define _LIBCPP_END_NAMESPACE_STD }} # define _VSTD std @@ -853,7 +851,7 @@ // clang-format on # else // _LIBCPP_CXX03_LANG -# define _LIBCPP_DECLARE_STRONG_ENUM(x) enum class _LIBCPP_ENUM_VIS x +# define _LIBCPP_DECLARE_STRONG_ENUM(x) enum class x # define _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(x) # endif // _LIBCPP_CXX03_LANG diff --git a/libcxx/include/__filesystem/copy_options.h b/libcxx/include/__filesystem/copy_options.h --- a/libcxx/include/__filesystem/copy_options.h +++ b/libcxx/include/__filesystem/copy_options.h @@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -enum class _LIBCPP_ENUM_VIS copy_options : unsigned short { +enum class copy_options : unsigned short { none = 0, skip_existing = 1, overwrite_existing = 2, diff --git a/libcxx/include/__filesystem/directory_options.h b/libcxx/include/__filesystem/directory_options.h --- a/libcxx/include/__filesystem/directory_options.h +++ b/libcxx/include/__filesystem/directory_options.h @@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -enum class _LIBCPP_ENUM_VIS directory_options : unsigned char { +enum class directory_options : unsigned char { none = 0, follow_directory_symlink = 1, skip_permission_denied = 2 diff --git a/libcxx/include/__filesystem/file_type.h b/libcxx/include/__filesystem/file_type.h --- a/libcxx/include/__filesystem/file_type.h +++ b/libcxx/include/__filesystem/file_type.h @@ -23,7 +23,7 @@ // On Windows, the library never identifies files as block, character, fifo // or socket. -enum class _LIBCPP_ENUM_VIS file_type : signed char { +enum class file_type : signed char { none = 0, not_found = -1, regular = 1, diff --git a/libcxx/include/__filesystem/path.h b/libcxx/include/__filesystem/path.h --- a/libcxx/include/__filesystem/path.h +++ b/libcxx/include/__filesystem/path.h @@ -465,7 +465,7 @@ typedef basic_string string_type; typedef basic_string_view __string_view; - enum _LIBCPP_ENUM_VIS format : unsigned char { + enum format : unsigned char { auto_format, native_format, generic_format diff --git a/libcxx/include/__filesystem/perm_options.h b/libcxx/include/__filesystem/perm_options.h --- a/libcxx/include/__filesystem/perm_options.h +++ b/libcxx/include/__filesystem/perm_options.h @@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -enum class _LIBCPP_ENUM_VIS perm_options : unsigned char { +enum class perm_options : unsigned char { replace = 1, add = 2, remove = 4, diff --git a/libcxx/include/__filesystem/perms.h b/libcxx/include/__filesystem/perms.h --- a/libcxx/include/__filesystem/perms.h +++ b/libcxx/include/__filesystem/perms.h @@ -25,7 +25,7 @@ // file, and the executable bit is always returned as set. When setting // permissions, as long as the write bit is set for either owner, group or // others, the readonly flag is cleared. -enum class _LIBCPP_ENUM_VIS perms : unsigned { +enum class perms : unsigned { none = 0, owner_read = 0400, diff --git a/libcxx/include/__format/format_arg.h b/libcxx/include/__format/format_arg.h --- a/libcxx/include/__format/format_arg.h +++ b/libcxx/include/__format/format_arg.h @@ -53,7 +53,7 @@ /// handle to satisfy the user observable behaviour. The internal function /// __visit_format_arg doesn't do this wrapping. So in the format functions /// this function is used to avoid unneeded overhead. -enum class _LIBCPP_ENUM_VIS __arg_t : uint8_t { +enum class __arg_t : uint8_t { __none, __boolean, __char_type, diff --git a/libcxx/include/__format/parser_std_format_spec.h b/libcxx/include/__format/parser_std_format_spec.h --- a/libcxx/include/__format/parser_std_format_spec.h +++ b/libcxx/include/__format/parser_std_format_spec.h @@ -176,7 +176,7 @@ inline constexpr __fields __fields_fill_align_width{}; # endif -enum class _LIBCPP_ENUM_VIS __alignment : uint8_t { +enum class __alignment : uint8_t { /// No alignment is set in the format string. __default, __left, @@ -185,7 +185,7 @@ __zero_padding }; -enum class _LIBCPP_ENUM_VIS __sign : uint8_t { +enum class __sign : uint8_t { /// No sign is set in the format string. /// /// The sign isn't allowed for certain format-types. By using this value @@ -197,7 +197,7 @@ __space }; -enum class _LIBCPP_ENUM_VIS __type : uint8_t { +enum class __type : uint8_t { __default = 0, __string, __binary_lower_case, diff --git a/libcxx/include/__format/write_escaped.h b/libcxx/include/__format/write_escaped.h --- a/libcxx/include/__format/write_escaped.h +++ b/libcxx/include/__format/write_escaped.h @@ -118,7 +118,7 @@ return static_cast>(__value); } -enum class _LIBCPP_ENUM_VIS __escape_quotation_mark { __apostrophe, __double_quote }; +enum class __escape_quotation_mark { __apostrophe, __double_quote }; // [format.string.escaped]/2 template diff --git a/libcxx/include/__fwd/subrange.h b/libcxx/include/__fwd/subrange.h --- a/libcxx/include/__fwd/subrange.h +++ b/libcxx/include/__fwd/subrange.h @@ -23,7 +23,7 @@ namespace ranges { -enum class _LIBCPP_ENUM_VIS subrange_kind : bool { unsized, sized }; +enum class subrange_kind : bool { unsized, sized }; template _Sent, subrange_kind _Kind> requires(_Kind == subrange_kind::sized || !sized_sentinel_for<_Sent, _Iter>) diff --git a/libcxx/include/new b/libcxx/include/new --- a/libcxx/include/new +++ b/libcxx/include/new @@ -185,7 +185,7 @@ #if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION) && \ !defined(_LIBCPP_ABI_VCRUNTIME) #ifndef _LIBCPP_CXX03_LANG -enum class _LIBCPP_ENUM_VIS align_val_t : size_t { }; +enum class align_val_t : size_t { }; #else enum align_val_t { __zero = 0, __max = (size_t)-1 }; #endif