2012-08-25 04:39:55 +08:00
// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core.CastToStruct -analyzer-store=region -analyzer-constraints=range -verify %s
2008-10-17 13:19:52 +08:00
2008-10-24 16:51:58 +08:00
struct s {
int data ;
int data_array [ 10 ] ;
} ;
2008-10-17 13:19:52 +08:00
2008-10-27 17:19:25 +08:00
typedef struct {
int data ;
} STYPE ;
2009-05-20 17:18:48 +08:00
void g ( char * p ) ;
2008-11-02 21:17:44 +08:00
void g1 ( struct s * p ) ;
2008-11-25 09:45:11 +08:00
// Array to pointer conversion. Array in the struct field.
2008-10-17 13:19:52 +08:00
void f ( void ) {
int a [ 10 ] ;
int ( * p ) [ 10 ] ;
p = & a ;
( * p ) [ 3 ] = 1 ;
struct s d ;
struct s * q ;
q = & d ;
2008-10-24 16:51:58 +08:00
q - > data = 3 ;
d . data_array [ 9 ] = 17 ;
2008-10-17 13:19:52 +08:00
}
2008-10-25 22:11:23 +08:00
2008-11-25 09:45:11 +08:00
// StringLiteral in lvalue context and pointer to array type.
// p: ElementRegion, q: StringRegion
2008-10-25 22:11:23 +08:00
void f2 ( ) {
char * p = " /usr/local " ;
char ( * q ) [ 4 ] ;
q = & " abc " ;
}
2008-10-27 17:19:25 +08:00
2008-11-25 09:45:11 +08:00
// Typedef'ed struct definition.
2008-10-27 17:19:25 +08:00
void f3 ( ) {
STYPE s ;
}
2008-10-31 18:23:14 +08:00
2008-11-25 09:45:11 +08:00
// Initialize array with InitExprList.
2008-10-31 18:23:14 +08:00
void f4 ( ) {
int a [ ] = { 1 , 2 , 3 } ;
int b [ 3 ] = { 1 , 2 } ;
2009-01-23 18:23:13 +08:00
struct s c [ ] = { { 1 , { 1 } } } ;
2008-10-31 18:23:14 +08:00
}
2008-11-02 21:17:44 +08:00
2008-11-25 09:45:11 +08:00
// Struct variable in lvalue context.
2009-01-13 09:49:57 +08:00
// Assign UnknownVal to the whole struct.
2008-11-02 21:17:44 +08:00
void f5 ( ) {
struct s data ;
g1 ( & data ) ;
}
2008-11-13 15:59:15 +08:00
2008-11-25 09:45:11 +08:00
// AllocaRegion test.
2008-11-13 15:59:15 +08:00
void f6 ( ) {
char * p ;
p = __builtin_alloca ( 10 ) ;
2009-05-20 17:18:48 +08:00
g ( p ) ;
char c = * p ;
2008-11-13 15:59:15 +08:00
p [ 1 ] = ' a ' ;
2009-05-20 17:03:10 +08:00
// Test if RegionStore::EvalBinOp converts the alloca region to element
// region.
2009-05-20 17:00:16 +08:00
p + = 2 ;
2008-11-13 15:59:15 +08:00
}
2008-11-13 16:44:52 +08:00
struct s2 ;
void g2 ( struct s2 * p ) ;
2008-11-25 09:45:11 +08:00
// Incomplete struct pointer used as function argument.
2008-11-13 16:44:52 +08:00
void f7 ( ) {
struct s2 * p = __builtin_alloca ( 10 ) ;
g2 ( p ) ;
}
2008-11-13 17:20:05 +08:00
2008-11-25 09:45:11 +08:00
// sizeof() is unsigned while -1 is signed in array index.
2008-11-13 17:20:05 +08:00
void f8 ( ) {
int a [ 10 ] ;
2008-11-25 07:45:56 +08:00
a [ sizeof ( a ) / sizeof ( int ) - 1 ] = 1 ; // no-warning
2008-11-13 17:20:05 +08:00
}
2008-11-18 21:30:46 +08:00
2008-11-25 09:45:11 +08:00
// Initialization of struct array elements.
2008-11-18 21:30:46 +08:00
void f9 ( ) {
struct s a [ 10 ] ;
}
2008-11-30 13:51:19 +08:00
// Initializing array with string literal.
void f10 ( ) {
char a1 [ 4 ] = " abc " ;
char a3 [ 6 ] = " abc " ;
}
2009-01-23 19:22:12 +08:00
// Retrieve the default value of element/field region.
void f11 ( ) {
struct s a ;
2009-05-20 17:18:48 +08:00
g1 ( & a ) ;
2009-01-23 19:22:12 +08:00
if ( a . data = = 0 ) // no-warning
a . data = 1 ;
}
2009-02-19 16:42:43 +08:00
// Convert unsigned offset to signed when creating ElementRegion from
// SymbolicRegion.
void f12 ( int * list ) {
unsigned i = 0 ;
list [ i ] = 1 ;
}
2009-03-18 10:07:30 +08:00
struct s1 {
struct s2 {
int d ;
} e ;
} ;
// The binding of a.e.d should not be removed. Test recursive subregion map
// building: a->e, e->d. Only then 'a' could be added to live region roots.
void f13 ( double timeout ) {
struct s1 a ;
2009-11-07 11:30:10 +08:00
a . e . d = ( int ) timeout ;
2009-03-18 10:07:30 +08:00
if ( a . e . d = = 10 )
a . e . d = 4 ;
}
2009-05-03 08:27:40 +08:00
struct s3 {
int a [ 2 ] ;
} ;
static struct s3 opt ;
// Test if the embedded array is retrieved correctly.
void f14 ( ) {
struct s3 my_opt = opt ;
}
2009-05-12 18:10:00 +08:00
void bar ( int * ) ;
// Test if the array is correctly invalidated.
void f15 ( ) {
int a [ 10 ] ;
bar ( a ) ;
if ( a [ 1 ] ) // no-warning
2009-07-31 06:37:41 +08:00
( void ) 1 ;
2009-05-12 18:10:00 +08:00
}
2009-06-11 17:11:27 +08:00
struct s3 p [ 1 ] ;
// Code from postgresql.
// Current cast logic of region store mistakenly leaves the final result region
// an ElementRegion of type 'char'. Then load a nonloc::SymbolVal from it and
// assigns to 'a'.
void f16 ( struct s3 * p ) {
Allow multiple PathDiagnosticConsumers to be used with a BugReporter at the same time.
This fixes several issues:
- removes egregious hack where PlistDiagnosticConsumer would forward to HTMLDiagnosticConsumer,
but diagnostics wouldn't be generated consistently in the same way if PlistDiagnosticConsumer
was used by itself.
- emitting diagnostics to the terminal (using clang's diagnostic machinery) is no longer a special
case, just another PathDiagnosticConsumer. This also magically resolved some duplicate warnings,
as we now use PathDiagnosticConsumer's diagnostic pruning, which has scope for the entire translation
unit, not just the scope of a BugReporter (which is limited to a particular ExprEngine).
As an interesting side-effect, diagnostics emitted to the terminal also have their trailing "." stripped,
just like with diagnostics emitted to plists and HTML. This required some tests to be updated, but now
the tests have higher fidelity with what users will see.
There are some inefficiencies in this patch. We currently generate the report graph (from the ExplodedGraph)
once per PathDiagnosticConsumer, which is a bit wasteful, but that could be pulled up higher in the
logic stack. There is some intended duplication, however, as we now generate different PathDiagnostics (for the same issue)
for different PathDiagnosticConsumers. This is necessary to produce the diagnostics that a particular
consumer expects.
llvm-svn: 162028
2012-08-17 01:45:23 +08:00
struct s3 a = * ( ( struct s3 * ) ( ( char * ) & p [ 0 ] ) ) ; // expected-warning{{Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption}}
2009-06-11 17:11:27 +08:00
}
2009-06-28 21:59:24 +08:00
void inv ( struct s1 * ) ;
// Invalidate the struct field.
void f17 ( ) {
struct s1 t ;
int x ;
inv ( & t ) ;
if ( t . e . d )
x = 1 ;
}
2009-06-29 14:43:40 +08:00
void read ( char * ) ;
void f18 ( ) {
char * q ;
char * p = ( char * ) __builtin_alloca ( 10 ) ;
read ( p ) ;
q = p ;
q + + ;
if ( * q ) { // no-warning
}
}
2012-10-02 03:07:19 +08:00
// [PR13927] offsetof replacement macro flagged as "dereference of a null pointer"
int offset_of_data_array ( void )
{
return ( ( char * ) & ( ( ( struct s * ) 0 ) - > data_array ) ) - ( ( char * ) 0 ) ; // no-warning
}
2015-02-05 09:02:59 +08:00
int testPointerArithmeticOnVoid ( void * bytes ) {
int p = 0 ;
if ( & bytes [ 0 ] = = & bytes [ 1 ] )
return 6 / p ; // no-warning
return 0 ;
}
int testRValueArraySubscriptExpr ( void * bytes ) {
int * p = ( int * ) & bytes [ 0 ] ;
* p = 0 ;
if ( * ( int * ) & bytes [ 0 ] = = 0 )
return 0 ;
return 5 / ( * p ) ; // no-warning
}