Explicitly mark _S_ti() as default visibility to work around clang -fvisibility-inlines-hidden bug

Message ID 20180719235838.qu33nbpp4c7ndc33@google.com
State New
Headers show
Series
  • Explicitly mark _S_ti() as default visibility to work around clang -fvisibility-inlines-hidden bug
Related show

Commit Message

Richard Biener via Gcc-patches July 19, 2018, 11:58 p.m.
clang (including trunk and many older versions) incorrectly marks static local variables (__tag) hidden when -fvisibility-inlines-hidden is used.

% cat b.cc
#include <memory>
std::shared_ptr<int> foo(int x) {
  return std::make_shared<int>(x);
}
% g++-8 -fvisibility-inlines-hidden -fno-rtti -c b.cc
% readelf -s b.o | grep _S_ti
   163: 0000000000000000     1 OBJECT  UNIQUE DEFAULT   67 _ZZNSt19_Sp_make_shared_tag5_S_tiEvE5__tag
   164: 0000000000000000     8 FUNC    WEAK   HIDDEN    68 _ZNSt19_Sp_make_shared_tag5_S_tiEv
% ~/Dev/llvm/static-release/bin/clang++ -fvisibility-inlines-hidden -fno-rtti -c b.cc
% readelf -s b.o | grep _S_ti
   129: 0000000000000000    16 FUNC    WEAK   HIDDEN    34 _ZNSt19_Sp_make_shared_tag5_S_tiEv
   155: 0000000000000000     1 OBJECT  WEAK   HIDDEN   202 _ZZNSt19_Sp_make_shared_tag5_S_tiEvE5__tag

This can lead to multiple instances of __tag when shares objects are used.
The function
virtual void* std::_Sp_counted_ptr_inplace::_M_get_deleter(const std::type_info& __ti) noexcept
may return nullptr and causes std::make_shared<T>() to return nullptr (-fvisibility-inlines-hidden -fno-rtti).

After applying this patch (tagging _S_ti() with default visibility to override -fvisibility-inlines-hidden)

% readelf -s b.o | grep _S_ti
   129: 0000000000000000    16 FUNC    WEAK   DEFAULT   34 _ZNSt19_Sp_make_shared_tag5_S_tiEv
   155: 0000000000000000     1 OBJECT  WEAK   DEFAULT  202 _ZZNSt19_Sp_make_shared_tag5_S_tiEvE5__tag


This issue caused 10+ check-all tests of a -DUSE_SHARED_LLVM=On build of llvm (compiled with clang trunk) to SIGSEGV (because std::make_shared returned nullptr) and this patch fixes it.


        * include/bits/shared_ptr_base.h (_S_ti): Use
        _GLIBCXX_VISIBILITY(default)


-- 
宋方睿
From 6da8cec298766ce043d9c6dcda7b87142228dafb Mon Sep 17 00:00:00 2001
From: Fangrui Song <maskray@google.com>

Date: Thu, 19 Jul 2018 16:40:26 -0700
Subject: [PATCH 1/1] Explicitly mark _S_ti() as default visibility to work
 around clang -fvisibility-inlines-hidden bug

clang (including trunk and many older versions) incorrectly marks static
local variables (__tag) hidden when -fvisibility-inlines-hidden is used.
This can lead to multiple instances of __tag when shares objects are used.

        * include/bits/shared_ptr_base.h (_S_ti): Use
        _GLIBCXX_VISIBILITY(default)
---
 libstdc++-v3/include/bits/shared_ptr_base.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

-- 
2.18.0

Comments

Jonathan Wakely July 20, 2018, 11:24 a.m. | #1
On 19/07/18 16:58 -0700, Fāng-ruì Sòng via libstdc++ wrote:
>clang (including trunk and many older versions) incorrectly marks static local variables (__tag) hidden when -fvisibility-inlines-hidden is used.

>

>% cat b.cc

>#include <memory>

>std::shared_ptr<int> foo(int x) {

> return std::make_shared<int>(x);

>}

>% g++-8 -fvisibility-inlines-hidden -fno-rtti -c b.cc

>% readelf -s b.o | grep _S_ti

