summaryrefslogtreecommitdiffstats
path: root/test/CXX
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2012-04-16 07:05:22 +0000
committerDouglas Gregor <dgregor@apple.com>2012-04-16 07:05:22 +0000
commitcefc3afac14d29de5aba7810cc8fe6c858949e9d (patch)
tree1ebfb2a0c67f5e253edc1a2900cdda348163f4f5 /test/CXX
parent275a8505420733a9e4c662289f36522a1dabaa51 (diff)
Implement C++11 [expr.prim.general]p3, which permits the use of 'this'
in the declaration of a non-static member function after the (optional) cv-qualifier-seq, which in practice means in the exception specification and late-specified return type. The new scheme here used to manage 'this' outside of a member function scope is more general than the Scope-based mechanism previously used for non-static data member initializers and late-parsesd attributes, because it can also handle the cv-qualifiers on the member function. Note, however, that a separate pass is required for static member functions to determine whether 'this' was used, because we might not know that we have a static function until after declaration matching. Finally, this introduces name mangling for 'this' and for the implicit 'this', which is intended to match GCC's mangling. Independent verification for the new mangling test case would be appreciated. Fixes PR10036 and PR12450. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154799 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CXX')
-rw-r--r--test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp90
1 files changed, 90 insertions, 0 deletions
diff --git a/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp b/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp
new file mode 100644
index 0000000000..f00e358f3a
--- /dev/null
+++ b/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp
@@ -0,0 +1,90 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
+
+struct A {
+ int &f(int*);
+ float &f(int*) const noexcept;
+
+ int *ptr;
+ auto g1() noexcept(noexcept(f(ptr))) -> decltype(f(this->ptr));
+ auto g2() const noexcept(noexcept(f((*this).ptr))) -> decltype(f(ptr));
+};
+
+void testA(A &a) {
+ int &ir = a.g1();
+ float &fr = a.g2();
+ static_assert(!noexcept(a.g1()), "exception-specification failure");
+ static_assert(noexcept(a.g2()), "exception-specification failure");
+}
+
+struct B {
+ char g();
+ template<class T> auto f(T t) -> decltype(t + g())
+ { return t + g(); }
+};
+
+template auto B::f(int t) -> decltype(t + g());
+
+template<typename T>
+struct C {
+ int &f(T*);
+ float &f(T*) const noexcept;
+
+ T* ptr;
+ auto g1() noexcept(noexcept(f(ptr))) -> decltype(f((*this).ptr));
+ auto g2() const noexcept(noexcept(f(((this))->ptr))) -> decltype(f(ptr));
+};
+
+void test_C(C<int> ci) {
+ int *p = 0;
+ int &ir = ci.g1();
+ float &fr = ci.g2();
+ static_assert(!noexcept(ci.g1()), "exception-specification failure");
+ static_assert(noexcept(ci.g2()), "exception-specification failure");
+}
+
+namespace PR10036 {
+ template <class I>
+ void
+ iter_swap(I x, I y) noexcept;
+
+ template <class T>
+ class A
+ {
+ T t_;
+ public:
+ void swap(A& a) noexcept(noexcept(iter_swap(&t_, &a.t_)));
+ };
+
+ void test() {
+ A<int> i, j;
+ i.swap(j);
+ }
+}
+
+namespace Static {
+ struct X1 {
+ int m;
+ static auto f() -> decltype(m); // expected-error{{'this' cannot be implicitly used in a static member function declaration}}
+ static auto g() -> decltype(this->m); // expected-error{{'this' cannot be used in a static member function declaration}}
+
+ static int h();
+
+ static int i() noexcept(noexcept(m + 2)); // expected-error{{'this' cannot be implicitly used in a static member function declaration}}
+ };
+
+ auto X1::h() -> decltype(m) { return 0; } // expected-error{{'this' cannot be implicitly used in a static member function declaration}}
+
+ template<typename T>
+ struct X2 {
+ int m;
+
+ T f(T*);
+ static T f(int);
+
+ auto g(T x) -> decltype(f(x)) { return 0; }
+ };
+
+ void test_X2() {
+ X2<int>().g(0);
+ }
+}