Cleanup exception handling in `clang_utils.py`.

http://reviews.llvm.org/D7542

Files:
  CMakeLists.txt
  cmake/Modules/GetCompilerRTOptions.cmake
  lib/CMakeLists.txt
  test/libcxx/clang_utils.py
  test/libcxx/compiler.py
  test/libcxx/test/config.py

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt
+++ CMakeLists.txt
@@ -96,9 +96,12 @@
 
 # Declare libc++ configuration variables.
 # They are intended for use as follows:
+# LIBCXX_TARGET_FLAGS: Compile and link flags that affect the output target or
+#                      arch. ex: -m32 -target
 # LIBCXX_CXX_FLAGS: General flags for both the compiler and linker.
 # LIBCXX_COMPILE_FLAGS: Compile only flags.
 # LIBCXX_LINK_FLAGS: Linker only flags.
+set(LIBCXX_TARGET_FLAGS "")
 set(LIBCXX_CXX_FLAGS "")
 set(LIBCXX_COMPILE_FLAGS "")
 set(LIBCXX_LINK_FLAGS "")
@@ -213,7 +216,7 @@
 if (CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32)
   if (LIBCXX_BUILD_32_BITS)
     message(STATUS "Building 32 bits executables and libraries.")
-    list(APPEND LIBCXX_CXX_FLAGS "-m32")
+    list(APPEND LIBCXX_TARGET_FLAGS "-m32")
   endif()
 elseif(LIBCXX_BUILD_32_BITS)
   message(FATAL_ERROR "LIBCXX_BUILD_32_BITS=ON is not supported on this platform.")
@@ -268,14 +271,29 @@
   endif()
 endif()
 
-append_if(LIBCXX_CXX_FLAGS LIBCXX_TARGET_TRIPLE
+append_if(LIBCXX_TARGET_FLAGS LIBCXX_TARGET_TRIPLE
           "-target ${LIBCXX_TARGET_TRIPLE}")
-append_if(LIBCXX_CXX_FLAGS LIBCXX_SYSROOT "--sysroot ${LIBCXX_SYSROOT}")
-append_if(LIBCXX_CXX_FLAGS LIBCXX_GCC_TOOLCHAIN
+
+append_if(LIBCXX_TARGET_FLAGS LIBCXX_SYSROOT "--sysroot ${LIBCXX_SYSROOT}")
+append_if(LIBCXX_TARGET_FLAGS LIBCXX_GCC_TOOLCHAIN
           "-gcc-toolchain ${LIBCXX_GCC_TOOLCHAIN}")
 
+# We need to probe and manually link the sanitizer libraries on OS X.
+if (APPLE AND LLVM_USE_SANITIZER)
+  set(LIBCXX_COMPILER_RT_OPTION "${LLVM_USE_SANITIZER}")
+endif()
+
+# Manually link the required sanitizer libraries.
+if (DEFINED LIBCXX_COMPILER_RT_OPTION)
+  include(GetCompilerRTOptions)
+  get_compiler_rt_option(LIBCXX_COMPILER_RT_LINK_LIBRARIES
+        "${LIBCXX_COMPILER_RT_OPTION}"
+        "${LIBCXX_TARGET_FLAGS}")
+endif()
+
 string(REPLACE ";" " " LIBCXX_CXX_FLAGS "${LIBCXX_CXX_FLAGS}")
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LIBCXX_CXX_FLAGS}")
+string(REPLACE ";" " " LIBCXX_TARGET_FLAGS "${LIBCXX_TARGET_FLAGS}")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LIBCXX_CXX_FLAGS} ${LIBCXX_TARGET_FLAGS}")
 
 #===============================================================================
 # Setup Source Code
