[libcxx] r240527 - Make support for thread-unsafe C functions optional.

Ed Schouten ed at nuxi.nl
Wed Jun 24 01:44:39 PDT 2015


Author: ed
Date: Wed Jun 24 03:44:38 2015
New Revision: 240527

URL: http://llvm.org/viewvc/llvm-project?rev=240527&view=rev
Log:
Make support for thread-unsafe C functions optional.

One of the aspects of CloudABI is that it aims to help you write code
that is thread-safe out of the box. This is very important if you want
to write libraries that are easy to reuse. For CloudABI we decided to
not provide the thread-unsafe functions. So far this is working out
pretty well, as thread-unsafety issues are detected really early on.

The following patch adds a knob to libc++,
_LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS, that can be set to disable
thread-unsafe functions that can easily be avoided in practice. The
following functions are not thread-safe:

- <clocale>: locale handles should be preferred over setlocale().
- <cstdlib>: mbrlen(), mbrtowc() and wcrtomb() should be preferred over
  their non-restartable counterparts.
- <ctime>: asctime(), ctime(), gmtime() and localtime() are not
  thread-safe. The first two are also deprecated by POSIX.

Differential Revision:	http://reviews.llvm.org/D8703
Reviewed by:	marshall

Added:
    libcxx/trunk/test/std/utilities/date.time/asctime.thread-unsafe.fail.cpp
    libcxx/trunk/test/std/utilities/date.time/ctime.thread-unsafe.fail.cpp
    libcxx/trunk/test/std/utilities/date.time/gmtime.thread-unsafe.fail.cpp
    libcxx/trunk/test/std/utilities/date.time/localtime.thread-unsafe.fail.cpp
Modified:
    libcxx/trunk/CMakeLists.txt
    libcxx/trunk/include/__config
    libcxx/trunk/include/clocale
    libcxx/trunk/include/cstdlib
    libcxx/trunk/include/cstring
    libcxx/trunk/include/ctime
    libcxx/trunk/test/CMakeLists.txt
    libcxx/trunk/test/libcxx/test/config.py
    libcxx/trunk/test/lit.site.cfg.in
    libcxx/trunk/test/std/depr/depr.c.headers/stdlib_h.pass.cpp
    libcxx/trunk/test/std/depr/depr.c.headers/string_h.pass.cpp
    libcxx/trunk/test/std/language.support/support.runtime/cstdlib.pass.cpp
    libcxx/trunk/test/std/language.support/support.runtime/ctime.pass.cpp
    libcxx/trunk/test/std/localization/c.locales/clocale.pass.cpp
    libcxx/trunk/test/std/strings/c.strings/cstring.pass.cpp

