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