Index: cmake/Modules/GetCompilerRTOptions.cmake
===================================================================
--- /dev/null
+++ cmake/Modules/GetCompilerRTOptions.cmake
@@ -0,0 +1,49 @@
+# An internal method to setup the python enviroment.
+macro(_setup_python)
+  if (LIT_EXECUTABLE)
+    get_filename_component(LIT_MODULE_PATH ${LIT_EXECUTABLE} DIRECTORY)
+  else()
+    set(LIT_MODULE_PATH "${CMAKE_SOURCE_DIR}/utils/lit")
+  endif()
+  if (NOT IS_DIRECTORY ${LIT_MODULE_PATH})
+    message(FATAL_ERROR "Failed to find the LIT module.")
+  endif()
+  set(LIBCXX_PYTHONPATH "${LIT_MODULE_PATH}:${LIBCXX_SOURCE_DIR}/test:$ENV{PYTHONPATH}")
+  set(ENV{PYTHONPATH} "${LIBCXX_PYTHONPATH}")
+  include(FindPythonInterp)
+  if(NOT PYTHONINTERP_FOUND)
+    message(FATAL_ERROR "Failed to find python executable")
+  endif()
+endmacro()
+
+#===============================================================================
+# Get CompilerRT link flags
+#===============================================================================
+#
+# get_compiler_rt_option: Get link flags for a given compiler-rt library.
+#
+# Parameters:
+#   output_var: The variable to write the list of flags to.
+#   opt: The compiler-rt configuration to get the flags for. It can be one of
+#        Profile, Address, Memory, MemoryWithOrigins, Undefined, Thread.
+#   extra_flags: A list of extra compiler flags used to help find the
+#                compiler_rt libraries.
+function(get_compiler_rt_option output_var opt extra_flags)
+  if (NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+    message(FATAL_ERROR
+        "GetCompilerRTOptions can only be used with a Clang compiler")
+  endif()
+  _setup_python()
+  separate_arguments(extra_flags)
+  foreach(e ${extra_flags})
+    list(APPEND EXTRA_FLAGS "--flag;${e}")
+  endforeach()
+  execute_process(COMMAND ${PYTHON_EXECUTABLE} ${LIBCXX_SOURCE_DIR}/test/libcxx/clang_utils.py --cxx ${CMAKE_CXX_COMPILER} ${EXTRA_FLAGS} ${opt}
+                  RESULT_VARIABLE RES_VAR
+                  OUTPUT_VARIABLE OUTPUT_VAR)
+  if (NOT RES_VAR EQUAL 0)
+    message(FATAL_ERROR "get_compiler_rt_option failed to get link options for ${opt}")
+  endif()
+  string(STRIP "${OUTPUT_VAR}" OUTPUT_VAR)
+  set(${output_var} "${OUTPUT_VAR}" PARENT_SCOPE)
+endfunction()
Index: lib/CMakeLists.txt
===================================================================
--- lib/CMakeLists.txt
+++ lib/CMakeLists.txt
@@ -50,6 +50,7 @@
 if (DEFINED LIBCXX_CXX_ABI_LIBRARY_PATH)
   target_link_libraries(cxx "-L${LIBCXX_CXX_ABI_LIBRARY_PATH}")
 endif()
+target_link_libraries(cxx ${LIBCXX_COMPILER_RT_LINK_LIBRARIES})
 target_link_libraries(cxx ${libraries})
 
 # Setup flags.
Index: test/libcxx/clang_utils.py
===================================================================
--- /dev/null
+++ test/libcxx/clang_utils.py
@@ -0,0 +1,357 @@
+"""
+clang_utils - Utilities for linking with the clang compiler.
+"""
+
+import os
+import libcxx.compiler
+
+
+class BasicClangLinkDriver(object):
+    """
+    BasicClangLinkDriver - A linker driver that mimics how clang links
+                           compiler-rt
+    """
+    def __init__(self, cxx):
+        self.cxx = cxx
+        if cxx.type is None or 'clang' not in cxx.type:
+            raise RuntimeError('Compiler is not a clang variant')
+        search_paths = self.cxx.getLibrarySearchPaths()
+        if not search_paths:
+            raise RuntimeError('Failed to get search paths')
+        self.clang_resource_dir = search_paths[0]
+        if not os.path.isdir(self.clang_resource_dir):
+            raise RuntimeError('Clang resource directory does not exist')
+        self.target_info = self.cxx.getTargetInfo()
+        sys = self.target_info.sys
+        if sys.startswith('darwin'):
+            self.target_info.sys = 'darwin'
+        self.clang_library_dir = os.path.join(
+            self.clang_resource_dir, 'lib', self.target_info.sys)
+        if not os.path.isdir(self.clang_library_dir):
+            raise RuntimeError('clang library path does not exist: %s' %
+                               self.clang_library_dir)
+
+    def getClangResourceDir(self):
+        """
+        Return clangs root resource dir.
+
+        If clang is /path/to/bin/clang++ then the resource dir is usually
+        /path/to/bin/../lib/clang/<X>.<Y>.<Z>/
+        """
+        return self.clang_resource_dir
+
+    def getClangLibraryDir(self):
+        """
+        Return clangs library dir. This directory contains the compiler-rt
+        libraries.
+
+        If clang is /path/to/bin/clang++ then the library dir is usually
+        /path/to/bin/../lib/clang/<X>.<Y>.<Z>/lib/<platform>
+        """
+        return self.clang_library_dir
+
+    def getStaticCompilerRTLibrary(self, suffix, required=False):
+        """
+        Return the full path to a static clang_rt library or None if it doesn't
+        exist.
+
+        If required is True then the function will throw if the library is not
+        found.
+        """
+        libname = 'libclang_rt.%s.a' % suffix
+        libpath = os.path.join(self.clang_library_dir, libname)
+        if os.path.isfile(libpath):
+            return libpath
+        elif required:
+            raise RuntimeError('Required library %s not found at %s' %
+                               (libname, libpath))
+        else:
+            return None
+
+    def getStaticCompilerRTLibraryWithArch(self, name, required=False):
+        """
+        Return the full path to a static architecture specific clang_rt library
+        or None if it doesn't exist.
+
+        If required is True then the function will throw if the library is not
+        found.
+        """
+        return self.getStaticCompilerRTLibrary(
+            '%s-%s' % (name, self.target_info.arch), required=required)
+
+    def getSharedCompilerRTLibrary(self, suffix, required=False):
+        """
+        Return the full path to a shared clang_rt library or None if it doesn't
+        exist.
+
+        If required is True then the function will throw if the library is not
+        found.
+        """
+        libname = 'libclang_rt.%s' % suffix
+        if self.target_info.sys == 'darwin':
+            libname += '.dylib'
+        else:
+            libname += '.so'
+        libpath = os.path.join(self.clang_library_dir, libname)
+        if os.path.isfile(libpath):
+            return libpath
+        elif required:
+            raise RuntimeError('Required library %s not found at %s' %
+                               (libname, libpath))
+        else:
+            return None
+
+    def getSharedCompilerRTLibraryWithArch(self, name, required=False):
+        """
+        Return the full path to a shared architecture specific clang_rt library
+        or None if it doesn't exist.
+
+        If required is True then the function will throw if the library is not
+        found.
+        """
+        return self.getSharedCompilerRTLibrary(
+            '%s-%s' % (name, self.target_info.arch), required=required)
+
+    def getCompilerRTLibrary(self, name):
+        """
+        Return the full path to a shared or static clang_rt library. Throw if
+        the library doesn't exist.
+
+        This function will try looking for the shared library first and if that
+        is not found will search for the static version.
+        """
+        ret = self.getSharedCompilerRTLibrary(name)
+        if ret is None:
+            ret = self.getStaticCompilerRTLibrary(name)
+        if ret is None:
+            raise RuntimeError('Failed to find library for name: %s' % name)
+        return ret
+
+    def getCompilerRTLibraryWithArch(self, name):
+        """
+        Return the full path to a shared or static architecture specific
+        clang_rt library. Throw if the library doesn't exist.
+
+        This function will try looking for the shared library first and if that
+        is not found will search for the static version.
+        """
+        ret = self.getSharedCompilerRTLibraryWithArch(name)
+        if ret is None:
+            ret = self.getStaticCompilerRTLibraryWithArch(name)
+        if ret is None:
+            raise RuntimeError('Failed to find library for name: %s' % name)
+        return ret
+
+    def getProfileRTLinkOptions(self):
+        """
+        Return a list of link options for ProfileRt
+        """
+        raise NotImplementedError("abstract method for %s" % type(self))
+
+    def getASanLinkOptions(self):
+        """
+        Return a list of link options for ASAN
+        """
+        raise NotImplementedError("abstract method for %s" % type(self))
+
+    def getMSanLinkOptions(self):
+        """
+        Return a list of link options for MSAN
+        """
+        raise NotImplementedError("abstract method for %s" % type(self))
+
+    def getUBSanLinkOptions(self):
+        """
+        Return a list of link options for UBSAN
+        """
+        raise NotImplementedError("abstract method for %s" % type(self))
+
+    def getTSanLinkOptions(self):
+        """
+        Return a list of link options for TSAN
+        """
+        raise NotImplementedError("abstract method for %s" % type(self))
+
+
+class DarwinClangLinkDriver(BasicClangLinkDriver):
+    """
+    The implementation of BasicClangLinkDriver for stock clang on OS X.
+    """
+    def __init__(self, cxx):
+        super(DarwinClangLinkDriver, self).__init__(cxx)
+
+    def getProfileRTLinkOptions(self):
+        return [
+            self.getCompilerRTLibrary('profile_osx'),
+        ]
+
+    def getASanLinkOptions(self):
+        return [
+            self.getCompilerRTLibrary('asan_osx_dynamic')
+        ]
+
+    def getMSanLinkOptions(self):
+        raise RuntimeError("MSan not supported")
+
+    def getUBSanLinkOptions(self):
+        return [
+            self.getCompilerRTLibrary('ubsan_osx')
+        ]
+
+    def getTSanLinkOptions(self):
+        raise RuntimeError("TSan not supported")
+
+
+class DarwinAppleClangLinkDriver(BasicClangLinkDriver):
+    """
+    The implementation of BasicClangLinkDriver for apple clang on OS X.
+    """
+    def __init__(self, cxx):
+        super(DarwinAppleClangLinkDriver, self).__init__(cxx)
+
+    def getProfileRTLinkOptions(self):
+        return [
+            self.getCompilerRTLibrary('profile_osx'),
+            '-lSystem',
+            self.getCompilerRTLibrary('osx')
+        ]
+
+    def getASanLinkOptions(self):
+        return [
+            self.getCompilerRTLibrary('asan_osx_dynamic'),
+            '-lSystem',
+            self.getCompilerRTLibrary('osx')
+        ]
+
+    def getMSanLinkOptions(self):
+        raise RuntimeError("MSan not supported")
+
+    def getUBSanLinkOptions(self):
+        return [
+            self.getCompilerRTLibrary('ubsan_osx'),
+            '-lSystem',
+            self.getCompilerRTLibrary('osx')
+        ]
+
+    def getTSanLinkOptions(self):
+        raise RuntimeError("TSan not supported")
+
+
+class LinuxClangLinkDriver(BasicClangLinkDriver):
+    """
+    The implementation of BasicClangLinkDriver for clang on linux.
+    """
+    def __init__(self, cxx):
+        super(LinuxClangLinkDriver, self).__init__(cxx)
+
+    def _getStaticLib(self, name):
+        return self.getStaticCompilerRTLibraryWithArch(name, required=True)
+
+    def _getWholeStaticLib(self, name):
+        libpath = self._getStaticLib(name)
+        return ['-Wl,--whole-archive', libpath, '-Wl,--no-whole-archive']
+
+    def _getWholeStaticLibWithSyms(self, name):
+        libpath = self._getStaticLib(name)
+        return ['-Wl,--whole-archive', libpath, '-Wl,--no-whole-archive',
+                '-Wl,--dynamic-list=' + libpath + '.syms']
+
+    def getProfileRTLinkOptions(self):
+        return [
+            self._getStaticLib('profile')
+        ]
+
+    def getASanLinkOptions(self):
+        args = []
+        args += self._getWholeStaticLibWithSyms('asan')
+        args += self._getWholeStaticLibWithSyms('asan_cxx')
+        return args
+
+    def getMSanLinkOptions(self):
+        return self._getWholeStaticLibWithSyms('msan')
+
+    def getUBSanLinkOptions(self):
+        args = []
+        args += self._getWholeStaticLib('san')
+        args += self._getWholeStaticLibWithSyms('ubsan')
+        args += self._getWholeStaticLibWithSyms('ubsan_cxx')
+        return args
+
+    def getTSanLinkOptions(self):
+        return self._getWholeStaticLibWithSyms('tsan')
+
+
+def getClangLinkDriver(cxx):
+    """
+    Return the implementation of the Clang linker driver for a giver platform
+    and compiler.
+    """
+    if cxx.type is None:
+        raise RuntimeError('Compiler type could not be determined')
+    elif 'clang' not in cxx.type:
+        raise RuntimeError('Compiler %s is not clang' % cxx.type)
+    elif cxx.type == 'apple-clang':
+        return DarwinAppleClangLinkDriver(cxx)
+    else:  # cxx.type == 'clang'
+        trip = cxx.getTriple()
+        if 'darwin' in trip:
+            return DarwinClangLinkDriver(cxx)
+        elif 'linux' in trip:
+            return LinuxClangLinkDriver(cxx)
+        else:
+            raise RuntimeError('Unsupported target: %s' % trip)
+    assert False
+
+
+def main():
+    """
+    Print a semi-colon list of compiler-rt link flags based on the compiler
+    and arguments.
+
+    clang-utils.py [--cxx compiler] [--flag cxx_flag]... Spec
+    options:
+      --cxx - The cxx compiler to use
+      --flag - A list of extra flags to configure with
+      Spec - One of Profile, Address, Memory, MemoryWithAddress, Undefined,
+                    Thread.
+    """
+    from optparse import OptionParser
+    parser = OptionParser("usage: %prog [options] {CompilerRT Spec}")
+    parser.add_option('-c', '--cxx', dest='compiler',
+                      help='The compiler to use',
+                      type=str, action='store', default='clang++')
+    parser.add_option("-f", "--flag", dest="extraFlags",
+                      metavar="NAME=VAL",
+                      help="Add 'NAME' = 'VAL' to the flags used",
+                      type=str, action='append', default=[])
+    (opts, args) = parser.parse_args()
+    cxx = libcxx.compiler.CXXCompiler(opts.compiler, flags=opts.extraFlags)
+    driver = getClangLinkDriver(cxx)
+    if len(args) != 1:
+        print('Invalid args: %s' % args)
+        exit(1)
+    spec = args[0]
+    info_specs = {
+        'Profile': driver.getProfileRTLinkOptions,
+        'Address': driver.getASanLinkOptions,
+        'Memory': driver.getMSanLinkOptions,
+        'MemoryWithAddress': driver.getMSanLinkOptions,
+        'Undefined': driver.getUBSanLinkOptions,
+        'Thread': driver.getUBSanLinkOptions
+    }
+    if spec not in info_specs.keys():
+        print('%s is not a valid spec' % spec)
+        exit(1)
+    try:
+        out = ';'.join(info_specs[spec]())
+        print(out)
+    except RuntimeError as e:
+        print('%s Exception thrown' % e)
+        exit(1)
+    except:
+        print('Unknown exception thrown')
+        exit(1)
+
+if __name__ == '__main__':
+    main()
+    exit(0)
Index: test/libcxx/compiler.py
===================================================================
--- test/libcxx/compiler.py
+++ test/libcxx/compiler.py
@@ -1,8 +1,17 @@
 import os
+import re
 import lit.util
 import libcxx.util
 
 
+class TargetInfo:
+    def __init__(self, arch=None, sys=None, vendor=None, abi=None):
+        self.arch = arch
+        self.sys = sys
+        self.vendor = vendor
+        self.abi = abi
+
+
 class CXXCompiler(object):
     def __init__(self, path, flags=None, compile_flags=None, link_flags=None,
                  use_ccache=False):
@@ -133,4 +142,41 @@
 
     def getTriple(self):
         cmd = [self.path] + self.flags + ['-dumpmachine']
-        return lit.util.capture(cmd).strip()
+        out, err, rc = lit.util.executeCommand(cmd)
+        if rc != 0:
+            raise Exception()
+        return out.strip()
+
+    def getTargetInfo(self):
+        triple = self.getTriple()
+        parts = triple.split('-')
+        assert len(parts) == 3 or len(parts) == 4
+        info = TargetInfo(parts[0])
+        if len(parts) == 3:
+            if parts[1] in ['apple'] or parts[2] in ['linux']:
+                info.vendor = parts[1]
+                info.sys = parts[2]
+            else:
+                info.vendor = 'unknown'
+                info.sys = parts[1]
+                info.abi = parts[2]
+            if info.sys == 'linux':
+                info.abi = 'gnu'
+        else:
+            info.vendor = parts[1]
+            info.sys = parts[2]
+            info.abi = parts[3]
+        return info
+
+    kSearchDirsRe = re.compile('libraries: =([^\n]*)\n')
+
+    def getLibrarySearchPaths(self):
+        cmd = [self.path] + self.flags + ['-print-search-dirs']
+        out, err, rc = lit.util.executeCommand(cmd)
+        if rc != 0:
+            raise Exception()
+        match = CXXCompiler.kSearchDirsRe.search(out)
+        assert match is not None
+        dir_list = match.group(1).strip().split(':')
+        assert len(dir_list) != 0
+        return dir_list
Index: test/libcxx/test/config.py
===================================================================
--- test/libcxx/test/config.py
+++ test/libcxx/test/config.py
@@ -11,6 +11,7 @@
 
 from libcxx.test.format import LibcxxTestFormat
 from libcxx.compiler import CXXCompiler
+from libcxx.clang_utils import getClangLinkDriver
 
 
 def loadSiteConfig(lit_config, config, param_name, env_name):
@@ -343,7 +344,9 @@
     def configure_compile_flags_header_includes(self):
         support_path = os.path.join(self.libcxx_src_root, 'test/support')
         self.cxx.compile_flags += ['-I' + support_path]
-        self.cxx.compile_flags += ['-include', os.path.join(support_path, 'nasty_macros.hpp')]
+        self.cxx.compile_flags += [
+            '-include', os.path.join(support_path, 'nasty_macros.hpp')
+        ]
         libcxx_headers = self.get_lit_conf(
             'libcxx_headers', os.path.join(self.libcxx_src_root, 'include'))
         if not os.path.isdir(libcxx_headers):
@@ -462,8 +465,8 @@
         enable_warnings = self.get_lit_bool('enable_warnings', False)
         if enable_warnings:
             self.cxx.compile_flags += ['-Wsystem-headers', '-Wall', '-Werror']
-            if ('clang' in self.config.available_features or
-                'apple-clang' in self.config.available_features):
+            if ('clang' in self.config.available_features
+                    or 'apple-clang' in self.config.available_features):
                 self.cxx.compile_flags += ['-Wno-user-defined-literals']
 
     def configure_sanitizer(self):
@@ -481,18 +484,30 @@
                                              symbolizer_search_paths)
             # Setup the sanitizer compile flags
             self.cxx.flags += ['-g', '-fno-omit-frame-pointer']
