144 lines · cpp
1// RUN: %clang_analyze_cc1 -std=c++14 -analyzer-checker=core,unix.Malloc,debug.ExprInspection %s -analyzer-config eagerly-assume=false -verify2 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 conjured24 // 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 of28 // 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 {}; // expected-warning {{does not declare anything}}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-warning123}124} // end namespace assume_union_contents125 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-crash139void bar() {140 foo();141 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}142}143} // end namespace pr37688_deleted_union_destructor144