xref: /aosp_15_r20/external/clang/test/Analysis/unions.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
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