| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| // RUN: %clang -target arm64-apple-xros1 -c -### %s 2>&1 | FileCheck --check-prefix=VERSION1 %s | ||
| // RUN: %clang -target arm64-apple-xros -c -### %s 2>&1 | FileCheck --check-prefix=VERSION1 %s | ||
|
|
||
| // RUN: %clang -target arm64-apple-xros1-simulator -c -### %s 2>&1 | FileCheck --check-prefix=VERSION1_ASi %s | ||
|
|
||
| // RUN: not %clang -target arm64-apple-xros1000 -c -### %s 2>&1 | FileCheck --check-prefix=INVALID-VERSION %s | ||
|
|
||
| // RUN: %clang -target arm64-apple-xros1 -### %s 2>&1 | FileCheck --check-prefix=LINK %s | ||
| // RUN: %clang -target arm64-apple-xros1-simulator -### %s 2>&1 | FileCheck --check-prefix=LINK-SIM %s | ||
|
|
||
| // RUN: %clang -target arm64-apple-xros1 -c -x objective-c -fobjc-arc -### %s 2>&1 | FileCheck --check-prefix=ARC %s | ||
| // RUN: %clang -target arm64-apple-xros -c -x objective-c -fobjc-arc -### %s 2>&1 | FileCheck --check-prefix=OBJC-RUNTIME %s | ||
| // RUN: %clang -target arm64-apple-xros2 -c -x objective-c -fobjc-arc -### %s 2>&1 | FileCheck --check-prefix=OBJC-RUNTIME2 %s | ||
|
|
||
| // RUN: %clang -target arm64-apple-xros1 -c -x objective-c -fobjc-arc -### %s 2>&1 | FileCheck --check-prefix=ARC %s | ||
| // RUN: %clang -target arm64-apple-xros1-simulator -c -x objective-c -fobjc-arc -### %s 2>&1 | FileCheck --check-prefix=ARC %s | ||
|
|
||
| // RUN: %clang -target arm64-apple-xros -c -### %s 2>&1 | FileCheck --check-prefix=SSP_ON %s | ||
|
|
||
| // RUN: %clang -target arm64e-apple-xros -c -### %s 2>&1 | FileCheck --check-prefix=CPU-ARM64E %s | ||
| // RUN: %clang -target arm64-apple-xros -c -### %s 2>&1 | FileCheck --check-prefix=CPU-ARM64 %s | ||
| // RUN: %clang -target arm64-apple-xros-simulator -c -### %s 2>&1 | FileCheck --check-prefix=CPU-ARM64-SIM %s | ||
|
|
||
| // VERSION1: "-cc1"{{.*}} "-triple" "arm64-apple-xros1.0.0" | ||
| // VERSION1_ASi: "-cc1"{{.*}} "-triple" "arm64-apple-xros1.0.0-simulator" | ||
| // INVALID-VERSION: error: invalid version number in | ||
|
|
||
| // VERSION1-NOT: -faligned-alloc-unavailable | ||
|
|
||
| // LINK: "-platform_version" "xros" "1.0.0" "1.0.0" | ||
| // LINK-SIM: "-platform_version" "xros-simulator" "1.0.0" "1.0.0" | ||
|
|
||
| // OBJC-RUNTIME: "-fobjc-runtime=ios-17.0.0.0" | ||
| // OBJC-RUNTIME2: "-fobjc-runtime=ios-18.0.0.0" | ||
| // ARC-NOT: error: | ||
|
|
||
| // SSP_ON: "-stack-protector" "1" | ||
|
|
||
| // CPU-ARM64E: "-cc1"{{.*}} "-triple" "arm64e-apple-xros1.0.0"{{.*}} "-target-cpu" "apple-a12"{{.*}} | ||
| // CPU-ARM64: "-cc1"{{.*}} "-triple" "arm64-apple-xros1.0.0"{{.*}} "-target-cpu" "apple-a12" | ||
| // CPU-ARM64-SIM: "-cc1"{{.*}} "-triple" "arm64-apple-xros1.0.0-simulator"{{.*}} "-target-cpu" "apple-m1" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| // RUN: %clang_cc1 -triple arm64-apple-xros1 -dM -E -o - %s | FileCheck %s | ||
|
|
||
| // CHECK: __ENVIRONMENT_OS_VERSION_MIN_REQUIRED__ 10000 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,182 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // REQUIRES: asan | ||
| // UNSUPPORTED: c++03 | ||
|
|
||
| #include <cassert> | ||
| #include <string> | ||
| #include <array> | ||
| #include <deque> | ||
| #include "test_macros.h" | ||
| #include "asan_testing.h" | ||
| #include "min_allocator.h" | ||
|
|
||
| // This tests exists to check if strings work well with deque, as those | ||
| // may be partialy annotated, we cannot simply call | ||
| // is_double_ended_contiguous_container_asan_correct, as it assumes that | ||
| // object memory inside is not annotated, so we check everything in a more careful way. | ||
|
|
||
| template <typename D> | ||
| void verify_inside(D const& d) { | ||
| for (size_t i = 0; i < d.size(); ++i) { | ||
| assert(is_string_asan_correct(d[i])); | ||
| } | ||
| } | ||
|
|
||
| template <typename S, size_t N> | ||
| S get_s(char c) { | ||
| S s; | ||
| for (size_t i = 0; i < N; ++i) | ||
| s.push_back(c); | ||
|
|
||
| return s; | ||
| } | ||
|
|
||
| template <class C, class S> | ||
| void test_string() { | ||
| size_t const N = sizeof(S) < 256 ? (4096 / sizeof(S)) : 16; | ||
|
|
||
| { | ||
| C d1a(1), d1b(N), d1c(N + 1), d1d(32 * N); | ||
| verify_inside(d1a); | ||
| verify_inside(d1b); | ||
| verify_inside(d1c); | ||
| verify_inside(d1d); | ||
| } | ||
| { | ||
| C d2; | ||
| for (size_t i = 0; i < 16 * N; ++i) { | ||
| d2.push_back(get_s<S, 1>(i % 10 + 'a')); | ||
| verify_inside(d2); | ||
| d2.push_back(get_s<S, 222>(i % 10 + 'b')); | ||
| verify_inside(d2); | ||
|
|
||
| d2.pop_front(); | ||
| verify_inside(d2); | ||
| } | ||
| } | ||
| { | ||
| C d3; | ||
| for (size_t i = 0; i < 16 * N; ++i) { | ||
| d3.push_front(get_s<S, 1>(i % 10 + 'a')); | ||
| verify_inside(d3); | ||
| d3.push_front(get_s<S, 222>(i % 10 + 'b')); | ||
| verify_inside(d3); | ||
|
|
||
| d3.pop_back(); | ||
| verify_inside(d3); | ||
| } | ||
| } | ||
| { | ||
| C d4; | ||
| for (size_t i = 0; i < 16 * N; ++i) { | ||
| // When there is no SSO, all elements inside should not be poisoned, | ||
| // so we can verify deque poisoning. | ||
| d4.push_front(get_s<S, 333>(i % 10 + 'a')); | ||
| verify_inside(d4); | ||
| assert(is_double_ended_contiguous_container_asan_correct(d4)); | ||
| d4.push_back(get_s<S, 222>(i % 10 + 'b')); | ||
| verify_inside(d4); | ||
| assert(is_double_ended_contiguous_container_asan_correct(d4)); | ||
| } | ||
| } | ||
| { | ||
| C d5; | ||
| for (size_t i = 0; i < 5 * N; ++i) { | ||
| // In d4 we never had poisoned memory inside deque. | ||
| // Here we start with SSO, so part of the inside of the container, | ||
| // will be poisoned. | ||
| d5.push_front(S()); | ||
| verify_inside(d5); | ||
| } | ||
| for (size_t i = 0; i < d5.size(); ++i) { | ||
| // We change the size to have long string. | ||
| // Memory owne by deque should not be poisoned by string. | ||
| d5[i].resize(1000); | ||
| verify_inside(d5); | ||
| } | ||
|
|
||
| assert(is_double_ended_contiguous_container_asan_correct(d5)); | ||
|
|
||
| d5.erase(d5.begin() + 2); | ||
| verify_inside(d5); | ||
|
|
||
| d5.erase(d5.end() - 2); | ||
| verify_inside(d5); | ||
|
|
||
| assert(is_double_ended_contiguous_container_asan_correct(d5)); | ||
| } | ||
| { | ||
| C d6a; | ||
| assert(is_double_ended_contiguous_container_asan_correct(d6a)); | ||
|
|
||
| C d6b(N + 2, get_s<S, 1000>('a')); | ||
| d6b.push_front(get_s<S, 1001>('b')); | ||
| while (!d6b.empty()) { | ||
| d6b.pop_back(); | ||
| assert(is_double_ended_contiguous_container_asan_correct(d6b)); | ||
| } | ||
|
|
||
| C d6c(N + 2, get_s<S, 1002>('c')); | ||
| while (!d6c.empty()) { | ||
| d6c.pop_back(); | ||
| assert(is_double_ended_contiguous_container_asan_correct(d6c)); | ||
| } | ||
| } | ||
| { | ||
| C d7(9 * N + 2); | ||
|
|
||
| d7.insert(d7.begin() + 1, S()); | ||
| verify_inside(d7); | ||
|
|
||
| d7.insert(d7.end() - 3, S()); | ||
| verify_inside(d7); | ||
|
|
||
| d7.insert(d7.begin() + 2 * N, get_s<S, 1>('a')); | ||
| verify_inside(d7); | ||
|
|
||
| d7.insert(d7.end() - 2 * N, get_s<S, 1>('b')); | ||
| verify_inside(d7); | ||
|
|
||
| d7.insert(d7.begin() + 2 * N, 3 * N, get_s<S, 1>('c')); | ||
| verify_inside(d7); | ||
|
|
||
| // It may not be short for big element types, but it will be checked correctly: | ||
| d7.insert(d7.end() - 2 * N, 3 * N, get_s<S, 2>('d')); | ||
| verify_inside(d7); | ||
|
|
||
| d7.erase(d7.begin() + 2); | ||
| verify_inside(d7); | ||
|
|
||
| d7.erase(d7.end() - 2); | ||
| verify_inside(d7); | ||
| } | ||
| } | ||
|
|
||
| template <class S> | ||
| void test_container() { | ||
| test_string<std::deque<S, std::allocator<S>>, S>(); | ||
| test_string<std::deque<S, min_allocator<S>>, S>(); | ||
| test_string<std::deque<S, safe_allocator<S>>, S>(); | ||
| } | ||
|
|
||
| int main(int, char**) { | ||
| // Those tests support only types based on std::basic_string. | ||
| test_container<std::string>(); | ||
| test_container<std::wstring>(); | ||
| #if TEST_STD_VER >= 11 | ||
| test_container<std::u16string>(); | ||
| test_container<std::u32string>(); | ||
| #endif | ||
| #if TEST_STD_VER >= 20 | ||
| test_container<std::u8string>(); | ||
| #endif | ||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // REQUIRES: asan | ||
| // UNSUPPORTED: c++03 | ||
|
|
||
| // <string> | ||
|
|
||
| // Basic test if ASan annotations work for short strings. | ||
|
|
||
| #include <string> | ||
| #include <cassert> | ||
| #include <cstdlib> | ||
|
|
||
| #include "asan_testing.h" | ||
| #include "min_allocator.h" | ||
| #include "test_iterators.h" | ||
| #include "test_macros.h" | ||
|
|
||
| extern "C" void __sanitizer_set_death_callback(void (*callback)(void)); | ||
|
|
||
| void do_exit() { exit(0); } | ||
|
|
||
| int main(int, char**) { | ||
| { | ||
| typedef cpp17_input_iterator<char*> MyInputIter; | ||
| // Should not trigger ASan. | ||
| std::basic_string<char, std::char_traits<char>, safe_allocator<char>> v; | ||
| char i[] = {'a', 'b', 'c', 'd'}; | ||
|
|
||
| v.insert(v.begin(), MyInputIter(i), MyInputIter(i + 4)); | ||
| assert(v[0] == 'a'); | ||
| assert(is_string_asan_correct(v)); | ||
| } | ||
|
|
||
| __sanitizer_set_death_callback(do_exit); | ||
| { | ||
| using T = char; | ||
| using C = std::basic_string<T, std::char_traits<T>, safe_allocator<T>>; | ||
| const T t[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g'}; | ||
| C c(std::begin(t), std::end(t)); | ||
| assert(is_string_asan_correct(c)); | ||
| assert(__sanitizer_verify_contiguous_container(c.data(), c.data() + c.size() + 1, c.data() + c.capacity() + 1) != | ||
| 0); | ||
| volatile T foo = c[c.size() + 1]; // should trigger ASAN. Use volatile to prevent being optimized away. | ||
| assert(false); // if we got here, ASAN didn't trigger | ||
| ((void)foo); | ||
| } | ||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,182 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // REQUIRES: asan | ||
| // UNSUPPORTED: c++03 | ||
|
|
||
| #include <cassert> | ||
| #include <string> | ||
| #include <vector> | ||
| #include <array> | ||
| #include "test_macros.h" | ||
| #include "asan_testing.h" | ||
| #include "min_allocator.h" | ||
|
|
||
| // This tests exists to check if strings work well with vector, as those | ||
| // may be partialy annotated, we cannot simply call | ||
| // is_contiguous_container_asan_correct, as it assumes that | ||
| // object memory inside is not annotated, so we check everything in a more careful way. | ||
|
|
||
| template <typename D> | ||
| void verify_inside(D const& d) { | ||
| for (size_t i = 0; i < d.size(); ++i) { | ||
| assert(is_string_asan_correct(d[i])); | ||
| } | ||
| } | ||
|
|
||
| template <typename S, size_t N> | ||
| S get_s(char c) { | ||
| S s; | ||
| for (size_t i = 0; i < N; ++i) | ||
| s.push_back(c); | ||
|
|
||
| return s; | ||
| } | ||
|
|
||
| template <class C, class S> | ||
| void test_string() { | ||
| size_t const N = sizeof(S) < 256 ? (4096 / sizeof(S)) : 16; | ||
|
|
||
| { | ||
| C d1a(1), d1b(N), d1c(N + 1), d1d(32 * N); | ||
| verify_inside(d1a); | ||
| verify_inside(d1b); | ||
| verify_inside(d1c); | ||
| verify_inside(d1d); | ||
| } | ||
| { | ||
| C d2; | ||
| for (size_t i = 0; i < 16 * N; ++i) { | ||
| d2.push_back(get_s<S, 1>(i % 10 + 'a')); | ||
| verify_inside(d2); | ||
| d2.push_back(get_s<S, 222>(i % 10 + 'b')); | ||
| verify_inside(d2); | ||
|
|
||
| d2.erase(d2.cbegin()); | ||
| verify_inside(d2); | ||
| } | ||
| } | ||
| { | ||
| C d3; | ||
| for (size_t i = 0; i < 16 * N; ++i) { | ||
| d3.push_back(get_s<S, 1>(i % 10 + 'a')); | ||
| verify_inside(d3); | ||
| d3.push_back(get_s<S, 222>(i % 10 + 'b')); | ||
| verify_inside(d3); | ||
|
|
||
| d3.pop_back(); | ||
| verify_inside(d3); | ||
| } | ||
| } | ||
| { | ||
| C d4; | ||
| for (size_t i = 0; i < 16 * N; ++i) { | ||
| // When there is no SSO, all elements inside should not be poisoned, | ||
| // so we can verify vector poisoning. | ||
| d4.push_back(get_s<S, 333>(i % 10 + 'a')); | ||
| verify_inside(d4); | ||
| assert(is_contiguous_container_asan_correct(d4)); | ||
| d4.push_back(get_s<S, 222>(i % 10 + 'b')); | ||
| verify_inside(d4); | ||
| assert(is_contiguous_container_asan_correct(d4)); | ||
| } | ||
| } | ||
| { | ||
| C d5; | ||
| for (size_t i = 0; i < 5 * N; ++i) { | ||
| // In d4 we never had poisoned memory inside vector. | ||
| // Here we start with SSO, so part of the inside of the container, | ||
| // will be poisoned. | ||
| d5.push_back(S()); | ||
| verify_inside(d5); | ||
| } | ||
| for (size_t i = 0; i < d5.size(); ++i) { | ||
| // We change the size to have long string. | ||
| // Memory owne by vector should not be poisoned by string. | ||
| d5[i].resize(1000); | ||
| verify_inside(d5); | ||
| } | ||
|
|
||
| assert(is_contiguous_container_asan_correct(d5)); | ||
|
|
||
| d5.erase(d5.begin() + 2); | ||
| verify_inside(d5); | ||
|
|
||
| d5.erase(d5.end() - 2); | ||
| verify_inside(d5); | ||
|
|
||
| assert(is_contiguous_container_asan_correct(d5)); | ||
| } | ||
| { | ||
| C d6a; | ||
| assert(is_contiguous_container_asan_correct(d6a)); | ||
|
|
||
| C d6b(N + 2, get_s<S, 1000>('a')); | ||
| d6b.push_back(get_s<S, 1001>('b')); | ||
| while (!d6b.empty()) { | ||
| d6b.pop_back(); | ||
| assert(is_contiguous_container_asan_correct(d6b)); | ||
| } | ||
|
|
||
| C d6c(N + 2, get_s<S, 1002>('c')); | ||
| while (!d6c.empty()) { | ||
| d6c.pop_back(); | ||
| assert(is_contiguous_container_asan_correct(d6c)); | ||
| } | ||
| } | ||
| { | ||
| C d7(9 * N + 2); | ||
|
|
||
| d7.insert(d7.begin() + 1, S()); | ||
| verify_inside(d7); | ||
|
|
||
| d7.insert(d7.end() - 3, S()); | ||
| verify_inside(d7); | ||
|
|
||
| d7.insert(d7.begin() + 2 * N, get_s<S, 1>('a')); | ||
| verify_inside(d7); | ||
|
|
||
| d7.insert(d7.end() - 2 * N, get_s<S, 1>('b')); | ||
| verify_inside(d7); | ||
|
|
||
| d7.insert(d7.begin() + 2 * N, 3 * N, get_s<S, 1>('c')); | ||
| verify_inside(d7); | ||
|
|
||
| // It may not be short for big element types, but it will be checked correctly: | ||
| d7.insert(d7.end() - 2 * N, 3 * N, get_s<S, 2>('d')); | ||
| verify_inside(d7); | ||
|
|
||
| d7.erase(d7.begin() + 2); | ||
| verify_inside(d7); | ||
|
|
||
| d7.erase(d7.end() - 2); | ||
| verify_inside(d7); | ||
| } | ||
| } | ||
|
|
||
| template <class S> | ||
| void test_container() { | ||
| test_string<std::vector<S, std::allocator<S>>, S>(); | ||
| test_string<std::vector<S, min_allocator<S>>, S>(); | ||
| test_string<std::vector<S, safe_allocator<S>>, S>(); | ||
| } | ||
|
|
||
| int main(int, char**) { | ||
| // Those tests support only types based on std::basic_string. | ||
| test_container<std::string>(); | ||
| test_container<std::wstring>(); | ||
| #if TEST_STD_VER >= 11 | ||
| test_container<std::u16string>(); | ||
| test_container<std::u32string>(); | ||
| #endif | ||
| #if TEST_STD_VER >= 20 | ||
| test_container<std::u8string>(); | ||
| #endif | ||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| // -*- C++ -*- | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef _LIBCPP___ASSERTION_HANDLER | ||
| #define _LIBCPP___ASSERTION_HANDLER | ||
|
|
||
| #include <__config> | ||
| #include <__verbose_abort> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| # pragma GCC system_header | ||
| #endif | ||
|
|
||
| // TODO(hardening): in production, trap rather than abort. | ||
| #define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_VERBOSE_ABORT("%s", message) | ||
|
|
||
| #endif // _LIBCPP___ASSERTION_HANDLER |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| //===- llvm/CodeGen/GlobalMerge.h -------------------------------*- C++ -*-===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LLVM_CODEGEN_GLOBALMERGE_H | ||
| #define LLVM_CODEGEN_GLOBALMERGE_H | ||
|
|
||
| #include "llvm/IR/PassManager.h" | ||
|
|
||
| namespace llvm { | ||
|
|
||
| class TargetMachine; | ||
|
|
||
| struct GlobalMergeOptions { | ||
| // FIXME: Infer the maximum possible offset depending on the actual users | ||
| // (these max offsets are different for the users inside Thumb or ARM | ||
| // functions), see the code that passes in the offset in the ARM backend | ||
| // for more information. | ||
| unsigned MaxOffset = 0; | ||
| bool GroupByUse = true; | ||
| bool IgnoreSingleUse = true; | ||
| bool MergeConst = false; | ||
| /// Whether we should merge global variables that have external linkage. | ||
| bool MergeExternal = true; | ||
| /// Whether we should try to optimize for size only. | ||
| /// Currently, this applies a dead simple heuristic: only consider globals | ||
| /// used in minsize functions for merging. | ||
| /// FIXME: This could learn about optsize, and be used in the cost model. | ||
| bool SizeOnly = false; | ||
| }; | ||
|
|
||
| // FIXME: This pass must run before AsmPrinterPass::doInitialization! | ||
| class GlobalMergePass : public PassInfoMixin<GlobalMergePass> { | ||
| const TargetMachine *TM; | ||
| GlobalMergeOptions Options; | ||
|
|
||
| public: | ||
| GlobalMergePass(const TargetMachine *TM, GlobalMergeOptions Options) | ||
| : TM(TM), Options(Options) {} | ||
|
|
||
| PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); | ||
| }; | ||
|
|
||
| } // namespace llvm | ||
|
|
||
| #endif // LLVM_CODEGEN_GLOBALMERGE_H |