Modified: libcxx/trunk/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/CMakeLists.txt?rev=240527&r1=240526&r2=240527&view=diff
==============================================================================
--- libcxx/trunk/CMakeLists.txt (original)
+++ libcxx/trunk/CMakeLists.txt Wed Jun 24 03:44:38 2015
@@ -58,6 +58,7 @@ option(LIBCXX_ENABLE_GLOBAL_FILESYSTEM_N
 option(LIBCXX_ENABLE_STDIN "Build libc++ with support for stdin/std::cin." ON)
 option(LIBCXX_ENABLE_STDOUT "Build libc++ with support for stdout/std::cout." ON)
 option(LIBCXX_ENABLE_THREADS "Build libc++ with support for threads." ON)
+option(LIBCXX_ENABLE_THREAD_UNSAFE_C_FUNCTIONS "Build libc++ with support for thread-unsafe C functions" ON)
 option(LIBCXX_BUILD_32_BITS "Build 32 bit libc++" OFF)
 option(LIBCXX_ENABLE_MONOTONIC_CLOCK
   "Build libc++ with support for a monotonic clock.
@@ -274,6 +275,11 @@ elseif(NOT LIBCXX_ENABLE_MONOTONIC_CLOCK
                       " when LIBCXX_ENABLE_THREADS is also set to OFF.")
 endif()
 
+# LIBCXX_ENABLE_THREAD_UNSAFE_C_FUNCTIONS configuration
+if (NOT LIBCXX_ENABLE_THREAD_UNSAFE_C_FUNCTIONS)
+  add_definitions(-D_LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS)
+endif()
+
 # Configure for sanitizers. If LIBCXX_BUILT_STANDALONE then we have to do
 # the flag translation ourselves. Othewise LLVM's CMakeList.txt will handle it.
 if (LIBCXX_BUILT_STANDALONE)

Modified: libcxx/trunk/include/__config
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__config?rev=240527&r1=240526&r2=240527&view=diff
==============================================================================
--- libcxx/trunk/include/__config (original)
+++ libcxx/trunk/include/__config Wed Jun 24 03:44:38 2015
@@ -766,4 +766,10 @@ extern "C" void __sanitizer_annotate_con
 #define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
 #endif
 
+// Thread-unsafe functions such as strtok(), mbtowc() and localtime()
+// are not available.
+#ifdef __CloudABI__
+#define _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
+#endif
+
 #endif  // _LIBCPP_CONFIG

Modified: libcxx/trunk/include/clocale
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/clocale?rev=240527&r1=240526&r2=240527&view=diff
==============================================================================
--- libcxx/trunk/include/clocale (original)
+++ libcxx/trunk/include/clocale Wed Jun 24 03:44:38 2015
@@ -45,7 +45,9 @@ lconv* localeconv();
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 using ::lconv;
+#ifndef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
 using ::setlocale;
+#endif
 using ::localeconv;
 
 _LIBCPP_END_NAMESPACE_STD

Modified: libcxx/trunk/include/cstdlib
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/cstdlib?rev=240527&r1=240526&r2=240527&view=diff
==============================================================================
--- libcxx/trunk/include/cstdlib (original)
+++ libcxx/trunk/include/cstdlib Wed Jun 24 03:44:38 2015
@@ -147,9 +147,11 @@ using ::ldiv;
 #undef lldiv
 using ::lldiv;
 #endif // _LIBCPP_HAS_NO_LONG_LONG
+#ifndef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
 using ::mblen;
 using ::mbtowc;
 using ::wctomb;
+#endif
 using ::mbstowcs;
 using ::wcstombs;
 #ifdef _LIBCPP_HAS_QUICK_EXIT

Modified: libcxx/trunk/include/cstring
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/cstring?rev=240527&r1=240526&r2=240527&view=diff
==============================================================================
--- libcxx/trunk/include/cstring (original)
+++ libcxx/trunk/include/cstring Wed Jun 24 03:44:38 2015
@@ -102,7 +102,9 @@ inline _LIBCPP_INLINE_VISIBILITY       v
 inline _LIBCPP_INLINE_VISIBILITY       char* strstr(      char* __s1, const char* __s2) {return ::strstr(__s1, __s2);}
 #endif
 
+#ifndef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
 using ::strtok;
+#endif
 using ::memset;
 using ::strerror;
 using ::strlen;

Modified: libcxx/trunk/include/ctime
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/ctime?rev=240527&r1=240526&r2=240527&view=diff
==============================================================================
--- libcxx/trunk/include/ctime (original)
+++ libcxx/trunk/include/ctime Wed Jun 24 03:44:38 2015
@@ -61,10 +61,12 @@ using ::clock;
 using ::difftime;
 using ::mktime;
 using ::time;
+#ifndef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
 using ::asctime;
 using ::ctime;
 using ::gmtime;
 using ::localtime;
+#endif
 using ::strftime;
 
 _LIBCPP_END_NAMESPACE_STD

Modified: libcxx/trunk/test/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/CMakeLists.txt?rev=240527&r1=240526&r2=240527&view=diff
==============================================================================
--- libcxx/trunk/test/CMakeLists.txt (original)
+++ libcxx/trunk/test/CMakeLists.txt Wed Jun 24 03:44:38 2015
@@ -46,6 +46,7 @@ if (LIT_EXECUTABLE)
   pythonize_bool(LIBCXX_ENABLE_STDIN)
   pythonize_bool(LIBCXX_ENABLE_STDOUT)
   pythonize_bool(LIBCXX_ENABLE_THREADS)
+  pythonize_bool(LIBCXX_ENABLE_THREAD_UNSAFE_C_FUNCTIONS)
   pythonize_bool(LIBCXX_ENABLE_MONOTONIC_CLOCK)
   pythonize_bool(LIBCXX_GENERATE_COVERAGE)
   pythonize_bool(LIBCXXABI_USE_LLVM_UNWINDER)

Modified: libcxx/trunk/test/libcxx/test/config.py
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/libcxx/test/config.py?rev=240527&r1=240526&r2=240527&view=diff
==============================================================================
--- libcxx/trunk/test/libcxx/test/config.py (original)
+++ libcxx/trunk/test/libcxx/test/config.py Wed Jun 24 03:44:38 2015
@@ -372,6 +372,8 @@ class Configuration(object):
         elif not enable_monotonic_clock:
             self.lit_config.fatal('enable_monotonic_clock cannot be false when'
                                   ' enable_threads is true.')
+        self.configure_compile_flags_no_thread_unsafe_c_functions()
+
         # Use verbose output for better errors
         self.cxx.flags += ['-v']
         sysroot = self.get_lit_conf('sysroot')
@@ -431,6 +433,15 @@ class Configuration(object):
         self.cxx.compile_flags += ['-D_LIBCPP_HAS_NO_THREADS']
         self.config.available_features.add('libcpp-has-no-threads')
 
+    def configure_compile_flags_no_thread_unsafe_c_functions(self):
+        enable_thread_unsafe_c_functions = self.get_lit_bool(
+            'enable_thread_unsafe_c_functions', True)
+        if not enable_thread_unsafe_c_functions:
+            self.cxx.compile_flags += [
+                '-D_LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS']
+            self.config.available_features.add(
+                'libcpp-has-no-thread-unsafe-c-functions')
+
     def configure_compile_flags_no_monotonic_clock(self):
         self.cxx.compile_flags += ['-D_LIBCPP_HAS_NO_MONOTONIC_CLOCK']
         self.config.available_features.add('libcpp-has-no-monotonic-clock')
@@ -522,7 +533,7 @@ class Configuration(object):
             else:
                 self.cxx.link_flags += ['-lgcc_s']
         elif target_platform.startswith('freebsd'):
-            self.cxx.link_flags += ['-lc', '-lm', '-lpthread', '-lgcc_s']
+            self.cxx.link_flags += ['-lc', '-lm', '-lpthread', '-lgcc_s', '-lcxxrt']
         else:
             self.lit_config.fatal("unrecognized system: %r" % target_platform)
 

Modified: libcxx/trunk/test/lit.site.cfg.in
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/lit.site.cfg.in?rev=240527&r1=240526&r2=240527&view=diff
==============================================================================
--- libcxx/trunk/test/lit.site.cfg.in (original)
+++ libcxx/trunk/test/lit.site.cfg.in Wed Jun 24 03:44:38 2015
@@ -12,6 +12,7 @@ config.enable_global_filesystem_namespac
 config.enable_stdin             = "@LIBCXX_ENABLE_STDIN@"
 config.enable_stdout            = "@LIBCXX_ENABLE_STDOUT@"
 config.enable_threads           = "@LIBCXX_ENABLE_THREADS@"
+config.enable_thread_unsafe_c_functions = "@LIBCXX_ENABLE_THREAD_UNSAFE_C_FUNCTIONS@"
 config.enable_monotonic_clock   = "@LIBCXX_ENABLE_MONOTONIC_CLOCK@"
 config.cxx_abi                  = "@LIBCXX_CXX_ABI_LIBNAME@"
 config.use_sanitizer            = "@LLVM_USE_SANITIZER@"

Modified: libcxx/trunk/test/std/depr/depr.c.headers/stdlib_h.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/depr/depr.c.headers/stdlib_h.pass.cpp?rev=240527&r1=240526&r2=240527&view=diff
==============================================================================
--- libcxx/trunk/test/std/depr/depr.c.headers/stdlib_h.pass.cpp (original)
+++ libcxx/trunk/test/std/depr/depr.c.headers/stdlib_h.pass.cpp Wed Jun 24 03:44:38 2015
@@ -71,12 +71,14 @@ int main()
     static_assert((std::is_same<decltype(div(0,0)), div_t>::value), "");
     static_assert((std::is_same<decltype(ldiv(0L,0L)), ldiv_t>::value), "");
     static_assert((std::is_same<decltype(lldiv(0LL,0LL)), lldiv_t>::value), "");
-    static_assert((std::is_same<decltype(mblen("",0)), int>::value), "");
     wchar_t* pw = 0;
     const wchar_t* pwc = 0;
     char* pc = 0;
+#ifndef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
+    static_assert((std::is_same<decltype(mblen("",0)), int>::value), "");
     static_assert((std::is_same<decltype(mbtowc(pw,"",0)), int>::value), "");
     static_assert((std::is_same<decltype(wctomb(pc,L' ')), int>::value), "");
+#endif
     static_assert((std::is_same<decltype(mbstowcs(pw,"",0)), size_t>::value), "");
     static_assert((std::is_same<decltype(wcstombs(pc,pwc,0)), size_t>::value), "");
 }

Modified: libcxx/trunk/test/std/depr/depr.c.headers/string_h.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/depr/depr.c.headers/string_h.pass.cpp?rev=240527&r1=240526&r2=240527&view=diff
==============================================================================
--- libcxx/trunk/test/std/depr/depr.c.headers/string_h.pass.cpp (original)
+++ libcxx/trunk/test/std/depr/depr.c.headers/string_h.pass.cpp Wed Jun 24 03:44:38 2015
@@ -41,7 +41,9 @@ int main()
     static_assert((std::is_same<decltype(strrchr(cp, 0)), char*>::value), "");
     static_assert((std::is_same<decltype(strspn(cpc, cpc)), size_t>::value), "");
     static_assert((std::is_same<decltype(strstr(cp, cpc)), char*>::value), "");
+#ifndef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
     static_assert((std::is_same<decltype(strtok(cp, cpc)), char*>::value), "");
+#endif
     static_assert((std::is_same<decltype(memset(vp, 0, s)), void*>::value), "");
     static_assert((std::is_same<decltype(strerror(0)), char*>::value), "");
     static_assert((std::is_same<decltype(strlen(cpc)), size_t>::value), "");

Modified: libcxx/trunk/test/std/language.support/support.runtime/cstdlib.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/language.support/support.runtime/cstdlib.pass.cpp?rev=240527&r1=240526&r2=240527&view=diff
==============================================================================
--- libcxx/trunk/test/std/language.support/support.runtime/cstdlib.pass.cpp (original)
+++ libcxx/trunk/test/std/language.support/support.runtime/cstdlib.pass.cpp Wed Jun 24 03:44:38 2015
@@ -75,12 +75,14 @@ int main()
     static_assert((std::is_same<decltype(std::div(0LL,0LL)), std::lldiv_t>::value), "");
     static_assert((std::is_same<decltype(std::ldiv(0L,0L)), std::ldiv_t>::value), "");
     static_assert((std::is_same<decltype(std::lldiv(0LL,0LL)), std::lldiv_t>::value), "");
-    static_assert((std::is_same<decltype(std::mblen("",0)), int>::value), "");
     wchar_t* pw = 0;
     const wchar_t* pwc = 0;
     char* pc = 0;
+#ifndef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
+    static_assert((std::is_same<decltype(std::mblen("",0)), int>::value), "");
     static_assert((std::is_same<decltype(std::mbtowc(pw,"",0)), int>::value), "");
     static_assert((std::is_same<decltype(std::wctomb(pc,L' ')), int>::value), "");
+#endif
     static_assert((std::is_same<decltype(std::mbstowcs(pw,"",0)), std::size_t>::value), "");
     static_assert((std::is_same<decltype(std::wcstombs(pc,pwc,0)), std::size_t>::value), "");
 }

