Skip to content

Commit

Permalink
[analyzer][NFC] Factor out the copy-paste code repetition of assumeDu…
Browse files Browse the repository at this point in the history
…al and assumeInclusiveRangeDual

Depends on D125892. There might be efficiency and performance
implications by using a lambda. Thus, I am going to conduct measurements
to see if there is any noticeable impact.
I've been thinking about two more alternatives:
1) Make `assumeDualImpl` a variadic template and (perfect) forward the
   arguments for the used `assume` function.
2) Use a macros.
I have concerns though, whether these alternatives would deteriorate the
readability of the code.

Differential Revision: https://reviews.llvm.org/D125954
  • Loading branch information
Gabor Marton committed May 23, 2022
1 parent 32f189b commit 96fba64
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@ class ConstraintManager {
/// Returns whether or not a symbol is known to be null ("true"), known to be
/// non-null ("false"), or may be either ("underconstrained").
virtual ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym);

template <typename AssumeFunction>
ProgramStatePair assumeDualImpl(ProgramStateRef &State,
AssumeFunction &Assume);
};

std::unique_ptr<ConstraintManager>
Expand Down
48 changes: 18 additions & 30 deletions clang/lib/StaticAnalyzer/Core/ConstraintManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,14 @@ ConditionTruthVal ConstraintManager::checkNull(ProgramStateRef State,
return {};
}

template <typename AssumeFunction>
ConstraintManager::ProgramStatePair
ConstraintManager::assumeDual(ProgramStateRef State, DefinedSVal Cond) {
ProgramStateRef StTrue = assumeInternal(State, Cond, true);
ConstraintManager::assumeDualImpl(ProgramStateRef &State,
AssumeFunction &Assume) {
ProgramStateRef StTrue = Assume(true);

if (!StTrue) {
ProgramStateRef StFalse = assumeInternal(State, Cond, false);
ProgramStateRef StFalse = Assume(false);
if (LLVM_UNLIKELY(!StFalse)) { // both infeasible
ProgramStateRef StInfeasible = State->cloneAsPosteriorlyOverconstrained();
assert(StInfeasible->isPosteriorlyOverconstrained());
Expand All @@ -63,44 +65,30 @@ ConstraintManager::assumeDual(ProgramStateRef State, DefinedSVal Cond) {
return ProgramStatePair(nullptr, StFalse);
}

ProgramStateRef StFalse = assumeInternal(State, Cond, false);
ProgramStateRef StFalse = Assume(false);
if (!StFalse) {
return ProgramStatePair(StTrue, nullptr);
}

return ProgramStatePair(StTrue, StFalse);
}

ConstraintManager::ProgramStatePair
ConstraintManager::assumeDual(ProgramStateRef State, DefinedSVal Cond) {
auto AssumeFun = [&](bool Assumption) {
return assumeInternal(State, Cond, Assumption);
};
return assumeDualImpl(State, AssumeFun);
}

ConstraintManager::ProgramStatePair
ConstraintManager::assumeInclusiveRangeDual(ProgramStateRef State, NonLoc Value,
const llvm::APSInt &From,
const llvm::APSInt &To) {
ProgramStateRef StInRange =
assumeInclusiveRangeInternal(State, Value, From, To, true);
if (!StInRange) {
ProgramStateRef StOutOfRange =
assumeInclusiveRangeInternal(State, Value, From, To, false);
if (LLVM_UNLIKELY(!StOutOfRange)) { // both infeasible
ProgramStateRef StInfeasible = State->cloneAsPosteriorlyOverconstrained();
assert(StInfeasible->isPosteriorlyOverconstrained());
// Checkers might rely on the API contract that both returned states
// cannot be null. Thus, we return StInfeasible for both branches because
// it might happen that a Checker uncoditionally uses one of them if the
// other is a nullptr. This may also happen with the non-dual and
// adjacent `assume(true)` and `assume(false)` calls. By implementing
// assume in therms of assumeDual, we can keep our API contract there as
// well.
return ProgramStatePair(StInfeasible, StInfeasible);
}
}

ProgramStateRef StOutOfRange =
assumeInclusiveRangeInternal(State, Value, From, To, false);
if (!StOutOfRange) {
return ProgramStatePair(StInRange, nullptr);
}

return ProgramStatePair(StInRange, StOutOfRange);
auto AssumeFun = [&](bool Assumption) {
return assumeInclusiveRangeInternal(State, Value, From, To, Assumption);
};
return assumeDualImpl(State, AssumeFun);
}

ProgramStateRef ConstraintManager::assume(ProgramStateRef State,
Expand Down

0 comments on commit 96fba64

Please sign in to comment.