Merge "Enable clang compilation with libc but not linker."
diff --git a/libc/arch-arm64/bionic/crtbegin.c b/libc/arch-arm64/bionic/crtbegin.c
index 11ba49f..fec0b11 100644
--- a/libc/arch-arm64/bionic/crtbegin.c
+++ b/libc/arch-arm64/bionic/crtbegin.c
@@ -36,10 +36,15 @@
 __attribute__ ((section (".init_array")))
 void (*__INIT_ARRAY__)(void) = (void (*)(void)) -1;
 
+__attribute__ ((section (".fini_array")))
+void (*__FINI_ARRAY__)(void) = (void (*)(void)) -1;
+
+
 __LIBC_HIDDEN__ void do_arm64_start(void* raw_args) {
   structors_array_t array;
   array.preinit_array = &__PREINIT_ARRAY__;
   array.init_array = &__INIT_ARRAY__;
+  array.fini_array = &__FINI_ARRAY__;
   __libc_init(raw_args, NULL, &main, &array);
 }
 
diff --git a/libc/arch-common/bionic/crtbegin.c b/libc/arch-common/bionic/crtbegin.c
index dad265e..fa9f3f3 100644
--- a/libc/arch-common/bionic/crtbegin.c
+++ b/libc/arch-common/bionic/crtbegin.c
@@ -36,6 +36,9 @@
 __attribute__ ((section (".init_array")))
 void (*__INIT_ARRAY__)(void) = (void (*)(void)) -1;
 
+__attribute__ ((section (".fini_array")))
+void (*__FINI_ARRAY__)(void) = (void (*)(void)) -1;
+
 __LIBC_HIDDEN__
 #ifdef __i386__
 __attribute__((force_align_arg_pointer))
@@ -44,6 +47,7 @@
   structors_array_t array;
   array.preinit_array = &__PREINIT_ARRAY__;
   array.init_array = &__INIT_ARRAY__;
+  array.fini_array = &__FINI_ARRAY__;
 
   void* raw_args = (void*) ((uintptr_t) __builtin_frame_address(0) + sizeof(void*));
 #ifdef __x86_64__
diff --git a/libc/arch-mips/bionic/crtbegin.c b/libc/arch-mips/bionic/crtbegin.c
index 33f7f40..28e8817 100644
--- a/libc/arch-mips/bionic/crtbegin.c
+++ b/libc/arch-mips/bionic/crtbegin.c
@@ -36,11 +36,15 @@
 __attribute__ ((section (".init_array")))
 void (*__INIT_ARRAY__)(void) = (void (*)(void)) -1;
 
+__attribute__ ((section (".fini_array")))
+void (*__FINI_ARRAY__)(void) = (void (*)(void)) -1;
+
 
 __LIBC_HIDDEN__  void do_mips_start(void *raw_args) {
   structors_array_t array;
   array.preinit_array = &__PREINIT_ARRAY__;
   array.init_array = &__INIT_ARRAY__;
+  array.fini_array = &__FINI_ARRAY__;
 
   __libc_init(raw_args, NULL, &main, &array);
 }
diff --git a/libc/arch-mips64/bionic/crtbegin.c b/libc/arch-mips64/bionic/crtbegin.c
index fe6985d..2ea31ad 100644
--- a/libc/arch-mips64/bionic/crtbegin.c
+++ b/libc/arch-mips64/bionic/crtbegin.c
@@ -36,10 +36,15 @@
 __attribute__ ((section (".init_array")))
 void (*__INIT_ARRAY__)(void) = (void (*)(void)) -1;
 
+__attribute__ ((section (".fini_array")))
+void (*__FINI_ARRAY__)(void) = (void (*)(void)) -1;
+
+
 __LIBC_HIDDEN__  void do_mips_start(void *raw_args) {
   structors_array_t array;
   array.preinit_array = &__PREINIT_ARRAY__;
   array.init_array = &__INIT_ARRAY__;
+  array.fini_array = &__FINI_ARRAY__;
 
   __libc_init(raw_args, NULL, &main, &array);
 }
