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-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 // Test the set of C++11 features that Clang provides as an extension in C++03 mode.
10 // The language features we expect are:
11 //
12 // 1. rvalue references (and perfect forwarding)
13 // 2. variadic templates
14 // 3. alias templates
15 // 4. defaulted and deleted functions.
16 // 5. default values for non-type template parameters.
17 //
18 // Some features we don't get and can't be used in extended C++03 mode:
19 //
20 // 1. noexcept and constexpr
21 // 2. Two closing '>' without a space.
22
23 #include <type_traits>
24 #include <cassert>
25
26 // Equals delete and default are allowed in minimal C++03 mode.
27 namespace test_eq_delete_and_default {
28 void t1() = delete;
29 struct T2 {
30 T2() = default;
31 T2(T2 const&) = delete;
32 };
33 }
34
35 namespace alias_templates {
36 template <class T>
37 using X = T;
38 static_assert((std::is_same<X<int>, int>::value), "");
39 }
40
41 namespace variadics_templates {
42 template <class ...Args>
t1(Args...)43 int t1(Args...) {
44 return sizeof...(Args);
45 }
test()46 void test() {
47 assert(t1() == 0);
48 assert(t1(42) == 1);
49 assert(t1(1, 2, 3) == 3);
50 }
51 }
52
53 namespace rvalue_references_move_semantics {
54 struct T {
Trvalue_references_move_semantics::T55 T() : moved(0) {}
Trvalue_references_move_semantics::T56 T(T const& other) : moved(other.moved) {}
Trvalue_references_move_semantics::T57 T(T&& other) : moved(other.moved) { ++moved; other.moved = -1; }
58 int moved;
59 };
f(T o,int expect_moved)60 void f(T o, int expect_moved) { assert(o.moved == expect_moved); }
test()61 void test() {
62 {
63 T t;
64 assert(t.moved == 0);
65 T t2(static_cast<T&&>(t));
66 assert(t2.moved == 1);
67 assert(t.moved == -1);
68 }
69 {
70 T t;
71 f(t, 0);
72 f(static_cast<T&&>(t), 1);
73 }
74 }
75 }
76
77 namespace rvalue_references_perfect_forwarding {
78 template <class Expect, class T>
f(T &&)79 void f(T&&) {
80 static_assert((std::is_same<Expect, T&&>::value), "");
81 }
test()82 void test() {
83 int x = 42;
84 f<int&>(x);
85 f<int&&>(42);
86 f<int&&>(static_cast<int&&>(x));
87 }
88 }
89
90 namespace default_values_for_nttp {
91 template <int I = 42>
f()92 void f() { assert(I == 42); }
test()93 void test() {
94 f();
95 }
96 }
97
98 namespace reference_qualified_functions {
99 struct T {
Treference_qualified_functions::T100 T() : lvalue_called(0), rvalue_called(0) {}
fooreference_qualified_functions::T101 void foo() const & { lvalue_called++; }
fooreference_qualified_functions::T102 void foo() && { rvalue_called++; }
103 mutable int lvalue_called;
104 int rvalue_called;
105 };
106
test()107 void test() {
108 {
109 T t;
110 t.foo();
111 assert(t.lvalue_called == 1);
112 assert(t.rvalue_called == 0);
113 }
114 {
115 T t;
116 static_cast<T&&>(t).foo();
117 assert(t.lvalue_called == 0);
118 assert(t.rvalue_called == 1);
119 }
120 }
121 }
122
main(int,char **)123 int main(int, char**) {
124 variadics_templates::test();
125 rvalue_references_move_semantics::test();
126 rvalue_references_perfect_forwarding::test();
127 default_values_for_nttp::test();
128 reference_qualified_functions::test();
129 return 0;
130 }
131