15a83710eSEric Fiselier //===----------------------------------------------------------------------===//
25a83710eSEric Fiselier //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65a83710eSEric Fiselier //
75a83710eSEric Fiselier //===----------------------------------------------------------------------===//
85a83710eSEric Fiselier 
9*a21a6ed8SMartin Storsjö // FIXME: This test needs to be rewritten for the MSVC exception_ptr semantics
103e254a6eSEric Fiselier // which copy the exception each time the exception_ptr is copied.
11*a21a6ed8SMartin Storsjö // XFAIL: msvc
129ddcc552SEric Fiselier 
138c61114cSLouis Dionne // UNSUPPORTED: no-exceptions
145a83710eSEric Fiselier // <exception>
155a83710eSEric Fiselier 
165a83710eSEric Fiselier // exception_ptr current_exception();
175a83710eSEric Fiselier 
185a83710eSEric Fiselier #include <exception>
195a83710eSEric Fiselier #include <cassert>
205a83710eSEric Fiselier 
217fc6a556SMarshall Clow #include "test_macros.h"
227fc6a556SMarshall Clow 
235a83710eSEric Fiselier struct A
245a83710eSEric Fiselier {
255a83710eSEric Fiselier     static int constructed;
265a83710eSEric Fiselier 
AA275a83710eSEric Fiselier     A() {++constructed;}
~AA285a83710eSEric Fiselier     ~A() {--constructed;}
AA295a83710eSEric Fiselier     A(const A&)  {++constructed;}
305a83710eSEric Fiselier };
315a83710eSEric Fiselier 
325a83710eSEric Fiselier int A::constructed = 0;
335a83710eSEric Fiselier 
main(int,char **)342df59c50SJF Bastien int main(int, char**)
355a83710eSEric Fiselier {
365a83710eSEric Fiselier     {
375a83710eSEric Fiselier         std::exception_ptr p = std::current_exception();
385a83710eSEric Fiselier         assert(p == nullptr);
395a83710eSEric Fiselier     }
405a83710eSEric Fiselier     {
415a83710eSEric Fiselier         try
425a83710eSEric Fiselier         {
435a83710eSEric Fiselier             assert(A::constructed == 0);
445a83710eSEric Fiselier             throw A();
455a83710eSEric Fiselier             assert(false);
465a83710eSEric Fiselier         }
475a83710eSEric Fiselier         catch (...)
485a83710eSEric Fiselier         {
495a83710eSEric Fiselier             assert(A::constructed == 1);
505a83710eSEric Fiselier         }
515a83710eSEric Fiselier         assert(A::constructed == 0);
525a83710eSEric Fiselier     }
535a83710eSEric Fiselier     assert(A::constructed == 0);
545a83710eSEric Fiselier     {
555a83710eSEric Fiselier         std::exception_ptr p2;
565a83710eSEric Fiselier         try
575a83710eSEric Fiselier         {
585a83710eSEric Fiselier             assert(A::constructed == 0);
595a83710eSEric Fiselier             throw A();
605a83710eSEric Fiselier             assert(false);
615a83710eSEric Fiselier         }
625a83710eSEric Fiselier         catch (...)
635a83710eSEric Fiselier         {
645a83710eSEric Fiselier             std::exception_ptr p = std::current_exception();
655a83710eSEric Fiselier             assert(A::constructed == 1);
665a83710eSEric Fiselier             assert(p != nullptr);
675a83710eSEric Fiselier             p2 = std::current_exception();
685a83710eSEric Fiselier             assert(A::constructed == 1);
695a83710eSEric Fiselier             assert(p == p2);
705a83710eSEric Fiselier         }
715a83710eSEric Fiselier         assert(A::constructed == 1);
725a83710eSEric Fiselier     }
735a83710eSEric Fiselier     assert(A::constructed == 0);
745a83710eSEric Fiselier     {
755a83710eSEric Fiselier         std::exception_ptr p2;
765a83710eSEric Fiselier         try
775a83710eSEric Fiselier         {
785a83710eSEric Fiselier             assert(A::constructed == 0);
795a83710eSEric Fiselier             throw A();
805a83710eSEric Fiselier             assert(false);
815a83710eSEric Fiselier         }
82fb42f4c4SEric Fiselier         catch (A&)
835a83710eSEric Fiselier         {
845a83710eSEric Fiselier             std::exception_ptr p = std::current_exception();
855a83710eSEric Fiselier             assert(A::constructed == 1);
865a83710eSEric Fiselier             assert(p != nullptr);
875a83710eSEric Fiselier             p2 = std::current_exception();
885a83710eSEric Fiselier             assert(A::constructed == 1);
895a83710eSEric Fiselier             assert(p == p2);
905a83710eSEric Fiselier         }
915a83710eSEric Fiselier         assert(A::constructed == 1);
925a83710eSEric Fiselier     }
935a83710eSEric Fiselier     assert(A::constructed == 0);
945a83710eSEric Fiselier     {
955a83710eSEric Fiselier         std::exception_ptr p2;
965a83710eSEric Fiselier         try
975a83710eSEric Fiselier         {
985a83710eSEric Fiselier             assert(A::constructed == 0);
995a83710eSEric Fiselier             throw A();
1005a83710eSEric Fiselier             assert(false);
1015a83710eSEric Fiselier         }
102fb42f4c4SEric Fiselier         catch (A)
1035a83710eSEric Fiselier         {
1045a83710eSEric Fiselier             std::exception_ptr p = std::current_exception();
1055a83710eSEric Fiselier             assert(A::constructed == 2);
1065a83710eSEric Fiselier             assert(p != nullptr);
1075a83710eSEric Fiselier             p2 = std::current_exception();
1085a83710eSEric Fiselier             assert(A::constructed == 2);
1095a83710eSEric Fiselier             assert(p == p2);
1105a83710eSEric Fiselier         }
1115a83710eSEric Fiselier         assert(A::constructed == 1);
1125a83710eSEric Fiselier     }
1135a83710eSEric Fiselier     assert(A::constructed == 0);
1145a83710eSEric Fiselier     {
1155a83710eSEric Fiselier         try
1165a83710eSEric Fiselier         {
1175a83710eSEric Fiselier             assert(A::constructed == 0);
1185a83710eSEric Fiselier             throw A();
1195a83710eSEric Fiselier             assert(false);
1205a83710eSEric Fiselier         }
1215a83710eSEric Fiselier         catch (...)
1225a83710eSEric Fiselier         {
1235a83710eSEric Fiselier             assert(A::constructed == 1);
1245a83710eSEric Fiselier             try
1255a83710eSEric Fiselier             {
1265a83710eSEric Fiselier                 assert(A::constructed == 1);
1275a83710eSEric Fiselier                 throw;
1285a83710eSEric Fiselier                 assert(false);
1295a83710eSEric Fiselier             }
1305a83710eSEric Fiselier             catch (...)
1315a83710eSEric Fiselier             {
1325a83710eSEric Fiselier                 assert(A::constructed == 1);
1335a83710eSEric Fiselier             }
1345a83710eSEric Fiselier             assert(A::constructed == 1);
1355a83710eSEric Fiselier         }
1365a83710eSEric Fiselier         assert(A::constructed == 0);
1375a83710eSEric Fiselier     }
1385a83710eSEric Fiselier     assert(A::constructed == 0);
1395a83710eSEric Fiselier     {
1405a83710eSEric Fiselier         try
1415a83710eSEric Fiselier         {
1425a83710eSEric Fiselier             assert(A::constructed == 0);
1435a83710eSEric Fiselier             throw A();
1445a83710eSEric Fiselier             assert(false);
1455a83710eSEric Fiselier         }
1465a83710eSEric Fiselier         catch (...)
1475a83710eSEric Fiselier         {
1485a83710eSEric Fiselier             assert(A::constructed == 1);
1495a83710eSEric Fiselier             try
1505a83710eSEric Fiselier             {
1515a83710eSEric Fiselier                 std::exception_ptr p = std::current_exception();
1525a83710eSEric Fiselier                 assert(A::constructed == 1);
1535a83710eSEric Fiselier                 assert(p != nullptr);
1545a83710eSEric Fiselier                 throw;
1555a83710eSEric Fiselier                 assert(false);
1565a83710eSEric Fiselier             }
1575a83710eSEric Fiselier             catch (...)
1585a83710eSEric Fiselier             {
1595a83710eSEric Fiselier                 assert(A::constructed == 1);
1605a83710eSEric Fiselier             }
1615a83710eSEric Fiselier             assert(A::constructed == 1);
1625a83710eSEric Fiselier         }
1635a83710eSEric Fiselier         assert(A::constructed == 0);
1645a83710eSEric Fiselier     }
1655a83710eSEric Fiselier     assert(A::constructed == 0);
1665a83710eSEric Fiselier     {
1675a83710eSEric Fiselier         try
1685a83710eSEric Fiselier         {
1695a83710eSEric Fiselier             assert(A::constructed == 0);
1705a83710eSEric Fiselier             throw A();
1715a83710eSEric Fiselier             assert(false);
1725a83710eSEric Fiselier         }
1735a83710eSEric Fiselier         catch (...)
1745a83710eSEric Fiselier         {
1755a83710eSEric Fiselier             assert(A::constructed == 1);
1765a83710eSEric Fiselier             try
1775a83710eSEric Fiselier             {
1785a83710eSEric Fiselier                 assert(A::constructed == 1);
1795a83710eSEric Fiselier                 throw;
1805a83710eSEric Fiselier                 assert(false);
1815a83710eSEric Fiselier             }
1825a83710eSEric Fiselier             catch (...)
1835a83710eSEric Fiselier             {
1845a83710eSEric Fiselier                 std::exception_ptr p = std::current_exception();
1855a83710eSEric Fiselier                 assert(A::constructed == 1);
1865a83710eSEric Fiselier                 assert(p != nullptr);
1875a83710eSEric Fiselier             }
1885a83710eSEric Fiselier             assert(A::constructed == 1);
1895a83710eSEric Fiselier         }
1905a83710eSEric Fiselier         assert(A::constructed == 0);
1915a83710eSEric Fiselier     }
1925a83710eSEric Fiselier     assert(A::constructed == 0);
1935a83710eSEric Fiselier     {
1945a83710eSEric Fiselier         try
1955a83710eSEric Fiselier         {
1965a83710eSEric Fiselier             assert(A::constructed == 0);
1975a83710eSEric Fiselier             throw A();
1985a83710eSEric Fiselier             assert(false);
1995a83710eSEric Fiselier         }
2005a83710eSEric Fiselier         catch (...)
2015a83710eSEric Fiselier         {
2025a83710eSEric Fiselier             assert(A::constructed == 1);
2035a83710eSEric Fiselier             try
2045a83710eSEric Fiselier             {
2055a83710eSEric Fiselier                 assert(A::constructed == 1);
2065a83710eSEric Fiselier                 throw;
2075a83710eSEric Fiselier                 assert(false);
2085a83710eSEric Fiselier             }
2095a83710eSEric Fiselier             catch (...)
2105a83710eSEric Fiselier             {
2115a83710eSEric Fiselier                 assert(A::constructed == 1);
2125a83710eSEric Fiselier             }
2135a83710eSEric Fiselier             std::exception_ptr p = std::current_exception();
2145a83710eSEric Fiselier             assert(A::constructed == 1);
2155a83710eSEric Fiselier             assert(p != nullptr);
2165a83710eSEric Fiselier         }
2175a83710eSEric Fiselier         assert(A::constructed == 0);
2185a83710eSEric Fiselier     }
2195a83710eSEric Fiselier     assert(A::constructed == 0);
2205a83710eSEric Fiselier     {
2215a83710eSEric Fiselier         try
2225a83710eSEric Fiselier         {
2235a83710eSEric Fiselier             assert(A::constructed == 0);
2245a83710eSEric Fiselier             throw A();
2255a83710eSEric Fiselier             assert(false);
2265a83710eSEric Fiselier         }
2275a83710eSEric Fiselier         catch (...)
2285a83710eSEric Fiselier         {
2295a83710eSEric Fiselier             assert(A::constructed == 1);
2305a83710eSEric Fiselier             try
2315a83710eSEric Fiselier             {
2325a83710eSEric Fiselier                 assert(A::constructed == 1);
2335a83710eSEric Fiselier                 throw;
2345a83710eSEric Fiselier                 assert(false);
2355a83710eSEric Fiselier             }
2365a83710eSEric Fiselier             catch (...)
2375a83710eSEric Fiselier             {
2385a83710eSEric Fiselier                 assert(A::constructed == 1);
2395a83710eSEric Fiselier             }
2405a83710eSEric Fiselier             assert(A::constructed == 1);
2415a83710eSEric Fiselier         }
2425a83710eSEric Fiselier         std::exception_ptr p = std::current_exception();
2435a83710eSEric Fiselier         assert(A::constructed == 0);
2445a83710eSEric Fiselier         assert(p == nullptr);
2455a83710eSEric Fiselier     }
2465a83710eSEric Fiselier     assert(A::constructed == 0);
2475a83710eSEric Fiselier     {
2485a83710eSEric Fiselier         std::exception_ptr p;
2495a83710eSEric Fiselier         try
2505a83710eSEric Fiselier         {
2515a83710eSEric Fiselier             assert(A::constructed == 0);
2525a83710eSEric Fiselier             throw A();
2535a83710eSEric Fiselier             assert(false);
2545a83710eSEric Fiselier         }
2555a83710eSEric Fiselier         catch (...)
2565a83710eSEric Fiselier         {
2575a83710eSEric Fiselier             assert(A::constructed == 1);
2585a83710eSEric Fiselier             try
2595a83710eSEric Fiselier             {
2605a83710eSEric Fiselier                 assert(A::constructed == 1);
2615a83710eSEric Fiselier                 throw;
2625a83710eSEric Fiselier                 assert(false);
2635a83710eSEric Fiselier             }
2645a83710eSEric Fiselier             catch (...)
2655a83710eSEric Fiselier             {
2665a83710eSEric Fiselier                 p = std::current_exception();
2675a83710eSEric Fiselier                 assert(A::constructed == 1);
2685a83710eSEric Fiselier             }
2695a83710eSEric Fiselier             assert(A::constructed == 1);
2705a83710eSEric Fiselier         }
2715a83710eSEric Fiselier         assert(A::constructed == 1);
2725a83710eSEric Fiselier         assert(p != nullptr);
2735a83710eSEric Fiselier     }
2745a83710eSEric Fiselier     assert(A::constructed == 0);
2752df59c50SJF Bastien 
2762df59c50SJF Bastien   return 0;
2775a83710eSEric Fiselier }
278