Modified: libcxx/trunk/test/std/language.support/support.runtime/ctime.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/language.support/support.runtime/ctime.pass.cpp?rev=240527&r1=240526&r2=240527&view=diff
==============================================================================
--- libcxx/trunk/test/std/language.support/support.runtime/ctime.pass.cpp (original)
+++ libcxx/trunk/test/std/language.support/support.runtime/ctime.pass.cpp Wed Jun 24 03:44:38 2015
@@ -30,10 +30,12 @@ int main()
     static_assert((std::is_same<decltype(std::difftime(t,t)), double>::value), "");
     static_assert((std::is_same<decltype(std::mktime(&tm)), std::time_t>::value), "");
     static_assert((std::is_same<decltype(std::time(&t)), std::time_t>::value), "");
+#ifndef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
     static_assert((std::is_same<decltype(std::asctime(&tm)), char*>::value), "");
     static_assert((std::is_same<decltype(std::ctime(&t)), char*>::value), "");
     static_assert((std::is_same<decltype(std::gmtime(&t)), std::tm*>::value), "");
     static_assert((std::is_same<decltype(std::localtime(&t)), std::tm*>::value), "");
+#endif
     char* c1 = 0;
     const char* c2 = 0;
     static_assert((std::is_same<decltype(std::strftime(c1,s,c2,&tm)), std::size_t>::value), "");

