Snap for 12397640 from 317e2c78a2956092234b97fbeb2642f46afa5687 to 24Q4-release

Change-Id: Iac879a717493efbfa9a0f6a70ab174139d5bc870
diff --git a/libc/bionic/wctype.cpp b/libc/bionic/wctype.cpp
index 403d2fb..94597d9 100644
--- a/libc/bionic/wctype.cpp
+++ b/libc/bionic/wctype.cpp
@@ -159,6 +159,7 @@
 wctrans_t wctrans(const char* name) {
   if (strcmp(name, "tolower") == 0) return wctrans_tolower;
   if (strcmp(name, "toupper") == 0) return wctrans_toupper;
+  errno = EINVAL;
   return nullptr;
 }
 __strong_alias(wctrans_l, wctrans);
@@ -167,6 +168,6 @@
   if (t == wctrans_tolower) return towlower(c);
   if (t == wctrans_toupper) return towupper(c);
   errno = EINVAL;
-  return 0;
+  return c;
 }
 __strong_alias(towctrans_l, towctrans);
diff --git a/tests/Android.bp b/tests/Android.bp
index d1ca78f..6aecb40 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -389,6 +389,7 @@
         "bug_26110743_test.cpp",
         "byteswap_test.cpp",
         "complex_test.cpp",
+        "cpu_target_features_test.cpp",
         "ctype_test.cpp",
         "dirent_test.cpp",
         "elf_test.cpp",
diff --git a/tests/cpu_target_features_test.cpp b/tests/cpu_target_features_test.cpp
new file mode 100644
index 0000000..3458bca
--- /dev/null
+++ b/tests/cpu_target_features_test.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <gtest/gtest.h>
+#include <stdlib.h>
+
+#include "utils.h"
+
+TEST(cpu_target_features, has_expected_x86_compiler_values) {
+#if defined(__x86_64__) || defined(__i386__)
+  ExecTestHelper eth;
+  char* const argv[] = {nullptr};
+  const auto invocation = [&] { execvp("cpu-target-features", argv); };
+  eth.Run(invocation, 0, "(^|\n)__AES__=1($|\n)");
+  eth.Run(invocation, 0, "(^|\n)__CRC32__=1($|\n)");
+#else
+  GTEST_SKIP() << "Not targeting an x86 architecture.";
+#endif
+}
+
+TEST(cpu_target_features, has_expected_aarch64_compiler_values) {
+#if defined(__aarch64__)
+  ExecTestHelper eth;
+  char* const argv[] = {nullptr};
+  const auto invocation = [&] { execvp("cpu-target-features", argv); };
+  eth.Run(invocation, 0, "(^|\n)__ARM_FEATURE_AES=1($|\n)");
+  eth.Run(invocation, 0, "(^|\n)__ARM_FEATURE_CRC32=1($|\n)");
+#else
+  GTEST_SKIP() << "Not targeting an aarch64 architecture.";
+#endif
+}
+
+TEST(cpu_target_features, has_expected_arm_compiler_values) {
+#if defined(__arm__)
+  ExecTestHelper eth;
+  char* const argv[] = {nullptr};
+  const auto invocation = [&] { execvp("cpu-target-features", argv); };
+  eth.Run(invocation, 0, "(^|\n)__ARM_FEATURE_AES=1($|\n)");
+  eth.Run(invocation, 0, "(^|\n)__ARM_FEATURE_CRC32=1($|\n)");
+#else
+  GTEST_SKIP() << "Not targeting an arm architecture.";
+#endif
+}
diff --git a/tests/stdatomic_test.cpp b/tests/stdatomic_test.cpp
index f5c6bb1..1c51b11 100644
--- a/tests/stdatomic_test.cpp
+++ b/tests/stdatomic_test.cpp
@@ -37,7 +37,7 @@
 }
 
 TEST(stdatomic, init) {
-  atomic_int v = ATOMIC_VAR_INIT(123);
+  atomic_int v = 123;
   ASSERT_EQ(123, atomic_load(&v));
 
   atomic_init(&v, 456);
@@ -145,35 +145,35 @@
 }
 
 TEST(stdatomic, atomic_fetch_add) {
-  atomic_int i = ATOMIC_VAR_INIT(123);
+  atomic_int i = 123;
   ASSERT_EQ(123, atomic_fetch_add(&i, 1));
   ASSERT_EQ(124, atomic_fetch_add_explicit(&i, 1, memory_order_relaxed));
   ASSERT_EQ(125, atomic_load(&i));
 }
 
 TEST(stdatomic, atomic_fetch_sub) {
-  atomic_int i = ATOMIC_VAR_INIT(123);
+  atomic_int i = 123;
   ASSERT_EQ(123, atomic_fetch_sub(&i, 1));
   ASSERT_EQ(122, atomic_fetch_sub_explicit(&i, 1, memory_order_relaxed));
   ASSERT_EQ(121, atomic_load(&i));
 }
 
 TEST(stdatomic, atomic_fetch_or) {
-  atomic_int i = ATOMIC_VAR_INIT(0x100);
+  atomic_int i = 0x100;
   ASSERT_EQ(0x100, atomic_fetch_or(&i, 0x020));
   ASSERT_EQ(0x120, atomic_fetch_or_explicit(&i, 0x003, memory_order_relaxed));
   ASSERT_EQ(0x123, atomic_load(&i));
 }
 
 TEST(stdatomic, atomic_fetch_xor) {
-  atomic_int i = ATOMIC_VAR_INIT(0x100);
+  atomic_int i = 0x100;
   ASSERT_EQ(0x100, atomic_fetch_xor(&i, 0x120));
   ASSERT_EQ(0x020, atomic_fetch_xor_explicit(&i, 0x103, memory_order_relaxed));
   ASSERT_EQ(0x123, atomic_load(&i));
 }
 
 TEST(stdatomic, atomic_fetch_and) {
-  atomic_int i = ATOMIC_VAR_INIT(0x123);
+  atomic_int i = 0x123;
   ASSERT_EQ(0x123, atomic_fetch_and(&i, 0x00f));
   ASSERT_EQ(0x003, atomic_fetch_and_explicit(&i, 0x2, memory_order_relaxed));
   ASSERT_EQ(0x002, atomic_load(&i));
diff --git a/tests/wctype_test.cpp b/tests/wctype_test.cpp
index 38d26ca..f4b7a8f 100644
--- a/tests/wctype_test.cpp
+++ b/tests/wctype_test.cpp
@@ -226,34 +226,64 @@
   EXPECT_EQ(0, iswctype_l(WEOF, wctype_l("alnum", l.l), l.l));
 }
 
