2020-03-24 06:05:38 +08:00
// RUN: %clang_cc1 -emit-llvm-only -verify -std=c++11 %s
2009-08-27 03:22:42 +08:00
struct A { } ;
enum Foo { F } ;
2020-02-08 08:34:08 +08:00
typedef Foo Bar ; // expected-note{{type 'Bar' (aka 'Foo') found by destructor name lookup}}
2009-08-27 03:22:42 +08:00
2009-09-05 01:36:40 +08:00
typedef int Integer ;
2010-02-22 02:36:56 +08:00
typedef double Double ;
2009-09-05 01:36:40 +08:00
void g ( ) ;
namespace N {
typedef Foo Wibble ;
2010-02-25 05:29:12 +08:00
typedef int OtherInteger ;
2009-09-05 01:36:40 +08:00
}
2010-06-12 01:36:40 +08:00
template < typename T >
void cv_test ( const volatile T * cvt ) {
cvt - > T : : ~ T ( ) ; // no-warning
}
2011-12-17 00:03:09 +08:00
void f ( A * a , Foo * f , int * i , double * d , int ii ) {
2009-08-27 03:22:42 +08:00
a - > ~ A ( ) ;
a - > A : : ~ A ( ) ;
2020-02-08 08:34:08 +08:00
a - > ~ foo ( ) ; // expected-error{{undeclared identifier 'foo' in destructor name}}
2009-09-05 01:36:40 +08:00
2011-03-05 06:32:08 +08:00
a - > ~ Bar ( ) ; // expected-error{{destructor type 'Bar' (aka 'Foo') in object destruction expression does not match the type 'A' of the object being destroyed}}
2009-09-05 01:36:40 +08:00
f - > ~ Bar ( ) ;
f - > ~ Foo ( ) ;
i - > ~ Bar ( ) ; // expected-error{{does not match}}
g ( ) . ~ Bar ( ) ; // expected-error{{non-scalar}}
2020-01-25 07:14:25 +08:00
f - > : : ~ Bar ( ) ; // expected-error {{not a structure or union}}
f - > : : Bar : : ~ Bar ( ) ;
2019-08-15 06:57:50 +08:00
f - > N : : ~ Wibble ( ) ; // expected-error{{'N' does not refer to a type}} expected-error{{'Wibble' does not refer to a type}}
2009-09-05 01:36:40 +08:00
2020-01-25 07:14:25 +08:00
f - > Bar : : ~ Bar ( 17 , 42 ) ; // expected-error{{cannot have any arguments}}
2010-02-22 02:36:56 +08:00
i - > ~ Integer ( ) ;
i - > Integer : : ~ Integer ( ) ;
2020-01-25 07:14:25 +08:00
i - > N : : ~ OtherInteger ( ) ; // expected-error{{'N' does not refer to a type name in pseudo-destructor expression; expected the name of type 'int'}}
// expected-error@-1{{'OtherInteger' does not refer to a type name in pseudo-destructor expression; expected the name of type 'int'}}
2010-02-25 05:29:12 +08:00
i - > N : : OtherInteger : : ~ OtherInteger ( ) ;
2020-01-25 07:14:25 +08:00
i - > N : : OtherInteger : : ~ OtherInteger ( ) ;
i - > N : : OtherInteger : : ~ Integer ( ) ; // expected-error{{'Integer' does not refer to a type name in pseudo-destructor expression; expected the name of type 'int'}}
i - > N : : ~ Integer ( ) ; // expected-error{{'N' does not refer to a type name in pseudo-destructor expression; expected the name of type 'int'}}
2010-02-25 05:29:12 +08:00
i - > N : : OtherInteger : : ~ Integer ( ) ; // expected-error{{'Integer' does not refer to a type name in pseudo-destructor expression; expected the name of type 'int'}}
i - > Integer : : ~ Double ( ) ; // expected-error{{the type of object expression ('int') does not match the type being destroyed ('Double' (aka 'double')) in pseudo-destructor expression}}
2010-06-12 01:36:40 +08:00
2015-04-03 06:10:06 +08:00
ii - > ~ Integer ( ) ; // expected-error{{member reference type 'int' is not a pointer; did you mean to use '.'?}}
2011-12-17 00:03:09 +08:00
ii . ~ Integer ( ) ;
2010-06-12 01:36:40 +08:00
cv_test ( a ) ;
cv_test ( f ) ;
cv_test ( i ) ;
cv_test ( d ) ;
2009-08-27 03:22:42 +08:00
}
2009-09-05 02:29:40 +08:00
2010-06-12 01:36:40 +08:00
2009-09-05 02:29:40 +08:00
typedef int Integer ;
void destroy_without_call ( int * ip ) {
2015-02-26 01:36:15 +08:00
ip - > ~ Integer ; // expected-error{{reference to pseudo-destructor must be called}}
}
void paren_destroy_with_call ( int * ip ) {
( ip - > ~ Integer ) ( ) ;
2009-11-08 09:45:36 +08:00
}
2009-11-21 06:03:38 +08:00
// PR5530
namespace N1 {
class X0 { } ;
}
void test_X0 ( N1 : : X0 & x0 ) {
x0 . ~ X0 ( ) ;
}
2010-06-12 01:36:40 +08:00
2011-11-09 10:19:47 +08:00
namespace PR11339 {
template < class T >
void destroy ( T * p ) {
p - > ~ T ( ) ; // ok
2020-02-08 08:34:08 +08:00
p - > ~ oops ( ) ; // expected-error{{undeclared identifier 'oops' in destructor name}}
2011-11-09 10:19:47 +08:00
}
template void destroy ( int * ) ; // expected-note{{in instantiation of function template specialization}}
}
2012-11-15 08:31:27 +08:00
template < typename T > using Id = T ;
void AliasTemplate ( int * p ) {
p - > ~ Id < int > ( ) ;
2020-03-24 06:05:38 +08:00
p - > template ~ Id < int > ( ) ; // expected-error {{'template' keyword not permitted in destructor name}}
( 0 ) . ~ Id < int > ( ) ;
( 0 ) . template ~ Id < int > ( ) ; // expected-error {{'template' keyword not permitted in destructor name}}
2012-11-15 08:31:27 +08:00
}
2017-01-20 23:38:58 +08:00
namespace dotPointerAccess {
struct Base {
virtual ~ Base ( ) { }
} ;
struct Derived : Base {
~ Derived ( ) { }
} ;
void test ( ) {
Derived d ;
static_cast < Base * > ( & d ) . ~ Base ( ) ; // expected-error {{member reference type 'dotPointerAccess::Base *' is a pointer; did you mean to use '->'}}
d - > ~ Derived ( ) ; // expected-error {{member reference type 'dotPointerAccess::Derived' is not a pointer; did you mean to use '.'}}
}
typedef Derived * Foo ;
void test2 ( Foo d ) {
d . ~ Foo ( ) ; // This is ok
2017-03-10 23:04:58 +08:00
d . ~ Derived ( ) ; // expected-error {{member reference type 'dotPointerAccess::Foo' (aka 'dotPointerAccess::Derived *') is a pointer; did you mean to use '->'}}
2017-01-20 23:38:58 +08:00
}
}
2020-03-28 11:59:49 +08:00
int pr45294 = 1 . ~ undeclared_tempate_name < > ( ) ; // expected-error {{use of undeclared 'undeclared_tempate_name'}}
namespace TwoPhaseLookup {
namespace NonTemplate {
struct Y { } ;
using G = Y ;
template < typename T > void f ( T * p ) { p - > ~ G ( ) ; } // expected-error {{no member named '~Y'}}
void h1 ( Y * p ) { p - > ~ G ( ) ; }
void h2 ( Y * p ) { f ( p ) ; }
namespace N { struct G { } ; }
void h3 ( N : : G * p ) { p - > ~ G ( ) ; }
void h4 ( N : : G * p ) { f ( p ) ; } // expected-note {{instantiation of}}
}
namespace NonTemplateUndeclared {
struct Y { } ;
template < typename T > void f ( T * p ) { p - > ~ G ( ) ; } // expected-error {{undeclared identifier 'G' in destructor name}}
using G = Y ;
void h1 ( Y * p ) { p - > ~ G ( ) ; }
void h2 ( Y * p ) { f ( p ) ; } // expected-note {{instantiation of}}
namespace N { struct G { } ; }
void h3 ( N : : G * p ) { p - > ~ G ( ) ; }
void h4 ( N : : G * p ) { f ( p ) ; }
}
namespace Template {
template < typename T > struct Y { } ;
template < class U > using G = Y < U > ;
template < typename T > void f ( T * p ) { p - > ~ G < int > ( ) ; } // expected-error {{no member named '~Y'}}
void h1 ( Y < int > * p ) { p - > ~ G < int > ( ) ; }
void h2 ( Y < int > * p ) { f ( p ) ; }
namespace N { template < typename T > struct G { } ; }
void h3 ( N : : G < int > * p ) { p - > ~ G < int > ( ) ; }
void h4 ( N : : G < int > * p ) { f ( p ) ; } // expected-note {{instantiation of}}
}
namespace TemplateUndeclared {
template < typename T > struct Y { } ;
// FIXME: Formally, this is ill-formed before we hit any instantiation,
// because we aren't supposed to treat the '<' as introducing a template
// name.
template < typename T > void f ( T * p ) { p - > ~ G < int > ( ) ; } // expected-error {{no member named 'G'}}
template < class U > using G = Y < U > ;
void h1 ( Y < int > * p ) { p - > ~ G < int > ( ) ; }
void h2 ( Y < int > * p ) { f ( p ) ; } // expected-note {{instantiation of}}
namespace N { template < typename T > struct G { } ; }
void h3 ( N : : G < int > * p ) { p - > ~ G < int > ( ) ; }
void h4 ( N : : G < int > * p ) { f ( p ) ; }
}
2020-03-30 04:13:57 +08:00
namespace TemplateNamesNonTemplate {
int A ; // expected-note 2{{non-template here}}
template < typename > int B ; // expected-note 2{{variable template 'B' declared here}} expected-warning {{extension}}
using C = int ; // expected-note 2{{non-template here}}
template < typename T > void f1 ( int * p ) { p - > ~ A < int > ( ) ; } // expected-error {{'A' does not refer to a template}}
template < typename T > void f2 ( int * p ) { p - > ~ B < int > ( ) ; } // expected-error {{template name refers to non-type template 'B'}}
template < typename T > void f3 ( int * p ) { p - > ~ C < int > ( ) ; } // expected-error {{'C' does not refer to a template}}
template < typename T > void f4 ( int * p ) { p - > TemplateNamesNonTemplate : : C : : ~ A < int > ( ) ; } // expected-error {{'A' does not refer to a template}}
template < typename T > void f5 ( int * p ) { p - > TemplateNamesNonTemplate : : C : : ~ B < int > ( ) ; } // expected-error {{template name refers to non-type template 'TemplateNamesNonTemplate::B'}}
template < typename T > void f6 ( int * p ) { p - > TemplateNamesNonTemplate : : C : : ~ C < int > ( ) ; } // expected-error {{'C' does not refer to a template}}
}
2020-03-28 11:59:49 +08:00
}