1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection %s -verify 2 3 extern void clang_analyzer_eval(bool); 4 extern "C" char *strdup(const char *s); 5 6 namespace PR14054_reduced { 7 struct Definition; 8 struct ParseNode { 9 union { 10 Definition *lexdef; 11 ParseNode *data; 12 } pn_u; 13 }; 14 struct Definition : public ParseNode { }; 15 CloneParseTree(ParseNode * opn,ParseNode * pn,ParseNode * x)16 void CloneParseTree(ParseNode *opn, ParseNode *pn, ParseNode *x) { 17 // This used to cause an assertion failure because: 18 // 1. The implicit operator= for unions assigns all members of the union, 19 // not just the active one (b/c there's no way to know which is active). 20 // 2. RegionStore dutifully stored all the variants at the same offset; 21 // the last one won. 22 // 3. We asked for the value of the first variant but got back a conjured 23 // symbol for the second variant. 24 // 4. We ended up trying to add a base cast to a region of the wrong type. 25 // 26 // Now (at the time this test was added), we instead treat all variants of 27 // a union as different offsets, but only allow one to be active at a time. 28 *pn = *opn; 29 x = pn->pn_u.lexdef->pn_u.lexdef; 30 } 31 } 32 33 namespace PR14054_original { 34 struct Definition; 35 struct ParseNode { 36 union { 37 struct { 38 union {}; 39 Definition *lexdef; 40 } name; 41 class { 42 int *target; 43 ParseNode *data; 44 } xmlpi; 45 } pn_u; 46 }; 47 struct Definition : public ParseNode { }; 48 CloneParseTree(ParseNode * opn,ParseNode * pn,ParseNode * x)49 void CloneParseTree(ParseNode *opn, ParseNode *pn, ParseNode *x) { 50 pn->pn_u = opn->pn_u; 51 x = pn->pn_u.name.lexdef->pn_u.name.lexdef; 52 } 53 } 54 55 namespace PR17596 { 56 union IntOrString { 57 int i; 58 char *s; 59 }; 60 61 extern void process(IntOrString); 62 test()63 void test() { 64 IntOrString uu; 65 uu.s = strdup(""); 66 process(uu); 67 } 68 testPositive()69 void testPositive() { 70 IntOrString uu; 71 uu.s = strdup(""); 72 } // expected-warning{{leak}} 73 testCopy()74 void testCopy() { 75 IntOrString uu; 76 uu.i = 4; 77 clang_analyzer_eval(uu.i == 4); // expected-warning{{TRUE}} 78 79 IntOrString vv; 80 vv.i = 5; 81 uu = vv; 82 // FIXME: Should be true. 83 clang_analyzer_eval(uu.i == 5); // expected-warning{{UNKNOWN}} 84 } 85 testInvalidation()86 void testInvalidation() { 87 IntOrString uu; 88 uu.s = strdup(""); 89 90 IntOrString vv; 91 char str[] = "abc"; 92 vv.s = str; 93 94 // FIXME: This is a leak of uu.s. 95 uu = vv; 96 } 97 testIndirectInvalidation()98 void testIndirectInvalidation() { 99 IntOrString uu; 100 char str[] = "abc"; 101 uu.s = str; 102 103 clang_analyzer_eval(uu.s[0] == 'a'); // expected-warning{{TRUE}} 104 105 process(uu); 106 clang_analyzer_eval(uu.s[0] == 'a'); // expected-warning{{UNKNOWN}} 107 } 108 } 109