forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			144 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			144 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			C++
		
	
	
	
| // RUN: %clang_analyze_cc1 -std=c++14 -analyzer-checker=core,unix.Malloc,debug.ExprInspection %s -analyzer-config eagerly-assume=false -verify
 | |
| 
 | |
| extern void clang_analyzer_eval(bool);
 | |
| extern void clang_analyzer_warnIfReached();
 | |
| extern "C" char *strdup(const char *s);
 | |
| 
 | |
| namespace PR14054_reduced {
 | |
|   struct Definition;
 | |
|   struct ParseNode {
 | |
|     union {
 | |
|       Definition *lexdef;
 | |
|       ParseNode *data;
 | |
|     } pn_u;
 | |
|   };
 | |
|   struct Definition : public ParseNode { };
 | |
| 
 | |
|   void CloneParseTree(ParseNode *opn, ParseNode *pn,  ParseNode *x) {
 | |
|     // This used to cause an assertion failure because:
 | |
|     // 1. The implicit operator= for unions assigns all members of the union,
 | |
|     //    not just the active one (b/c there's no way to know which is active).
 | |
|     // 2. RegionStore dutifully stored all the variants at the same offset;
 | |
|     //    the last one won.
 | |
|     // 3. We asked for the value of the first variant but got back a conjured
 | |
|     //    symbol for the second variant.
 | |
|     // 4. We ended up trying to add a base cast to a region of the wrong type.
 | |
|     //
 | |
|     // Now (at the time this test was added), we instead treat all variants of
 | |
|     // a union as different offsets, but only allow one to be active at a time.
 | |
|     *pn = *opn;
 | |
|     x = pn->pn_u.lexdef->pn_u.lexdef;
 | |
|   }
 | |
| }
 | |
| 
 | |
| namespace PR14054_original {
 | |
|   struct Definition;
 | |
|   struct ParseNode {
 | |
|     union {
 | |
|       struct {
 | |
|         union {}; // expected-warning {{does not declare anything}}
 | |
|         Definition *lexdef;
 | |
|       } name;
 | |
|       class {
 | |
|         int *target;
 | |
|         ParseNode *data;
 | |
|       } xmlpi;
 | |
|     } pn_u;
 | |
|   };
 | |
|   struct Definition : public ParseNode { };
 | |
| 
 | |
|   void CloneParseTree(ParseNode *opn, ParseNode *pn,  ParseNode *x) {
 | |
|     pn->pn_u = opn->pn_u;
 | |
|     x = pn->pn_u.name.lexdef->pn_u.name.lexdef;
 | |
|   }
 | |
| }
 | |
| 
 | |
| namespace PR17596 {
 | |
|   union IntOrString {
 | |
|     int i;
 | |
|     char *s;
 | |
|   };
 | |
| 
 | |
|   extern void process(IntOrString);
 | |
| 
 | |
|   void test() {
 | |
|     IntOrString uu;
 | |
|     uu.s = strdup("");
 | |
|     process(uu);
 | |
|   }
 | |
| 
 | |
|   void testPositive() {
 | |
|     IntOrString uu;
 | |
|     uu.s = strdup("");
 | |
|   } // expected-warning{{leak}}
 | |
| 
 | |
|   void testCopy() {
 | |
|     IntOrString uu;
 | |
|     uu.i = 4;
 | |
|     clang_analyzer_eval(uu.i == 4); // expected-warning{{TRUE}}
 | |
| 
 | |
|     IntOrString vv;
 | |
|     vv.i = 5;
 | |
|     uu = vv;
 | |
|     clang_analyzer_eval(uu.i == 5); // expected-warning{{TRUE}}
 | |
|   }
 | |
| 
 | |
|   void testInvalidation() {
 | |
|     IntOrString uu;
 | |
|     uu.s = strdup("");
 | |
| 
 | |
|     IntOrString vv;
 | |
|     char str[] = "abc";
 | |
|     vv.s = str;
 | |
| 
 | |
|     uu = vv;
 | |
|   } // expected-warning{{leak}}
 | |
| 
 | |
|   void testIndirectInvalidation() {
 | |
|     IntOrString uu;
 | |
|     char str[] = "abc";
 | |
|     uu.s = str;
 | |
| 
 | |
|     clang_analyzer_eval(uu.s[0] == 'a'); // expected-warning{{TRUE}}
 | |
| 
 | |
|     process(uu);
 | |
|     clang_analyzer_eval(uu.s[0] == 'a'); // expected-warning{{UNKNOWN}}
 | |
|   }
 | |
| }
 | |
| 
 | |
| namespace assume_union_contents {
 | |
| union U {
 | |
|   int x;
 | |
| };
 | |
| 
 | |
| U get();
 | |
| 
 | |
| void test() {
 | |
|   U u = get();
 | |
|   int y = 0;
 | |
|   if (u.x)
 | |
|     y = 1;
 | |
|   if (u.x)
 | |
|     y = 1 / y; // no-warning
 | |
| }
 | |
| } // end namespace assume_union_contents
 | |
| 
 | |
| namespace pr37688_deleted_union_destructor {
 | |
| struct S { ~S(); };
 | |
| struct A {
 | |
|   ~A() noexcept {}
 | |
|   union {
 | |
|     struct {
 | |
|       S s;
 | |
|     } ss;
 | |
|   };
 | |
| };
 | |
| void foo() {
 | |
|   A a;
 | |
| } // no-crash
 | |
| void bar() {
 | |
|   foo();
 | |
|   clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
 | |
| }
 | |
| } // end namespace pr37688_deleted_union_destructor
 |