-TEST(wctype, towctrans) {
+TEST(wctype, wctrans) {
   EXPECT_TRUE(wctrans("tolower") != nullptr);
   EXPECT_TRUE(wctrans("toupper") != nullptr);
 
+  errno = 0;
   EXPECT_TRUE(wctrans("monkeys") == nullptr);
-}
-
-TEST(wctype, towctrans_l) {
-  UtfLocale l;
-  EXPECT_TRUE(wctrans_l("tolower", l.l) != nullptr);
-  EXPECT_TRUE(wctrans_l("toupper", l.l) != nullptr);
-
-  EXPECT_TRUE(wctrans_l("monkeys", l.l) == nullptr);
-}
-
-TEST(wctype, wctrans) {
-  EXPECT_EQ(wint_t('a'), towctrans(L'A', wctrans("tolower")));
-  EXPECT_EQ(WEOF, towctrans(WEOF, wctrans("tolower")));
-
-  EXPECT_EQ(wint_t('A'), towctrans(L'a', wctrans("toupper")));
-  EXPECT_EQ(WEOF, towctrans(WEOF, wctrans("toupper")));
+  #if defined(__BIONIC__)
+  // Android/FreeBSD/iOS set errno, but musl/glibc don't.
+  EXPECT_ERRNO(EINVAL);
+  #endif
 }
 
 TEST(wctype, wctrans_l) {
   UtfLocale l;
-  EXPECT_EQ(wint_t('a'), towctrans_l(L'A', wctrans_l("tolower", l.l), l.l));
-  EXPECT_EQ(WEOF, towctrans_l(WEOF, wctrans_l("tolower", l.l), l.l));
+  EXPECT_TRUE(wctrans_l("tolower", l.l) != nullptr);
+  EXPECT_TRUE(wctrans_l("toupper", l.l) != nullptr);
 
-  EXPECT_EQ(wint_t('A'), towctrans_l(L'a', wctrans_l("toupper", l.l), l.l));
-  EXPECT_EQ(WEOF, towctrans_l(WEOF, wctrans_l("toupper", l.l), l.l));
+  errno = 0;
+  EXPECT_TRUE(wctrans_l("monkeys", l.l) == nullptr);
+  #if defined(__BIONIC__)
+  // Android/FreeBSD/iOS set errno, but musl/glibc don't.
+  EXPECT_ERRNO(EINVAL);
+  #endif
+}
+
+TEST(wctype, towctrans) {
+  wctrans_t lower = wctrans("tolower");
+  EXPECT_EQ(wint_t('a'), towctrans(L'A', lower));
+  EXPECT_EQ(WEOF, towctrans(WEOF, lower));
+
+  wctrans_t upper = wctrans("toupper");
+  EXPECT_EQ(wint_t('A'), towctrans(L'a', upper));
+  EXPECT_EQ(WEOF, towctrans(WEOF, upper));
+
+  wctrans_t invalid = wctrans("monkeys");
+  errno = 0;
+  EXPECT_EQ(wint_t('a'), towctrans(L'a', invalid));
+  #if defined(__BIONIC__)
+  // Android/FreeBSD/iOS set errno, but musl/glibc don't.
+  EXPECT_ERRNO(EINVAL);
+  #endif
+}
+
+TEST(wctype, towctrans_l) {
+  UtfLocale l;
+  wctrans_t lower = wctrans_l("tolower", l.l);
+  EXPECT_EQ(wint_t('a'), towctrans_l(L'A', lower, l.l));
+  EXPECT_EQ(WEOF, towctrans_l(WEOF, lower, l.l));
+
+  wctrans_t upper = wctrans_l("toupper", l.l);
+  EXPECT_EQ(wint_t('A'), towctrans_l(L'a', upper, l.l));
+  EXPECT_EQ(WEOF, towctrans_l(WEOF, upper, l.l));
+
+  wctrans_t invalid = wctrans_l("monkeys", l.l);
+  errno = 0;
+  EXPECT_EQ(wint_t('a'), towctrans_l(L'a', invalid, l.l));
+  #if defined(__BIONIC__)
+  // Android/FreeBSD/iOS set errno, but musl/glibc don't.
+  EXPECT_ERRNO(EINVAL);
+  #endif
 }