2017-07-14 20:20:19 +08:00
// RUN: %check_clang_tidy %s bugprone-undefined-memory-manipulation %t
void * memset ( void * , int , __SIZE_TYPE__ ) ;
void * memcpy ( void * , const void * , __SIZE_TYPE__ ) ;
void * memmove ( void * , const void * , __SIZE_TYPE__ ) ;
namespace std {
using : : memcpy ;
using : : memmove ;
using : : memset ;
}
2017-08-24 20:11:05 +08:00
namespace types {
2017-07-14 20:20:19 +08:00
// TriviallyCopyable types:
struct Plain {
int n ;
} ;
enum E {
X ,
Y ,
Z
} ;
struct Base {
float b ;
} ;
struct Derived : Base {
bool d ;
} ;
// not TriviallyCopyable types:
struct Destruct {
~ Destruct ( ) { }
} ;
struct Copy {
Copy ( ) { }
Copy ( const Copy & ) { }
} ;
struct Move {
Move ( ) { }
Move ( Move & & ) { }
} ;
struct VirtualFunc {
virtual void f ( ) { }
} ;
struct VirtualBase : virtual Base {
int vb ;
} ;
2017-07-25 14:52:08 +08:00
// Incomplete type, assume it is TriviallyCopyable.
struct NoDef ;
2017-08-24 20:11:05 +08:00
} // end namespace types
void f ( types : : NoDef * s ) {
2017-07-25 14:52:08 +08:00
memset ( s , 0 , 5 ) ;
}
2017-07-14 20:20:19 +08:00
template < typename T >
void memset_temp ( T * b ) {
memset ( b , 0 , sizeof ( T ) ) ;
2017-08-24 20:11:05 +08:00
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualFunc' is not TriviallyCopyable [bugprone-undefined-memory-manipulation]
2017-07-14 20:20:19 +08:00
}
template < typename S , typename T >
void memcpy_temp ( S * a , T * b ) {
memcpy ( a , b , sizeof ( T ) ) ;
2017-08-24 20:11:05 +08:00
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::VirtualFunc'
2017-07-14 20:20:19 +08:00
}
template < typename S , typename T >
void memmove_temp ( S * a , T * b ) {
memmove ( a , b , sizeof ( T ) ) ;
2017-08-24 20:11:05 +08:00
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::VirtualFunc'
}
namespace aliases {
using Copy2 = types : : Copy ;
typedef types : : Move Move2 ;
2017-07-14 20:20:19 +08:00
}
void notTriviallyCopyable ( ) {
2017-08-24 20:11:05 +08:00
types : : Plain p ; // TriviallyCopyable for variety
types : : Destruct d ;
types : : Copy c ;
types : : Move m ;
types : : VirtualFunc vf ;
types : : VirtualBase vb ;
2017-07-14 20:20:19 +08:00
memset ( & vf , 0 , sizeof ( int ) ) ;
2017-08-24 20:11:05 +08:00
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualFunc'
2017-07-14 20:20:19 +08:00
memset ( & d , 0 , sizeof ( int ) ) ;
2017-08-24 20:11:05 +08:00
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Destruct'
2017-07-14 20:20:19 +08:00
memset ( & c , 0 , sizeof ( int ) ) ;
2017-08-24 20:11:05 +08:00
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Copy'
2017-07-14 20:20:19 +08:00
std : : memset ( & m , 0 , sizeof ( int ) ) ;
2017-08-24 20:11:05 +08:00
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Move'
2017-07-14 20:20:19 +08:00
: : memset ( & vb , 0 , sizeof ( int ) ) ;
2017-08-24 20:11:05 +08:00
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualBase'
2017-07-14 20:20:19 +08:00
memcpy ( & p , & vf , sizeof ( int ) ) ;
2017-08-24 20:11:05 +08:00
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::VirtualFunc'
2017-07-14 20:20:19 +08:00
memcpy ( & p , & d , sizeof ( int ) ) ;
2017-08-24 20:11:05 +08:00
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::Destruct'
2017-07-14 20:20:19 +08:00
memcpy ( & c , & p , sizeof ( int ) ) ;
2017-08-24 20:11:05 +08:00
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Copy'
2017-07-14 20:20:19 +08:00
std : : memcpy ( & m , & p , sizeof ( int ) ) ;
2017-08-24 20:11:05 +08:00
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Move'
2017-07-14 20:20:19 +08:00
: : memcpy ( & vb , & p , sizeof ( int ) ) ;
2017-08-24 20:11:05 +08:00
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualBase'
2017-07-14 20:20:19 +08:00
memmove ( & vf , & p , sizeof ( int ) ) ;
2017-08-24 20:11:05 +08:00
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualFunc'
2017-07-14 20:20:19 +08:00
memmove ( & d , & p , sizeof ( int ) ) ;
2017-08-24 20:11:05 +08:00
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Destruct'
2017-07-14 20:20:19 +08:00
memmove ( & p , & c , sizeof ( int ) ) ;
2017-08-24 20:11:05 +08:00
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::Copy'
2017-07-14 20:20:19 +08:00
std : : memmove ( & p , & m , sizeof ( int ) ) ;
2017-08-24 20:11:05 +08:00
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::Move'
2017-07-14 20:20:19 +08:00
: : memmove ( & p , & vb , sizeof ( int ) ) ;
2017-08-24 20:11:05 +08:00
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::VirtualBase'
2017-07-14 20:20:19 +08:00
# define MEMSET memset(&vf, 0, sizeof(int));
MEMSET
2017-08-24 20:11:05 +08:00
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualFunc'
2017-07-14 20:20:19 +08:00
# define MEMCPY memcpy(&d, &p, sizeof(int));
MEMCPY
2017-08-24 20:11:05 +08:00
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Destruct'
2017-07-14 20:20:19 +08:00
# define MEMMOVE memmove(&p, &c, sizeof(int));
MEMMOVE
2017-08-24 20:11:05 +08:00
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::Copy'
memset_temp < types : : VirtualFunc > ( & vf ) ;
memcpy_temp < types : : Plain , types : : VirtualFunc > ( & p , & vf ) ;
memmove_temp < types : : Plain , types : : VirtualFunc > ( & p , & vf ) ;
aliases : : Copy2 c2 ;
aliases : : Move2 m2 ;
memset ( & c2 , 0 , sizeof ( int ) ) ;
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'aliases::Copy2'
memset ( & m2 , 0 , sizeof ( int ) ) ;
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'aliases::Move2'
typedef aliases : : Copy2 Copy3 ;
typedef aliases : : Copy2 * PCopy2 ;
typedef Copy3 * PCopy3 ;
Copy3 c3 ;
PCopy2 pc2 ;
PCopy3 pc3 ;
memset ( & c3 , 0 , sizeof ( int ) ) ;
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'Copy3'
memset ( pc2 , 0 , sizeof ( int ) ) ;
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'aliases::Copy2'
memset ( pc3 , 0 , sizeof ( int ) ) ;
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'Copy3'
2017-07-14 20:20:19 +08:00
}
void triviallyCopyable ( ) {
2017-08-24 20:11:05 +08:00
types : : Plain p ;
types : : Base base ;
types : : Derived derived ;
2017-07-14 20:20:19 +08:00
int i = 5 ;
int ia [ 3 ] = { 1 , 2 , 3 } ;
float f = 3.14 ;
float fa [ 3 ] = { 1.1 , 2.2 , 3.3 } ;
bool b = false ;
bool ba [ 2 ] = { true , false } ;
2017-08-24 20:11:05 +08:00
types : : E e = types : : X ;
2017-07-14 20:20:19 +08:00
p . n = 2 ;
memset ( & p , 0 , sizeof ( int ) ) ;
memset ( & base , 0 , sizeof ( float ) ) ;
memset ( & derived , 0 , sizeof ( bool ) ) ;
memset ( & i , 0 , sizeof ( int ) ) ;
memset ( ia , 0 , sizeof ( int ) ) ;
memset ( & f , 0 , sizeof ( float ) ) ;
memset ( fa , 0 , sizeof ( float ) ) ;
memset ( & b , 0 , sizeof ( bool ) ) ;
memset ( ba , 0 , sizeof ( bool ) ) ;
memset ( & e , 0 , sizeof ( int ) ) ;
memset ( & p . n , 0 , sizeof ( int ) ) ;
memcpy ( & p , & p , sizeof ( int ) ) ;
memcpy ( & base , & base , sizeof ( float ) ) ;
memcpy ( & derived , & derived , sizeof ( bool ) ) ;
memcpy ( & i , & i , sizeof ( int ) ) ;
memcpy ( ia , ia , sizeof ( int ) ) ;
memcpy ( & f , & f , sizeof ( float ) ) ;
memcpy ( fa , fa , sizeof ( float ) ) ;
memcpy ( & b , & b , sizeof ( bool ) ) ;
memcpy ( ba , ba , sizeof ( bool ) ) ;
memcpy ( & e , & e , sizeof ( int ) ) ;
memcpy ( & p . n , & p . n , sizeof ( int ) ) ;
memmove ( & p , & p , sizeof ( int ) ) ;
memmove ( & base , & base , sizeof ( float ) ) ;
memmove ( & derived , & derived , sizeof ( bool ) ) ;
memmove ( & i , & i , sizeof ( int ) ) ;
memmove ( ia , ia , sizeof ( int ) ) ;
memmove ( & f , & f , sizeof ( float ) ) ;
memmove ( fa , fa , sizeof ( float ) ) ;
memmove ( & b , & b , sizeof ( bool ) ) ;
memmove ( ba , ba , sizeof ( bool ) ) ;
memmove ( & e , & e , sizeof ( int ) ) ;
memmove ( & p . n , & p . n , sizeof ( int ) ) ;
}