普通文本  |  199行  |  3.91 KB

//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// Test asan vector annotations with a class that throws in a CTOR.

#include <vector>
#include <cassert>

#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;
};

void test_push_back() {
  std::vector<X> 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_emplace_back() {
#ifndef _LIBCPP_HAS_NO_VARIADICS
  std::vector<X> v;
  v.reserve(2);
  v.push_back(X(2));
  assert(v.size() == 1);
  try {
    v.emplace_back(42);
    assert(0);
  } catch (int e) {
    assert(v.size() == 1);
  }
  assert(v.size() == 1);
  assert(is_contiguous_container_asan_correct(v));
#endif // _LIBCPP_HAS_NO_VARIADICS
}

void test_insert_range() {
  std::vector<X> 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() == 3);
  }
  assert(v.size() == 3);
  assert(is_contiguous_container_asan_correct(v));
}

void test_insert() {
  std::vector<X> 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_emplace() {
#ifndef _LIBCPP_HAS_NO_VARIADICS
  std::vector<X> v;
  v.reserve(3);
  v.insert(v.end(), X(1));
  v.insert(v.begin(), X(2));
  assert(v.size() == 2);
  try {
    v.emplace(v.end(), 42);
    assert(0);
  } catch (int e) {
    assert(v.size() == 2);
  }
  assert(v.size() == 2);
  assert(is_contiguous_container_asan_correct(v));
#endif // _LIBCPP_HAS_NO_VARIADICS
}

void test_insert_range2() {
  std::vector<X> 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<X> 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_resize() {
  std::vector<X> 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<X> 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() {
  test_push_back();
  test_emplace_back();
  test_insert_range();
  test_insert();
  test_emplace();
  test_insert_range2();
  test_insert_n();
  test_resize();
  test_resize_param();
}