mirror of https://github.com/microsoft/clang.git
[analyzer] pr34404: Fix a crash on modeling pointers to indirect members.
We were crashing whenever a C++ pointer-to-member was taken, that was pointing to a member of an anonymous structure field within a class, eg. struct A { struct { int x; }; }; // ... &A::x; Differential Revision: https://reviews.llvm.org/D39800 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@319055 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
3d35a943a9
commit
37d08be31c
|
@ -2108,10 +2108,12 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
|
|||
ProgramPoint::PostLValueKind);
|
||||
return;
|
||||
}
|
||||
if (isa<FieldDecl>(D)) {
|
||||
if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D)) {
|
||||
// FIXME: Compute lvalue of field pointers-to-member.
|
||||
// Right now we just use a non-null void pointer, so that it gives proper
|
||||
// results in boolean contexts.
|
||||
// FIXME: Maybe delegate this to the surrounding operator&.
|
||||
// Note how this expression is lvalue, however pointer-to-member is NonLoc.
|
||||
SVal V = svalBuilder.conjureSymbolVal(Ex, LCtx, getContext().VoidPtrTy,
|
||||
currBldrCtx->blockCount());
|
||||
state = state->assume(V.castAs<DefinedOrUnknownSVal>(), true);
|
||||
|
|
|
@ -230,3 +230,42 @@ void double_diamond() {
|
|||
clang_analyzer_eval(d2.*(static_cast<int D2::*>(static_cast<int R2::*>(static_cast<int R1::*>(&B::f)))) == 4); // expected-warning {{TRUE}}
|
||||
}
|
||||
} // end of testPointerToMemberDiamond namespace
|
||||
|
||||
namespace testAnonymousMember {
|
||||
struct A {
|
||||
struct {
|
||||
int x;
|
||||
};
|
||||
struct {
|
||||
struct {
|
||||
int y;
|
||||
};
|
||||
};
|
||||
struct {
|
||||
union {
|
||||
int z;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
void test() {
|
||||
clang_analyzer_eval(&A::x); // expected-warning{{TRUE}}
|
||||
clang_analyzer_eval(&A::y); // expected-warning{{TRUE}}
|
||||
clang_analyzer_eval(&A::z); // expected-warning{{TRUE}}
|
||||
|
||||
// FIXME: These should be true.
|
||||
int A::*l = &A::x, A::*m = &A::y, A::*n = &A::z;
|
||||
clang_analyzer_eval(l); // expected-warning{{UNKNOWN}}
|
||||
clang_analyzer_eval(m); // expected-warning{{UNKNOWN}}
|
||||
clang_analyzer_eval(n); // expected-warning{{UNKNOWN}}
|
||||
|
||||
// FIXME: These should be true as well.
|
||||
A a;
|
||||
a.x = 1;
|
||||
clang_analyzer_eval(a.*l == 1); // expected-warning{{UNKNOWN}}
|
||||
a.y = 2;
|
||||
clang_analyzer_eval(a.*m == 2); // expected-warning{{UNKNOWN}}
|
||||
a.z = 3;
|
||||
clang_analyzer_eval(a.*n == 3); // expected-warning{{UNKNOWN}}
|
||||
}
|
||||
} // end of testAnonymousMember namespace
|
||||
|
|
Loading…
Reference in New Issue