blob: f363ab81ae7259a98092b9ecc757fc1e637d207f [file] [log] [blame]
Jordan Rose1dc31f52013-10-23 20:08:55 +00001// 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);
Jordan Rose786e6202012-10-10 23:23:21 +00005
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}
Jordan Rose1dc31f52013-10-23 20:08:55 +000054
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}