diff options
Diffstat (limited to 'gcc/testsuite/g++.dg')
26 files changed, 348 insertions, 0 deletions
diff --git a/gcc/testsuite/g++.dg/tm/composite1.C b/gcc/testsuite/g++.dg/tm/composite1.C new file mode 100644 index 00000000000..6e823176128 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/composite1.C @@ -0,0 +1,14 @@ +// Test for composite pointer type. +// { dg-options -fgnu-tm } + +void f(bool b) +{ + void (*p)() transaction_safe = 0; + void (*g)() = 0; + + g = b ? p : g; // OK + p = b ? p : g; // { dg-error "" } + + p == g; + p != g; +} diff --git a/gcc/testsuite/g++.dg/tm/dynamic1.C b/gcc/testsuite/g++.dg/tm/dynamic1.C new file mode 100644 index 00000000000..a6f49567432 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/dynamic1.C @@ -0,0 +1,13 @@ +// Test that transaction_safe_dynamic can only be used on virtual functions. +// { dg-options "-fgnu-tm -std=c++14" } + +void f() transaction_safe_dynamic; // { dg-error "virtual" } +auto a = []() transaction_safe_dynamic {}; // { dg-error "virtual" } +struct A { + void f() transaction_safe_dynamic; // { dg-error "virtual" } + virtual void g(); +}; + +struct B: A { + void g() transaction_safe_dynamic; +}; diff --git a/gcc/testsuite/g++.dg/tm/dynamic2.C b/gcc/testsuite/g++.dg/tm/dynamic2.C new file mode 100644 index 00000000000..3003b62ca0a --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/dynamic2.C @@ -0,0 +1,17 @@ +// { dg-options "-fgnu-tm -std=c++14 -O2" } + +void unsafe(); +struct A { + virtual void f() transaction_safe_dynamic; +}; +struct B:A { + void f() { unsafe(); } +}; + +void f() transaction_safe { + B b; + A& ar = b; + // This is undefined behavior, we want to give an error with + // devirtualization. + ar.f(); // { dg-error "unsafe" } +} diff --git a/gcc/testsuite/g++.dg/tm/eh1.C b/gcc/testsuite/g++.dg/tm/eh1.C new file mode 100644 index 00000000000..156121142e7 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/eh1.C @@ -0,0 +1,10 @@ +// A handler can involve a transaction-safety conversion. +// { dg-do run } +// { dg-options "-fgnu-tm" } + +void g() transaction_safe {} +int main() +{ + try { throw g; } + catch (void (*p)()) { } +} diff --git a/gcc/testsuite/g++.dg/tm/eh2.C b/gcc/testsuite/g++.dg/tm/eh2.C new file mode 100644 index 00000000000..307a63924c3 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/eh2.C @@ -0,0 +1,14 @@ +// A handler cannot do the reverse of a transaction-safety conversion. +// { dg-do run } +// { dg-options "-fgnu-tm" } + +extern "C" void abort(); + +void g() {} + +int main() +{ + try { throw g; } + catch (void (*p)() transaction_safe) { abort(); } + catch (...) { } +} diff --git a/gcc/testsuite/g++.dg/tm/eh4.C b/gcc/testsuite/g++.dg/tm/eh4.C new file mode 100644 index 00000000000..68275e99706 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/eh4.C @@ -0,0 +1,21 @@ +// Test that throwing out of an atomic_commit block commits the transaction. + +// { dg-do run } +// { dg-options "-fgnu-tm" } + +int main() +{ + static int i; + bool caught = false; + try { + atomic_commit { + i = 12; + throw 42; + i = 24; + } + } catch (int x) { + caught = (x == 42); + } + if (!caught || i != 12) + __builtin_abort(); +} diff --git a/gcc/testsuite/g++.dg/tm/inherit1.C b/gcc/testsuite/g++.dg/tm/inherit1.C new file mode 100644 index 00000000000..b8480a10892 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/inherit1.C @@ -0,0 +1,11 @@ +// Testcase from TM TS +// { dg-options "-std=c++14 -fgnu-tm" } + +struct B { + virtual void f() transaction_safe; +}; + +struct D3 : B +{ + void f() transaction_safe_dynamic override; // { dg-error "" "B::f() is transaction_safe" } +}; diff --git a/gcc/testsuite/g++.dg/tm/inherit2.C b/gcc/testsuite/g++.dg/tm/inherit2.C new file mode 100644 index 00000000000..3b696a9ffb6 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/inherit2.C @@ -0,0 +1,33 @@ +// Testcase from TM TS +// { dg-options "-std=c++14 -fgnu-tm" } + +#include <iostream> + +struct B { + virtual void f() transaction_safe; + virtual ~B() transaction_safe_dynamic; +}; +// pre-existing code +struct D1 : B +{ + void f() override { } // ok + ~D1() override { } // ok +}; +struct D2 : B +{ + void f() override { std::cout << "D2::f" << std::endl; } // { dg-error "" "transaction-safe f has transaction-unsafe definition" } + ~D2() override { std::cout << "~D2" << std::endl; } // ok +}; +int main() +{ + D2 * d2 = new D2; + B * b2 = d2; + atomic_commit { + B b; // ok + D1 d1; // ok + B& b1 = d1; + D2 x; // { dg-error "" "destructor of D2 is not transaction-safe" } + b1.f(); // ok, calls D1::f() + delete b2; // undefined behavior: calls unsafe destructor of D2 + } +} diff --git a/gcc/testsuite/g++.dg/tm/jump1.C b/gcc/testsuite/g++.dg/tm/jump1.C new file mode 100644 index 00000000000..003eed034c9 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/jump1.C @@ -0,0 +1,23 @@ +// A goto or switch statement shall not be used to transfer control into a +// synchronized or atomic block. +// { dg-options "-fgnu-tm" } + +void f() +{ + static int i; + synchronized { + ++i; + inside: // { dg-message "" } + ++i; + } + goto inside; // { dg-message "" } + + switch (i) + { + synchronized { + ++i; + case 42: // { dg-error "" } + ++i; + } + } +} diff --git a/gcc/testsuite/g++.dg/tm/keyword1.C b/gcc/testsuite/g++.dg/tm/keyword1.C new file mode 100644 index 00000000000..3537e0fe992 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/keyword1.C @@ -0,0 +1,9 @@ +// Test that these aren't keywords without -fgnu-tm. + +int main() +{ + synchronized { } // { dg-error "not declared" } + atomic_noexcept { } // { dg-error "not declared" } + atomic_cancel { } // { dg-error "not declared" } + atomic_commit { } // { dg-error "not declared" } +} diff --git a/gcc/testsuite/g++.dg/tm/lambda1.C b/gcc/testsuite/g++.dg/tm/lambda1.C new file mode 100644 index 00000000000..d0cffbff22f --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/lambda1.C @@ -0,0 +1,10 @@ +// Test for lambda conversion. +// { dg-options "-fgnu-tm -std=c++14" } + +void f(bool b) +{ + void (*p)() transaction_safe; + + p = []() transaction_safe {}; + p = []{}; // { dg-error "transaction_safe" } +} diff --git a/gcc/testsuite/g++.dg/tm/lambda2.C b/gcc/testsuite/g++.dg/tm/lambda2.C new file mode 100644 index 00000000000..82e509e3658 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/lambda2.C @@ -0,0 +1,9 @@ +// Test for lambda call. +// { dg-options "-fgnu-tm -std=c++14" } + +void unsafe (); +void f() transaction_safe +{ + []{}(); // OK, implicitly transaction-safe. + []{unsafe();}(); // { dg-error "unsafe" } +} diff --git a/gcc/testsuite/g++.dg/tm/macro1.C b/gcc/testsuite/g++.dg/tm/macro1.C new file mode 100644 index 00000000000..dcf388839b1 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/macro1.C @@ -0,0 +1,5 @@ +// { dg-options -fgnu-tm } + +#ifndef __cpp_transactional_memory +#error __cpp_transactional_memory not defined +#endif diff --git a/gcc/testsuite/g++.dg/tm/mangle1.C b/gcc/testsuite/g++.dg/tm/mangle1.C new file mode 100644 index 00000000000..f081f8e0289 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/mangle1.C @@ -0,0 +1,18 @@ +// Test for transaction_safe mangling. +// { dg-options -fgnu-tm } + +// { dg-final { scan-assembler "_Z1fPDxFvvE" } } +void f(void (*)() transaction_safe) {} + +// { dg-final { scan-assembler "_Z1fPDxFvvEPFvvE" } } +void f(void (*)() transaction_safe, void (*)()) {} + +// { dg-final { scan-assembler "_Z1fPDxFvvES0_" } } +void f(void (*)() transaction_safe, void (*)() transaction_safe) {} + +// { dg-final { scan-assembler "_Z1f1AIKDxFvvEE" } } +template <class T> struct A { }; +void f(A<void () const transaction_safe>) { } + +// { dg-final { scan-assembler "_Z1fM1AIiEKDxFvvE" } } +void f(void (A<int>::*)() const transaction_safe) { } diff --git a/gcc/testsuite/g++.dg/tm/noexcept-7.C b/gcc/testsuite/g++.dg/tm/noexcept-7.C new file mode 100644 index 00000000000..bfa675c987f --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/noexcept-7.C @@ -0,0 +1,7 @@ +// FIXME the TS says atomic_noexcept calls abort, not terminate. +// { dg-options "-fgnu-tm" } + +void f() +{ + atomic_noexcept { throw; } // { dg-warning "terminate" } +} diff --git a/gcc/testsuite/g++.dg/tm/overload1.C b/gcc/testsuite/g++.dg/tm/overload1.C new file mode 100644 index 00000000000..71ecab9ff15 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/overload1.C @@ -0,0 +1,6 @@ +// Function declarations that differ only in the presence or absence of a +// tx-qualifier cannot be overloaded. +// { dg-options "-fgnu-tm" } + +void f(); // { dg-message "" } +void f() transaction_safe; // { dg-error "" } diff --git a/gcc/testsuite/g++.dg/tm/overload2.C b/gcc/testsuite/g++.dg/tm/overload2.C new file mode 100644 index 00000000000..3510779644e --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/overload2.C @@ -0,0 +1,9 @@ +// 13.4p1: A function with type F is selected for the function type FT of the +// target type required in the context if F (after possibly applying the +// transaction-safety conversion (4.14 [conv.tx])) is identical to FT. +// { dg-options "-fgnu-tm" } + +void f() transaction_safe; +void f(int); + +void (*p)() = f; diff --git a/gcc/testsuite/g++.dg/tm/pretty-print1.C b/gcc/testsuite/g++.dg/tm/pretty-print1.C new file mode 100644 index 00000000000..d7c1de0ae52 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/pretty-print1.C @@ -0,0 +1,6 @@ +// Test for pretty-printing in diagnostics. +// { dg-options "-fgnu-tm" } + +void f(); +void (*p)() transaction_safe = f; // { dg-error "void \\(\\*\\)\\(\\) transaction_safe" } + diff --git a/gcc/testsuite/g++.dg/tm/static_cast1.C b/gcc/testsuite/g++.dg/tm/static_cast1.C new file mode 100644 index 00000000000..31606c57a7e --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/static_cast1.C @@ -0,0 +1,9 @@ +// The inverse of a transaction-safety conversion cannot be performed with +// static_cast. +// { dg-options "-fgnu-tm" } + +typedef void (*TS)() transaction_safe; +void f() +{ + static_cast<TS>(f); // { dg-error "static_cast" } +} diff --git a/gcc/testsuite/g++.dg/tm/sync1.C b/gcc/testsuite/g++.dg/tm/sync1.C new file mode 100644 index 00000000000..a567b2cc3e2 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/sync1.C @@ -0,0 +1,15 @@ +// Testcase from TM TS. +// { dg-options -fgnu-tm } + +extern "C" int printf (const char *, ...); + +int f() +{ + static int i = 0; + synchronized { + printf("before %d\n", i); + ++i; + printf("after %d\n", i); + return i; + } +} diff --git a/gcc/testsuite/g++.dg/tm/sync2.C b/gcc/testsuite/g++.dg/tm/sync2.C new file mode 100644 index 00000000000..f13c9c55e90 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/sync2.C @@ -0,0 +1,21 @@ +// { dg-do compile { target c++11 } } +// { dg-options "-fgnu-tm -fdump-tree-optimized-asmname" } + +struct Tsafe +{ + void f() transaction_safe; +}; + +void Tsafe::f() { } + +struct Tcall +{ + [[optimize_for_synchronized]] void f(); +}; + +void Tcall::f() { } + +// { dg-final { scan-tree-dump-times "_ZN5Tsafe1fEv" 1 "optimized" } } +// { dg-final { scan-tree-dump-times "_ZN5Tcall1fEv" 1 "optimized" } } +// { dg-final { scan-tree-dump-times "_ZGTtN5Tsafe1fEv" 1 "optimized" } } +// { dg-final { scan-tree-dump-times "_ZGTtN5Tcall1fEv" 1 "optimized" } } diff --git a/gcc/testsuite/g++.dg/tm/template-3.C b/gcc/testsuite/g++.dg/tm/template-3.C new file mode 100644 index 00000000000..356d2a89b9b --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/template-3.C @@ -0,0 +1,15 @@ +// { dg-options "-fgnu-tm" } + +void fn(int) transaction_safe; +void fn(double); + +template <class T> void f(T t) transaction_safe +{ + fn(t); // { dg-error "double" } +} + +void g() +{ + f(42); // OK + f(3.14); +} diff --git a/gcc/testsuite/g++.dg/tm/template-4.C b/gcc/testsuite/g++.dg/tm/template-4.C new file mode 100644 index 00000000000..dd257111bda --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/template-4.C @@ -0,0 +1,13 @@ +// Test for transaction-safety conversion in deduction. +// { dg-options "-fgnu-tm" } + +void fn(int) transaction_safe; +void fn(); + +template <class T> void f(void(*)(T)); +template <class T> void f2(void(*)(T) transaction_safe); + +void g() +{ + f(fn); +} diff --git a/gcc/testsuite/g++.dg/tm/template-5.C b/gcc/testsuite/g++.dg/tm/template-5.C new file mode 100644 index 00000000000..6501ed1a073 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/template-5.C @@ -0,0 +1,12 @@ +// Test for deduction based on transaction_safe. +// { dg-options "-fgnu-tm -std=c++11" } + +void f() transaction_safe; +void g(); + +template <class T> struct A; +template <class R, class...Ps> +struct A<R (Ps...) transaction_safe> { }; + +A<decltype(f)> a; +A<decltype(g)> b; // { dg-error "incomplete" } diff --git a/gcc/testsuite/g++.dg/tm/unsafe1.C b/gcc/testsuite/g++.dg/tm/unsafe1.C new file mode 100644 index 00000000000..91dd7b110ec --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/unsafe1.C @@ -0,0 +1,15 @@ +// Transaction-unsafe testcase from TM TS. +// { dg-options -fgnu-tm } + +struct S { + virtual ~S(); +}; +int f() transaction_safe { + S s; // { dg-error "unsafe" "invocation of unsafe destructor" } +} + +int g(int x) { // is transaction-safe + if (x <= 0) + return 0; + return x + g(x-1); +} diff --git a/gcc/testsuite/g++.dg/tm/unsafe2.C b/gcc/testsuite/g++.dg/tm/unsafe2.C new file mode 100644 index 00000000000..1b81b310057 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/unsafe2.C @@ -0,0 +1,13 @@ +// Transaction-unsafe testcase from TM TS. +// { dg-options -fgnu-tm } + +template<class T> +void f(T) transaction_safe; +template<> +void f(bool); // not transaction-safe + +int g() transaction_safe +{ + f(42); // OK + f(true); // { dg-error "unsafe" } +} |