Merge "Introducing linker namespaces"
diff --git a/.clang-format b/.clang-format
index ea19538..9b7478c 100644
--- a/.clang-format
+++ b/.clang-format
@@ -2,6 +2,7 @@
 AllowShortBlocksOnASingleLine: false
 AllowShortFunctionsOnASingleLine: false
 
+ColumnLimit: 100
 CommentPragmas: NOLINT:.*
 DerivePointerAlignment: false
 IndentWidth: 2
diff --git a/libc/Android.mk b/libc/Android.mk
index 4ffdf57..a89fe23 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -725,6 +725,7 @@
 LOCAL_CFLAGS += -DALL_STATE
 # Include tzsetwall, timelocal, timegm, time2posix, and posix2time.
 LOCAL_CFLAGS += -DSTD_INSPIRED
+# Obviously, we want to be thread-safe.
 LOCAL_CFLAGS += -DTHREAD_SAFE
 # The name of the tm_gmtoff field in our struct tm.
 LOCAL_CFLAGS += -DTM_GMTOFF=tm_gmtoff
@@ -732,6 +733,8 @@
 LOCAL_CFLAGS += -DTZDIR=\"/system/usr/share/zoneinfo\"
 # Include timezone and daylight globals.
 LOCAL_CFLAGS += -DUSG_COMPAT=1
+# Use the empty string (instead of "   ") as the timezone abbreviation fallback.
+LOCAL_CFLAGS += -DWILDABBR=\"\"
 LOCAL_CFLAGS += -DNO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
 LOCAL_CFLAGS += -Dlint
 
@@ -1043,15 +1046,15 @@
 LOCAL_CPPFLAGS := $(libc_common_cppflags) -Wold-style-cast
 LOCAL_C_INCLUDES := $(libc_common_c_includes)
 LOCAL_MODULE := libc_thread_atexit_impl
-# TODO: Clang tries to use __tls_get_addr which is not supported yet
-# remove after it is implemented.
-LOCAL_CLANG := false
 LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 LOCAL_CXX_STL := none
 LOCAL_SYSTEM_SHARED_LIBRARIES :=
 LOCAL_SANITIZE := never
 LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 
+# b/25662915, clang compiled __cxa_thread_atexit_impl.cpp still failed.
+LOCAL_CLANG_arm64 := false
+
 include $(BUILD_STATIC_LIBRARY)
 
 # ========================================================
diff --git a/libc/tzcode/localtime.c b/libc/tzcode/localtime.c
index cb8aeed..b1ebb24 100644
--- a/libc/tzcode/localtime.c
+++ b/libc/tzcode/localtime.c
@@ -1316,9 +1316,10 @@
 tzset_unlocked(void)
 {
 #if defined(__ANDROID__)
+  // The TZ environment variable is meant to override the system-wide setting.
   const char * name = getenv("TZ");
 
-  // Try the "persist.sys.timezone" system property.
+  // If that's not set, look at the "persist.sys.timezone" system property.
   if (name == NULL) {
     static const prop_info *pi;
 
@@ -1340,6 +1341,10 @@
     }
   }
 
+  // If that's not available (because you're running AOSP on a WiFi-only
+  // device, say), fall back to GMT.
+  if (name == NULL) name = gmt;
+
   tzsetlcl(name);
 #else
   tzsetlcl(getenv("TZ"));
diff --git a/libc/tzcode/strftime.c b/libc/tzcode/strftime.c
index 10dfb4b..4349cf6 100644
--- a/libc/tzcode/strftime.c
+++ b/libc/tzcode/strftime.c
@@ -502,7 +502,23 @@
                 continue;
             case 'Z':
 #ifdef TM_ZONE
-                pt = _add(t->TM_ZONE, pt, ptlim, modifier);
+                // BEGIN: Android-changed.
+                {
+                    const char* zone = t->TM_ZONE;
+                    if (!zone || !*zone) {
+                        // "The value of tm_isdst shall be positive if Daylight Savings Time is
+                        // in effect, 0 if Daylight Savings Time is not in effect, and negative
+                        // if the information is not available."
+                        if (t->tm_isdst == 0) zone = tzname[0];
+                        else if (t->tm_isdst > 0) zone = tzname[1];
+
+                        // "Replaced by the timezone name or abbreviation, or by no bytes if no
+                        // timezone information exists."
+                        if (!zone || !*zone) zone = "";
+                    }
+                    pt = _add(zone, pt, ptlim, modifier);
+                }
+                // END: Android-changed.
 #else
                 if (t->tm_isdst >= 0)
                     pt = _add(tzname[t->tm_isdst != 0],
diff --git a/tests/Android.mk b/tests/Android.mk
index 8de3b22..8f2d3cf 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -142,7 +142,9 @@
 # Clang/llvm has incompatible long double (fp128) for x86_64.
 # https://llvm.org/bugs/show_bug.cgi?id=23897
 # This affects most of math_test.cpp.
+ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),x86_64))
 libBionicStandardTests_clang_target := false
+endif
 
 module := libBionicStandardTests
 module_tag := optional
@@ -169,6 +171,7 @@
   ) \
 )
 
+fortify1-tests-gcc_clang_target := false
 module := fortify1-tests-gcc
 module_tag := optional
 build_type := target
@@ -177,6 +180,7 @@
 build_type := host
 include $(LOCAL_PATH)/Android.build.mk
 
