[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

llvm-svn: 319055
This commit is contained in:
Artem Dergachev 2017-11-27 17:31:16 +00:00
parent 18fc7ff93a
commit db9a5954d4
2 changed files with 42 additions and 1 deletions

View File

@ -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);

View File

@ -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