[libc++] Make _LIBCPP_TYPE_VIS export members

Summary:
Most classes annotated with _LIBCPP_TYPE_VIS need to have at least some
of their members exported, otherwise we have a lot of link errors when
linking against a libc++ built with hidden visibility. This also makes
_LIBCPP_TYPE_VIS be consistent across platforms, since on Windows it
already exports members.

With this change made, any template methods of a class marked
_LIBCPP_TYPE_VIS will also get default visibility when instantiatied,
which is not desirable for clients of libc++ headers who wish to control
their visibility; this is the same issue as PR30642. Annotate all
problematic methods with an explicit visibility specifier to avoid this.

The problematic methods were found by running bad-visibility-finder [1]
against the libc++ headers after making the _LIBCPP_TYPE_VIS change. The
small methods were marked for inlining; the larger ones hidden.

[1] https://github.com/smeenai/bad-visibility-finder

Reviewers: mclow.lists, EricWF

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D25208

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@296732 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Shoaib Meenai
2017-03-02 03:22:18 +00:00
parent 24e8dbdd2d
commit 6b7349243e
9 changed files with 35 additions and 14 deletions

View File

@@ -47,18 +47,17 @@ Visibility Macros
A synonym for `_LIBCPP_INLINE_VISIBILITY` A synonym for `_LIBCPP_INLINE_VISIBILITY`
**_LIBCPP_TYPE_VIS** **_LIBCPP_TYPE_VIS**
Mark a type's typeinfo, vtable and members as having default visibility.
This attribute cannot be used on class templates.
**_LIBCPP_TEMPLATE_VIS**
Mark a type's typeinfo and vtable as having default visibility. Mark a type's typeinfo and vtable as having default visibility.
`_LIBCPP_TYPE_VIS`. This macro has no effect on the visibility of the This macro has no effect on the visibility of the type's member functions.
type's member functions. This attribute cannot be used on class templates.
**GCC Behavior**: GCC does not support Clang's `type_visibility(...)` **GCC Behavior**: GCC does not support Clang's `type_visibility(...)`
attribute. With GCC the `visibility(...)` attribute is used and member attribute. With GCC the `visibility(...)` attribute is used and member
functions are affected. functions are affected.
**_LIBCPP_TEMPLATE_VIS**
The same as `_LIBCPP_TYPE_VIS` except that it may be applied to class
templates.
**Windows Behavior**: DLLs do not support dllimport/export on class templates. **Windows Behavior**: DLLs do not support dllimport/export on class templates.
The macro has an empty definition on this platform. The macro has an empty definition on this platform.

View File

