//===----------------------------------------------------------------------===// // // 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 // //===----------------------------------------------------------------------===// // UNSUPPORTED: no-exceptions // Test asan vector annotations with a class that throws in a CTOR. #include #include #include "test_macros.h" #include "asan_testing.h" class X { public: X(const X& x) { Init(x.a); } X(char arg) { Init(arg); } X() { Init(42); } X& operator=(const X& x) { Init(x.a); return *this; } void Init(char arg) { if (arg == 42) throw 0; if (arg == 66) arg = 42; a = arg; } char get() const { return a; } void set(char arg) { a = arg; } private: char a; }; class ThrowOnCopy { public: ThrowOnCopy() : should_throw(false) {} explicit ThrowOnCopy(bool xshould_throw) : should_throw(xshould_throw) {} ThrowOnCopy(ThrowOnCopy const& other) : should_throw(other.should_throw) { if (should_throw) { throw 0; } } ThrowOnCopy& operator=(ThrowOnCopy const&) = default; bool should_throw; }; void test_push_back() { std::vector v; v.reserve(2); v.push_back(X(2)); assert(v.size() == 1); try { v.push_back(X(66)); assert(0); } catch (int e) { assert(v.size() == 1); } assert(v.size() == 1); assert(is_contiguous_container_asan_correct(v)); } void test_insert_range() { std::vector v; v.reserve(4); v.push_back(X(1)); v.push_back(X(2)); assert(v.size() == 2); assert(v.capacity() >= 4); try { char a[2] = {21, 42}; v.insert(v.end(), a, a + 2); assert(0); } catch (int e) { assert(v.size() == 2); } assert(v.size() == 2); assert(is_contiguous_container_asan_correct(v)); } void test_insert() { std::vector v; v.reserve(3); v.insert(v.end(), X(1)); v.insert(v.begin(), X(2)); assert(v.size() == 2); try { v.insert(v.end(), X(66)); assert(0); } catch (int e) { assert(v.size() == 2); } assert(v.size() == 2); assert(is_contiguous_container_asan_correct(v)); } void test_insert_range2() { std::vector v; v.reserve(4); v.insert(v.end(), X(1)); v.insert(v.begin(), X(2)); assert(v.size() == 2); assert(v.capacity() >= 4); try { char a[2] = {10, 42}; v.insert(v.begin(), a, a + 2); assert(0); } catch (int e) { assert(v.size() <= 4); assert(is_contiguous_container_asan_correct(v)); return; } assert(0); } void test_insert_n() { std::vector v; v.reserve(10); v.insert(v.end(), X(1)); v.insert(v.begin(), X(2)); assert(v.size() == 2); try { v.insert(v.begin(), 1, X(66)); assert(0); } catch (int e) { assert(v.size() <= 3); assert(is_contiguous_container_asan_correct(v)); return; } assert(0); } void test_insert_n2() { std::vector v(10); v.reserve(100); assert(v.size() == 10); v[6].should_throw = true; try { v.insert(v.cbegin(), 5, ThrowOnCopy()); assert(0); } catch (int e) { assert(v.size() == 11); assert(is_contiguous_container_asan_correct(v)); return; } assert(0); } void test_resize() { std::vector v; v.reserve(3); v.push_back(X(0)); try { v.resize(3); assert(0); } catch (int e) { assert(v.size() == 1); } assert(v.size() == 1); assert(is_contiguous_container_asan_correct(v)); } void test_resize_param() { std::vector v; v.reserve(3); v.push_back(X(0)); try { v.resize(3, X(66)); assert(0); } catch (int e) { assert(v.size() == 1); } assert(v.size() == 1); assert(is_contiguous_container_asan_correct(v)); } int main(int, char**) { test_push_back(); test_insert_range(); test_insert(); test_insert_range2(); test_insert_n(); test_insert_n2(); test_resize(); test_resize_param(); return 0; }