diff --git a/libc/bionic/libc_init_common.h b/libc/bionic/libc_init_common.h
index ee3d32b..3032f99 100644
--- a/libc/bionic/libc_init_common.h
+++ b/libc/bionic/libc_init_common.h
@@ -33,6 +33,7 @@
 typedef struct {
   void (**preinit_array)(void);
   void (**init_array)(void);
+  void (**fini_array)(void);
 } structors_array_t;
 
 __BEGIN_DECLS
diff --git a/libc/bionic/libc_init_dynamic.cpp b/libc/bionic/libc_init_dynamic.cpp
index 3d9fa1a..78125f9 100644
--- a/libc/bionic/libc_init_dynamic.cpp
+++ b/libc/bionic/libc_init_dynamic.cpp
@@ -60,9 +60,6 @@
   extern int __cxa_atexit(void (*)(void *), void *, void *);
 };
 
-__attribute__ ((section (".fini_array")))
-void (*__FINI_ARRAY__)(void) = (void (*)(void)) -1;
-
 // We flag the __libc_preinit function as a constructor to ensure
 // that its address is listed in libc.so's .init_array section.
 // This ensures that the function is called by the dynamic linker
@@ -82,11 +79,6 @@
   // Hooks for various libraries to let them know that we're starting up.
   malloc_debug_init();
   netdClientInit();