@@ -628,18 +628,22 @@ namespace std {
#ifndef _LIBCPP_TYPE_VIS #ifndef _LIBCPP_TYPE_VIS
# if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) # if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS)
# if __has_attribute(__type_visibility__)
# define _LIBCPP_TYPE_VIS __attribute__ ((__type_visibility__("default")))
# else
# define _LIBCPP_TYPE_VIS __attribute__ ((__visibility__("default"))) # define _LIBCPP_TYPE_VIS __attribute__ ((__visibility__("default")))
# endif
# else # else
# define _LIBCPP_TYPE_VIS # define _LIBCPP_TYPE_VIS
# endif # endif
#endif #endif
#ifndef _LIBCPP_TEMPLATE_VIS #ifndef _LIBCPP_TEMPLATE_VIS
# define _LIBCPP_TEMPLATE_VIS _LIBCPP_TYPE_VIS # 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
# else
# define _LIBCPP_TEMPLATE_VIS
# endif
#endif #endif
#ifndef _LIBCPP_FUNC_VIS_ONLY #ifndef _LIBCPP_FUNC_VIS_ONLY

View File

@@ -92,13 +92,16 @@ public:
const locale& operator=(const locale&) _NOEXCEPT; const locale& operator=(const locale&) _NOEXCEPT;
template <class _Facet> locale combine(const locale&) const; template <class _Facet>
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
locale combine(const locale&) const;
// locale operations: // locale operations:
string name() const; string name() const;
bool operator==(const locale&) const; bool operator==(const locale&) const;
bool operator!=(const locale& __y) const {return !(*this == __y);} bool operator!=(const locale& __y) const {return !(*this == __y);}
template <class _CharT, class _Traits, class _Allocator> template <class _CharT, class _Traits, class _Allocator>
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
bool operator()(const basic_string<_CharT, _Traits, _Allocator>&, bool operator()(const basic_string<_CharT, _Traits, _Allocator>&,
const basic_string<_CharT, _Traits, _Allocator>&) const; const basic_string<_CharT, _Traits, _Allocator>&) const;

View File

@@ -316,20 +316,24 @@ public:
void wait(unique_lock<mutex>& __lk) _NOEXCEPT; void wait(unique_lock<mutex>& __lk) _NOEXCEPT;
template <class _Predicate> template <class _Predicate>
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
void wait(unique_lock<mutex>& __lk, _Predicate __pred); void wait(unique_lock<mutex>& __lk, _Predicate __pred);
template <class _Clock, class _Duration> template <class _Clock, class _Duration>
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
cv_status cv_status
wait_until(unique_lock<mutex>& __lk, wait_until(unique_lock<mutex>& __lk,
const chrono::time_point<_Clock, _Duration>& __t); const chrono::time_point<_Clock, _Duration>& __t);
template <class _Clock, class _Duration, class _Predicate> template <class _Clock, class _Duration, class _Predicate>
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
bool bool
wait_until(unique_lock<mutex>& __lk, wait_until(unique_lock<mutex>& __lk,
const chrono::time_point<_Clock, _Duration>& __t, const chrono::time_point<_Clock, _Duration>& __t,
_Predicate __pred); _Predicate __pred);
template <class _Rep, class _Period> template <class _Rep, class _Period>
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
cv_status cv_status
wait_for(unique_lock<mutex>& __lk, wait_for(unique_lock<mutex>& __lk,
const chrono::duration<_Rep, _Period>& __d); const chrono::duration<_Rep, _Period>& __d);

View File

@@ -133,12 +133,14 @@ public:
void notify_all() _NOEXCEPT; void notify_all() _NOEXCEPT;
template <class _Lock> template <class _Lock>
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
void wait(_Lock& __lock); void wait(_Lock& __lock);
template <class _Lock, class _Predicate> template <class _Lock, class _Predicate>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
void wait(_Lock& __lock, _Predicate __pred); void wait(_Lock& __lock, _Predicate __pred);
template <class _Lock, class _Clock, class _Duration> template <class _Lock, class _Clock, class _Duration>
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
cv_status cv_status
wait_until(_Lock& __lock, wait_until(_Lock& __lock,
const chrono::time_point<_Clock, _Duration>& __t); const chrono::time_point<_Clock, _Duration>& __t);

View File

@@ -582,6 +582,7 @@ public:
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const; wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const;
template <class _Clock, class _Duration> template <class _Clock, class _Duration>
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
future_status future_status
wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const; wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const;
@@ -1674,6 +1675,7 @@ class _LIBCPP_TYPE_VIS promise<void>
public: public:
promise(); promise();
template <class _Allocator> template <class _Allocator>
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
promise(allocator_arg_t, const _Allocator& __a); promise(allocator_arg_t, const _Allocator& __a);
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY

View File

@@ -248,6 +248,7 @@ public:
bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) bool try_lock_for(const chrono::duration<_Rep, _Period>& __d)
{return try_lock_until(chrono::steady_clock::now() + __d);} {return try_lock_until(chrono::steady_clock::now() + __d);}
template <class _Clock, class _Duration> template <class _Clock, class _Duration>
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
void unlock() _NOEXCEPT; void unlock() _NOEXCEPT;
}; };
@@ -291,6 +292,7 @@ public:
bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) bool try_lock_for(const chrono::duration<_Rep, _Period>& __d)
{return try_lock_until(chrono::steady_clock::now() + __d);} {return try_lock_until(chrono::steady_clock::now() + __d);}
template <class _Clock, class _Duration> template <class _Clock, class _Duration>
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
void unlock() _NOEXCEPT; void unlock() _NOEXCEPT;
}; };

View File

@@ -220,6 +220,7 @@ public:
return try_lock_until(chrono::steady_clock::now() + __rel_time); return try_lock_until(chrono::steady_clock::now() + __rel_time);
} }
template <class _Clock, class _Duration> template <class _Clock, class _Duration>
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
bool bool
try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time); try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time);
void unlock(); void unlock();
@@ -235,6 +236,7 @@ public:
return try_lock_shared_until(chrono::steady_clock::now() + __rel_time); return try_lock_shared_until(chrono::steady_clock::now() + __rel_time);
} }
template <class _Clock, class _Duration> template <class _Clock, class _Duration>
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
bool bool
try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time); try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time);
void unlock_shared(); void unlock_shared();

View File

@@ -298,9 +298,12 @@ public:
!is_same<typename decay<_Fp>::type, thread>::value !is_same<typename decay<_Fp>::type, thread>::value
>::type >::type
> >
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
explicit thread(_Fp&& __f, _Args&&... __args); explicit thread(_Fp&& __f, _Args&&... __args);
#else // _LIBCPP_HAS_NO_VARIADICS #else // _LIBCPP_HAS_NO_VARIADICS
template <class _Fp> explicit thread(_Fp __f); template <class _Fp>
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
explicit thread(_Fp __f);
#endif #endif
~thread(); ~thread();