+            manual_link = ('darwin' in self.config.target_triple and
+                           '-nodefaultlibs' in self.cxx.link_flags)
+            link_cxx = CXXCompiler(self.cxx.path, self.cxx.flags)
+            link_driver = getClangLinkDriver(link_cxx)
+            if manual_link:
+                self.cxx.link_flags += [
+                    '-Wl,-rpath,' + link_driver.getClangLibraryDir()
+                ]
             if sys.platform.startswith('linux'):
                 self.cxx.link_flags += ['-ldl']
             if san == 'Address':
                 self.cxx.flags += ['-fsanitize=address']
                 if llvm_symbolizer is not None:
                     self.env['ASAN_SYMBOLIZER_PATH'] = llvm_symbolizer
+                if manual_link:
+                    self.cxx.link_flags += link_driver.getASanLinkOptions()
                 self.config.available_features.add('asan')
             elif san == 'Memory' or san == 'MemoryWithOrigins':
                 self.cxx.flags += ['-fsanitize=memory']
                 if san == 'MemoryWithOrigins':
                     self.cxx.compile_flags += [
                         '-fsanitize-memory-track-origins']
+                if manual_link:
+                    self.cxx.link_flags += link_driver.getMSanLinkOptions()
                 if llvm_symbolizer is not None:
                     self.env['MSAN_SYMBOLIZER_PATH'] = llvm_symbolizer
                 self.config.available_features.add('msan')
@@ -501,9 +516,13 @@
                                    '-fno-sanitize=vptr,function',
                                    '-fno-sanitize-recover']
                 self.cxx.compile_flags += ['-O3']
+                if manual_link:
+                    self.cxx.link_flags += link_driver.getUBSanLinkOptions()
                 self.config.available_features.add('ubsan')
             elif san == 'Thread':
                 self.cxx.flags += ['-fsanitize=thread']
+                if manual_link:
+                    self.cxx.link_flags += link_driver.getTSanLinkOptions()
                 self.config.available_features.add('tsan')
             else:
                 self.lit_config.fatal('unsupported value for '
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to