Modified: libcxx/trunk/test/std/localization/c.locales/clocale.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/localization/c.locales/clocale.pass.cpp?rev=240527&r1=240526&r2=240527&view=diff
==============================================================================
--- libcxx/trunk/test/std/localization/c.locales/clocale.pass.cpp (original)
+++ libcxx/trunk/test/std/localization/c.locales/clocale.pass.cpp Wed Jun 24 03:44:38 2015
@@ -12,6 +12,8 @@
 #include <clocale>
 #include <type_traits>
 
+#ifndef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
+
 #ifndef LC_ALL
 #error LC_ALL not defined
 #endif
@@ -36,6 +38,8 @@
 #error LC_TIME not defined
 #endif
 
+#endif // !_LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
+
 #ifndef NULL
 #error NULL not defined
 #endif
@@ -43,6 +47,8 @@
 int main()
 {
     std::lconv lc;
+#ifndef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
     static_assert((std::is_same<decltype(std::setlocale(0, "")), char*>::value), "");
+#endif
     static_assert((std::is_same<decltype(std::localeconv()), std::lconv*>::value), "");
 }

Modified: libcxx/trunk/test/std/strings/c.strings/cstring.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/strings/c.strings/cstring.pass.cpp?rev=240527&r1=240526&r2=240527&view=diff
==============================================================================
--- libcxx/trunk/test/std/strings/c.strings/cstring.pass.cpp (original)
+++ libcxx/trunk/test/std/strings/c.strings/cstring.pass.cpp Wed Jun 24 03:44:38 2015
@@ -46,7 +46,9 @@ int main()
     static_assert((std::is_same<decltype(std::strspn(cpc, cpc)), std::size_t>::value), "");
 //    static_assert((std::is_same<decltype(std::strstr(cpc, cpc)), const char*>::value), "");
     static_assert((std::is_same<decltype(std::strstr(cp, cpc)), char*>::value), "");
