brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.2 KiB · e24ce66 Raw
341 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++1410// UNSUPPORTED: no-exceptions11// `check_assertion.h` requires Unix headers and regex support.12// REQUIRES: has-unix-headers13// UNSUPPORTED: no-localization14 15// UNSUPPORTED: libcpp-has-no-incomplete-pstl16 17// <algorithm>18// <numeric>19//20// Check that PSTL algorithms terminate on user-thrown exceptions.21 22#include <algorithm>23#include <numeric>24 25#include "check_assertion.h"26#include "test_execution_policies.h"27#include "test_iterators.h"28 29template <class F>30void assert_non_throwing(F f) {31  // We wrap this whole test in EXPECT_STD_TERMINATE because if f() terminates, we want the test to pass,32  // since this signals proper handling of user exceptions in the PSTL.33  EXPECT_STD_TERMINATE([&] {34    bool threw = false;35    try {36      f();37    } catch (...) {38      threw = true;39    }40    // If nothing was thrown, call std::terminate() to pass the EXPECT_STD_TERMINATE assertion.41    // Otherwise, don't call std::terminate() to fail the assertion.42    if (!threw)43      std::terminate();44  });45}46 47struct ThrowToken {48  void activate() { active_ = true; }49  void deactivate() { active_ = false; }50  bool active() const { return active_; }51 52private:53  bool active_{false};54};55 56template <class Func>57struct on_scope_exit {58  explicit on_scope_exit(Func func) : func_(func) {}59  ~on_scope_exit() { func_(); }60 61private:62  Func func_;63};64template <class Func>65on_scope_exit(Func) -> on_scope_exit<Func>;66 67int main(int, char**) {68  test_execution_policies([&](auto&& policy) {69    int a[] = {1, 2, 3, 4};70    int b[] = {1, 2, 3};71    int n   = 2;72    int storage[999];73    int val  = 99;74    int init = 1;75 76    // We generate a certain number of "tokens" and we activate exactly one on each iteration. We then77    // throw in a given operation only when that token is active. That way we check that each argument78    // of the algorithm is handled properly.79    ThrowToken tokens[7];80    for (ThrowToken& t : tokens) {81      t.activate();82      on_scope_exit _([&] { t.deactivate(); });83 84      auto first1      = util::throw_on_move_iterator(std::begin(a), tokens[0].active() ? 1 : -1);85      auto last1       = util::throw_on_move_iterator(std::end(a), tokens[1].active() ? 1 : -1);86      auto first2      = util::throw_on_move_iterator(std::begin(b), tokens[2].active() ? 1 : -1);87      auto last2       = util::throw_on_move_iterator(std::end(b), tokens[3].active() ? 1 : -1);88      auto dest        = util::throw_on_move_iterator(std::end(storage), tokens[4].active() ? 1 : -1);89      auto maybe_throw = [](ThrowToken const& token, auto f) {90        return [&token, f](auto... args) {91          if (token.active())92            throw 1;93          return f(args...);94        };95      };96 97      {98        auto pred = maybe_throw(tokens[5], [](int x) -> bool { return x % 2 == 0; });99 100        // all_of(first, last, pred)101        assert_non_throwing([=, &policy] { (void)std::all_of(policy, std::move(first1), std::move(last1), pred); });102 103        // any_of(first, last, pred)104        assert_non_throwing([=, &policy] { (void)std::any_of(policy, std::move(first1), std::move(last1), pred); });105 106        // none_of(first, last, pred)107        assert_non_throwing([=, &policy] { (void)std::none_of(policy, std::move(first1), std::move(last1), pred); });108      }109 110      {111        // copy(first, last, dest)112        assert_non_throwing([=, &policy] {113          (void)std::copy(policy, std::move(first1), std::move(last1), std::move(dest));114        });115 116        // copy_n(first, n, dest)117        assert_non_throwing([=, &policy] { (void)std::copy_n(policy, std::move(first1), n, std::move(dest)); });118      }119 120      {121        auto pred = maybe_throw(tokens[5], [](int x) -> bool { return x % 2 == 0; });122 123        // count(first, last, val)124        assert_non_throwing([=, &policy] { (void)std::count(policy, std::move(first1), std::move(last1), val); });125 126        // count_if(first, last, pred)127        assert_non_throwing([=, &policy] { (void)std::count_if(policy, std::move(first1), std::move(last1), pred); });128      }129 130      {131        auto binary_pred = maybe_throw(tokens[5], [](int x, int y) -> bool { return x == y; });132 133        // equal(first1, last1, first2)134        assert_non_throwing([=, &policy] {135          (void)std::equal(policy, std::move(first1), std::move(last1), std::move(first2));136        });137 138        // equal(first1, last1, first2, binary_pred)139        assert_non_throwing([=, &policy] {140          (void)std::equal(policy, std::move(first1), std::move(last1), std::move(first2), binary_pred);141        });142 143        // equal(first1, last1, first2, last2)144        assert_non_throwing([=, &policy] {145          (void)std::equal(policy, std::move(first1), std::move(last1), std::move(first2), std::move(last2));146        });147 148        // equal(first1, last1, first2, last2, binary_pred)149        assert_non_throwing([=, &policy] {150          (void)std::equal(151              policy, std::move(first1), std::move(last1), std::move(first2), std::move(last2), binary_pred);152        });153      }154 155      {156        // fill(first, last, val)157        assert_non_throwing([=, &policy] { (void)std::fill(policy, std::move(first1), std::move(last1), val); });158 159        // fill_n(first, n, val)160        assert_non_throwing([=, &policy] { (void)std::fill_n(policy, std::move(first1), n, val); });161      }162 163      {164        auto pred = maybe_throw(tokens[5], [](int x) -> bool { return x % 2 == 0; });165 166        // find(first, last, val)167        assert_non_throwing([=, &policy] { (void)std::find(policy, std::move(first1), std::move(last1), val); });168 169        // find_if(first, last, pred)170        assert_non_throwing([=, &policy] { (void)std::find_if(policy, std::move(first1), std::move(last1), pred); });171 172        // find_if_not(first, last, pred)173        assert_non_throwing([=, &policy] {174          (void)std::find_if_not(policy, std::move(first1), std::move(last1), pred);175        });176      }177 178      {179        auto func = maybe_throw(tokens[5], [](int) {});180 181        // for_each(first, last, func)182        assert_non_throwing([=, &policy] { (void)std::for_each(policy, std::move(first1), std::move(last1), func); });183 184        // for_each_n(first, n, func)185        assert_non_throwing([=, &policy] { (void)std::for_each_n(policy, std::move(first1), n, func); });186      }187 188      {189        auto gen = maybe_throw(tokens[5], []() -> int { return 42; });190 191        // generate(first, last, func)192        assert_non_throwing([=, &policy] { (void)std::generate(policy, std::move(first1), std::move(last1), gen); });193 194        // generate_n(first, n, func)195        assert_non_throwing([=, &policy] { (void)std::generate_n(policy, std::move(first1), n, gen); });196      }197 198      {199        auto pred = maybe_throw(tokens[5], [](int x) -> bool { return x % 2 == 0; });200 201        // is_partitioned(first, last, pred)202        assert_non_throwing([=, &policy] {203          (void)std::is_partitioned(policy, std::move(first1), std::move(last1), pred);204        });205      }206 207      {208        auto compare = maybe_throw(tokens[5], [](int x, int y) -> bool { return x < y; });209 210        // merge(first1, last1, first2, last2, dest)211        assert_non_throwing([=, &policy] {212          (void)std::merge(213              policy, std::move(first1), std::move(last1), std::move(first2), std::move(last2), std::move(dest));214        });215 216        // merge(first1, last1, first2, last2, dest, comp)217        assert_non_throwing([=, &policy] {218          (void)std::merge(219              policy,220              std::move(first1),221              std::move(last1),222              std::move(first2),223              std::move(last2),224              std::move(dest),225              compare);226        });227      }228 229      {230        // move(first, last, dest)231        assert_non_throwing([=, &policy] {232          (void)std::move(policy, std::move(first1), std::move(last1), std::move(dest));233        });234      }235 236      {237        auto pred = maybe_throw(tokens[5], [](int x) -> bool { return x % 2 == 0; });238 239        // replace_if(first, last, pred, val)240        assert_non_throwing([=, &policy] {241          (void)std::replace_if(policy, std::move(first1), std::move(last1), pred, val);242        });243 244        // replace(first, last, val1, val2)245        assert_non_throwing([=, &policy] {246          (void)std::replace(policy, std::move(first1), std::move(last1), val, val);247        });248 249        // replace_copy_if(first, last, dest, pred, val)250        assert_non_throwing([=, &policy] {251          (void)std::replace_copy_if(policy, std::move(first1), std::move(last1), std::move(dest), pred, val);252        });253 254        // replace_copy(first, last, dest, val1, val2)255        assert_non_throwing([=, &policy] {256          (void)std::replace_copy(policy, std::move(first1), std::move(last1), std::move(dest), val, val);257        });258      }259 260      {261        auto mid1 = util::throw_on_move_iterator(std::begin(a) + 2, tokens[5].active() ? 1 : -1);262 263        // rotate_copy(first, mid, last, dest)264        assert_non_throwing([=, &policy] {265          (void)std::rotate_copy(policy, std::move(first1), std::move(mid1), std::move(last1), std::move(dest));266        });267      }268 269      {270        auto compare = maybe_throw(tokens[5], [](int x, int y) -> bool { return x < y; });271 272        // sort(first, last)273        assert_non_throwing([=, &policy] { (void)std::sort(policy, std::move(first1), std::move(last1)); });274 275        // sort(first, last, comp)276        assert_non_throwing([=, &policy] { (void)std::sort(policy, std::move(first1), std::move(last1), compare); });277 278        // stable_sort(first, last)279        assert_non_throwing([=, &policy] { (void)std::stable_sort(policy, std::move(first1), std::move(last1)); });280 281        // stable_sort(first, last, comp)282        assert_non_throwing([=, &policy] {283          (void)std::stable_sort(policy, std::move(first1), std::move(last1), compare);284        });285      }286 287      {288        auto unary  = maybe_throw(tokens[5], [](int x) -> int { return x * 2; });289        auto binary = maybe_throw(tokens[5], [](int x, int y) -> int { return x * y; });290 291        // transform(first, last, dest, func)292        assert_non_throwing([=, &policy] {293          (void)std::transform(policy, std::move(first1), std::move(last1), std::move(dest), unary);294        });295 296        // transform(first1, last1, first2, dest, func)297        assert_non_throwing([=, &policy] {298          (void)std::transform(policy, std::move(first1), std::move(last1), std::move(first2), std::move(dest), binary);299        });300      }301 302      {303        auto reduction        = maybe_throw(tokens[5], [](int x, int y) -> int { return x + y; });304        auto transform_unary  = maybe_throw(tokens[6], [](int x) -> int { return x * 2; });305        auto transform_binary = maybe_throw(tokens[6], [](int x, int y) -> int { return x * y; });306 307        // transform_reduce(first1, last1, first2, init)308        assert_non_throwing([=, &policy] {309          (void)std::transform_reduce(policy, std::move(first1), std::move(last1), std::move(first2), init);310        });311 312        // transform_reduce(first1, last1, init, reduce, transform)313        assert_non_throwing([=, &policy] {314          (void)std::transform_reduce(policy, std::move(first1), std::move(last1), init, reduction, transform_unary);315        });316 317        // transform_reduce(first1, last1, first2, init, reduce, transform)318        assert_non_throwing([=, &policy] {319          (void)std::transform_reduce(320              policy, std::move(first1), std::move(last1), std::move(first2), init, reduction, transform_binary);321        });322      }323 324      {325        auto reduction = maybe_throw(tokens[5], [](int x, int y) -> int { return x + y; });326 327        // reduce(first, last)328        assert_non_throwing([=, &policy] { (void)std::reduce(policy, std::move(first1), std::move(last1)); });329 330        // reduce(first, last, init)331        assert_non_throwing([=, &policy] { (void)std::reduce(policy, std::move(first1), std::move(last1), init); });332 333        // reduce(first, last, init, binop)334        assert_non_throwing([=, &policy] {335          (void)std::reduce(policy, std::move(first1), std::move(last1), init, reduction);336        });337      }338    }339  });340}341