Revert "[analyzer] Handle zeroing CXXConstructExprs."

Per review from Anna, this really should have been two commits, and besides
it's causing problems on our internal buildbot. Reverting until these have
been worked out.

This reverts r184511 / 98123284826bb4ce422775563ff1a01580ec5766.

llvm-svn: 184561
This commit is contained in:
Jordan Rose 2013-06-21 16:30:32 +00:00
parent 963c553564
commit e83cb0922b
3 changed files with 77 additions and 123 deletions

View File

@ -176,7 +176,6 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
}
// FIXME: This will eventually need to handle new-expressions as well.
// Don't forget to update the pre-constructor initialization code below.
}
// If we couldn't find an existing region to construct into, assume we're
@ -216,60 +215,22 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
ExplodedNodeSet DstPreVisit;
getCheckerManager().runCheckersForPreStmt(DstPreVisit, Pred, CE, *this);
bool IsArray = isa<ElementRegion>(Target);
ExplodedNodeSet PreInitialized;
{
StmtNodeBuilder Bldr(DstPreVisit, PreInitialized, *currBldrCtx);
if (CE->requiresZeroInitialization()) {
// Type of the zero doesn't matter.
SVal ZeroVal = svalBuilder.makeZeroVal(getContext().CharTy);
for (ExplodedNodeSet::iterator I = DstPreVisit.begin(),
E = DstPreVisit.end();
I != E; ++I) {
ProgramStateRef State = (*I)->getState();
// FIXME: Once we properly handle constructors in new-expressions, we'll
// need to invalidate the region before setting a default value, to make
// sure there aren't any lingering bindings around. This probably needs
// to happen regardless of whether or not the object is zero-initialized
// to handle random fields of a placement-initialized object picking up
// old bindings. We might only want to do it when we need to, though.
// FIXME: This isn't actually correct for arrays -- we need to zero-
// initialize the entire array, not just the first element -- but our
// handling of arrays everywhere else is weak as well, so this shouldn't
// actually make things worse.
State = State->bindDefault(loc::MemRegionVal(Target), ZeroVal);
Bldr.generateNode(CE, *I, State, /*tag=*/0, ProgramPoint::PreStmtKind);
}
}
}
ExplodedNodeSet DstPreCall;
getCheckerManager().runCheckersForPreCall(DstPreCall, PreInitialized,
getCheckerManager().runCheckersForPreCall(DstPreCall, DstPreVisit,
*Call, *this);
ExplodedNodeSet DstEvaluated;
StmtNodeBuilder Bldr(DstPreCall, DstEvaluated, *currBldrCtx);
if (CE->getConstructor()->isTrivial() && !IsArray) {
if (CE->getConstructor()->isCopyOrMoveConstructor()) {
for (ExplodedNodeSet::iterator I = DstPreCall.begin(),
E = DstPreCall.end();
I != E; ++I)
performTrivialCopy(Bldr, *I, *Call);
} else {
assert(CE->getConstructor()->isDefaultConstructor());
bool IsArray = isa<ElementRegion>(Target);
if (CE->getConstructor()->isTrivial() &&
CE->getConstructor()->isCopyOrMoveConstructor() &&
!IsArray) {
// FIXME: Handle other kinds of trivial constructors as well.
for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
I != E; ++I)
performTrivialCopy(Bldr, *I, *Call);
// We still have to bind the return value.
for (ExplodedNodeSet::iterator I = DstPreCall.begin(),
E = DstPreCall.end();
I != E; ++I) {
ProgramStateRef State = (*I)->getState();
State = bindReturnValue(*Call, LCtx, State);
Bldr.generateNode(CE, *I, State);
}
}
} else {
for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
I != E; ++I)

View File

@ -500,78 +500,3 @@ namespace ArrayMembers {
clang_analyzer_eval(c.values[2].x == 3); // expected-warning{{UNKNOWN}}
}
};
namespace ZeroInitialization {
struct raw_pair {
int p1;
int p2;
};
void testVarDecl() {
raw_pair p{};
clang_analyzer_eval(p.p1 == 0); // expected-warning{{TRUE}}
clang_analyzer_eval(p.p2 == 0); // expected-warning{{TRUE}}
}
void testTemporary() {
clang_analyzer_eval(raw_pair().p1 == 0); // expected-warning{{TRUE}}
clang_analyzer_eval(raw_pair().p2 == 0); // expected-warning{{TRUE}}
}
void testArray() {
raw_pair p[2] = {};
clang_analyzer_eval(p[0].p1 == 0); // expected-warning{{TRUE}}
clang_analyzer_eval(p[0].p2 == 0); // expected-warning{{TRUE}}
clang_analyzer_eval(p[1].p1 == 0); // expected-warning{{TRUE}}
clang_analyzer_eval(p[1].p2 == 0); // expected-warning{{TRUE}}
}
void testNew() {
// FIXME: Pending proper implementation of constructors for 'new'.
raw_pair *pp = new raw_pair();
clang_analyzer_eval(pp->p1 == 0); // expected-warning{{UNKNOWN}}
clang_analyzer_eval(pp->p2 == 0); // expected-warning{{UNKNOWN}}
}
void testArrayNew() {
// FIXME: Pending proper implementation of constructors for 'new[]'.
raw_pair *p = new raw_pair[2]();
clang_analyzer_eval(p[0].p1 == 0); // expected-warning{{UNKNOWN}}
clang_analyzer_eval(p[0].p2 == 0); // expected-warning{{UNKNOWN}}
clang_analyzer_eval(p[1].p1 == 0); // expected-warning{{UNKNOWN}}
clang_analyzer_eval(p[1].p2 == 0); // expected-warning{{UNKNOWN}}
}
struct initializing_pair {
public:
int x;
raw_pair y;
initializing_pair() : x(), y() {}
};
void testFieldInitializers() {
initializing_pair p;
clang_analyzer_eval(p.x == 0); // expected-warning{{TRUE}}
clang_analyzer_eval(p.y.p1 == 0); // expected-warning{{TRUE}}
clang_analyzer_eval(p.y.p2 == 0); // expected-warning{{TRUE}}
}
struct subclass : public raw_pair {
subclass() = default;
};
void testSubclass() {
subclass p;
clang_analyzer_eval(p.p1 == 0); // expected-warning{{garbage}}
}
struct initializing_subclass : public raw_pair {
initializing_subclass() : raw_pair() {}
};
void testInitializingSubclass() {
initializing_subclass p;
clang_analyzer_eval(p.p1 == 0); // expected-warning{{TRUE}}
clang_analyzer_eval(p.p2 == 0); // expected-warning{{TRUE}}
}
}

View File

@ -300,6 +300,40 @@ int callGenerateNoteOnDefaultArgument(int o) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>31</integer>
// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>31</integer>
// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
// CHECK-NEXT: <key>edges</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>31</integer>
// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>31</integer>
// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>32</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
@ -853,6 +887,40 @@ int callGenerateNoteOnDefaultArgument(int o) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>44</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>44</integer>
// CHECK-NEXT: <key>col</key><integer>13</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
// CHECK-NEXT: <key>edges</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>44</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>44</integer>
// CHECK-NEXT: <key>col</key><integer>13</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>46</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>