summaryrefslogtreecommitdiffstats
path: root/clang/test/CXX
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-02-22 02:04:18 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-02-22 02:04:18 +0000
commitfd555f6b1fd950eff620e74da887dc37d919a276 (patch)
tree3c3ce70944db709410b9c1753550d399b57aae6c /clang/test/CXX
parent3715c691b3f4e88d05ae92d7b831cfceb5865285 (diff)
downloadbcm5719-llvm-fd555f6b1fd950eff620e74da887dc37d919a276.tar.gz
bcm5719-llvm-fd555f6b1fd950eff620e74da887dc37d919a276.zip
Implement C++11 [expr.call]p11: If the operand to a decltype-specifier is a
function call (or a comma expression with a function call on its right-hand side), possibly parenthesized, then the return type is not required to be complete and a temporary is not bound. Other subexpressions inside a decltype expression do not get this treatment. This is implemented by deferring the relevant checks for all calls immediately within a decltype expression, then, when the expression is fully-parsed, checking the relevant constraints and stripping off any top-level temporary binding. Deferring the completion of the return type exposed a bug in overload resolution where completion of the argument types was not attempted, which is also fixed by this change. llvm-svn: 151117
Diffstat (limited to 'clang/test/CXX')
-rw-r--r--clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p5-cxx0x.cpp108
1 files changed, 108 insertions, 0 deletions
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p5-cxx0x.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p5-cxx0x.cpp
new file mode 100644
index 00000000000..2bd5d234ce7
--- /dev/null
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p5-cxx0x.cpp
@@ -0,0 +1,108 @@
+// RUN: %clang_cc1 -std=c++11 -verify %s
+
+namespace std_example {
+
+template<class T> struct A { ~A() = delete; }; // expected-note {{deleted here}}
+template<class T> auto h() -> A<T>;
+template<class T> auto i(T) -> T;
+template<class T> auto f(T) -> decltype(i(h<T>())); // #1
+template<class T> auto f(T) -> void; // #2
+auto g() -> void {
+ f(42); // ok, calls #2, since #1 is not viable.
+}
+template<class T> auto q(T) -> decltype((h<T>()));
+void r() {
+ // Deduction against q succeeds, but results in a temporary which can't be
+ // destroyed.
+ q(42); // expected-error {{attempt to use a deleted function}}
+}
+
+}
+
+class PD {
+ friend struct A;
+ ~PD(); // expected-note 4{{here}}
+public:
+ typedef int n;
+};
+struct DD {
+ ~DD() = delete; // expected-note 2{{here}}
+ typedef int n;
+};
+
+struct A {
+ decltype(PD()) s; // ok
+ decltype(PD())::n n; // ok
+ decltype(DD()) *p = new decltype(DD()); // ok
+};
+
+// Two errors here: one for the decltype, one for the variable.
+decltype(PD(), PD()) pd1; // expected-error 2{{private destructor}}
+decltype(DD(), DD()) dd1; // expected-error 2{{deleted function}}
+
+decltype(((13, ((DD())))))::n dd_parens; // ok
+decltype(((((42)), PD())))::n pd_parens_comma; // ok
+
+// Ensure parens aren't stripped from a decltype node.
+extern decltype(PD()) pd_ref; // ok
+decltype((pd_ref)) pd_ref3 = pd_ref; // ok, PD &
+decltype(pd_ref) pd_ref2 = pd_ref; // expected-error {{private destructor}}
+
+namespace libcxx_example {
+ struct nat {
+ nat() = delete;
+ nat(const nat&) = delete;
+ nat &operator=(const nat&) = delete;
+ ~nat() = delete;
+ };
+ struct any {
+ any(...);
+ };
+
+ template<typename T, typename U> struct is_same { static const bool value = false; };
+ template<typename T> struct is_same<T, T> { static const bool value = true; };
+
+ template<typename T> T declval();
+
+ void swap(int &a, int &b);
+ nat swap(any, any);
+
+ template<typename T> struct swappable {
+ typedef decltype(swap(declval<T&>(), declval<T&>())) type;
+ static const bool value = !is_same<type, nat>::value;
+ constexpr operator bool() { return value; }
+ };
+
+ static_assert(swappable<int>(), "");
+ static_assert(!swappable<const int>(), "");
+}
+
+namespace RequireCompleteType {
+ template<int N, bool OK> struct S {
+ static_assert(OK, "boom!"); // expected-error 2{{boom!}}
+ };
+
+ template<typename T> T make();
+ template<int N, bool OK> S<N, OK> make();
+ void consume(...);
+
+ decltype(make<0, false>()) *p1; // ok
+ decltype((make<1, false>())) *p2; // ok
+
+ // A complete type is required here in order to detect an overloaded 'operator,'.
+ decltype(123, make<2, false>()) *p3; // expected-note {{here}}
+
+ decltype(consume(make<3, false>())) *p4; // expected-note {{here}}
+
+ decltype(make<decltype(make<4, false>())>()) *p5; // ok
+}
+
+namespace Overload {
+ DD operator+(PD &a, PD &b);
+ decltype(PD()) *pd_ptr;
+ decltype(*pd_ptr + *pd_ptr) *dd_ptr; // ok
+
+ decltype(0, *pd_ptr) pd_ref2 = pd_ref; // ok
+ DD operator,(int a, PD b);
+ decltype(0, *pd_ptr) *dd_ptr2; // expected-error {{private destructor}}
+}
OpenPOWER on IntegriCloud