mirror of
https://github.com/llvm-mirror/libcxx.git
synced 2025-10-23 01:18:52 +08:00

Summary: GCC and Clang handle visibility attributes on the out-of-line definition of externally instantiated templates differently. For example in the reproducer below Clang will emit both 'foo' and 'bar' with default visibility while GCC only emits a non-hidden 'foo'. ``` // RUN: g++ -std=c++11 -shared -O3 test.cpp && sym_extract.py a.out // RUN: clang++ -std=c++11 -shared -O3 test.cpp && sym_extract.py a.out #define INLINE_VISIBILITY __attribute__((visibility("hidden"), always_inline)) template <class T> struct Foo { void foo(); void bar(); }; template <class T> void Foo<T>::foo() {} template <class T> inline INLINE_VISIBILITY void Foo<T>::bar() {} template struct Foo<int>; ``` This difference creates ABI incompatibilities between Clang and GCC built dylibs. Specifically GCC built dylibs lack definitions for various member functions of `basic_string`, `basic_istream`, `basic_ostream`, `basic_iostream`, and `basic_streambuf` (All of these types are externally instantiated). Surprisingly these missing symbols don't cause many problems because the functions are marked `always_inline` therefore the dylib definition is rarely needed. However when an out-of-line definition is required then GCC built dylibs will fail to link. For example [GCC built dylibs cannot build Clang](http://stackoverflow.com/questions/39454262/clang-build-errors). This patch works around this issue by adding `_LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY` which is used to mark externally instantiated member functions as always inline. When building the library `_LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY` sets the symbol's visibility to "default" instead of "hidden", otherwise it acts exactly the same as `_LIBCPP_INLINE_VISIBILITY`. After applying this patch GCC dylibs now contain: * `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE7sungetcEv` * `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE5gbumpEi` * `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE7sungetcEv` * `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE9sputbackcEc` * `_ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE3getERNS_15basic_streambufIwS2_EE` * `_ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEElsEPFRNS_9basic_iosIwS2_EES6_E` * `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE4setpEPcS4_` * `_ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEEC1EPNS_15basic_streambufIwS2_EE` * `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE6snextcEv` * `_ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE4swapERS3_` * `_ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE4swapERS3_` * `_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEPKcm` * `_ZNSt3__113basic_istreamIcNS_11char_traitsIcEEErsEPFRNS_8ios_baseES5_E` * `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE9pubsetbufEPcl` * `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE10pubseekoffExNS_8ios_base7seekdirEj` * `_ZNSt3__113basic_istreamIwNS_11char_traitsIwEEErsEPFRNS_9basic_iosIwS2_EES6_E` * `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE5pbumpEi` * `_ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE5seekpENS_4fposI11__mbstate_tEE` * `_ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE7getlineEPcl` * `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE5sgetcEv` * `_ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE3getERNS_15basic_streambufIcS2_EE` * `_ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEPFRNS_8ios_baseES5_E` * `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE8in_availEv` * `_ZNSt3__113basic_istreamIwNS_11char_traitsIwEEErsEPFRNS_8ios_baseES5_E` * `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE6sbumpcEv` * `_ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEPFRNS_9basic_iosIcS2_EES6_E` * `_ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE3getERc` * `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE6snextcEv` * `_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6__initEmw` * `_ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE7getlineEPwl` * `_ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE5tellpEv` * `_ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE3getERw` * `_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEmc` * `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE7pubsyncEv` * `_ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE3getEPcl` * `_ZNSt3__113basic_istreamIcNS_11char_traitsIcEEEC2EPNS_15basic_streambufIcS2_EE` * `_ZNSt3__113basic_istreamIcNS_11char_traitsIcEEErsEPFRNS_9basic_iosIcS2_EES6_E` * `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE7pubsyncEv` * `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE5sputcEc` * `_ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEE5seekpExNS_8ios_base7seekdirE` * `_ZNKSt3__115basic_streambufIcNS_11char_traitsIcEEE6getlocEv` * `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE5gbumpEi` * `_ZNSt3__114basic_iostreamIcNS_11char_traitsIcEEE4swapERS3_` * `_ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEE5seekpENS_4fposI11__mbstate_tEE` * `_ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEE5tellpEv` * `_ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEElsEPFRS3_S4_E` * `_ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE3getEPwl` * `_ZNSt3__113basic_istreamIwNS_11char_traitsIwEEEC2EPNS_15basic_streambufIwS2_EE` * `_ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEPFRS3_S4_E` * `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE4setgEPcS4_S4_` * `_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6__initEPKwmm` * `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE4setgEPwS4_S4_` * `_ZNSt3__113basic_istreamIwNS_11char_traitsIwEEEC1EPNS_15basic_streambufIwS2_EE` * `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE8pubimbueERKNS_6localeE` * `_ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE4swapERS3_` * `_ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEEC2EPNS_15basic_streambufIwS2_EE` * `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE10pubseekposENS_4fposI11__mbstate_tEEj` * `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE5pbumpEi` * `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE5sgetcEv` * `_ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEE4swapERS3_` * `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE10pubseekposENS_4fposI11__mbstate_tEEj` * `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE5sputnEPKcl` * `_ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE5seekpExNS_8ios_base7seekdirE` * `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE5sgetnEPwl` * `_ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEElsEPFRNS_8ios_baseES5_E` * `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE4setpEPwS4_` * `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE5sgetnEPcl` * `_ZNKSt3__115basic_streambufIwNS_11char_traitsIwEEE6getlocEv` * `_ZNSt3__114basic_iostreamIcNS_11char_traitsIcEEEC2EPNS_15basic_streambufIcS2_EE` * `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE8pubimbueERKNS_6localeE` * `_ZNSt3__114basic_iostreamIcNS_11char_traitsIcEEEC1EPNS_15basic_streambufIcS2_EE` * `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE8in_availEv` * `_ZNSt3__113basic_istreamIcNS_11char_traitsIcEEEC1EPNS_15basic_streambufIcS2_EE` * `_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEPKcmm` * `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE6sbumpcEv` * `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE10pubseekoffExNS_8ios_base7seekdirEj` * `_ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEEC2EPNS_15basic_streambufIcS2_EE` * `_ZNSt3__113basic_istreamIwNS_11char_traitsIwEEErsEPFRS3_S4_E` * `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE9sputbackcEw` * `_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6__initEPKwm` * `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE5sputnEPKwl` * `_ZNSt3__113basic_istreamIcNS_11char_traitsIcEEErsEPFRS3_S4_E` * `_ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEEC1EPNS_15basic_streambufIcS2_EE` * `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE9pubsetbufEPwl` * `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE5sputcEw` This patch has no effect on Clang based builds. Reviewers: mclow.lists, eugenis, danalbert, jroelofs, EricWF Subscribers: beanz, cfe-commits, mgorny Differential Revision: https://reviews.llvm.org/D24600 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@281681 91177308-0d34-0410-b5e6-96231b3b80d8
63 lines
2.1 KiB
Python
Executable File
63 lines
2.1 KiB
Python
Executable File
#!/usr/bin/env python
|
|
#===----------------------------------------------------------------------===##
|
|
#
|
|
# The LLVM Compiler Infrastructure
|
|
#
|
|
# This file is dual licensed under the MIT and the University of Illinois Open
|
|
# Source Licenses. See LICENSE.TXT for details.
|
|
#
|
|
#===----------------------------------------------------------------------===##
|
|
"""
|
|
sym_diff - Compare two symbol lists and output the differences.
|
|
"""
|
|
|
|
from argparse import ArgumentParser
|
|
import sys
|
|
from sym_check import diff, util
|
|
|
|
|
|
def main():
|
|
parser = ArgumentParser(
|
|
description='Extract a list of symbols from a shared library.')
|
|
parser.add_argument(
|
|
'--names-only', dest='names_only',
|
|
help='Only print symbol names',
|
|
action='store_true', default=False)
|
|
parser.add_argument(
|
|
'--removed-only', dest='removed_only',
|
|
help='Only print removed symbols',
|
|
action='store_true', default=False)
|
|
parser.add_argument(
|
|
'-o', '--output', dest='output',
|
|
help='The output file. stdout is used if not given',
|
|
type=str, action='store', default=None)
|
|
parser.add_argument(
|
|
'--demangle', dest='demangle', action='store_true', default=False)
|
|
parser.add_argument(
|
|
'old_syms', metavar='old-syms', type=str,
|
|
help='The file containing the old symbol list or a library')
|
|
parser.add_argument(
|
|
'new_syms', metavar='new-syms', type=str,
|
|
help='The file containing the new symbol list or a library')
|
|
args = parser.parse_args()
|
|
|
|
old_syms_list = util.extract_or_load(args.old_syms)
|
|
new_syms_list = util.extract_or_load(args.new_syms)
|
|
|
|
added, removed, changed = diff.diff(old_syms_list, new_syms_list)
|
|
if args.removed_only:
|
|
added = {}
|
|
report, is_break = diff.report_diff(added, removed, changed,
|
|
names_only=args.names_only,
|
|
demangle=args.demangle)
|
|
if args.output is None:
|
|
print(report)
|
|
else:
|
|
with open(args.output, 'w') as f:
|
|
f.write(report + '\n')
|
|
sys.exit(is_break)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|