1// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection %s -verify
2
3extern void clang_analyzer_eval(bool);
4extern "C" char *strdup(const char *s);
5
6namespace 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
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
33namespace 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
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
55namespace PR17596 {
56  union IntOrString {
57    int i;
58    char *s;
59  };
60
61  extern void process(IntOrString);
62
63  void test() {
64    IntOrString uu;
65    uu.s = strdup("");
66    process(uu);
67  }
68
69  void testPositive() {
70    IntOrString uu;
71    uu.s = strdup("");
72  } // expected-warning{{leak}}
73
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
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
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