unions.cpp revision 8e8fb3be5bd78f0564444eca02b404566a5f3b5d
1// RUN: %clang_cc1 -analyze -analyzer-checker=core %s -verify
2// expected-no-diagnostics
3
4namespace PR14054_reduced {
5  struct Definition;
6  struct ParseNode {
7    union {
8      Definition *lexdef;
9      ParseNode *data;
10    } pn_u;
11  };
12  struct Definition : public ParseNode { };
13
14  void CloneParseTree(ParseNode *opn, ParseNode *pn,  ParseNode *x) {
15    // This used to cause an assertion failure because:
16    // 1. The implicit operator= for unions assigns all members of the union,
17    //    not just the active one (b/c there's no way to know which is active).
18    // 2. RegionStore dutifully stored all the variants at the same offset;
19    //    the last one won.
20    // 3. We asked for the value of the first variant but got back a conjured
21    //    symbol for the second variant.
22    // 4. We ended up trying to add a base cast to a region of the wrong type.
23    //
24    // Now (at the time this test was added), we instead treat all variants of
25    // a union as different offsets, but only allow one to be active at a time.
26    *pn = *opn;
27    x = pn->pn_u.lexdef->pn_u.lexdef;
28  }
29}
30
31namespace PR14054_original {
32  struct Definition;
33  struct ParseNode {
34    union {
35      struct {
36        union {};
37        Definition *lexdef;
38      } name;
39      class {
40        int *target;
41        ParseNode *data;
42      } xmlpi;
43    } pn_u;
44  };
45  struct Definition : public ParseNode { };
46
47  void CloneParseTree(ParseNode *opn, ParseNode *pn,  ParseNode *x) {
48    pn->pn_u = opn->pn_u;
49    x = pn->pn_u.name.lexdef->pn_u.name.lexdef;
50  }
51}
52