summaryrefslogtreecommitdiffstats
path: root/clang/test/CXX/dcl.decl/dcl.decomp/p4.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test/CXX/dcl.decl/dcl.decomp/p4.cpp')
-rw-r--r--clang/test/CXX/dcl.decl/dcl.decomp/p4.cpp173
1 files changed, 173 insertions, 0 deletions
diff --git a/clang/test/CXX/dcl.decl/dcl.decomp/p4.cpp b/clang/test/CXX/dcl.decl/dcl.decomp/p4.cpp
new file mode 100644
index 00000000000..3a72ae0e33a
--- /dev/null
+++ b/clang/test/CXX/dcl.decl/dcl.decomp/p4.cpp
@@ -0,0 +1,173 @@
+// RUN: %clang_cc1 -std=c++1z -verify -triple i686-linux-gnu %s
+
+template<typename T, typename U> struct same;
+template<typename T> struct same<T, T> { ~same(); };
+
+struct Empty {};
+
+struct A {
+ int a;
+};
+
+namespace NonPublicMembers {
+ struct NonPublic1 {
+ protected:
+ int a; // expected-note {{declared protected here}}
+ };
+
+ struct NonPublic2 {
+ private:
+ int a; // expected-note 2{{declared private here}}
+ };
+
+ struct NonPublic3 : private A {}; // expected-note {{constrained by private inheritance}}
+
+ struct NonPublic4 : NonPublic2 {};
+
+ void test() {
+ auto [a1] = NonPublic1(); // expected-error {{cannot decompose non-public member 'a' of 'NonPublicMembers::NonPublic1'}}
+ auto [a2] = NonPublic2(); // expected-error {{cannot decompose non-public member 'a' of 'NonPublicMembers::NonPublic2'}}
+ auto [a3] = NonPublic3(); // expected-error {{cannot decompose members of non-public base class 'A' of 'NonPublic3'}}
+ auto [a4] = NonPublic4(); // expected-error {{cannot decompose non-public member 'a' of 'NonPublicMembers::NonPublic4'}}
+ }
+}
+
+namespace MultipleClasses {
+ struct B : A {
+ int a;
+ };
+
+ struct C { int a; };
+ struct D : A, C {};
+
+ struct E : virtual A {};
+ struct F : A, E {}; // expected-warning {{direct base 'A' is inaccessible due to ambiguity}}
+
+ struct G : virtual A {};
+ struct H : E, G {};
+
+ struct I { int i; };
+ struct J : I {};
+ struct K : I, virtual J {}; // expected-warning {{direct base 'MultipleClasses::I' is inaccessible due to ambiguity}}
+
+ struct L : virtual J {};
+ struct M : virtual J, L {};
+
+ void test() {
+ auto [b] = B(); // expected-error {{cannot decompose class type 'B': both it and its base class 'A' have non-static data members}}
+ auto [d] = D(); // expected-error {{cannot decompose class type 'D': its base classes 'A' and 'MultipleClasses::C' have non-static data members}}
+ auto [e] = E();
+ auto [f] = F(); // expected-error-re {{cannot decompose members of ambiguous base class 'A' of 'F':{{.*}}struct MultipleClasses::F -> struct A{{.*}}struct MultipleClasses::F -> struct MultipleClasses::E -> struct A}}
+ auto [h] = H(); // ok, only one (virtual) base subobject even though there are two paths to it
+ auto [k] = K(); // expected-error {{cannot decompose members of ambiguous base class 'MultipleClasses::I'}}
+ auto [m] = M(); // ok, all paths to I are through the same virtual base subobject J
+
+ same<decltype(m), int>();
+ }
+}
+
+namespace BindingTypes {
+ struct A {
+ int i = 0;
+ int &r = i;
+ const float f = i;
+ mutable volatile int mvi;
+ };
+ void e() {
+ auto [i,r,f,mvi] = A();
+
+ same<decltype(i), int>();
+ same<decltype(r), int&>();
+ same<decltype(f), const float>();
+ same<decltype(mvi), volatile int>();
+
+ same<decltype((i)), int&>();
+ same<decltype((r)), int&>();
+ same<decltype((f)), const float&>();
+ same<decltype((mvi)), volatile int&>();
+ }
+ void f() {
+ auto &&[i,r,f,mvi] = A();
+
+ same<decltype(i), int>();
+ same<decltype(r), int&>();
+ same<decltype(f), const float>();
+ same<decltype(mvi), volatile int>();
+
+ same<decltype((i)), int&>();
+ same<decltype((r)), int&>();
+ same<decltype((f)), const float&>();
+ same<decltype((mvi)), volatile int&>();
+ }
+ void g() {
+ const auto [i,r,f,mvi] = A();
+
+ same<decltype(i), const int>();
+ same<decltype(r), int&>();
+ same<decltype(f), const float>();
+ same<decltype(mvi), volatile int>(); // not 'const volatile int', per expected resolution of DRxxx
+
+ same<decltype((i)), const int&>();
+ same<decltype((r)), int&>();
+ same<decltype((f)), const float&>();
+ same<decltype((mvi)), volatile int&>(); // not 'const volatile int&', per expected resolution of DRxxx
+ }
+ void h() {
+ typedef const A CA;
+ auto &[i,r,f,mvi] = CA(); // type of var is 'const A &'
+
+ same<decltype(i), const int>(); // not 'int', per expected resolution of DRxxx
+ same<decltype(r), int&>();
+ same<decltype(f), const float>();
+ same<decltype(mvi), volatile int>(); // not 'const volatile int', per expected resolution of DRxxx
+
+ same<decltype((i)), const int&>(); // not 'int&', per expected resolution of DRxxx
+ same<decltype((r)), int&>();
+ same<decltype((f)), const float&>();
+ same<decltype((mvi)), volatile int&>(); // not 'const volatile int&', per expected resolution of DRxxx
+ }
+ struct B {
+ mutable int i;
+ };
+ void mut() {
+ auto [i] = B();
+ const auto [ci] = B();
+ volatile auto [vi] = B();
+ same<decltype(i), int>();
+ same<decltype(ci), int>();
+ same<decltype(vi), volatile int>();
+ }
+}
+
+namespace Bitfield {
+ struct S { unsigned long long x : 4, y : 32; int z; }; // expected-note 2{{here}}
+ int f(S s) {
+ auto [a, b, c] = s;
+ unsigned long long &ra = a; // expected-error {{bit-field 'x'}}
+ unsigned long long &rb = b; // expected-error {{bit-field 'y'}}
+ int &rc = c;
+
+ // the type of the binding is the type of the field
+ same<decltype(a), unsigned long long>();
+ same<decltype(b), unsigned long long>();
+
+ // the type of the expression is an lvalue of the field type
+ // (even though a reference can't bind to the field)
+ same<decltype((a)), unsigned long long&>();
+ same<decltype((b)), unsigned long long&>();
+
+ // the expression promotes to a type large enough to hold the result
+ same<decltype(+a), int>();
+ same<decltype(+b), unsigned int>();
+ return rc;
+ }
+}
+
+namespace std_example {
+ struct S { int x1 : 2; volatile double y1; };
+ S f();
+ const auto [x, y] = f();
+
+ same<decltype((x)), const int&> same1;
+ same<decltype((y)), const volatile double&> same2;
+}
OpenPOWER on IntegriCloud