llvm-project/clang/test/Analysis/unions.cpp

125 lines
2.8 KiB
C++

// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection %s -verify
extern void clang_analyzer_eval(bool);
extern "C" char *strdup(const char *s);
namespace PR14054_reduced {
struct Definition;
struct ParseNode {
union {
Definition *lexdef;
ParseNode *data;
} pn_u;
};
struct Definition : public ParseNode { };
void CloneParseTree(ParseNode *opn, ParseNode *pn, ParseNode *x) {
// This used to cause an assertion failure because:
// 1. The implicit operator= for unions assigns all members of the union,
// not just the active one (b/c there's no way to know which is active).
// 2. RegionStore dutifully stored all the variants at the same offset;
// the last one won.
// 3. We asked for the value of the first variant but got back a conjured
// symbol for the second variant.
// 4. We ended up trying to add a base cast to a region of the wrong type.
//
// Now (at the time this test was added), we instead treat all variants of
// a union as different offsets, but only allow one to be active at a time.
*pn = *opn;
x = pn->pn_u.lexdef->pn_u.lexdef;
}
}
namespace PR14054_original {
struct Definition;
struct ParseNode {
union {
struct {
union {};
Definition *lexdef;
} name;
class {
int *target;
ParseNode *data;
} xmlpi;
} pn_u;
};
struct Definition : public ParseNode { };
void CloneParseTree(ParseNode *opn, ParseNode *pn, ParseNode *x) {
pn->pn_u = opn->pn_u;
x = pn->pn_u.name.lexdef->pn_u.name.lexdef;
}
}
namespace PR17596 {
union IntOrString {
int i;
char *s;
};
extern void process(IntOrString);
void test() {
IntOrString uu;
uu.s = strdup("");
process(uu);
}
void testPositive() {
IntOrString uu;
uu.s = strdup("");
} // expected-warning{{leak}}
void testCopy() {
IntOrString uu;
uu.i = 4;
clang_analyzer_eval(uu.i == 4); // expected-warning{{TRUE}}
IntOrString vv;
vv.i = 5;
uu = vv;
clang_analyzer_eval(uu.i == 5); // expected-warning{{TRUE}}
}
void testInvalidation() {
IntOrString uu;
uu.s = strdup("");
IntOrString vv;
char str[] = "abc";
vv.s = str;
// FIXME: This is a leak of uu.s.
uu = vv;
}
void testIndirectInvalidation() {
IntOrString uu;
char str[] = "abc";
uu.s = str;
clang_analyzer_eval(uu.s[0] == 'a'); // expected-warning{{TRUE}}
process(uu);
clang_analyzer_eval(uu.s[0] == 'a'); // expected-warning{{UNKNOWN}}
}
}
namespace assume_union_contents {
union U {
int x;
};
U get();
void test() {
U u = get();
int y = 0;
if (u.x)
y = 1;
if (u.x)
y = 1 / y; // no-warning
}
} // end namespace assume_union_contents