Merge to upstream r334917.
Test: ndk/checkbuild.py && ndk/run_tests.py
Bug: None
Change-Id: I0ec4d4cdaa80aa4879290bd96a69f28a12fbcb98
diff --git a/.gitignore b/.gitignore
index 49657ed..3e1b759 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,6 @@
+# Android edit. We're still bad people and build to the source directory :(
+/libs/
+
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..1794282
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,129 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// host + device static lib
+cc_library_static {
+ name: "libc++_static",
+ host_supported: true,
+ vendor_available: true,
+ clang: true,
+ srcs: [
+ "src/algorithm.cpp",
+ "src/any.cpp",
+ "src/bind.cpp",
+ "src/chrono.cpp",
+ "src/condition_variable.cpp",
+ "src/debug.cpp",
+ "src/exception.cpp",
+ "src/future.cpp",
+ "src/hash.cpp",
+ "src/ios.cpp",
+ "src/iostream.cpp",
+ "src/locale.cpp",
+ "src/memory.cpp",
+ "src/mutex.cpp",
+ "src/new.cpp",
+ "src/optional.cpp",
+ "src/random.cpp",
+ "src/regex.cpp",
+ "src/shared_mutex.cpp",
+ "src/stdexcept.cpp",
+ "src/string.cpp",
+ "src/strstream.cpp",
+ "src/system_error.cpp",
+ "src/thread.cpp",
+ "src/typeinfo.cpp",
+ "src/utility.cpp",
+ "src/valarray.cpp",
+ "src/variant.cpp",
+ ],
+ local_include_dirs: ["include"],
+ export_include_dirs: ["include"],
+ cppflags: [
+ "-std=c++14",
+ "-nostdinc++",
+ "-fexceptions",
+ "-DLIBCXX_BUILDING_LIBCXXABI",
+ "-D_LIBCPP_BUILDING_LIBRARY",
+ ],
+ rtti: true,
+ whole_static_libs: [
+ "libc++abi",
+ ],
+ stl: "none",
+ target: {
+ linux_bionic: {
+ enabled: true,
+ },
+ },
+}
+
+// host + device dynamic lib
+cc_library_shared {
+ name: "libc++",
+ host_supported: true,
+ vendor_available: true,
+ clang: true,
+ whole_static_libs: ["libc++_static"],
+ stl: "none",
+
+ target: {
+ android: {
+ shared_libs: ["libdl"],
+ },
+ android_arm: {
+ static_libs: ["libunwind_llvm"],
+ ldflags: ["-Wl,--exclude-libs,libunwind_llvm.a"],
+ },
+ darwin: {
+ unexported_symbols_list: "lib/libc++unexp.exp",
+ force_symbols_not_weak_list: "lib/notweak.exp",
+ force_symbols_weak_list: "lib/weak.exp",
+ ldflags: [
+ "-nodefaultlibs",
+ "-Wl,-undefined,dynamic_lookup",
+ ],
+ },
+
+ linux: {
+ ldflags: ["-nodefaultlibs"],
+ host_ldlibs: [
+ "-lrt",
+ "-lpthread",
+ "-ldl",
+ ],
+ },
+ linux_bionic: {
+ enabled: true,
+ static_libs: ["libunwindbacktrace"],
+ shared_libs: [
+ "libdl",
+ "liblzma",
+ ],
+ },
+ },
+}
+
+
+// ANDROIDMK TRANSLATION ERROR: unsupported conditional
+// ifdef LIBCXX_TESTING
+// ANDROIDMK TRANSLATION ERROR: unsupported include
+// include $(LOCAL_PATH)/buildcmds/Android.mk
+
+// ANDROIDMK TRANSLATION ERROR: endif from unsupported contitional
+// endif
+// TARGET_BUILD_APPS
+
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..11c1614
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,206 @@
+# This file is dual licensed under the MIT and the University of Illinois Open
+# Source Licenses. See LICENSE.TXT for details.
+
+LOCAL_PATH := $(call my-dir)
+
+# Normally, we distribute the NDK with prebuilt binaries of libc++
+# in $LOCAL_PATH/libs/<abi>/. However,
+#
+
+LIBCXX_FORCE_REBUILD := $(strip $(LIBCXX_FORCE_REBUILD))
+ifndef LIBCXX_FORCE_REBUILD
+ ifeq (,$(strip $(wildcard $(LOCAL_PATH)/libs/$(TARGET_ARCH_ABI)/libc++_static$(TARGET_LIB_EXTENSION))))
+ $(call __ndk_info,WARNING: Rebuilding libc++ libraries from sources!)
+ $(call __ndk_info,You might want to use $$NDK/build/tools/build-cxx-stl.sh --stl=libc++)
+ $(call __ndk_info,in order to build prebuilt versions to speed up your builds!)
+ LIBCXX_FORCE_REBUILD := true
+ endif
+endif
+
+libcxx_includes := $(LOCAL_PATH)/include
+libcxx_export_includes := $(libcxx_includes)
+libcxx_sources := \
+ algorithm.cpp \
+ any.cpp \
+ bind.cpp \
+ chrono.cpp \
+ condition_variable.cpp \
+ debug.cpp \
+ exception.cpp \
+ functional.cpp \
+ future.cpp \
+ hash.cpp \
+ ios.cpp \
+ iostream.cpp \
+ locale.cpp \
+ memory.cpp \
+ mutex.cpp \
+ new.cpp \
+ optional.cpp \
+ random.cpp \
+ regex.cpp \
+ shared_mutex.cpp \
+ stdexcept.cpp \
+ string.cpp \
+ strstream.cpp \
+ system_error.cpp \
+ thread.cpp \
+ typeinfo.cpp \
+ utility.cpp \
+ valarray.cpp \
+ variant.cpp \
+ vector.cpp \
+
+libcxx_sources := $(libcxx_sources:%=src/%)
+
+libcxx_export_cxxflags :=
+
+ifeq (,$(filter clang%,$(NDK_TOOLCHAIN_VERSION)))
+# Add -fno-strict-aliasing because __list_imp::_end_ breaks TBAA rules by declaring
+# simply as __list_node_base then casted to __list_node derived from that. See
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61571 for details
+libcxx_export_cxxflags += -fno-strict-aliasing
+endif
+
+libcxx_cxxflags := \
+ -std=c++1z \
+ -DLIBCXX_BUILDING_LIBCXXABI \
+ -D_LIBCPP_BUILDING_LIBRARY \
+ -D_LIBCPP_DISABLE_NEW_DELETE_DEFINITIONS \
+ -D__STDC_FORMAT_MACROS \
+ $(libcxx_export_cxxflags) \
+
+libcxx_ldflags :=
+libcxx_export_ldflags :=
+# Need to make sure the unwinder is always linked with hidden visibility.
+ifneq (,$(filter armeabi%,$(TARGET_ARCH_ABI)))
+ libcxx_ldflags += -Wl,--exclude-libs,libunwind.a
+ libcxx_export_ldflags += -Wl,--exclude-libs,libunwind.a
+endif
+
+ifneq ($(LIBCXX_FORCE_REBUILD),true)
+
+$(call ndk_log,Using prebuilt libc++ libraries)
+
+libcxxabi_c_includes := $(LOCAL_PATH)/../llvm-libc++abi/include
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := c++_static
+LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/lib$(LOCAL_MODULE)$(TARGET_LIB_EXTENSION)
+LOCAL_EXPORT_C_INCLUDES := $(libcxx_export_includes)
+LOCAL_STATIC_LIBRARIES := libc++abi
+LOCAL_EXPORT_CPPFLAGS := $(libcxx_export_cxxflags)
+LOCAL_EXPORT_LDFLAGS := $(libcxx_export_ldflags)
+LOCAL_EXPORT_STATIC_LIBRARIES := libc++abi
+
+ifeq ($(NDK_PLATFORM_NEEDS_ANDROID_SUPPORT),true)
+ # This doesn't affect the prebuilt itself since this is a prebuilt library,
+ # but the build system needs to know about the dependency so we can sort the
+ # exported includes properly.
+ LOCAL_STATIC_LIBRARIES += libandroid_support
+ LOCAL_EXPORT_STATIC_LIBRARIES += libandroid_support
+endif
+
+# We use the LLVM unwinder for 32-bit ARM.
+ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
+ LOCAL_EXPORT_STATIC_LIBRARIES += libunwind
+endif
+include $(PREBUILT_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := c++_shared
+LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/lib$(LOCAL_MODULE)$(TARGET_SONAME_EXTENSION)
+LOCAL_EXPORT_C_INCLUDES := \
+ $(libcxx_export_includes) \
+ $(libcxxabi_c_includes) \
+
+LOCAL_EXPORT_CPPFLAGS := $(libcxx_export_cxxflags)
+LOCAL_EXPORT_LDFLAGS := $(libcxx_export_ldflags)
+
+ifeq ($(NDK_PLATFORM_NEEDS_ANDROID_SUPPORT),true)
+ # This doesn't affect the prebuilt itself since this is a prebuilt library,
+ # but the build system needs to know about the dependency so we can sort the
+ # exported includes properly.
+ LOCAL_STATIC_LIBRARIES := libandroid_support
+ LOCAL_EXPORT_STATIC_LIBRARIES := libandroid_support
+endif
+
+# We use the LLVM unwinder for 32-bit ARM.
+ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
+ LOCAL_EXPORT_STATIC_LIBRARIES += libunwind
+endif
+include $(PREBUILT_SHARED_LIBRARY)
+
+ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
+# We define this module here rather than in a separate cxx-stl/libunwind because
+# we don't actually want to make the API available (yet).
+include $(CLEAR_VARS)
+LOCAL_MODULE := libunwind
+LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/$(LOCAL_MODULE)$(TARGET_LIB_EXTENSION)
+LOCAL_EXPORT_LDLIBS := -ldl
+include $(PREBUILT_STATIC_LIBRARY)
+endif
+
+$(call import-module, cxx-stl/llvm-libc++abi)
+
+else
+# LIBCXX_FORCE_REBUILD == true
+
+$(call ndk_log,Rebuilding libc++ libraries from sources)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := c++_static
+LOCAL_SRC_FILES := $(libcxx_sources)
+LOCAL_C_INCLUDES := $(libcxx_includes)
+LOCAL_CPPFLAGS := $(libcxx_cxxflags)
+LOCAL_CPP_FEATURES := rtti exceptions
+LOCAL_EXPORT_C_INCLUDES := $(libcxx_export_includes)
+LOCAL_EXPORT_CPPFLAGS := $(libcxx_export_cxxflags)
+LOCAL_EXPORT_LDFLAGS := $(libcxx_export_ldflags)
+LOCAL_STATIC_LIBRARIES := libc++abi
+
+ifeq ($(NDK_PLATFORM_NEEDS_ANDROID_SUPPORT),true)
+ LOCAL_STATIC_LIBRARIES += android_support
+endif
+
+# We use the LLVM unwinder for all the 32-bit ARM targets.
+ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
+ LOCAL_STATIC_LIBRARIES += libunwind
+ LOCAL_EXPORT_STATIC_LIBRARIES += libunwind
+endif
+
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := c++_shared
+LOCAL_WHOLE_STATIC_LIBRARIES := c++_static libc++abi
+LOCAL_EXPORT_C_INCLUDES := $(libcxx_export_includes)
+LOCAL_EXPORT_CPPFLAGS := $(libcxx_export_cxxflags)
+LOCAL_EXPORT_LDFLAGS := $(libcxx_export_ldflags)
+ifeq ($(NDK_PLATFORM_NEEDS_ANDROID_SUPPORT),true)
+ LOCAL_STATIC_LIBRARIES := android_support
+endif
+LOCAL_LDFLAGS := $(libcxx_ldflags)
+# Use --as-needed to strip the DT_NEEDED on libstdc++.so (bionic's) that the
+# driver always links for C++ but we don't use.
+# See https://github.com/android-ndk/ndk/issues/105
+LOCAL_LDFLAGS += -Wl,--as-needed
+
+# We use the LLVM unwinder for all the 32-bit ARM targets.
+ifneq (,$(filter armeabi%,$(TARGET_ARCH_ABI)))
+ LOCAL_STATIC_LIBRARIES += libunwind
+ LOCAL_EXPORT_STATIC_LIBRARIES += libunwind
+endif
+
+# But only need -latomic for armeabi.
+ifeq ($(TARGET_ARCH_ABI),armeabi)
+ LOCAL_LDLIBS += -latomic
+endif
+include $(BUILD_SHARED_LIBRARY)
+
+$(call import-add-path, $(LOCAL_PATH)/../..)
+$(call import-module, external/libcxxabi)
+
+endif # LIBCXX_FORCE_REBUILD == true
+
+$(call import-module, android/support)
diff --git a/Application.mk b/Application.mk
new file mode 100644
index 0000000..eada7ed
--- /dev/null
+++ b/Application.mk
@@ -0,0 +1,4 @@
+NDK_TOOLCHAIN_VERSION := clang
+# Even the system STL is too much because it will link libsupc++ for rtti and
+# exceptions.
+APP_STL := none
diff --git a/MODULE_LICENSE_BSD_LIKE b/MODULE_LICENSE_BSD_LIKE
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_BSD_LIKE
diff --git a/NOTICE b/NOTICE
new file mode 120000
index 0000000..2acbe45
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1 @@
+LICENSE.TXT
\ No newline at end of file
diff --git a/README.version b/README.version
new file mode 100644
index 0000000..ec7580e
--- /dev/null
+++ b/README.version
@@ -0,0 +1,4 @@
+URL: http://llvm.org/git/libcxx.git
+Version: ba865ff66b36f99a1dc5d9e31af3d8943f94e349
+BugComponent: 117395
+Owners: danalbert, srhines, android-llvm
diff --git a/buildcmds/.gitignore b/buildcmds/.gitignore
new file mode 100644
index 0000000..a77d525
--- /dev/null
+++ b/buildcmds/.gitignore
@@ -0,0 +1,4 @@
+cxx_under_test
+cxx.cmds
+link.cmds
+testconfig.mk
diff --git a/buildcmds/Android.mk b/buildcmds/Android.mk
new file mode 100644
index 0000000..c188b08
--- /dev/null
+++ b/buildcmds/Android.mk
@@ -0,0 +1,43 @@
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+# Don't build for unbundled branches
+ifeq (,$(TARGET_BUILD_APPS))
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libc++_build_commands_$(ANDROID_DEVICE)
+LOCAL_SRC_FILES := dummy.cpp
+LOCAL_CXX_STL := libc++
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/../test/support
+LOCAL_CPPFLAGS := \
+ -std=c++1z \
+ -fsized-deallocation \
+ -fexceptions \
+ -UNDEBUG \
+ -w \
+ -Wno-error=non-virtual-dtor \
+ -Wno-reserved-user-defined-literal \
+
+# Optimization is causing relocation for nothrow new to be thrown away.
+# http://llvm.org/bugs/show_bug.cgi?id=21421
+LOCAL_CPPFLAGS += -O0
+
+LOCAL_RTTI_FLAG := -frtti
+include $(LOCAL_PATH)/testconfig.mk
+
+endif
diff --git a/buildcmds/buildcmdscc b/buildcmds/buildcmdscc
new file mode 100755
index 0000000..b169e92
--- /dev/null
+++ b/buildcmds/buildcmdscc
@@ -0,0 +1,16 @@
+#!/bin/bash
+CXX=$1
+ARGS=${*:2}
+DIR=external/libcxx/buildcmds
+echo $ANDROID_BUILD_TOP/$CXX > $DIR/cxx_under_test
+
+echo $ARGS | grep -P '\S+\.cpp\b' > /dev/null
+if [ $? -eq 0 ]; then
+ echo $ARGS | perl -ne 's/\S+\.cpp\b/%SOURCE%/; print' \
+ | perl -ne 's/\S+\.o\b/%OUT%/; print' > $DIR/cxx.cmds
+else
+ echo $ARGS | perl -ne 's/out\/\S+\/EXECUTABLES\/\S+\.o\b/%SOURCE%/; print' \
+ | perl -ne 's/-o\s+\S+\b/-o %OUT%/; print' > $DIR/link.cmds
+fi
+
+$CXX $ARGS
diff --git a/buildcmds/dummy.cpp b/buildcmds/dummy.cpp
new file mode 100644
index 0000000..4cce7f6
--- /dev/null
+++ b/buildcmds/dummy.cpp
@@ -0,0 +1,3 @@
+int main() {
+ return 0;
+}
diff --git a/include/__config b/include/__config
index 52c7142..4fe161f 100644
--- a/include/__config
+++ b/include/__config
@@ -111,7 +111,7 @@
#define _LIBCPP_CONCAT1(_LIBCPP_X,_LIBCPP_Y) _LIBCPP_X##_LIBCPP_Y
#define _LIBCPP_CONCAT(_LIBCPP_X,_LIBCPP_Y) _LIBCPP_CONCAT1(_LIBCPP_X,_LIBCPP_Y)
-#define _LIBCPP_NAMESPACE _LIBCPP_CONCAT(__,_LIBCPP_ABI_VERSION)
+#define _LIBCPP_NAMESPACE _LIBCPP_CONCAT(__ndk,_LIBCPP_ABI_VERSION)
#if __cplusplus < 201103L
#define _LIBCPP_CXX03_LANG
@@ -917,7 +917,7 @@
#endif
#ifndef _LIBCPP_EXTERN_TEMPLATE
-#define _LIBCPP_EXTERN_TEMPLATE(...) extern template __VA_ARGS__;
+#define _LIBCPP_EXTERN_TEMPLATE(...)
#endif
#ifndef _LIBCPP_EXTERN_TEMPLATE2
diff --git a/include/cstdio b/include/cstdio
index 00b989f..4b2d961 100644
--- a/include/cstdio
+++ b/include/cstdio
@@ -132,9 +132,15 @@
using ::ungetc;
using ::fread;
using ::fwrite;
+#if !defined(__ANDROID__) || !defined(__USE_FILE_OFFSET64) || \
+ (__ANDROID_API__ >= __ANDROID_API_N__)
using ::fgetpos;
+#endif
using ::fseek;
+#if !defined(__ANDROID__) || !defined(__USE_FILE_OFFSET64) || \
+ (__ANDROID_API__ >= __ANDROID_API_N__)
using ::fsetpos;
+#endif
using ::ftell;
using ::rewind;
using ::clearerr;
diff --git a/include/regex b/include/regex
index 612fa84..cbe66ae 100644
--- a/include/regex
+++ b/include/regex
@@ -985,9 +985,15 @@
typedef _CharT char_type;
typedef basic_string<char_type> string_type;
typedef locale locale_type;
+#ifdef __BIONIC__
+ typedef uint16_t char_class_type;
+#else
typedef ctype_base::mask char_class_type;
+#endif
-#if defined(__mips__) && defined(__GLIBC__)
+#ifdef __BIONIC__
+ static const char_class_type __regex_word = 0x8000;
+#elif defined(__mips__) && defined(__GLIBC__)
static const char_class_type __regex_word = static_cast<char_class_type>(_ISbit(15));
#else
static const char_class_type __regex_word = 0x80;
diff --git a/lit.site.cfg b/lit.site.cfg
new file mode 100644
index 0000000..efc75d0
--- /dev/null
+++ b/lit.site.cfg
@@ -0,0 +1,42 @@
+import os
+import sys
+
+# Tell pylint that we know config and lit_config exist somewhere.
+if 'PYLINT_IMPORT' in os.environ:
+ config = object()
+ lit_config = object()
+
+ndk = os.getenv('NDK')
+if ndk is None:
+ sys.exit('The environment variable NDK must point to an NDK toolchain.')
+
+top = os.getenv('ANDROID_BUILD_TOP')
+out_dir = os.getenv('ANDROID_PRODUCT_OUT')
+
+if top is None or out_dir is None:
+ sys.exit('ANDROID_BUILD_TOP or ANDROID_PRODUCT_OUT is not set. Have you '
+ 'run lunch?')
+
+config.cxx_under_test = os.path.join(
+ top, "prebuilts/clang/linux-x86/host/3.6/bin/clang++")
+config.std = "c++11"
+config.libcxx_src_root = os.path.join(top, "external/libcxx")
+config.libcxx_obj_root = os.path.join(top, "external/libcxx")
+config.cxx_library_root = os.path.join(out_dir, 'system/lib')
+config.enable_exceptions = "True"
+config.enable_rtti = "True"
+config.enable_shared = "False"
+config.enable_32bit = "False"
+config.enable_threads = "True"
+config.enable_monotonic_clock = "True"
+config.cxx_abi = "libcxxabi"
+config.use_sanitizer = ""
+config.configuration_variant = "libcxx.ndk"
+config.target_triple = "armv7a-linux-androideabi"
+config.sysroot = os.path.join(ndk, "platforms/android-21/arch-arm/")
+config.gcc_toolchain = os.path.join(
+ top, "prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9")
+
+# Let the main config do the real work.
+lit_config.load_config(
+ config, os.path.join(top, "external/libcxx/test/lit.cfg"))
diff --git a/ndk-test.sh b/ndk-test.sh
new file mode 100755
index 0000000..b98b22d
--- /dev/null
+++ b/ndk-test.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+# This file should reside in test/, but it seems that if there is already one
+# lit.site.cfg in the test/ directory it is impossible to tell LIT to use
+# another. This will need to be fixed upstream before this can get a proper
+# home. The downside of this is that there isn't a way to run a subset of the
+# libc++ tests against the NDK.
+if [ -z "$ANDROID_PRODUCT_OUT" ]; then
+ >&2 echo "Error: ANDROID_PRODUCT_OUT is not set. Have you run lunch?"
+ exit 1
+fi
+
+if [ ! -f $ANDROID_PRODUCT_OUT/system/lib/libc++_ndk.so ]; then
+ >&2 echo "Error: libc++_ndk.so has not been built for this target."
+ exit 1
+fi
+
+adb push $ANDROID_PRODUCT_OUT/system/lib/libc++_ndk.so /data/local/tmp
+lit -sv $* .
diff --git a/run_tests.py b/run_tests.py
new file mode 100755
index 0000000..bc988f1
--- /dev/null
+++ b/run_tests.py
@@ -0,0 +1,148 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+"""Runs the libc++ tests against the platform libc++."""
+from __future__ import print_function
+
+import argparse
+import logging
+import os
+import sys
+
+
+THIS_DIR = os.path.dirname(os.path.realpath(__file__))
+ANDROID_DIR = os.path.realpath(os.path.join(THIS_DIR, '../..'))
+
+
+def logger():
+ """Returns the logger for the module."""
+ return logging.getLogger(__name__)
+
+
+def call(cmd, *args, **kwargs):
+ """subprocess.call with logging."""
+ import subprocess
+ logger().info('call %s', ' '.join(cmd))
+ return subprocess.call(cmd, *args, **kwargs)
+
+
+def check_call(cmd, *args, **kwargs):
+ """subprocess.check_call with logging."""
+ import subprocess
+ logger().info('check_call %s', ' '.join(cmd))
+ return subprocess.check_call(cmd, *args, **kwargs)
+
+
+class ArgParser(argparse.ArgumentParser):
+ """Parses command line arguments."""
+ def __init__(self):
+ super(ArgParser, self).__init__()
+ self.add_argument(
+ '--compiler', choices=('clang', 'gcc'), default='clang')
+ self.add_argument(
+ '--bitness', choices=(32, 64), type=int, default=32)
+ self.add_argument('--host', action='store_true')
+
+
+def gen_test_config(bitness, compiler, host):
+ """Generates the test configuration makefile for buildcmds."""
+ testconfig_mk_path = os.path.join(THIS_DIR, 'buildcmds/testconfig.mk')
+ with open(testconfig_mk_path, 'w') as test_config:
+ if compiler == 'clang':
+ print('LOCAL_CLANG := true', file=test_config)
+ elif compiler == 'gcc':
+ print('LOCAL_CLANG := false', file=test_config)
+
+ if bitness == 32:
+ print('LOCAL_MULTILIB := 32', file=test_config)
+ elif bitness == 64:
+ print('LOCAL_MULTILIB := 64', file=test_config)
+
+ if compiler == 'clang':
+ print('LOCAL_CXX := $(LOCAL_PATH)/buildcmdscc $(CLANG_CXX)',
+ file=test_config)
+ else:
+ if host:
+ prefix = 'HOST_'
+ else:
+ prefix = 'TARGET_'
+ print('LOCAL_CXX := $(LOCAL_PATH)/buildcmdscc '
+ '$($(LOCAL_2ND_ARCH_VAR_PREFIX){}CXX)'.format(prefix),
+ file=test_config)
+
+ if host:
+ print('include $(BUILD_HOST_EXECUTABLE)', file=test_config)
+ else:
+ print('include $(BUILD_EXECUTABLE)', file=test_config)
+
+
+def mmm(path):
+ """Invokes the Android build command mmm."""
+ makefile = os.path.join(path, 'Android.mk')
+ main_mk = 'build/core/main.mk'
+
+ env = dict(os.environ)
+ env['ONE_SHOT_MAKEFILE'] = makefile
+ env['LIBCXX_TESTING'] = 'true'
+ cmd = [
+ 'make', '-j', '-C', ANDROID_DIR, '-f', main_mk,
+ 'MODULES-IN-' + path.replace('/', '-'),
+ ]
+ check_call(cmd, env=env)
+
+
+def gen_build_cmds(bitness, compiler, host):
+ """Generates the build commands file for the test runner."""
+ gen_test_config(bitness, compiler, host)
+ mmm('external/libcxx/buildcmds')
+
+
+def main():
+ """Program entry point."""
+ logging.basicConfig(level=logging.INFO)
+
+ args, lit_args = ArgParser().parse_known_args()
+ lit_path = os.path.join(ANDROID_DIR, 'external/llvm/utils/lit/lit.py')
+ gen_build_cmds(args.bitness, args.compiler, args.host)
+
+ mode_str = 'host' if args.host else 'device'
+ android_mode_arg = '--param=android_mode=' + mode_str
+ site_cfg_path = os.path.join(THIS_DIR, 'test/lit.site.cfg')
+ site_cfg_arg = '--param=libcxx_site_config=' + site_cfg_path
+ default_test_path = os.path.join(THIS_DIR, 'test')
+
+ have_filter_args = False
+ for arg in lit_args:
+ # If the argument is a valid path with default_test_path, it is a test
+ # filter.
+ real_path = os.path.realpath(arg)
+ if not real_path.startswith(default_test_path):
+ continue
+ if not os.path.exists(real_path):
+ continue
+
+ have_filter_args = True
+ break # No need to keep scanning.
+
+ lit_args = ['-sv', android_mode_arg, site_cfg_arg] + lit_args
+ cmd = ['python', lit_path] + lit_args
+ if not have_filter_args:
+ cmd.append(default_test_path)
+ sys.exit(call(cmd))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/algorithm.cpp b/src/algorithm.cpp
index f036eb7..132a51d 100644
--- a/src/algorithm.cpp
+++ b/src/algorithm.cpp
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+#undef _LIBCPP_EXTERN_TEMPLATE
+#define _LIBCPP_EXTERN_TEMPLATE(...) extern template __VA_ARGS__;
#include "algorithm"
#include "random"
#include "mutex"
diff --git a/src/ios.cpp b/src/ios.cpp
index 0f1d88e..c1d2327 100644
--- a/src/ios.cpp
+++ b/src/ios.cpp
@@ -9,6 +9,9 @@
#include "__config"
+#undef _LIBCPP_EXTERN_TEMPLATE
+#define _LIBCPP_EXTERN_TEMPLATE(...) extern template __VA_ARGS__;
+
#include "ios"
#include <stdlib.h>
diff --git a/src/locale.cpp b/src/locale.cpp
index b9c7011..8cd17e2 100644
--- a/src/locale.cpp
+++ b/src/locale.cpp
@@ -7,6 +7,9 @@
//
//===----------------------------------------------------------------------===//
+#undef _LIBCPP_EXTERN_TEMPLATE
+#define _LIBCPP_EXTERN_TEMPLATE(...) extern template __VA_ARGS__;
+
// On Solaris, we need to define something to make the C99 parts of localeconv
// visible.
#ifdef __sun__
diff --git a/src/string.cpp b/src/string.cpp
index d7ebdd3..6a175f2 100644
--- a/src/string.cpp
+++ b/src/string.cpp
@@ -7,6 +7,9 @@
//
//===----------------------------------------------------------------------===//
+#undef _LIBCPP_EXTERN_TEMPLATE
+#define _LIBCPP_EXTERN_TEMPLATE(...) extern template __VA_ARGS__;
+
#include "string"
#include "cstdlib"
#include "cwchar"
diff --git a/src/valarray.cpp b/src/valarray.cpp
index 2d8db52..f6745df 100644
--- a/src/valarray.cpp
+++ b/src/valarray.cpp
@@ -7,6 +7,9 @@
//
//===----------------------------------------------------------------------===//
+#undef _LIBCPP_EXTERN_TEMPLATE
+#define _LIBCPP_EXTERN_TEMPLATE(...) extern template __VA_ARGS__;
+
#include "valarray"
_LIBCPP_BEGIN_NAMESPACE_STD
diff --git a/test.mk b/test.mk
new file mode 100644
index 0000000..040040f
--- /dev/null
+++ b/test.mk
@@ -0,0 +1,4 @@
+.NOTPARALLEL:
+default:
+ python $(LIT) -sv --param android_mode=$(LIT_MODE) $(LIT_ARGS) \
+ $(ANDROID_BUILD_TOP)/external/libcxx/test
diff --git a/test/lit.ndk.cfg.in b/test/lit.ndk.cfg.in
new file mode 100644
index 0000000..be9c770
--- /dev/null
+++ b/test/lit.ndk.cfg.in
@@ -0,0 +1,48 @@
+import os
+import sys
+
+# pylint: disable=invalid-name
+
+# Tell pylint that we know config and lit_config exist somewhere.
+if 'PYLINT_IMPORT' in os.environ:
+ config = object()
+ lit_config = object()
+ lit_config.params = {}
+
+ndk = os.getenv('NDK')
+if ndk is None:
+ sys.exit('The environment variable NDK must point to an NDK toolchain.')
+
+top = os.getenv('ANDROID_BUILD_TOP')
+libcxx_dir = os.path.join(ndk, 'sources/cxx-stl/llvm-libc++')
+
+abi = lit_config.params["abi"]
+host_tag = lit_config.params["host_tag"]
+toolchain = lit_config.params["toolchain"]
+triple = lit_config.params["triple"]
+
+config.cxx_under_test = os.path.join(
+ ndk, "toolchains/llvm/prebuilt", host_tag, "bin/clang++")
+config.std = "c++14"
+config.libcxx_src_root = libcxx_dir
+config.libcxx_obj_root = libcxx_dir
+config.cxx_include = os.path.join(libcxx_dir, "include")
+config.cxx_library_root = os.path.join(libcxx_dir, "libs", abi)
+config.use_target = "True"
+config.enable_exceptions = "True"
+config.enable_rtti = "True"
+config.enable_shared = "False"
+config.enable_32bit = "False"
+config.enable_threads = "True"
+config.enable_monotonic_clock = "True"
+config.cxx_abi = "libcxxabi"
+config.use_sanitizer = ""
+config.configuration_variant = "libcxx.ndk"
+config.target_triple = triple
+config.gcc_toolchain = os.path.join(
+ ndk, "toolchains", toolchain + "-4.9", "prebuilt", host_tag)
+
+# Let the main config do the real work.
+config.loaded_site_config = True
+lit_config.load_config(
+ config, os.path.join(libcxx_dir, "test/lit.cfg"))
diff --git a/test/lit.site.cfg b/test/lit.site.cfg
new file mode 100644
index 0000000..c9dbdfb
--- /dev/null
+++ b/test/lit.site.cfg
@@ -0,0 +1,12 @@
+import os
+
+config.configuration_variant = 'libcxx.android'
+config.android_root = os.getenv('ANDROID_BUILD_TOP')
+config.libcxx_src_root = os.path.join(config.android_root, 'external/libcxx')
+config.python_executable = '/usr/bin/python'
+
+config.timeout = '300'
+
+# Let the main config do the real work.
+lit_config.load_config(
+ config, os.path.join(config.libcxx_src_root, 'test/lit.cfg'))
diff --git a/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/generic_category.pass.cpp b/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/generic_category.pass.cpp
index cd76a9f..da96c1c 100644
--- a/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/generic_category.pass.cpp
+++ b/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/generic_category.pass.cpp
@@ -32,7 +32,9 @@
errno = E2BIG; // something that message will never generate
const std::error_category& e_cat1 = std::generic_category();
const std::string msg = e_cat1.message(-1);
- LIBCPP_ASSERT(msg == "Unknown error -1" || msg == "Unknown error");
+ // Exact message format varies by platform.
+ LIBCPP_ASSERT(msg == "Unknown error -1" || msg == "Unknown error" ||
+ msg == "Unknown error: -1");
assert(errno == E2BIG);
}
diff --git a/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/system_category.pass.cpp b/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/system_category.pass.cpp
index c9c6d52..93b0583 100644
--- a/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/system_category.pass.cpp
+++ b/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/system_category.pass.cpp
@@ -32,7 +32,9 @@
errno = E2BIG; // something that message will never generate
const std::error_category& e_cat1 = std::system_category();
const std::string msg = e_cat1.message(-1);
- LIBCPP_ASSERT(msg == "Unknown error -1" || msg == "Unknown error");
+ // Exact message format varries by platform.
+ LIBCPP_ASSERT(msg == "Unknown error -1" || msg == "Unknown error" ||
+ msg == "Unknown error: -1");
assert(errno == E2BIG);
}
diff --git a/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_nothrow_replace.pass.cpp b/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_nothrow_replace.pass.cpp
index 3d8467f..1553036 100644
--- a/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_nothrow_replace.pass.cpp
+++ b/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_nothrow_replace.pass.cpp
@@ -18,24 +18,9 @@
#include <cassert>
#include <limits>
+#include "count_new.hpp"
#include "test_macros.h"
-int new_called = 0;
-
-void* operator new(std::size_t s) TEST_THROW_SPEC(std::bad_alloc)
-{
- ++new_called;
- void* ret = std::malloc(s);
- if (!ret) std::abort(); // placate MSVC's unchecked malloc warning
- return ret;
-}
-
-void operator delete(void* p) TEST_NOEXCEPT
-{
- --new_called;
- std::free(p);
-}
-
int A_constructed = 0;
struct A
@@ -46,13 +31,15 @@
int main()
{
+ globalMemCounter.reset();
+ assert(globalMemCounter.checkOutstandingNewEq(0));
A *ap = new (std::nothrow) A[3];
DoNotOptimize(ap);
assert(ap);
assert(A_constructed == 3);
- assert(new_called);
+ assert(globalMemCounter.checkOutstandingNewNotEq(0));
delete [] ap;
DoNotOptimize(ap);
assert(A_constructed == 0);
- assert(!new_called);
+ assert(globalMemCounter.checkOutstandingNewEq(0));
}
diff --git a/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_replace.pass.cpp b/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_replace.pass.cpp
index ad4d9f4..ea89b98 100644
--- a/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_replace.pass.cpp
+++ b/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_replace.pass.cpp
@@ -19,24 +19,9 @@
#include <cassert>
#include <limits>
+#include "count_new.hpp"
#include "test_macros.h"
-int new_called = 0;
-
-void* operator new(std::size_t s) TEST_THROW_SPEC(std::bad_alloc)
-{
- ++new_called;
- void* ret = std::malloc(s);
- if (!ret) std::abort(); // placate MSVC's unchecked malloc warning
- return ret;
-}
-
-void operator delete(void* p) TEST_NOEXCEPT
-{
- --new_called;
- std::free(p);
-}
-
int A_constructed = 0;
struct A
@@ -47,13 +32,15 @@
int main()
{
+ globalMemCounter.reset();
+ assert(globalMemCounter.checkOutstandingNewEq(0));
A *ap = new A[3];
DoNotOptimize(ap);
assert(ap);
assert(A_constructed == 3);
- assert(new_called == 1);
+ assert(globalMemCounter.checkOutstandingNewEq(1));
delete [] ap;
DoNotOptimize(ap);
assert(A_constructed == 0);
- assert(new_called == 0);
+ assert(globalMemCounter.checkOutstandingNewEq(0));
}
diff --git a/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_nothrow_replace.pass.cpp b/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_nothrow_replace.pass.cpp
index a0e3eda..a3877f3 100644
--- a/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_nothrow_replace.pass.cpp
+++ b/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_nothrow_replace.pass.cpp
@@ -18,24 +18,9 @@
#include <cassert>
#include <limits>
+#include "count_new.hpp"
#include "test_macros.h"
-int new_called = 0;
-
-void* operator new(std::size_t s) TEST_THROW_SPEC(std::bad_alloc)
-{
- ++new_called;
- void* ret = std::malloc(s);
- if (!ret) std::abort(); // placate MSVC's unchecked malloc warning
- return ret;
-}
-
-void operator delete(void* p) TEST_NOEXCEPT
-{
- --new_called;
- std::free(p);
-}
-
bool A_constructed = false;
struct A
@@ -46,13 +31,15 @@
int main()
{
+ globalMemCounter.reset();
+ assert(globalMemCounter.checkOutstandingNewEq(0));
A *ap = new (std::nothrow) A;
DoNotOptimize(ap);
assert(ap);
assert(A_constructed);
- assert(new_called);
+ assert(globalMemCounter.checkOutstandingNewNotEq(0));
delete ap;
DoNotOptimize(ap);
assert(!A_constructed);
- assert(!new_called);
+ assert(globalMemCounter.checkOutstandingNewEq(0));
}
diff --git a/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_replace.pass.cpp b/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_replace.pass.cpp
index aa00fee..7570bfb 100644
--- a/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_replace.pass.cpp
+++ b/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_replace.pass.cpp
@@ -17,24 +17,9 @@
#include <cassert>
#include <limits>
+#include "count_new.hpp"
#include "test_macros.h"
-int new_called = 0;
-
-void* operator new(std::size_t s) TEST_THROW_SPEC(std::bad_alloc)
-{
- ++new_called;
- void* ret = std::malloc(s);
- if (!ret) std::abort(); // placate MSVC's unchecked malloc warning
- return ret;
-}
-
-void operator delete(void* p) TEST_NOEXCEPT
-{
- --new_called;
- std::free(p);
-}
-
bool A_constructed = false;
struct A
@@ -45,13 +30,15 @@
int main()
{
+ globalMemCounter.reset();
+ assert(globalMemCounter.checkOutstandingNewEq(0));
A *ap = new A;
DoNotOptimize(ap);
assert(ap);
assert(A_constructed);
- assert(new_called);
+ assert(globalMemCounter.checkOutstandingNewEq(1));
delete ap;
DoNotOptimize(ap);
assert(!A_constructed);
- assert(!new_called);
+ assert(globalMemCounter.checkOutstandingNewEq(0));
}
diff --git a/test/std/localization/locale.categories/category.numeric/locale.nm.put/facet.num.put.members/put_long_double.pass.cpp b/test/std/localization/locale.categories/category.numeric/locale.nm.put/facet.num.put.members/put_long_double.pass.cpp
index cdd1639..43e85f2 100644
--- a/test/std/localization/locale.categories/category.numeric/locale.nm.put/facet.num.put.members/put_long_double.pass.cpp
+++ b/test/std/localization/locale.categories/category.numeric/locale.nm.put/facet.num.put.members/put_long_double.pass.cpp
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+// XFAIL: android
+
// <locale>
// class num_put<charT, OutputIterator>
diff --git a/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long_double.pass.cpp b/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long_double.pass.cpp
index cf671b0..ddc7d21 100644
--- a/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long_double.pass.cpp
+++ b/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long_double.pass.cpp
@@ -25,6 +25,8 @@
#include "test_iterators.h"
#include "hexfloat.h"
+#include "float_comparison.h"
+
typedef std::num_get<char, input_iterator<const char*> > F;
class my_facet
@@ -228,9 +230,10 @@
f.get(input_iterator<const char*>(str),
input_iterator<const char*>(str+sizeof(str)),
ios, err, v);
- assert(iter.base() == str+sizeof(str)-1);
- assert(err != ios.failbit);
- assert(v == 304888344611713860501504000000.0L);
+
+ FloatingPoint<long double> actual(v);
+ FloatingPoint<long double> expected(304888344611713860501504000000.0L);
+ assert(actual.AlmostEquals(expected));
}
{
v = -1;
diff --git a/test/std/localization/locale.stdcvt/codecvt_utf16.pass.cpp b/test/std/localization/locale.stdcvt/codecvt_utf16.pass.cpp
index a61a9c9..a6a2c22 100644
--- a/test/std/localization/locale.stdcvt/codecvt_utf16.pass.cpp
+++ b/test/std/localization/locale.stdcvt/codecvt_utf16.pass.cpp
@@ -27,6 +27,7 @@
int main()
{
+ globalMemCounter.reset();
assert(globalMemCounter.checkOutstandingNewEq(0));
{
typedef std::codecvt_utf16<wchar_t> C;
diff --git a/test/std/localization/locale.stdcvt/codecvt_utf8.pass.cpp b/test/std/localization/locale.stdcvt/codecvt_utf8.pass.cpp
index 5fa0eaa..daa3458 100644
--- a/test/std/localization/locale.stdcvt/codecvt_utf8.pass.cpp
+++ b/test/std/localization/locale.stdcvt/codecvt_utf8.pass.cpp
@@ -27,6 +27,7 @@
int main()
{
+ globalMemCounter.reset();
assert(globalMemCounter.checkOutstandingNewEq(0));
{
typedef std::codecvt_utf8<wchar_t> C;
diff --git a/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/ctor.pass.cpp b/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/ctor.pass.cpp
index 6f0994a..634a740 100644
--- a/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/ctor.pass.cpp
+++ b/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/ctor.pass.cpp
@@ -24,6 +24,7 @@
int main()
{
+ globalMemCounter.reset();
typedef std::wbuffer_convert<std::codecvt_utf8<wchar_t> > B;
#if TEST_STD_VER > 11
static_assert(!std::is_convertible<std::streambuf*, B>::value, "");
diff --git a/test/std/localization/locales/locale/locale.members/combine.pass.cpp b/test/std/localization/locales/locale/locale.members/combine.pass.cpp
index a9919f6..d24decc 100644
--- a/test/std/localization/locales/locale/locale.members/combine.pass.cpp
+++ b/test/std/localization/locales/locale/locale.members/combine.pass.cpp
@@ -67,6 +67,7 @@
int main()
{
{
+ globalMemCounter.reset();
{
std::locale loc;
std::locale loc2(loc, new my_facet);
diff --git a/test/std/strings/basic.string/string.cons/implicit_deduction_guides.pass.cpp b/test/std/strings/basic.string/string.cons/implicit_deduction_guides.pass.cpp
index 0fbd663..443e88e 100644
--- a/test/std/strings/basic.string/string.cons/implicit_deduction_guides.pass.cpp
+++ b/test/std/strings/basic.string/string.cons/implicit_deduction_guides.pass.cpp
@@ -9,6 +9,10 @@
// UNSUPPORTED: c++98, c++03, c++11, c++14
// UNSUPPORTED: libcpp-no-deduction-guides
+//
+// This feature is not yet ready in clang
+// http://b/36401676
+// XFAIL: *
// <string>
diff --git a/test/std/strings/string.view/string.view.cons/implicit_deduction_guides.pass.cpp b/test/std/strings/string.view/string.view.cons/implicit_deduction_guides.pass.cpp
index 7dd99d9..d9e1883 100644
--- a/test/std/strings/string.view/string.view.cons/implicit_deduction_guides.pass.cpp
+++ b/test/std/strings/string.view/string.view.cons/implicit_deduction_guides.pass.cpp
@@ -9,6 +9,10 @@
// UNSUPPORTED: c++98, c++03, c++11, c++14
// UNSUPPORTED: libcpp-no-deduction-guides
+//
+// This feature is not yet ready in clang
+// http://b/36401676
+// XFAIL: *
// <string_view>
diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.alg/swap.pass.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.alg/swap.pass.cpp
index 1a9206e..9dba116 100644
--- a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.alg/swap.pass.cpp
+++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.alg/swap.pass.cpp
@@ -60,6 +60,7 @@
int main()
{
+ globalMemCounter.reset();
assert(globalMemCounter.checkOutstandingNewEq(0));
{
std::function<int(int)> f1 = A(1);
diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F.pass.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F.pass.cpp
index fd296a7..886eafc 100644
--- a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F.pass.cpp
+++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F.pass.cpp
@@ -63,6 +63,7 @@
int main()
{
+ globalMemCounter.reset();
assert(globalMemCounter.checkOutstandingNewEq(0));
{
std::function<int(int)> f = A();
diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F_assign.pass.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F_assign.pass.cpp
index e927ad4..aab0d40 100644
--- a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F_assign.pass.cpp
+++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F_assign.pass.cpp
@@ -66,6 +66,7 @@
int main()
{
+ globalMemCounter.reset();
assert(globalMemCounter.checkOutstandingNewEq(0));
{
std::function<int(int)> f;
diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_assign.pass.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_assign.pass.cpp
index 1c2be02..b480f6a 100644
--- a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_assign.pass.cpp
+++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_assign.pass.cpp
@@ -50,6 +50,7 @@
int g3(int, int, int) { return 3; }
int main() {
+ globalMemCounter.reset();
assert(globalMemCounter.checkOutstandingNewEq(0));
{
std::function<int(int)> f = A();
diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_move.pass.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_move.pass.cpp
index faf4f11..cdedf07 100644
--- a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_move.pass.cpp
+++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_move.pass.cpp
@@ -53,6 +53,7 @@
int main()
{
+ globalMemCounter.reset();
assert(globalMemCounter.checkOutstandingNewEq(0));
{
std::function<int(int)> f = A();
diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/nullptr_t_assign.pass.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/nullptr_t_assign.pass.cpp
index 9b2482f..e29989d 100644
--- a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/nullptr_t_assign.pass.cpp
+++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/nullptr_t_assign.pass.cpp
@@ -49,6 +49,7 @@
int main()
{
+ globalMemCounter.reset();
assert(globalMemCounter.checkOutstandingNewEq(0));
{
std::function<int(int)> f = A();
diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/swap.pass.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/swap.pass.cpp
index 214c3f7..2e6d77d 100644
--- a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/swap.pass.cpp
+++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/swap.pass.cpp
@@ -59,6 +59,7 @@
int g3(int, int, int) { return 3; }
int main() {
+ globalMemCounter.reset();
assert(globalMemCounter.checkOutstandingNewEq(0));
{
std::function<int(int)> f1 = A(1);
diff --git a/test/std/utilities/memory/default.allocator/allocator.members/construct.pass.cpp b/test/std/utilities/memory/default.allocator/allocator.members/construct.pass.cpp
index 9ba9874..fb83dc9 100644
--- a/test/std/utilities/memory/default.allocator/allocator.members/construct.pass.cpp
+++ b/test/std/utilities/memory/default.allocator/allocator.members/construct.pass.cpp
@@ -56,6 +56,7 @@
int main()
{
+ globalMemCounter.reset();
{
std::allocator<A> a;
assert(globalMemCounter.checkOutstandingNewEq(0));
diff --git a/test/std/utilities/memory/util.smartptr/util.smartptr.enab/enable_shared_from_this.pass.cpp b/test/std/utilities/memory/util.smartptr/util.smartptr.enab/enable_shared_from_this.pass.cpp
index 8bd8993..c919850 100644
--- a/test/std/utilities/memory/util.smartptr/util.smartptr.enab/enable_shared_from_this.pass.cpp
+++ b/test/std/utilities/memory/util.smartptr/util.smartptr.enab/enable_shared_from_this.pass.cpp
@@ -55,6 +55,7 @@
int main()
{
+ globalMemCounter.reset();
{ // https://bugs.llvm.org/show_bug.cgi?id=18843
std::shared_ptr<T const> t1(new T);
std::shared_ptr<T const> t2(std::make_shared<T>());
diff --git a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_throw.pass.cpp b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_throw.pass.cpp
index 13c2d43..8095867 100644
--- a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_throw.pass.cpp
+++ b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_throw.pass.cpp
@@ -37,6 +37,7 @@
int main()
{
+ globalMemCounter.reset();
A* ptr = new A;
globalMemCounter.throw_after = 0;
try
diff --git a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_throw.pass.cpp b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_throw.pass.cpp
index 182d5f4..5f02b83 100644
--- a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_throw.pass.cpp
+++ b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_throw.pass.cpp
@@ -36,6 +36,7 @@
int main()
{
+ globalMemCounter.reset();
A* ptr = new A;
assert(A::count == 1);
globalMemCounter.throw_after = 0;
diff --git a/test/support/float_comparison.h b/test/support/float_comparison.h
new file mode 100644
index 0000000..4a29e17
--- /dev/null
+++ b/test/support/float_comparison.h
@@ -0,0 +1,315 @@
+// Copyright 2005, Google Inc.
+// 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.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+//
+// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file declares functions and macros used internally by
+// Google Test. They are subject to change without notice.
+
+#ifndef FLOAT_COMPARISON_H
+#define FLOAT_COMPARISON_H
+
+#if GTEST_OS_LINUX
+# include <stdlib.h>
+# include <sys/types.h>
+# include <sys/wait.h>
+# include <unistd.h>
+#endif // GTEST_OS_LINUX
+
+#if GTEST_HAS_EXCEPTIONS
+# include <stdexcept>
+#endif
+
+#include <ctype.h>
+#include <float.h>
+#include <string.h>
+#include <iomanip>
+#include <limits>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+// This template class serves as a compile-time function from size to
+// type. It maps a size in bytes to a primitive type with that
+// size. e.g.
+//
+// TypeWithSize<4>::UInt
+//
+// is typedef-ed to be unsigned int (unsigned integer made up of 4
+// bytes).
+//
+// Such functionality should belong to STL, but I cannot find it
+// there.
+//
+// Google Test uses this class in the implementation of floating-point
+// comparison.
+//
+// For now it only handles UInt (unsigned int) as that's all Google Test
+// needs. Other types can be easily added in the future if need
+// arises.
+template <size_t size>
+class TypeWithSize {
+ public:
+ // This prevents the user from using TypeWithSize<N> with incorrect
+ // values of N.
+ typedef void UInt;
+};
+
+// The specialization for size 4.
+template <>
+class TypeWithSize<4> {
+ public:
+ // unsigned int has size 4 in both gcc and MSVC.
+ //
+ // As base/basictypes.h doesn't compile on Windows, we cannot use
+ // uint32, uint64, and etc here.
+ typedef int Int;
+ typedef unsigned int UInt;
+};
+
+// The specialization for size 8.
+template <>
+class TypeWithSize<8> {
+ public:
+#if GTEST_OS_WINDOWS
+ typedef __int64 Int;
+ typedef unsigned __int64 UInt;
+#else
+ typedef long long Int; // NOLINT
+ typedef unsigned long long UInt; // NOLINT
+#endif // GTEST_OS_WINDOWS
+};
+
+#ifdef __LP64__
+// The specialization for size 16.
+template <>
+class TypeWithSize<16> {
+ public:
+ typedef __int128 Int; // NOLINT
+ typedef unsigned __int128 UInt; // NOLINT
+};
+#endif
+
+// This template class represents an IEEE floating-point number
+// (either single-precision or double-precision, depending on the
+// template parameters).
+//
+// The purpose of this class is to do more sophisticated number
+// comparison. (Due to round-off error, etc, it's very unlikely that
+// two floating-points will be equal exactly. Hence a naive
+// comparison by the == operation often doesn't work.)
+//
+// Format of IEEE floating-point:
+//
+// The most-significant bit being the leftmost, an IEEE
+// floating-point looks like
+//
+// sign_bit exponent_bits fraction_bits
+//
+// Here, sign_bit is a single bit that designates the sign of the
+// number.
+//
+// For float, there are 8 exponent bits and 23 fraction bits.
+//
+// For double, there are 11 exponent bits and 52 fraction bits.
+//
+// More details can be found at
+// http://en.wikipedia.org/wiki/IEEE_floating-point_standard.
+//
+// Template parameter:
+//
+// RawType: the raw floating-point type (either float or double)
+template <typename RawType>
+class FloatingPoint {
+ public:
+ // Defines the unsigned integer type that has the same size as the
+ // floating point number.
+ typedef typename TypeWithSize<sizeof(RawType)>::UInt Bits;
+
+ // Constants.
+
+ // # of bits in a number.
+ static const size_t kBitCount = 8*sizeof(RawType);
+
+ // # of fraction bits in a number.
+ static const size_t kFractionBitCount =
+ std::numeric_limits<RawType>::digits - 1;
+
+ // # of exponent bits in a number.
+ static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount;
+
+ // The mask for the sign bit.
+ static const Bits kSignBitMask = static_cast<Bits>(1) << (kBitCount - 1);
+
+ // The mask for the fraction bits.
+ static const Bits kFractionBitMask =
+ ~static_cast<Bits>(0) >> (kExponentBitCount + 1);
+
+ // The mask for the exponent bits.
+ static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask);
+
+ // How many ULP's (Units in the Last Place) we want to tolerate when
+ // comparing two numbers. The larger the value, the more error we
+ // allow. A 0 value means that two numbers must be exactly the same
+ // to be considered equal.
+ //
+ // The maximum error of a single floating-point operation is 0.5
+ // units in the last place. On Intel CPU's, all floating-point
+ // calculations are done with 80-bit precision, while double has 64
+ // bits. Therefore, 4 should be enough for ordinary use.
+ //
+ // See the following article for more details on ULP:
+ // http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
+ static const size_t kMaxUlps = 4;
+
+ // Constructs a FloatingPoint from a raw floating-point number.
+ //
+ // On an Intel CPU, passing a non-normalized NAN (Not a Number)
+ // around may change its bits, although the new value is guaranteed
+ // to be also a NAN. Therefore, don't expect this constructor to
+ // preserve the bits in x when x is a NAN.
+ explicit FloatingPoint(const RawType& x) { u_.value_ = x; }
+
+ // Static methods
+
+ // Reinterprets a bit pattern as a floating-point number.
+ //
+ // This function is needed to test the AlmostEquals() method.
+ static RawType ReinterpretBits(const Bits bits) {
+ FloatingPoint fp(0);
+ fp.u_.bits_ = bits;
+ return fp.u_.value_;
+ }
+
+ // Returns the floating-point number that represent positive infinity.
+ static RawType Infinity() {
+ return ReinterpretBits(kExponentBitMask);
+ }
+
+ // Returns the maximum representable finite floating-point number.
+ static RawType Max();
+
+ // Non-static methods
+
+ // Returns the bits that represents this number.
+ const Bits &bits() const { return u_.bits_; }
+
+ // Returns the exponent bits of this number.
+ Bits exponent_bits() const { return kExponentBitMask & u_.bits_; }
+
+ // Returns the fraction bits of this number.
+ Bits fraction_bits() const { return kFractionBitMask & u_.bits_; }
+
+ // Returns the sign bit of this number.
+ Bits sign_bit() const { return kSignBitMask & u_.bits_; }
+
+ // Returns true iff this is NAN (not a number).
+ bool is_nan() const {
+ // It's a NAN if the exponent bits are all ones and the fraction
+ // bits are not entirely zeros.
+ return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0);
+ }
+
+ // Returns true iff this number is at most kMaxUlps ULP's away from
+ // rhs. In particular, this function:
+ //
+ // - returns false if either number is (or both are) NAN.
+ // - treats really large numbers as almost equal to infinity.
+ // - thinks +0.0 and -0.0 are 0 DLP's apart.
+ bool AlmostEquals(const FloatingPoint& rhs) const {
+ // The IEEE standard says that any comparison operation involving
+ // a NAN must return false.
+ if (is_nan() || rhs.is_nan()) return false;
+
+ return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_)
+ <= kMaxUlps;
+ }
+
+ private:
+ // The data type used to store the actual floating-point number.
+ union FloatingPointUnion {
+ RawType value_; // The raw floating-point number.
+ Bits bits_; // The bits that represent the number.
+ };
+
+ // Converts an integer from the sign-and-magnitude representation to
+ // the biased representation. More precisely, let N be 2 to the
+ // power of (kBitCount - 1), an integer x is represented by the
+ // unsigned number x + N.
+ //
+ // For instance,
+ //
+ // -N + 1 (the most negative number representable using
+ // sign-and-magnitude) is represented by 1;
+ // 0 is represented by N; and
+ // N - 1 (the biggest number representable using
+ // sign-and-magnitude) is represented by 2N - 1.
+ //
+ // Read http://en.wikipedia.org/wiki/Signed_number_representations
+ // for more details on signed number representations.
+ static Bits SignAndMagnitudeToBiased(const Bits &sam) {
+ if (kSignBitMask & sam) {
+ // sam represents a negative number.
+ return ~sam + 1;
+ } else {
+ // sam represents a positive number.
+ return kSignBitMask | sam;
+ }
+ }
+
+ // Given two numbers in the sign-and-magnitude representation,
+ // returns the distance between them as an unsigned number.
+ static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits &sam1,
+ const Bits &sam2) {
+ const Bits biased1 = SignAndMagnitudeToBiased(sam1);
+ const Bits biased2 = SignAndMagnitudeToBiased(sam2);
+ return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1);
+ }
+
+ FloatingPointUnion u_;
+};
+
+// We cannot use std::numeric_limits<T>::max() as it clashes with the max()
+// macro defined by <windows.h>.
+template <>
+inline float FloatingPoint<float>::Max() { return FLT_MAX; }
+template <>
+inline double FloatingPoint<double>::Max() { return DBL_MAX; }
+
+// Typedefs the instances of the FloatingPoint template class that we
+// care to use.
+typedef FloatingPoint<float> Float;
+typedef FloatingPoint<double> Double;
+
+
+#endif // FLOAT_COMPARISON_H
+
diff --git a/utils/libcxx/android/__init__.py b/utils/libcxx/android/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/utils/libcxx/android/__init__.py
diff --git a/utils/libcxx/android/adb.py b/utils/libcxx/android/adb.py
new file mode 100644
index 0000000..43bd2b5
--- /dev/null
+++ b/utils/libcxx/android/adb.py
@@ -0,0 +1,24 @@
+import lit.util # pylint: disable=import-error
+
+
+class AdbError(RuntimeError):
+ def __init__(self, cmd, out, err, exit_code):
+ super(AdbError, self).__init__(err)
+ self.cmd = cmd
+ self.out = out
+ self.err = err
+ self.exit_code = exit_code
+
+
+def mkdir(path):
+ cmd = ['adb', 'shell', 'mkdir', path]
+ out, err, exit_code = lit.util.executeCommand(cmd)
+ if exit_code != 0:
+ raise AdbError(cmd, out, err, exit_code)
+
+
+def push(src, dst):
+ cmd = ['adb', 'push', src, dst]
+ out, err, exit_code = lit.util.executeCommand(cmd)
+ if exit_code != 0:
+ raise AdbError(cmd, out, err, exit_code)
diff --git a/utils/libcxx/android/build.py b/utils/libcxx/android/build.py
new file mode 100644
index 0000000..a0d1be3
--- /dev/null
+++ b/utils/libcxx/android/build.py
@@ -0,0 +1,13 @@
+import os
+import subprocess
+
+
+def mm(path, android_build_top):
+ env = os.environ
+ env['ONE_SHOT_MAKEFILE'] = os.path.join(path, 'Android.mk')
+
+ cmd = [
+ 'make', '-C', android_build_top, '-f', 'build/core/main.mk',
+ 'MODULES-IN-' + path.replace('/', '-'), '-B'
+ ]
+ return not subprocess.Popen(cmd, stdout=None, stderr=None, env=env).wait()
diff --git a/utils/libcxx/android/compiler.py b/utils/libcxx/android/compiler.py
new file mode 100644
index 0000000..16ed44a
--- /dev/null
+++ b/utils/libcxx/android/compiler.py
@@ -0,0 +1,79 @@
+import copy
+import os
+import re
+import shlex
+import subprocess
+
+import libcxx.compiler
+
+
+class AndroidCXXCompiler(libcxx.compiler.CXXCompiler):
+ def __init__(self, cxx_under_test, cxx_template, link_template):
+ super(AndroidCXXCompiler, self).__init__(cxx_under_test)
+ self.cxx_template = cxx_template
+ self.link_template = link_template
+ self.build_top = os.getenv('ANDROID_BUILD_TOP')
+
+ def copy(self):
+ return copy.deepcopy(self)
+
+ def get_triple(self):
+ if 'clang' in self.path:
+ return self.get_clang_triple()
+ else:
+ return self.get_gcc_triple()
+
+ raise RuntimeError('Could not determine target triple.')
+
+ def get_clang_triple(self):
+ match = re.search(r'-target\s+(\S+)', self.cxx_template)
+ if match:
+ return match.group(1)
+ return None
+
+ def get_gcc_triple(self):
+ proc = subprocess.Popen([self.path, '-v'],
+ stderr=subprocess.PIPE)
+ _, stderr = proc.communicate()
+ for line in stderr.split('\n'):
+ print 'Checking {}'.format(line)
+ match = re.search(r'^Target: (.+)$', line)
+ if match:
+ return match.group(1)
+ return None
+
+ def compile(self, source_files, out=None, flags=None, cwd=None):
+ flags = [] if flags is None else flags
+ return super(AndroidCXXCompiler, self).compile(source_files, out, flags,
+ self.build_top)
+
+ def link(self, source_files, out=None, flags=None, cwd=None):
+ flags = [] if flags is None else flags
+ return super(AndroidCXXCompiler, self).link(source_files, out, flags,
+ self.build_top)
+
+ def compileCmd(self, source_files, out=None, flags=None):
+ if out is None:
+ raise RuntimeError('The Android compiler requires an out path.')
+
+ if isinstance(source_files, str):
+ source_files = [source_files]
+ cxx_args = self.cxx_template.replace('%OUT%', out)
+ cxx_args = cxx_args.replace('%SOURCE%', ' '.join(source_files))
+ return [self.path] + shlex.split(cxx_args)
+
+ def linkCmd(self, source_files, out=None, flags=None):
+ if out is None:
+ raise RuntimeError('The Android compiler requires an out path.')
+
+ if isinstance(source_files, str):
+ source_files = [source_files]
+ link_args = self.link_template.replace('%OUT%', out)
+ link_args = link_args.replace('%SOURCE%', ' '.join(source_files))
+ return [self.path] + shlex.split(link_args)
+
+ def _basicCmd(self, source_files, out, is_link=False, input_is_cxx=False):
+ raise NotImplementedError()
+
+ def _initTypeAndVersion(self):
+ pass
diff --git a/utils/libcxx/android/executors.py b/utils/libcxx/android/executors.py
new file mode 100644
index 0000000..4d9cb35
--- /dev/null
+++ b/utils/libcxx/android/executors.py
@@ -0,0 +1,75 @@
+import posixpath
+import random
+import time
+
+import libcxx.test.executor
+
+from libcxx.android import adb
+from lit.util import executeCommand # pylint: disable=import-error
+
+
+class AdbExecutor(libcxx.test.executor.RemoteExecutor):
+ def __init__(self, device_dir, serial=None):
+ # TODO(danalbert): Should factor out the shared pieces of SSHExecutor
+ # so we don't have this ugly parent constructor...
+ super(AdbExecutor, self).__init__()
+ self.device_dir = device_dir
+ self.serial = serial
+ self.local_run = executeCommand
+
+ def _remote_temp(self, is_dir):
+ # Android didn't have mktemp until M :(
+ # Just use a random number generator and hope for no collisions. Should
+ # be very unlikely for a 64-bit number.
+ test_dir_name = 'test.{}'.format(random.randrange(2 ** 64))
+ return posixpath.join(self.device_dir, test_dir_name)
+
+ def _copy_in_file(self, src, dst):
+ device_dirname = posixpath.dirname(dst)
+ device_temp_path = posixpath.join(device_dirname, 'temp.exe')
+ adb.push(src, device_temp_path)
+
+ # `adb push`ed executables can fail with ETXTBSY because adbd doesn't
+ # close file descriptors http://b.android.com/65857 before invoking the
+ # shell. Work around it by copying the file we just copied to a new
+ # location.
+ # ICS and Jelly Bean didn't have /system/bin/cp. Use cat :(
+ cmd = ['cat', device_temp_path, '>', dst, '&&', 'chmod', '777', dst]
+ _, out, err, exit_code = self._execute_command_remote(cmd)
+ if exit_code != 0:
+ raise RuntimeError('Failed to copy {} to {}:\n{}\n{}'.format(
+ src, dst, out, err))
+
+ def _execute_command_remote(self, cmd, remote_work_dir='.', env=None):
+ adb_cmd = ['adb', 'shell']
+ if self.serial:
+ adb_cmd.extend(['-s', self.serial])
+
+ delimiter = 'x'
+ probe_cmd = ' '.join(cmd) + '; echo {}$?'.format(delimiter)
+
+ env_cmd = []
+ if env is not None:
+ env_cmd = ['%s=%s' % (k, v) for k, v in env.items()]
+
+ remote_cmd = ' '.join(env_cmd + [probe_cmd])
+ if remote_work_dir != '.':
+ remote_cmd = 'cd {} && {}'.format(remote_work_dir, remote_cmd)
+
+ adb_cmd.append(remote_cmd)
+ out, err, exit_code = self.local_run(adb_cmd)
+ assert 'Text file busy' not in out and 'text busy' not in out
+ out, _, rc_str = out.rpartition(delimiter)
+ if rc_str == '':
+ result_text = 'Did not receive exit status from test.'
+ return adb_cmd, result_text, '', 1
+
+ out = out.strip()
+ exit_code = int(rc_str)
+ return adb_cmd, out, err, exit_code
+
+
+class NoopExecutor(libcxx.test.executor.Executor):
+ def run(self, exe_path, cmd=None, work_dir='.', file_deps=None, env=None):
+ cmd = cmd or [exe_path]
+ return (cmd, '', '', 0)
diff --git a/utils/libcxx/android/test/__init__.py b/utils/libcxx/android/test/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/utils/libcxx/android/test/__init__.py
diff --git a/utils/libcxx/android/test/config.py b/utils/libcxx/android/test/config.py
new file mode 100644
index 0000000..898d10b
--- /dev/null
+++ b/utils/libcxx/android/test/config.py
@@ -0,0 +1,88 @@
+import os
+import re
+
+import libcxx.test.config
+import libcxx.android.build
+import libcxx.android.compiler
+import libcxx.android.test.format
+
+
+class Configuration(libcxx.test.config.Configuration):
+ def __init__(self, lit_config, config):
+ super(Configuration, self).__init__(lit_config, config)
+ self.build_cmds_dir = None
+
+ def configure(self):
+ self.configure_src_root()
+ self.configure_build_cmds()
+ self.configure_obj_root()
+
+ self.configure_cxx()
+ self.configure_triple()
+ self.configure_features()
+
+ def print_config_info(self):
+ self.lit_config.note(
+ 'Using compiler: {}'.format(self.cxx.path))
+ self.lit_config.note(
+ 'Using compile template: {}'.format(self.cxx.cxx_template))
+ self.lit_config.note(
+ 'Using link template: {}'.format(self.cxx.link_template))
+ self.lit_config.note('Using available_features: %s' %
+ list(self.config.available_features))
+
+ def configure_obj_root(self):
+ test_config_file = os.path.join(self.build_cmds_dir, 'testconfig.mk')
+ if 'HOST_NATIVE_TEST' in open(test_config_file).read():
+ self.libcxx_obj_root = os.getenv('ANDROID_HOST_OUT')
+ else:
+ self.libcxx_obj_root = os.getenv('ANDROID_PRODUCT_OUT')
+
+ def configure_build_cmds(self):
+ os.chdir(self.config.android_root)
+ self.build_cmds_dir = 'external/libcxx/buildcmds'
+ if not libcxx.android.build.mm(self.build_cmds_dir,
+ self.config.android_root):
+ raise RuntimeError('Could not generate build commands.')
+
+ def configure_cxx(self):
+ cxx_under_test_file = os.path.join(self.build_cmds_dir,
+ 'cxx_under_test')
+ cxx_under_test = open(cxx_under_test_file).read().strip()
+
+ cxx_template_file = os.path.join(self.build_cmds_dir, 'cxx.cmds')
+ cxx_template = open(cxx_template_file).read().strip()
+
+ link_template_file = os.path.join(self.build_cmds_dir, 'link.cmds')
+ link_template = open(link_template_file).read().strip()
+
+ self.cxx = libcxx.android.compiler.AndroidCXXCompiler(
+ cxx_under_test, cxx_template, link_template)
+
+ def configure_triple(self):
+ self.config.target_triple = self.cxx.get_triple()
+
+ def configure_features(self):
+ self.config.available_features.add('long_tests')
+ std_pattern = re.compile(r'-std=(c\+\+\d[0-9x-z])')
+ match = std_pattern.search(self.cxx.cxx_template)
+ if match:
+ self.config.available_features.add(match.group(1))
+
+ def get_test_format(self):
+ mode = self.lit_config.params.get('android_mode', 'device')
+ if mode == 'device':
+ return libcxx.android.test.format.TestFormat(
+ self.cxx,
+ self.libcxx_src_root,
+ self.libcxx_obj_root,
+ getattr(self.config, 'device_dir', '/data/local/tmp/'),
+ getattr(self.config, 'timeout', '60'))
+ elif mode == 'host':
+ return libcxx.android.test.format.HostTestFormat(
+ self.cxx,
+ self.libcxx_src_root,
+ self.libcxx_obj_root,
+ getattr(self.config, 'timeout', '60'))
+ else:
+ raise RuntimeError('Invalid android_mode: {}'.format(mode))
diff --git a/utils/libcxx/android/test/format.py b/utils/libcxx/android/test/format.py
new file mode 100644
index 0000000..fb07282
--- /dev/null
+++ b/utils/libcxx/android/test/format.py
@@ -0,0 +1,65 @@
+import os
+
+import lit.util # pylint: disable=import-error
+
+from libcxx.android.executors import AdbExecutor, NoopExecutor
+from libcxx.test.executor import LocalExecutor, TimeoutExecutor
+import libcxx.test.format
+import libcxx.android.adb as adb
+
+
+class HostTestFormat(libcxx.test.format.LibcxxTestFormat):
+ # pylint: disable=super-init-not-called
+ def __init__(self, cxx, libcxx_src_root, libcxx_obj_root, timeout,
+ exec_env=None):
+ self.cxx = cxx
+ self.libcxx_src_root = libcxx_src_root
+ self.libcxx_obj_root = libcxx_obj_root
+ self.use_verify_for_fail = False
+ self.executor = TimeoutExecutor(timeout, LocalExecutor())
+
+ if exec_env is None:
+ # We need to use LD_LIBRARY_PATH because the build system's rpath
+ # is relative, which won't work since we're running from /tmp. We
+ # can either scan `cxx_under_test`/`link_template` to determine
+ # whether we're 32-bit or 64-bit, scan testconfig.mk, or just add
+ # both directories and let the linker sort it out. I'm choosing the
+ # lazy option.
+ outdir = os.getenv('ANDROID_HOST_OUT')
+ libpath = os.pathsep.join([
+ os.path.join(outdir, 'lib'),
+ os.path.join(outdir, 'lib64'),
+ ])
+ self.exec_env = {'LD_LIBRARY_PATH': libpath}
+ else:
+ self.exec_env = exec_env
+
+
+class TestFormat(HostTestFormat):
+ def __init__(self, cxx, libcxx_src_root, libcxx_obj_root, device_dir,
+ timeout, exec_env=None, build_only=False):
+ HostTestFormat.__init__(
+ self,
+ cxx,
+ libcxx_src_root,
+ libcxx_obj_root,
+ timeout,
+ exec_env)
+ self.device_dir = device_dir
+ self.build_only = build_only
+ if self.build_only:
+ self.executor = NoopExecutor()
+ else:
+ self.executor = AdbExecutor(device_dir)
+
+ def _working_directory(self, file_name):
+ return os.path.join(self.device_dir, file_name)
+
+ def _clean(self, exec_path):
+ exec_file = os.path.basename(exec_path)
+ cmd = ['adb', 'shell', 'rm', '-r', self._working_directory(exec_file)]
+ lit.util.executeCommand(cmd)
+ try:
+ os.remove(exec_path)
+ except OSError:
+ pass
diff --git a/utils/libcxx/ndk/__init__.py b/utils/libcxx/ndk/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/utils/libcxx/ndk/__init__.py
diff --git a/utils/libcxx/ndk/test/__init__.py b/utils/libcxx/ndk/test/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/utils/libcxx/ndk/test/__init__.py
diff --git a/utils/libcxx/ndk/test/config.py b/utils/libcxx/ndk/test/config.py
new file mode 100644
index 0000000..4aa6045
--- /dev/null
+++ b/utils/libcxx/ndk/test/config.py
@@ -0,0 +1,146 @@
+import os
+
+import lit.util # pylint: disable=import-error
+
+import libcxx.test.config
+import libcxx.test.target_info
+import libcxx.android.build
+import libcxx.ndk.test.format
+
+
+class AndroidTargetInfo(libcxx.test.target_info.DefaultTargetInfo):
+ def platform(self):
+ return 'android'
+
+ def system(self):
+ raise NotImplementedError
+
+ def add_cxx_compile_flags(self, flags):
+ flags.extend(['-D__STDC_FORMAT_MACROS'])
+
+ def platform_ver(self):
+ raise NotImplementedError
+
+ def platform_name(self):
+ raise NotImplementedError
+
+ def supports_locale(self, loc):
+ raise NotImplementedError
+
+
+class Configuration(libcxx.test.config.Configuration):
+ def __init__(self, lit_config, config):
+ super(Configuration, self).__init__(lit_config, config)
+ self.cxx_under_test = None
+ self.build_cmds_dir = None
+ self.cxx_template = None
+ self.link_template = None
+ self.with_availability = False
+
+ def configure(self):
+ self.configure_target_info()
+ self.configure_cxx()
+ self.configure_triple()
+ self.configure_src_root()
+ self.configure_obj_root()
+ self.configure_cxx_stdlib_under_test()
+ self.configure_cxx_library_root()
+ self.configure_compile_flags()
+ self.configure_link_flags()
+ self.configure_features()
+
+ def configure_target_info(self):
+ self.target_info = AndroidTargetInfo(self)
+
+ def configure_compile_flags(self):
+ super(Configuration, self).configure_compile_flags()
+
+ arch = self.get_lit_conf('arch')
+ api = int(self.get_lit_conf('api'))
+
+ sysroot = os.path.join(os.environ['NDK'], 'sysroot')
+ self.cxx.compile_flags.extend(['--sysroot', sysroot])
+
+ triple = self.get_lit_conf('target_triple')
+ header_triple = triple.rstrip('0123456789')
+ header_triple = header_triple.replace('armv7', 'arm')
+ arch_includes = os.path.join(sysroot, 'usr/include', header_triple)
+ self.cxx.compile_flags.extend(['-isystem', arch_includes])
+
+ self.cxx.compile_flags.append('-D__ANDROID_API__={}'.format(api))
+
+ if arch == 'arm':
+ self.cxx.flags.extend([
+ '-march=armv7-a',
+ '-mfloat-abi=softfp',
+ '-mfpu=vfpv3-d16',
+ '-mthumb',
+ ])
+
+ if api < 21:
+ android_support_headers = os.path.join(
+ os.environ['NDK'], 'sources/android/support/include')
+ self.cxx.compile_flags.append('-I' + android_support_headers)
+
+ def configure_link_flags(self):
+ self.cxx.link_flags.append('-nodefaultlibs')
+
+ arch = self.get_lit_conf('arch')
+ api = int(self.get_lit_conf('api'))
+
+ sysroot_path = 'platforms/android-{}/arch-{}'.format(api, arch)
+ platform_sysroot = os.path.join(os.environ['NDK'], sysroot_path)
+ self.cxx.link_flags.extend(['--sysroot', platform_sysroot])
+
+ # Configure libc++ library paths.
+ self.cxx.link_flags.append('-L' + self.cxx_library_root)
+
+ self.cxx.link_flags.append('-nostdlib++')
+
+ gcc_toolchain = self.get_lit_conf('gcc_toolchain')
+ self.cxx.link_flags.append('-gcc-toolchain')
+ self.cxx.link_flags.append(gcc_toolchain)
+
+ if api < 21:
+ self.cxx.link_flags.append('-landroid_support')
+ triple = self.get_lit_conf('target_triple')
+ if triple.startswith('arm-') or triple.startswith('armv7-'):
+ self.cxx.link_flags.append('-lunwind')
+ self.cxx.link_flags.append('-Wl,--exclude-libs,libunwind.a')
+
+ self.cxx.link_flags.append('-lcompiler_rt-extras')
+ self.cxx.link_flags.append(
+ '-Wl,--exclude-libs,libcompiler_rt-extras.a')
+
+ self.cxx.link_flags.append('-latomic')
+ self.cxx.link_flags.append('-Wl,--exclude-libs,libatomic.a')
+
+ self.cxx.link_flags.append('-lgcc')
+ self.cxx.link_flags.append('-Wl,--exclude-libs,libgcc.a')
+
+ self.cxx.link_flags.append('-lc++_shared')
+ self.cxx.link_flags.append('-lc')
+ self.cxx.link_flags.append('-lm')
+ self.cxx.link_flags.append('-ldl')
+ self.cxx.link_flags.append('-pie')
+
+ def configure_features(self):
+ self.config.available_features.add(self.get_lit_conf('std'))
+ self.config.available_features.add('long_tests')
+
+ def get_test_format(self):
+ # Note that we require that the caller has cleaned this directory,
+ # ensured its existence, and copied libc++_shared.so into it.
+ tmp_dir = getattr(self.config, 'device_dir', '/data/local/tmp/libcxx')
+ build_only = self.get_lit_conf('build_only', False)
+ build_dir = self.get_lit_conf('build_dir')
+
+ return libcxx.ndk.test.format.TestFormat(
+ self.cxx,
+ self.libcxx_src_root,
+ self.libcxx_obj_root,
+ build_dir,
+ tmp_dir,
+ getattr(self.config, 'timeout', '300'),
+ exec_env={'LD_LIBRARY_PATH': tmp_dir},
+ build_only=build_only)
diff --git a/utils/libcxx/ndk/test/format.py b/utils/libcxx/ndk/test/format.py
new file mode 100644
index 0000000..50485d4
--- /dev/null
+++ b/utils/libcxx/ndk/test/format.py
@@ -0,0 +1,53 @@
+"""Test format for the NDK tests."""
+import os
+
+import libcxx.android.test.format
+import lit.util # pylint: disable=import-error
+
+
+def prune_xfails(test):
+ """Removes most xfail handling from tests.
+
+ We need to keep some xfail handling because some tests in libc++ that
+ really should be using REQUIRES actually used XFAIL (i.e. `XFAIL: c++11`).
+ """
+ test.xfails = [x for x in test.xfails if x.startswith('c++')]
+
+
+class TestFormat(libcxx.android.test.format.TestFormat):
+ """Loose wrapper around the Android format that disables XFAIL handling."""
+
+ # pylint: disable=too-many-arguments
+ def __init__(self, cxx, libcxx_src_root, libcxx_obj_root, build_dir,
+ device_dir, timeout, exec_env=None, build_only=False):
+ libcxx.android.test.format.TestFormat.__init__(
+ self,
+ cxx,
+ libcxx_src_root,
+ libcxx_obj_root,
+ device_dir,
+ timeout,
+ exec_env,
+ build_only)
+ self.build_dir = build_dir
+
+ def _evaluate_pass_test(self, test, tmp_base, lit_config, test_cxx,
+ parsers):
+ """Clears the test's xfail list before delegating to the parent."""
+ prune_xfails(test)
+ tmp_base = os.path.join(self.build_dir, *test.path_in_suite)
+ return super(TestFormat, self)._evaluate_pass_test(
+ test, tmp_base, lit_config, test_cxx, parsers)
+
+ def _evaluate_fail_test(self, test, test_cxx, parsers):
+ """Clears the test's xfail list before delegating to the parent."""
+ prune_xfails(test)
+ return super(TestFormat, self)._evaluate_fail_test(
+ test, test_cxx, parsers)
+
+ def _clean(self, exec_path):
+ exec_file = os.path.basename(exec_path)
+ if not self.build_only:
+ device_path = self._working_directory(exec_file)
+ cmd = ['adb', 'shell', 'rm', '-r', device_path]
+ lit.util.executeCommand(cmd)