diff options
| author | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-12-12 01:27:02 +0000 |
|---|---|---|
| committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-12-12 01:27:02 +0000 |
| commit | c934e4fd2ce25d0fece0e7aa04c4a4c52edb62ff (patch) | |
| tree | 5196b803467306420fc6f2bab5e3f4dbb4fa8852 /clang/test | |
| parent | 49e69ee557ad492d7a36319671f85b88b9f66827 (diff) | |
| download | bcm5719-llvm-c934e4fd2ce25d0fece0e7aa04c4a4c52edb62ff.tar.gz bcm5719-llvm-c934e4fd2ce25d0fece0e7aa04c4a4c52edb62ff.zip | |
PR18217: Rewrite JumpDiagnostics' handling of temporaries, to correctly handle
declarations that might lifetime-extend multiple temporaries. In passing, fix a
crasher (PR18217) if an initializer was dependent and exactly the wrong shape,
and remove a bogus function (Expr::findMaterializedTemporary) now its last use
is gone.
llvm-svn: 197103
Diffstat (limited to 'clang/test')
| -rw-r--r-- | clang/test/SemaCXX/scope-check.cpp | 118 |
1 files changed, 116 insertions, 2 deletions
diff --git a/clang/test/SemaCXX/scope-check.cpp b/clang/test/SemaCXX/scope-check.cpp index 90c9317ecdf..c5fdb09f237 100644 --- a/clang/test/SemaCXX/scope-check.cpp +++ b/clang/test/SemaCXX/scope-check.cpp @@ -226,7 +226,7 @@ namespace test12 { static void *ips[] = { &&l0 }; const C c0 = 17; l0: // expected-note {{possible target of indirect goto}} - const C &c1 = 42; // expected-note {{jump exits scope of variable with non-trivial destructor}} + const C &c1 = 42; // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}} const C &c2 = c0; goto *ip; // expected-error {{indirect goto might cross protected scopes}} } @@ -241,7 +241,7 @@ namespace test13 { void f(void **ip) { static void *ips[] = { &&l0 }; l0: // expected-note {{possible target of indirect goto}} - const int &c1 = C(1).i; // expected-note {{jump exits scope of variable with non-trivial destructor}} + const int &c1 = C(1).i; // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}} goto *ip; // expected-error {{indirect goto might cross protected scopes}} } } @@ -295,6 +295,120 @@ x: return s.get(); } #endif +namespace test18 { + struct A { ~A(); }; + struct B { const int &r; const A &a; }; + int f() { + void *p = &&x; + const A a = A(); + x: + B b = { 0, a }; // ok + goto *p; + } + int g() { + void *p = &&x; + x: // expected-note {{possible target of indirect goto}} + B b = { 0, A() }; // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}} + goto *p; // expected-error {{indirect goto might cross protected scopes}} + } +} + +#if __cplusplus >= 201103L +namespace std { + typedef decltype(sizeof(int)) size_t; + template<typename T> struct initializer_list { + const T *begin; + size_t size; + initializer_list(const T *, size_t); + }; +} +namespace test19 { + struct A { ~A(); }; + + int f() { + void *p = &&x; + A a; + x: // expected-note {{possible target of indirect goto}} + std::initializer_list<A> il = { a }; // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}} + goto *p; // expected-error {{indirect goto might cross protected scopes}} + } +} + +namespace test20 { + struct A { ~A(); }; + struct B { + const A &a; + }; + + int f() { + void *p = &&x; + A a; + x: + std::initializer_list<B> il = { + a, + a + }; + goto *p; + } + int g() { + void *p = &&x; + A a; + x: // expected-note {{possible target of indirect goto}} + std::initializer_list<B> il = { + a, + { A() } // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}} + }; + goto *p; // expected-error {{indirect goto might cross protected scopes}} + } +} +#endif + +namespace test21 { + template<typename T> void f() { + goto x; // expected-error {{protected scope}} + T t; // expected-note {{bypasses}} + x: return; + } + + template void f<int>(); + struct X { ~X(); }; + template void f<X>(); // expected-note {{instantiation of}} +} + +namespace PR18217 { + typedef int *X; + + template <typename T> + class MyCl { + T mem; + }; + + class Source { + MyCl<X> m; + public: + int getKind() const; + }; + + bool b; + template<typename TT> + static void foo(const Source &SF, MyCl<TT *> Source::*m) { + switch (SF.getKind()) { + case 1: return; + case 2: break; + case 3: + case 4: return; + }; + if (b) { + auto &y = const_cast<MyCl<TT *> &>(SF.*m); // expected-warning 0-1{{extension}} + } + } + + int Source::getKind() const { + foo(*this, &Source::m); + return 0; + } +} + // This test must be last, because the error prohibits further jump diagnostics. namespace testInvalid { Invalid inv; // expected-error {{unknown type name}} |

