2009-12-16 04:14:24 +08:00
// RUN: %clang_cc1 -fsyntax-only -verify %s
2016-04-14 04:00:45 +08:00
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
2009-05-20 03:05:47 +08:00
2016-04-14 04:00:45 +08:00
struct A { int x ; } ;
// expected-note@-1 {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const A' for 1st argument}}
# if __cplusplus >= 201103L
// expected-note@-3 {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int' to 'A' for 1st argument}}
# endif
// expected-note@-5 {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}}
2009-05-20 03:05:47 +08:00
class Base {
public :
virtual void f ( ) ;
} ;
class Derived : public Base { } ;
struct ConvertibleToInt {
operator int ( ) const ;
} ;
struct Constructible {
Constructible ( int , float ) ;
} ;
// ---------------------------------------------------------------------
// C-style casts
// ---------------------------------------------------------------------
template < typename T , typename U >
struct CStyleCast0 {
void f ( T t ) {
2011-02-15 02:34:10 +08:00
( void ) ( ( U ) t ) ; // expected-error{{cannot convert 'A' to 'int' without a conversion operator}}
2009-05-20 03:05:47 +08:00
}
} ;
template struct CStyleCast0 < int , float > ;
template struct CStyleCast0 < A , int > ; // expected-note{{instantiation}}
// ---------------------------------------------------------------------
// static_cast
// ---------------------------------------------------------------------
template < typename T , typename U >
struct StaticCast0 {
void f ( T t ) {
2011-02-15 02:34:10 +08:00
( void ) static_cast < U > ( t ) ; // expected-error{{no matching conversion for static_cast from 'int' to 'A'}}
2009-05-20 03:05:47 +08:00
}
} ;
template struct StaticCast0 < ConvertibleToInt , bool > ;
template struct StaticCast0 < int , float > ;
template struct StaticCast0 < int , A > ; // expected-note{{instantiation}}
// ---------------------------------------------------------------------
// dynamic_cast
// ---------------------------------------------------------------------
template < typename T , typename U >
struct DynamicCast0 {
void f ( T t ) {
2019-11-04 23:26:21 +08:00
( void ) dynamic_cast < U > ( t ) ; // expected-error{{invalid target type 'A' for dynamic_cast; target type must be a reference or pointer type to a defined class}}
2009-05-20 03:05:47 +08:00
}
} ;
template struct DynamicCast0 < Base * , Derived * > ;
template struct DynamicCast0 < Base * , A > ; // expected-note{{instantiation}}
// ---------------------------------------------------------------------
// reinterpret_cast
// ---------------------------------------------------------------------
template < typename T , typename U >
struct ReinterpretCast0 {
void f ( T t ) {
Implement appropriate semantics for C++ casting and conversion when
dealing with address-space- and GC-qualified pointers. Previously,
these qualifiers were being treated just like cvr-qualifiers (in some
cases) or were completely ignored, leading to uneven behavior. For
example, const_cast would allow conversion between pointers to
different address spaces.
The new semantics are fairly simple: reinterpret_cast can be used to
explicitly cast between pointers to different address spaces
(including adding/removing addresss spaces), while
static_cast/dynamic_cast/const_cast do not tolerate any changes in the
address space. C-style casts can add/remove/change address spaces
through the reinterpret_cast mechanism. Other non-CVR qualifiers
(e.g., Objective-C GC qualifiers) work similarly.
As part of this change, I tweaked the "casts away constness"
diagnostic to use the term "casts away qualifiers". The term
"constness" actually comes from the C++ standard, despite the fact
that removing "volatile" also falls under that category. In Clang, we
also have restrict, address spaces, ObjC GC attributes, etc., so the
more general "qualifiers" is clearer.
llvm-svn: 129583
2011-04-16 01:59:54 +08:00
( void ) reinterpret_cast < U > ( t ) ; // expected-error{{qualifiers}}
2009-05-20 03:05:47 +08:00
}
} ;
template struct ReinterpretCast0 < void ( * ) ( int ) , void ( * ) ( float ) > ;
template struct ReinterpretCast0 < int const * , float * > ; // expected-note{{instantiation}}
// ---------------------------------------------------------------------
// const_cast
// ---------------------------------------------------------------------
template < typename T , typename U >
struct ConstCast0 {
void f ( T t ) {
( void ) const_cast < U > ( t ) ; // expected-error{{not allowed}}
}
} ;
template struct ConstCast0 < int const * * , int * * > ;
template struct ConstCast0 < int const * , float * > ; // expected-note{{instantiation}}
// ---------------------------------------------------------------------
// C++ functional cast
// ---------------------------------------------------------------------
template < typename T , typename U >
struct FunctionalCast1 {
void f ( T t ) {
2011-02-15 02:34:10 +08:00
( void ) U ( t ) ; // expected-error{{cannot convert 'A' to 'int' without a conversion operator}}
2009-05-20 03:05:47 +08:00
}
} ;
template struct FunctionalCast1 < int , float > ;
template struct FunctionalCast1 < A , int > ; // expected-note{{instantiation}}
// Generates temporaries, which we cannot handle yet.
template < int N , long M >
struct FunctionalCast2 {
void f ( ) {
( void ) Constructible ( N , M ) ;
}
} ;
template struct FunctionalCast2 < 1 , 3 > ;
2009-10-30 07:08:22 +08:00
// ---------------------------------------------------------------------
// implicit casting
// ---------------------------------------------------------------------
template < typename T >
struct Derived2 : public Base { } ;
void test_derived_to_base ( Base * & bp , Derived2 < int > * dp ) {
bp = dp ;
}