-
-  // The executable may have its own destructors listed in its .fini_array
-  // so we need to ensure that these are called when the program exits
-  // normally.
-  __cxa_atexit(__libc_fini, &__FINI_ARRAY__, NULL);
 }
 
 __LIBC_HIDDEN__ void __libc_postfini() {
@@ -104,11 +96,19 @@
 __noreturn void __libc_init(void* raw_args,
                             void (*onexit)(void) __unused,
                             int (*slingshot)(int, char**, char**),
-                            structors_array_t const * const structors __unused) {
+                            structors_array_t const * const structors) {
+
   KernelArgumentBlock args(raw_args);
 
   // Several Linux ABIs don't pass the onexit pointer, and the ones that
   // do never use it.  Therefore, we ignore it.
 
+  // The executable may have its own destructors listed in its .fini_array
+  // so we need to ensure that these are called when the program exits
+  // normally.
+  if (structors->fini_array) {
+    __cxa_atexit(__libc_fini,structors->fini_array,NULL);
+  }
+
   exit(slingshot(args.argc, args.argv, args.envp));
 }
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index f2e34c2..bc11f3d 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -61,9 +61,6 @@
 
 extern "C" int __cxa_atexit(void (*)(void *), void *, void *);
 
-__attribute__ ((section (".fini_array")))
-void (*__FINI_ARRAY__)(void) = (void (*)(void)) -1;
-
 static void call_array(void(**list)()) {
   // First element is -1, list is null-terminated
   while (*++list) {
@@ -102,13 +99,14 @@
   // do never use it.  Therefore, we ignore it.
 
   call_array(structors->preinit_array);
+  call_array(structors->init_array);
 
   // The executable may have its own destructors listed in its .fini_array
   // so we need to ensure that these are called when the program exits
   // normally.
-  __cxa_atexit(__libc_fini,&__FINI_ARRAY__, NULL);
-
-  call_array(structors->init_array);
+  if (structors->fini_array != NULL) {
+    __cxa_atexit(__libc_fini,structors->fini_array,NULL);
+  }
 
   exit(slingshot(args.argc, args.argv, args.envp));
 }
diff --git a/tests/math_test.cpp b/tests/math_test.cpp
index b4f5b14..ad4654e 100644
--- a/tests/math_test.cpp
+++ b/tests/math_test.cpp
@@ -53,6 +53,8 @@
 #include <limits.h>
 #include <stdint.h>
 
+#include <private/ScopeGuard.h>
+
 float float_subnormal() {
   union {
     float f;
@@ -760,6 +762,10 @@
 }
 
 TEST(math, lrint) {
+  auto guard = create_scope_guard([]() {
+    fesetenv(FE_DFL_ENV);
+  });
+
   fesetround(FE_UPWARD); // lrint/lrintf/lrintl obey the rounding mode.
   ASSERT_EQ(1235, lrint(1234.01));
   ASSERT_EQ(1235, lrintf(1234.01f));
@@ -780,6 +786,10 @@
 }
 
 TEST(math, rint) {
+  auto guard = create_scope_guard([]() {
+    fesetenv(FE_DFL_ENV);
+  });
+
   fesetround(FE_UPWARD); // rint/rintf/rintl obey the rounding mode.
   feclearexcept(FE_ALL_EXCEPT); // rint/rintf/rintl do set the FE_INEXACT flag.
   ASSERT_EQ(1234.0, rint(1234.0));
@@ -806,6 +816,9 @@
 }
 
 TEST(math, nearbyint) {
+  auto guard = create_scope_guard([]() {
+    fesetenv(FE_DFL_ENV);
+  });
   fesetround(FE_UPWARD); // nearbyint/nearbyintf/nearbyintl obey the rounding mode.
   feclearexcept(FE_ALL_EXCEPT); // nearbyint/nearbyintf/nearbyintl don't set the FE_INEXACT flag.
   ASSERT_EQ(1234.0, nearbyint(1234.0));
@@ -832,6 +845,9 @@
 }
 
 TEST(math, lround) {
+  auto guard = create_scope_guard([]() {
+    fesetenv(FE_DFL_ENV);
+  });
   fesetround(FE_UPWARD); // lround ignores the rounding mode.
   ASSERT_EQ(1234, lround(1234.01));
   ASSERT_EQ(1234, lroundf(1234.01f));
@@ -839,6 +855,9 @@
 }
 
 TEST(math, llround) {
+  auto guard = create_scope_guard([]() {
+    fesetenv(FE_DFL_ENV);
+  });
   fesetround(FE_UPWARD); // llround ignores the rounding mode.
   ASSERT_EQ(1234L, llround(1234.01));
   ASSERT_EQ(1234L, llroundf(1234.01f));
@@ -933,6 +952,9 @@
 }
 
 TEST(math, round) {
+  auto guard = create_scope_guard([]() {
+    fesetenv(FE_DFL_ENV);
+  });
   fesetround(FE_TOWARDZERO); // round ignores the rounding mode and always rounds away from zero.
   ASSERT_DOUBLE_EQ(1.0, round(0.5));
   ASSERT_DOUBLE_EQ(-1.0, round(-0.5));
@@ -943,6 +965,9 @@
 }
 
 TEST(math, roundf) {
+  auto guard = create_scope_guard([]() {
+    fesetenv(FE_DFL_ENV);
+  });
   fesetround(FE_TOWARDZERO); // roundf ignores the rounding mode and always rounds away from zero.
   ASSERT_FLOAT_EQ(1.0f, roundf(0.5f));
   ASSERT_FLOAT_EQ(-1.0f, roundf(-0.5f));
@@ -953,6 +978,9 @@
 }
 
 TEST(math, roundl) {
+  auto guard = create_scope_guard([]() {
+    fesetenv(FE_DFL_ENV);
+  });
   fesetround(FE_TOWARDZERO); // roundl ignores the rounding mode and always rounds away from zero.
   ASSERT_DOUBLE_EQ(1.0L, roundl(0.5L));
   ASSERT_DOUBLE_EQ(-1.0L, roundl(-0.5L));
@@ -963,6 +991,9 @@
 }
 
 TEST(math, trunc) {
+  auto guard = create_scope_guard([]() {
+    fesetenv(FE_DFL_ENV);
+  });
   fesetround(FE_UPWARD); // trunc ignores the rounding mode and always rounds toward zero.
   ASSERT_DOUBLE_EQ(1.0, trunc(1.5));
   ASSERT_DOUBLE_EQ(-1.0, trunc(-1.5));
@@ -973,6 +1004,9 @@
 }
 
 TEST(math, truncf) {
+  auto guard = create_scope_guard([]() {
+    fesetenv(FE_DFL_ENV);
+  });
   fesetround(FE_UPWARD); // truncf ignores the rounding mode and always rounds toward zero.
   ASSERT_FLOAT_EQ(1.0f, truncf(1.5f));
   ASSERT_FLOAT_EQ(-1.0f, truncf(-1.5f));
@@ -983,6 +1017,9 @@
 }
 
 TEST(math, truncl) {
+  auto guard = create_scope_guard([]() {
+    fesetenv(FE_DFL_ENV);
+  });
   fesetround(FE_UPWARD); // truncl ignores the rounding mode and always rounds toward zero.
   ASSERT_DOUBLE_EQ(1.0L, truncl(1.5L));
   ASSERT_DOUBLE_EQ(-1.0L, truncl(-1.5L));
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index bbac7fe..9a9e515 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -27,6 +27,7 @@
 #include <time.h>
 #include <unistd.h>
 
+#include "private/ScopeGuard.h"
 #include "ScopedSignalHandler.h"
 
 TEST(pthread, pthread_key_create) {
@@ -862,8 +863,19 @@
   // The stack size should correspond to RLIMIT_STACK.
   rlimit rl;
   ASSERT_EQ(0, getrlimit(RLIMIT_STACK, &rl));
+  uint64_t original_rlim_cur = rl.rlim_cur;
+#if defined(__BIONIC__)
+  if (rl.rlim_cur == RLIM_INFINITY) {
+    rl.rlim_cur = 8 * 1024 * 1024; // Bionic reports unlimited stacks as 8MiB.
+  }
+#endif
   EXPECT_EQ(rl.rlim_cur, stack_size);
 
+  auto guard = create_scope_guard([&rl, original_rlim_cur]() {
+    rl.rlim_cur = original_rlim_cur;
+    ASSERT_EQ(0, setrlimit(RLIMIT_STACK, &rl));
+  });
+
   // The high address of the /proc/self/maps [stack] region should equal stack_base + stack_size.
   // Remember that the stack grows down (and is mapped in on demand), so the low address of the
   // region isn't very interesting.
diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp
index e53fd3a..8fd8b72 100644
--- a/tests/signal_test.cpp
+++ b/tests/signal_test.cpp
@@ -202,7 +202,7 @@
   // arm64, x86, and x86-64. The version of glibc we're using also doesn't
   // define SA_RESTORER, but luckily it's the same value everywhere, and mips
   // doesn't use the bit for anything.
-  static const int sa_restorer = 0x4000000;
+  static const unsigned sa_restorer = 0x4000000;
 
   // See what's currently set for SIGALRM.
   struct sigaction original_sa;
@@ -210,7 +210,7 @@
   ASSERT_EQ(0, sigaction(SIGALRM, NULL, &original_sa));
   ASSERT_TRUE(original_sa.sa_handler == NULL);
   ASSERT_TRUE(original_sa.sa_sigaction == NULL);
-  ASSERT_EQ(0, original_sa.sa_flags & ~sa_restorer);
+  ASSERT_EQ(0U, original_sa.sa_flags & ~sa_restorer);
 
   // Set a traditional sa_handler signal handler.
   struct sigaction sa;
@@ -225,7 +225,7 @@
   ASSERT_EQ(0, sigaction(SIGALRM, NULL, &sa));
   ASSERT_TRUE(sa.sa_handler == EmptySignalHandler);
   ASSERT_TRUE((void*) sa.sa_sigaction == (void*) sa.sa_handler);
-  ASSERT_EQ(SA_ONSTACK, sa.sa_flags & ~sa_restorer);
+  ASSERT_EQ(static_cast<unsigned>(SA_ONSTACK), sa.sa_flags & ~sa_restorer);
 
   // Set a new-style sa_sigaction signal handler.
   memset(&sa, 0, sizeof(sa));
@@ -239,7 +239,7 @@
   ASSERT_EQ(0, sigaction(SIGALRM, NULL, &sa));
   ASSERT_TRUE(sa.sa_sigaction == EmptySignalAction);
   ASSERT_TRUE((void*) sa.sa_sigaction == (void*) sa.sa_handler);
-  ASSERT_EQ((SA_ONSTACK | SA_SIGINFO), sa.sa_flags & ~sa_restorer);
+  ASSERT_EQ(static_cast<unsigned>(SA_ONSTACK | SA_SIGINFO), sa.sa_flags & ~sa_restorer);
 
   // Put everything back how it was.
   ASSERT_EQ(0, sigaction(SIGALRM, &original_sa, NULL));
diff --git a/tests/string_test.cpp b/tests/string_test.cpp
index ad0040a..6ecbb64 100644
--- a/tests/string_test.cpp
+++ b/tests/string_test.cpp
@@ -196,7 +196,7 @@
   const size_t MAX_LEN;
   Character *ptr, *ptr1, *ptr2;
   size_t n;
-  int len[ITER + 1];
+  size_t len[ITER + 1];
 
  private:
   static size_t alignments[];
@@ -212,7 +212,7 @@
     n = 0;
     len[n++] = 0;
     for (size_t i = 1; i < ITER; ++i) {
-      int l = (int) exp(log((double) MAX_LEN) * i / ITER);
+      size_t l = static_cast<size_t>(exp(log(static_cast<double>(MAX_LEN)) * i / ITER));
       if (l != len[n - 1]) {
         len[n++] = l;
       }
@@ -430,7 +430,7 @@
       }
       state.ptr1[state.len[i] - 1] = '\0';
 
-      int pos = random() % state.MAX_LEN;
+      size_t pos = random() % state.MAX_LEN;
       char* expected;
       if (pos >= state.len[i] - 1) {
         if (seek_char == 0) {
@@ -457,7 +457,7 @@
       state.ptr1[state.len[i] - 1] = '\0';
       state.ptr2[state.len[i] - 1] = '\0';
 
-      int pos = 1 + (random() % (state.MAX_LEN - 1));
+      size_t pos = 1 + (random() % (state.MAX_LEN - 1));
       int actual;
       int expected;
       if (pos >= state.len[i] - 1) {
@@ -540,7 +540,7 @@
       state.ptr2[state.MAX_LEN - 1] = '\0';
       memcpy(state.ptr, state.ptr2, state.MAX_LEN + state.len[i]);
 
-      int pos = random() % state.MAX_LEN;
+      size_t pos = random() % state.MAX_LEN;
       memset(state.ptr1, '\3', pos);
       state.ptr1[pos] = '\0';
       if (pos < state.len[i]) {
@@ -625,7 +625,7 @@
       state.ptr1[state.len[i] - 1] = '\0';
       state.ptr2[state.len[i] - 1] = '\0';
 
-      int pos = 1 + (random() % (state.MAX_LEN - 1));
+      size_t pos = 1 + (random() % (state.MAX_LEN - 1));
       int actual;
       int expected;
       if (pos >= state.len[i] - 1) {
@@ -735,7 +735,7 @@
       }
       state.ptr1[state.len[i] - 1] = '\0';
 
-      int pos = random() % state.MAX_LEN;
+      size_t pos = random() % state.MAX_LEN;
       char* expected;
       if (pos >= state.len[i] - 1) {
         if (seek_char == 0) {
@@ -760,7 +760,7 @@
     for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
       memset(state.ptr1, ~seek_char, state.len[i]);
 
-      int pos = random() % state.MAX_LEN;
+      size_t pos = random() % state.MAX_LEN;
       char* expected;
       if (pos >= state.len[i]) {
         expected = NULL;
@@ -789,7 +789,7 @@
     for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
       memset(state.ptr1, ~seek_char, state.len[i]);
 
-      int pos = random() % state.MAX_LEN;
+      size_t pos = random() % state.MAX_LEN;
       char* expected;
       if (pos >= state.len[i]) {
         expected = NULL;