+fortify2-tests-gcc_clang_target := false
 module := fortify2-tests-gcc
 module_tag := optional
 build_type := target
@@ -309,9 +313,14 @@
     libdl_preempt_test_1 \
     libdl_preempt_test_2
 
-# TODO: clang support for thread_local on arm is done via __aeabi_read_tp()
-# which bionic does not support. Reenable this once this question is resolved.
+# Clang/llvm has incompatible long double (fp128) for x86_64.
+# https://llvm.org/bugs/show_bug.cgi?id=23897
+# This affects most of math_test.cpp.
+# For arm and arm64 target, b/25643775:
+# external/libcxx/include/sstream:859: warning: relocation refers to discarded section
+ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),x86_64 arm arm64))
 bionic-unit-tests_clang_target := false
+endif
 
 bionic-unit-tests_shared_libraries_target += libdl_test_df_1_global
 
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index fc64d44..e764283 100755
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -1303,11 +1303,14 @@
 }
 
 #if defined(__BIONIC__)
-static pthread_mutex_t gettid_mutex;
+static pthread_mutex_t pthread_gettid_np_mutex = PTHREAD_MUTEX_INITIALIZER;
+
 static void* pthread_gettid_np_helper(void* arg) {
-  pthread_mutex_lock(&gettid_mutex);
   *reinterpret_cast<pid_t*>(arg) = gettid();
-  pthread_mutex_unlock(&gettid_mutex);
+
+  // Wait for our parent to call pthread_gettid_np on us before exiting.
+  pthread_mutex_lock(&pthread_gettid_np_mutex);
+  pthread_mutex_unlock(&pthread_gettid_np_mutex);
   return NULL;
 }
 #endif
@@ -1316,17 +1319,19 @@
 #if defined(__BIONIC__)
   ASSERT_EQ(gettid(), pthread_gettid_np(pthread_self()));
 
+  // Ensure the other thread doesn't exit until after we've called
+  // pthread_gettid_np on it.
+  pthread_mutex_lock(&pthread_gettid_np_mutex);
+
   pid_t t_gettid_result;
   pthread_t t;
-  pthread_mutex_init(&gettid_mutex, NULL);
-  pthread_mutex_lock(&gettid_mutex);
   pthread_create(&t, NULL, pthread_gettid_np_helper, &t_gettid_result);
 
   pid_t t_pthread_gettid_np_result = pthread_gettid_np(t);
-  pthread_mutex_unlock(&gettid_mutex);
 
+  // Release the other thread and wait for it to exit.
+  pthread_mutex_unlock(&pthread_gettid_np_mutex);
   pthread_join(t, NULL);
-  pthread_mutex_destroy(&gettid_mutex);
 
   ASSERT_EQ(t_gettid_result, t_pthread_gettid_np_result);
 #else
diff --git a/tests/thread_local_test.cpp b/tests/thread_local_test.cpp
index aeba2ba..1422ed2 100644
--- a/tests/thread_local_test.cpp
+++ b/tests/thread_local_test.cpp
@@ -18,7 +18,8 @@
 #include <stdint.h>
 #include <string.h>
 
-#ifdef __GNUC__
+#if defined(__GNUC__) && !defined(__clang__) && \
+    (defined(__arm__) || defined(__aarch64__))
 // Gcc has a bug with -O -fdata-section for the arm target: http://b/22772147.
 // Until that bug is fixed, disable optimization since
 // it is not essential for this test.
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index c685e94..a04c449 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -143,6 +143,44 @@
   EXPECT_STREQ("Sun Mar 10 00:00:00 2100", buf);
 }
 
+TEST(time, strftime_null_tm_zone) {
+  // Netflix on Nexus Player wouldn't start (http://b/25170306).
+  struct tm t;
+  memset(&t, 0, sizeof(tm));
+
+  char buf[64];
+
+  setenv("TZ", "America/Los_Angeles", 1);
+  tzset();
+
+  t.tm_isdst = 0; // "0 if Daylight Savings Time is not in effect".
+  EXPECT_EQ(5U, strftime(buf, sizeof(buf), "<%Z>", &t));
+  EXPECT_STREQ("<PST>", buf);
+
+#if defined(__BIONIC__) // glibc 2.19 only copes with tm_isdst being 0 and 1.
+  t.tm_isdst = 2; // "positive if Daylight Savings Time is in effect"
+  EXPECT_EQ(5U, strftime(buf, sizeof(buf), "<%Z>", &t));
+  EXPECT_STREQ("<PDT>", buf);
+
+  t.tm_isdst = -123; // "and negative if the information is not available".
+  EXPECT_EQ(2U, strftime(buf, sizeof(buf), "<%Z>", &t));
+  EXPECT_STREQ("<>", buf);
+#endif
+
+  setenv("TZ", "UTC", 1);
+  tzset();
+
+  t.tm_isdst = 0;
+  EXPECT_EQ(5U, strftime(buf, sizeof(buf), "<%Z>", &t));
+  EXPECT_STREQ("<UTC>", buf);
+
+#if defined(__BIONIC__) // glibc 2.19 thinks UTC DST is "UTC".
+  t.tm_isdst = 1; // UTC has no DST.
+  EXPECT_EQ(2U, strftime(buf, sizeof(buf), "<%Z>", &t));
+  EXPECT_STREQ("<>", buf);
+#endif
+}
+
 TEST(time, strptime) {
   setenv("TZ", "UTC", 1);