>  163: 0000000000000000     1 OBJECT  UNIQUE DEFAULT   67 _ZZNSt19_Sp_make_shared_tag5_S_tiEvE5__tag

>  164: 0000000000000000     8 FUNC    WEAK   HIDDEN    68 _ZNSt19_Sp_make_shared_tag5_S_tiEv

>% ~/Dev/llvm/static-release/bin/clang++ -fvisibility-inlines-hidden -fno-rtti -c b.cc

>% readelf -s b.o | grep _S_ti

>  129: 0000000000000000    16 FUNC    WEAK   HIDDEN    34 _ZNSt19_Sp_make_shared_tag5_S_tiEv

>  155: 0000000000000000     1 OBJECT  WEAK   HIDDEN   202 _ZZNSt19_Sp_make_shared_tag5_S_tiEvE5__tag

>

>This can lead to multiple instances of __tag when shares objects are used.

>The function

>virtual void* std::_Sp_counted_ptr_inplace::_M_get_deleter(const std::type_info& __ti) noexcept

>may return nullptr and causes std::make_shared<T>() to return nullptr (-fvisibility-inlines-hidden -fno-rtti).

>

>After applying this patch (tagging _S_ti() with default visibility to override -fvisibility-inlines-hidden)

>

>% readelf -s b.o | grep _S_ti

>  129: 0000000000000000    16 FUNC    WEAK   DEFAULT   34 _ZNSt19_Sp_make_shared_tag5_S_tiEv

>  155: 0000000000000000     1 OBJECT  WEAK   DEFAULT  202 _ZZNSt19_Sp_make_shared_tag5_S_tiEvE5__tag

>

>

>This issue caused 10+ check-all tests of a -DUSE_SHARED_LLVM=On build of llvm (compiled with clang trunk) to SIGSEGV (because std::make_shared returned nullptr) and this patch fixes it.

>

>

>       * include/bits/shared_ptr_base.h (_S_ti): Use

>       _GLIBCXX_VISIBILITY(default)

>


Thanks, I've tested this and committed it to trunk.

I think we want this on gcc-8-branch too, but it's too late for the
8.2 release now.


>-- 

>宋方睿


>From 6da8cec298766ce043d9c6dcda7b87142228dafb Mon Sep 17 00:00:00 2001

>From: Fangrui Song <maskray@google.com>

>Date: Thu, 19 Jul 2018 16:40:26 -0700

>Subject: [PATCH 1/1] Explicitly mark _S_ti() as default visibility to work

> around clang -fvisibility-inlines-hidden bug

>

>clang (including trunk and many older versions) incorrectly marks static

>local variables (__tag) hidden when -fvisibility-inlines-hidden is used.

>This can lead to multiple instances of __tag when shares objects are used.

>

>        * include/bits/shared_ptr_base.h (_S_ti): Use

>        _GLIBCXX_VISIBILITY(default)

>---

> libstdc++-v3/include/bits/shared_ptr_base.h | 2 +-

> 1 file changed, 1 insertion(+), 1 deletion(-)

>

>diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h

>index f3994da158f..870aeb9bfda 100644

>--- a/libstdc++-v3/include/bits/shared_ptr_base.h

>+++ b/libstdc++-v3/include/bits/shared_ptr_base.h

>@@ -508,7 +508,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION

>       friend class _Sp_counted_ptr_inplace;

>

>     static const type_info&

>-    _S_ti() noexcept

>+    _S_ti() noexcept _GLIBCXX_VISIBILITY(default)

>     {

>       alignas(type_info) static constexpr _Sp_make_shared_tag __tag;

>       return reinterpret_cast<const type_info&>(__tag);

>-- 

>2.18.0

>

Patch

diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h
index f3994da158f..870aeb9bfda 100644
--- a/libstdc++-v3/include/bits/shared_ptr_base.h
+++ b/libstdc++-v3/include/bits/shared_ptr_base.h
@@ -508,7 +508,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       friend class _Sp_counted_ptr_inplace;
 
     static const type_info&
-    _S_ti() noexcept
+    _S_ti() noexcept _GLIBCXX_VISIBILITY(default)
     {
       alignas(type_info) static constexpr _Sp_make_shared_tag __tag;
       return reinterpret_cast<const type_info&>(__tag);