+#ifndef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
     static_assert((std::is_same<decltype(std::strtok(cp, cpc)), char*>::value), "");
+#endif
     static_assert((std::is_same<decltype(std::memset(vp, 0, s)), void*>::value), "");
     static_assert((std::is_same<decltype(std::strerror(0)), char*>::value), "");
     static_assert((std::is_same<decltype(std::strlen(cpc)), std::size_t>::value), "");

Added: libcxx/trunk/test/std/utilities/date.time/asctime.thread-unsafe.fail.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/date.time/asctime.thread-unsafe.fail.cpp?rev=240527&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/date.time/asctime.thread-unsafe.fail.cpp (added)
+++ libcxx/trunk/test/std/utilities/date.time/asctime.thread-unsafe.fail.cpp Wed Jun 24 03:44:38 2015
@@ -0,0 +1,18 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: libcpp-has-no-thread-unsafe-c-functions
+
+#include <ctime>
+
+int main() {
+    // asctime is not thread-safe.
+    std::time_t t = 0;
+    std::asctime(&t);
+}

Added: libcxx/trunk/test/std/utilities/date.time/ctime.thread-unsafe.fail.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/date.time/ctime.thread-unsafe.fail.cpp?rev=240527&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/date.time/ctime.thread-unsafe.fail.cpp (added)
+++ libcxx/trunk/test/std/utilities/date.time/ctime.thread-unsafe.fail.cpp Wed Jun 24 03:44:38 2015
@@ -0,0 +1,18 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: libcpp-has-no-thread-unsafe-c-functions
+
+#include <ctime>
+
+int main() {
+    // ctime is not thread-safe.
+    std::time_t t = 0;
+    std::ctime(&t);
+}

Added: libcxx/trunk/test/std/utilities/date.time/gmtime.thread-unsafe.fail.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/date.time/gmtime.thread-unsafe.fail.cpp?rev=240527&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/date.time/gmtime.thread-unsafe.fail.cpp (added)
+++ libcxx/trunk/test/std/utilities/date.time/gmtime.thread-unsafe.fail.cpp Wed Jun 24 03:44:38 2015
@@ -0,0 +1,18 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: libcpp-has-no-thread-unsafe-c-functions
+
+#include <ctime>
+
+int main() {
+    // gmtime is not thread-safe.
+    std::time_t t = 0;
+    std::gmtime(&t);
+}

Added: libcxx/trunk/test/std/utilities/date.time/localtime.thread-unsafe.fail.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/date.time/localtime.thread-unsafe.fail.cpp?rev=240527&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/date.time/localtime.thread-unsafe.fail.cpp (added)
+++ libcxx/trunk/test/std/utilities/date.time/localtime.thread-unsafe.fail.cpp Wed Jun 24 03:44:38 2015
@@ -0,0 +1,18 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: libcpp-has-no-thread-unsafe-c-functions
+
+#include <ctime>
+
+int main() {
+    // localtime is not thread-safe.
+    std::time_t t = 0;
+    std::localtime(&t);
+}





More information about the cfe-commits mailing list