summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/CXX/drs/dr0xx.cpp48
-rw-r--r--clang/test/CXX/drs/dr10xx.cpp14
-rw-r--r--clang/test/CXX/drs/dr1xx.cpp26
-rw-r--r--clang/test/CXX/drs/dr4xx.cpp23
-rw-r--r--clang/test/CodeGenCXX/cxx1z-copy-omission.cpp81
-rw-r--r--clang/test/SemaCXX/aggregate-initialization.cpp12
-rw-r--r--clang/test/SemaCXX/cxx1z-copy-omission.cpp134
7 files changed, 307 insertions, 31 deletions
diff --git a/clang/test/CXX/drs/dr0xx.cpp b/clang/test/CXX/drs/dr0xx.cpp
index d65917a5682..a009b8a353d 100644
--- a/clang/test/CXX/drs/dr0xx.cpp
+++ b/clang/test/CXX/drs/dr0xx.cpp
@@ -248,7 +248,7 @@ namespace dr20 { // dr20: yes
private:
X(const X&); // expected-note {{here}}
};
- X f();
+ X &f();
X x = f(); // expected-error {{private}}
}
@@ -316,8 +316,15 @@ namespace dr25 { // dr25: yes
namespace dr26 { // dr26: yes
struct A { A(A, const A & = A()); }; // expected-error {{must pass its first argument by reference}}
struct B {
- B(); // expected-note {{candidate}}
- B(const B &, B = B()); // expected-error {{no matching constructor}} expected-note {{candidate}} expected-note {{here}}
+ B(); // expected-note 0-1{{candidate}}
+ B(const B &, B = B());
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{no matching constructor}} expected-note@-2 {{candidate}} expected-note@-2 {{here}}
+#endif
+ };
+ struct C {
+ static C &f();
+ C(const C &, C = f()); // expected-error {{no matching constructor}} expected-note {{candidate}} expected-note {{here}}
};
}
@@ -662,25 +669,33 @@ namespace dr58 { // dr58: yes
namespace dr59 { // dr59: yes
template<typename T> struct convert_to { operator T() const; };
- struct A {}; // expected-note 2{{volatile qualifier}} expected-note 2{{requires 0 arguments}}
- struct B : A {}; // expected-note 2{{volatile qualifier}} expected-note 2{{requires 0 arguments}}
-#if __cplusplus >= 201103L // move constructors
- // expected-note@-3 2{{volatile qualifier}}
- // expected-note@-3 2{{volatile qualifier}}
-#endif
+ struct A {}; // expected-note 5+{{candidate}}
+ struct B : A {}; // expected-note 0+{{candidate}}
A a1 = convert_to<A>();
A a2 = convert_to<A&>();
A a3 = convert_to<const A>();
- A a4 = convert_to<const volatile A>(); // expected-error {{no viable}}
+ A a4 = convert_to<const volatile A>();
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{no viable}}
+#endif
A a5 = convert_to<const volatile A&>(); // expected-error {{no viable}}
B b1 = convert_to<B>();
B b2 = convert_to<B&>();
B b3 = convert_to<const B>();
- B b4 = convert_to<const volatile B>(); // expected-error {{no viable}}
+ B b4 = convert_to<const volatile B>();
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{no viable}}
+#endif
B b5 = convert_to<const volatile B&>(); // expected-error {{no viable}}
+ A c1 = convert_to<B>();
+ A c2 = convert_to<B&>();
+ A c3 = convert_to<const B>();
+ A c4 = convert_to<const volatile B>(); // expected-error {{no viable}}
+ A c5 = convert_to<const volatile B&>(); // expected-error {{no viable}}
+
int n1 = convert_to<int>();
int n2 = convert_to<int&>();
int n3 = convert_to<const int>();
@@ -920,14 +935,17 @@ namespace dr84 { // dr84: yes
struct A { operator B() const; };
struct C {};
struct B {
- B(B&); // expected-note {{candidate}}
- B(C); // expected-note {{no known conversion from 'dr84::B' to 'dr84::C'}}
+ B(B&); // expected-note 0-1{{candidate}}
+ B(C); // expected-note 0-1{{no known conversion from 'dr84::B' to 'dr84::C'}}
operator C() const;
};
A a;
// Cannot use B(C) / operator C() pair to construct the B from the B temporary
- // here.
- B b = a; // expected-error {{no viable}}
+ // here. In C++1z, we initialize the B object directly using 'A::operator B()'.
+ B b = a;
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{no viable}}
+#endif
}
namespace dr85 { // dr85: yes
diff --git a/clang/test/CXX/drs/dr10xx.cpp b/clang/test/CXX/drs/dr10xx.cpp
index a1d7ef67c66..e11e796165e 100644
--- a/clang/test/CXX/drs/dr10xx.cpp
+++ b/clang/test/CXX/drs/dr10xx.cpp
@@ -3,8 +3,6 @@
// RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++1z %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
-// expected-no-diagnostics
-
namespace std {
__extension__ typedef __SIZE_TYPE__ size_t;
@@ -32,6 +30,18 @@ namespace dr1048 { // dr1048: 3.6
#endif
}
+namespace dr1054 { // dr1054: no
+ // FIXME: Test is incomplete.
+ struct A {} volatile a;
+ void f() {
+ // FIXME: This is wrong: an lvalue-to-rvalue conversion is applied here,
+ // which copy-initializes a temporary from 'a'. Therefore this is
+ // ill-formed because A does not have a volatile copy constructor.
+ // (We might want to track this aspect under dr1383 instead?)
+ a; // expected-warning {{assign into a variable to force a volatile load}}
+ }
+}
+
namespace dr1070 { // dr1070: 3.5
#if __cplusplus >= 201103L
struct A {
diff --git a/clang/test/CXX/drs/dr1xx.cpp b/clang/test/CXX/drs/dr1xx.cpp
index 58626c99780..9eb6b712f32 100644
--- a/clang/test/CXX/drs/dr1xx.cpp
+++ b/clang/test/CXX/drs/dr1xx.cpp
@@ -576,11 +576,18 @@ namespace dr151 { // dr151: yes
namespace dr152 { // dr152: yes
struct A {
- A(); // expected-note {{not viable}}
+ A(); // expected-note 0-2{{not viable}}
explicit A(const A&);
};
- A a1 = A(); // expected-error {{no matching constructor}}
+ A a1 = A();
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{no matching constructor}}
+#endif
A a2((A()));
+
+ A &f();
+ A a3 = f(); // expected-error {{no matching constructor}}
+ A a4(f());
}
// dr153: na
@@ -823,11 +830,20 @@ namespace dr176 { // dr176: yes
namespace dr177 { // dr177: yes
struct B {};
struct A {
- A(A &); // expected-note {{not viable: expects an l-value}}
- A(const B &); // expected-note {{not viable: no known conversion from 'dr177::A' to}}
+ A(A &); // expected-note 0-1{{not viable: expects an l-value}}
+ A(const B &); // expected-note 0-1{{not viable: no known conversion from 'dr177::A' to}}
};
B b;
- A a = b; // expected-error {{no viable constructor copying variable}}
+ A a = b;
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{no viable constructor copying variable}}
+#endif
+
+ struct C { C(C&); }; // expected-note {{not viable: no known conversion from 'dr177::D' to 'dr177::C &'}}
+ struct D : C {};
+ struct E { operator D(); };
+ E e;
+ C c = e; // expected-error {{no viable constructor copying variable of type 'dr177::D'}}
}
namespace dr178 { // dr178: yes
diff --git a/clang/test/CXX/drs/dr4xx.cpp b/clang/test/CXX/drs/dr4xx.cpp
index ff23ab39eac..759f1b5241c 100644
--- a/clang/test/CXX/drs/dr4xx.cpp
+++ b/clang/test/CXX/drs/dr4xx.cpp
@@ -553,12 +553,21 @@ namespace dr446 { // dr446: yes
void(b ? a : a);
b ? A() : a; // expected-error {{deleted}}
b ? a : A(); // expected-error {{deleted}}
- b ? A() : A(); // expected-error {{deleted}}
+ b ? A() : A();
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{deleted}}
+#endif
void(b ? a : c);
b ? a : C(); // expected-error {{deleted}}
- b ? c : A(); // expected-error {{deleted}}
- b ? A() : C(); // expected-error {{deleted}}
+ b ? c : A();
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{deleted}}
+#endif
+ b ? A() : C();
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{deleted}}
+#endif
}
}
@@ -874,10 +883,12 @@ namespace dr479 { // dr479: yes
void f() {
throw S();
// expected-error@-1 {{temporary of type 'dr479::S' has private destructor}}
- // expected-error@-2 {{calling a private constructor}}
- // expected-error@-3 {{exception object of type 'dr479::S' has private destructor}}
+ // expected-error@-2 {{exception object of type 'dr479::S' has private destructor}}
#if __cplusplus < 201103L
- // expected-error@-5 {{C++98 requires an accessible copy constructor}}
+ // expected-error@-4 {{C++98 requires an accessible copy constructor}}
+#endif
+#if __cplusplus <= 201402L
+ // expected-error@-7 {{calling a private constructor}} (copy ctor)
#endif
}
void g() {
diff --git a/clang/test/CodeGenCXX/cxx1z-copy-omission.cpp b/clang/test/CodeGenCXX/cxx1z-copy-omission.cpp
new file mode 100644
index 00000000000..234e4b12589
--- /dev/null
+++ b/clang/test/CodeGenCXX/cxx1z-copy-omission.cpp
@@ -0,0 +1,81 @@
+// RUN: %clang_cc1 -std=c++1z -emit-llvm -triple x86_64-linux-gnu -o - %s | FileCheck %s
+
+struct A {
+ A(int);
+ A(A&&);
+ A(const A&);
+ ~A();
+
+ int arr[10];
+};
+
+A f();
+void h();
+
+// CHECK-LABEL: define {{.*}} @_Z1gv(
+void g() {
+ // CHECK: %[[A:.*]] = alloca
+ // CHECK-NOT: alloca
+ // CHECK-NOT: call
+ // CHECK: call {{.*}} @_Z1fv({{.*}}* sret %[[A]])
+ A a = A( A{ f() } );
+ // CHECK-NOT: call
+
+ // CHECK: call void @_Z1hv(
+ h();
+ // CHECK-NOT: call
+
+ // CHECK: call void @_ZN1AD1Ev({{.*}}* %[[A]])
+ // CHECK-NOT: call
+ // CHECK-LABEL: }
+}
+
+void f(A);
+
+// CHECK-LABEL: define {{.*}} @_Z1hv(
+void h() {
+ // CHECK: %[[A:.*]] = alloca
+ // CHECK-NOT: alloca
+ // CHECK-NOT: call
+
+ // CHECK: call {{.*}} @_Z1fv({{.*}}* sret %[[A]])
+ // CHECK-NOT: call
+ // CHECK: call {{.*}} @_Z1f1A({{.*}}* %[[A]])
+ f(f());
+ // CHECK-NOT: call
+ // CHECK: call void @_ZN1AD1Ev({{.*}}* %[[A]])
+
+ // CHECK: call void @_Z1hv(
+ h();
+
+ // CHECK-NOT: call
+ // CHECK-LABEL: }
+}
+
+// We still pass classes with trivial copy/move constructors and destructors in
+// registers, even if the copy is formally omitted.
+struct B {
+ B(int);
+ int n;
+};
+
+B fB();
+void fB(B);
+
+// CHECK-LABEL: define {{.*}} @_Z1iv(
+void i() {
+ // CHECK: %[[B:.*]] = alloca
+ // CHECK-NOT: alloca
+ // CHECK-NOT: call
+
+ // CHECK: %[[B_N:.*]] = call i32 @_Z2fBv()
+ // CHECK-NOT: call
+ // CHECK: store i32 %[[B_N]],
+ // CHECK-NOT: call
+ // CHECK: %[[B_N:.*]] = load i32
+ // CHECK-NOT: call
+ // CHECK: call void @_Z2fB1B(i32 %[[B_N]])
+ fB(fB());
+
+ // CHECK-LABEL: }
+}
diff --git a/clang/test/SemaCXX/aggregate-initialization.cpp b/clang/test/SemaCXX/aggregate-initialization.cpp
index ddaf33fc1bf..b4169634663 100644
--- a/clang/test/SemaCXX/aggregate-initialization.cpp
+++ b/clang/test/SemaCXX/aggregate-initialization.cpp
@@ -57,7 +57,7 @@ struct A {
A(int);
~A();
- A(const A&) = delete; // expected-note 2 {{'A' has been explicitly marked deleted here}}
+ A(const A&) = delete; // expected-note 0-2{{'A' has been explicitly marked deleted here}}
};
struct B {
@@ -70,10 +70,16 @@ struct C {
void f() {
A as1[1] = { };
- A as2[1] = { 1 }; // expected-error {{copying array element of type 'A' invokes deleted constructor}}
+ A as2[1] = { 1 };
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{copying array element of type 'A' invokes deleted constructor}}
+#endif
B b1 = { };
- B b2 = { 1 }; // expected-error {{copying member subobject of type 'A' invokes deleted constructor}}
+ B b2 = { 1 };
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{copying member subobject of type 'A' invokes deleted constructor}}
+#endif
C c1 = { 1 };
}
diff --git a/clang/test/SemaCXX/cxx1z-copy-omission.cpp b/clang/test/SemaCXX/cxx1z-copy-omission.cpp
new file mode 100644
index 00000000000..fbcff942e78
--- /dev/null
+++ b/clang/test/SemaCXX/cxx1z-copy-omission.cpp
@@ -0,0 +1,134 @@
+// RUN: %clang_cc1 -std=c++1z -verify %s
+
+struct Noncopyable {
+ Noncopyable();
+ Noncopyable(const Noncopyable &) = delete; // expected-note 1+{{deleted}}
+ virtual ~Noncopyable();
+};
+struct Derived : Noncopyable {};
+struct NoncopyableAggr {
+ Noncopyable nc;
+};
+struct Indestructible {
+ Indestructible();
+ ~Indestructible() = delete; // expected-note 1+{{deleted}}
+};
+struct Incomplete; // expected-note 1+{{declar}}
+
+Noncopyable make(int kind = 0) {
+ switch (kind) {
+ case 0: return {};
+ case 1: return Noncopyable();
+ case 2: return Noncopyable{};
+ case 3: return make();
+ }
+ __builtin_unreachable();
+}
+
+Indestructible make_indestructible();
+Incomplete make_incomplete(); // expected-note 1+{{here}}
+
+void take(Noncopyable nc) {}
+
+Noncopyable nrvo() {
+ Noncopyable nrvo;
+ return nrvo; // expected-error {{deleted constructor}}
+}
+
+Noncopyable nc1 = make();
+Noncopyable nc2 = Noncopyable();
+Noncopyable nc3 = Derived(); // expected-error {{deleted constructor}}
+
+NoncopyableAggr nca1 = NoncopyableAggr{};
+NoncopyableAggr nca2 = NoncopyableAggr{{}};
+NoncopyableAggr nca3 = NoncopyableAggr{NoncopyableAggr{Noncopyable()}};
+
+void test_expressions(bool b) {
+ auto lambda = [a = make()] {};
+
+ take({});
+ take(Noncopyable());
+ take(Noncopyable{});
+ take(make());
+
+ Noncopyable &&dc1 = dynamic_cast<Noncopyable&&>(Noncopyable());
+ Noncopyable &&dc2 = dynamic_cast<Noncopyable&&>(nc1);
+ Noncopyable &&dc3 = dynamic_cast<Noncopyable&&>(Derived());
+
+ Noncopyable sc1 = static_cast<Noncopyable>(Noncopyable());
+ Noncopyable sc2 = static_cast<Noncopyable>(nc1); // expected-error {{deleted}}
+ Noncopyable sc3 = static_cast<Noncopyable&&>(Noncopyable()); // expected-error {{deleted}}
+ Noncopyable sc4 = static_cast<Noncopyable>(static_cast<Noncopyable&&>(Noncopyable())); // expected-error {{deleted}}
+
+ Noncopyable cc1 = (Noncopyable)Noncopyable();
+ Noncopyable cc2 = (Noncopyable)Derived(); // expected-error {{deleted}}
+
+ Noncopyable fc1 = Noncopyable(Noncopyable());
+ Noncopyable fc2 = Noncopyable(Derived()); // expected-error {{deleted}}
+
+ // We must check for a complete type for every materialized temporary. (Note
+ // that in the special case of the top level of a decltype, no temporary is
+ // materialized.)
+ make_incomplete(); // expected-error {{incomplete}}
+ make_incomplete().a; // expected-error {{incomplete}}
+ make_incomplete().*(int Incomplete::*)nullptr; // expected-error {{incomplete}}
+ dynamic_cast<Incomplete&&>(make_incomplete()); // expected-error {{incomplete}}
+ const_cast<Incomplete&&>(make_incomplete()); // expected-error {{incomplete}}
+
+ sizeof(Indestructible{}); // expected-error {{deleted}}
+ sizeof(make_indestructible()); // expected-error {{deleted}}
+ sizeof(make_incomplete()); // expected-error {{incomplete}}
+ typeid(Indestructible{}); // expected-error {{deleted}}
+ typeid(make_indestructible()); // expected-error {{deleted}}
+ typeid(make_incomplete()); // expected-error {{incomplete}}
+
+ // FIXME: The first two cases here are now also valid in C++17 onwards.
+ using I = decltype(Indestructible()); // expected-error {{deleted}}
+ using I = decltype(Indestructible{}); // expected-error {{deleted}}
+ using I = decltype(make_indestructible());
+ using J = decltype(make_incomplete());
+
+ Noncopyable cond1 = b ? Noncopyable() : make();
+ Noncopyable cond2 = b ? Noncopyable() : Derived(); // expected-error {{incompatible}}
+ Noncopyable cond3 = b ? Derived() : Noncopyable(); // expected-error {{incompatible}}
+ Noncopyable cond4 = b ? Noncopyable() : nc1; // expected-error {{deleted}}
+ Noncopyable cond5 = b ? nc1 : Noncopyable(); // expected-error {{deleted}}
+ // Could convert both to an xvalue of type Noncopyable here, but we're not
+ // permitted to consider that.
+ Noncopyable &&cond6 = b ? Noncopyable() : Derived(); // expected-error {{incompatible}}
+ Noncopyable &&cond7 = b ? Derived() : Noncopyable(); // expected-error {{incompatible}}
+ // Could convert both to a const lvalue of type Noncopyable here, but we're
+ // not permitted to consider that, either.
+ const Noncopyable cnc;
+ const Noncopyable &cond8 = b ? cnc : Derived(); // expected-error {{incompatible}}
+ const Noncopyable &cond9 = b ? Derived() : cnc; // expected-error {{incompatible}}
+
+ extern const volatile Noncopyable make_cv();
+ Noncopyable cv_difference1 = make_cv();
+ const volatile Noncopyable cv_difference2 = make();
+}
+
+template<typename T> struct ConversionFunction { operator T(); };
+Noncopyable cf1 = ConversionFunction<Noncopyable>();
+Noncopyable cf2 = ConversionFunction<Noncopyable&&>(); // expected-error {{deleted}}
+Noncopyable cf3 = ConversionFunction<const volatile Noncopyable>();
+const volatile Noncopyable cf4 = ConversionFunction<Noncopyable>();
+Noncopyable cf5 = ConversionFunction<Derived>(); // expected-error {{deleted}}
+
+struct AsMember {
+ Noncopyable member;
+ AsMember() : member(make()) {}
+};
+// FIXME: DR (no number yet): we still get a copy for base or delegating construction.
+struct AsBase : Noncopyable {
+ AsBase() : Noncopyable(make()) {} // expected-error {{deleted}}
+};
+struct AsDelegating final {
+ AsDelegating(const AsDelegating &) = delete;
+ static AsDelegating make(int);
+
+ // The base constructor version of this is problematic; the complete object
+ // version would be OK. Perhaps we could allow copy omission here for final
+ // classes?
+ AsDelegating(int n) : AsDelegating(make(n)) {} // expected-error {{deleted}}
+};
OpenPOWER on IntegriCloud