// returns whether the error condition is satisfiable within frame. bool TestErrorSatisfiable(CheckerState *state, CheckerFrame *frame, Bit *bit) { BlockMemory *mcfg = frame->Memory(); Solver *solver = state->GetSolver(); if (!solver->IsSatisfiable()) { if (checker_verbose.IsSpecified()) logout << "CHECK: " << frame << ": Guard unsatisfiable: " << bit << " [" << bit->Hash() << "]" << endl; return false; } state->PushContext(); state->AssertBaseBits(); if (!solver->IsSatisfiable()) { if (checker_verbose.IsSpecified()) logout << "CHECK: " << frame << ": Error unsatisfiable: " << bit << " [" << bit->Hash() << "]" << endl; state->PopContext(); return false; } if (!frame->m_checked_assertions) { frame->m_checked_assertions = true; // check to see if the error is contradicted by previous assertions // in this frame. assert the previous assertions, but don't keep // them around past this function to avoid polluting the solver // with worthless extra checks. BlockSummary *sum = GetBlockSummary(mcfg->GetId()); const Vector<AssertInfo> *asserts = sum->GetAsserts(); size_t assert_count = VectorSize<AssertInfo>(asserts); for (size_t ind = 0; ind < assert_count; ind++) { const AssertInfo &info = asserts->At(ind); // only use the same kind of assertion to check for redundancy. if (info.kind != state->GetAssertKind()) continue; if (info.cls != ASC_Check) continue; if (info.point < frame->EndPoint()) { // get the asserted condition relative to block entry. Bit *assert_value; mcfg->TranslateBit(TRK_Point, info.point, info.bit, &assert_value); assert_value->MoveRef(&assert_value, NULL); Bit *point_guard = mcfg->GetGuard(info.point); point_guard->IncRef(); Bit *imply_assert = Bit::MakeImply(point_guard, assert_value); solver->AddConstraint(frame->Id(), imply_assert); } } sum->DecRef(); if (!solver->IsSatisfiable()) { if (checker_verbose.IsSpecified()) logout << "CHECK: " << frame << ": Unsatisfiable from assertions" << endl; state->PopContext(); return false; } } state->PopContext(); return true; }