Clang Project

clang_source_code/test/Analysis/unions.cpp
1// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection %s -analyzer-config eagerly-assume=false -verify
2
3extern void clang_analyzer_eval(bool);
4extern void clang_analyzer_warnIfReached();
5extern "C" char *strdup(const char *s);
6
7namespace PR14054_reduced {
8  struct Definition;
9  struct ParseNode {
10    union {
11      Definition *lexdef;
12      ParseNode *data;
13    } pn_u;
14  };
15  struct Definition : public ParseNode { };
16
17  void CloneParseTree(ParseNode *opn, ParseNode *pn,  ParseNode *x) {
18    // This used to cause an assertion failure because:
19    // 1. The implicit operator= for unions assigns all members of the union,
20    //    not just the active one (b/c there's no way to know which is active).
21    // 2. RegionStore dutifully stored all the variants at the same offset;
22    //    the last one won.
23    // 3. We asked for the value of the first variant but got back a conjured
24    //    symbol for the second variant.
25    // 4. We ended up trying to add a base cast to a region of the wrong type.
26    //
27    // Now (at the time this test was added), we instead treat all variants of
28    // a union as different offsets, but only allow one to be active at a time.
29    *pn = *opn;
30    x = pn->pn_u.lexdef->pn_u.lexdef;
31  }
32}
33
34namespace PR14054_original {
35  struct Definition;
36  struct ParseNode {
37    union {
38      struct {
39        union {};
40        Definition *lexdef;
41      } name;
42      class {
43        int *target;
44        ParseNode *data;
45      } xmlpi;
46    } pn_u;
47  };
48  struct Definition : public ParseNode { };
49
50  void CloneParseTree(ParseNode *opn, ParseNode *pn,  ParseNode *x) {
51    pn->pn_u = opn->pn_u;
52    x = pn->pn_u.name.lexdef->pn_u.name.lexdef;
53  }
54}
55
56namespace PR17596 {
57  union IntOrString {
58    int i;
59    char *s;
60  };
61
62  extern void process(IntOrString);
63
64  void test() {
65    IntOrString uu;
66    uu.s = strdup("");
67    process(uu);
68  }
69
70  void testPositive() {
71    IntOrString uu;
72    uu.s = strdup("");
73  } // expected-warning{{leak}}
74
75  void testCopy() {
76    IntOrString uu;
77    uu.i = 4;
78    clang_analyzer_eval(uu.i == 4); // expected-warning{{TRUE}}
79
80    IntOrString vv;
81    vv.i = 5;
82    uu = vv;
83    clang_analyzer_eval(uu.i == 5); // expected-warning{{TRUE}}
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    uu = vv;
95  } // expected-warning{{leak}}
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
109namespace assume_union_contents {
110union U {
111  int x;
112};
113
114U get();
115
116void 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
126namespace pr37688_deleted_union_destructor {
127struct S { ~S(); };
128struct A {
129  ~A() noexcept {}
130  union {
131    struct {
132      S s;
133    } ss;
134  };
135};
136void foo() {
137  A a;
138} // no-crash
139void bar() {
140  foo();
141  clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
142}
143} // end namespace pr37688_deleted_union_destructor
144