1 // RUN: %clang_analyze_cc1 -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 
mallocnull6 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 
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 {
test_PR10163null36     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   }
makePointnull53 }
54 
55 namespace 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     clang_analyzer_eval(uu.i == 5); // expected-warning{{TRUE}}
83   }
84 
85   void testInvalidation() {
86     IntOrString uu;
87     uu.s = strdup("");
88 
89     IntOrString vv;
90     char str[] = "abc";
91     vv.s = str;
92 
93     // FIXME: This is a leak of uu.s.
94     uu = vv;
95   }
96 
97   void testIndirectInvalidation() {
98     IntOrString uu;
99     char str[] = "abc";
100     uu.s = str;
101 
102     clang_analyzer_eval(uu.s[0] == 'a'); // expected-warning{{TRUE}}
103 
104     process(uu);
105     clang_analyzer_eval(uu.s[0] == 'a'); // expected-warning{{UNKNOWN}}
106   }
107 }
108 
109 namespace assume_union_contents {
110 union U {
111   int x;
112 };
113 
114 U get();
115 
116 void test() {
117   U u = get();
118   int y = 0;
119   if (u.x)
120     y = 1;
121   if (u.x)
122     y = 1 / y; // no-warning
123 }
124 } // end namespace assume_union_contents
125