From 96fba640cf58402b1015924f6582b14c6ac8cc32 Mon Sep 17 00:00:00 2001 From: Gabor Marton Date: Thu, 19 May 2022 11:14:56 +0200 Subject: [PATCH] [analyzer][NFC] Factor out the copy-paste code repetition of assumeDual 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 --- .../Core/PathSensitive/ConstraintManager.h | 4 ++ .../lib/StaticAnalyzer/Core/ConstraintManager.cpp | 48 ++++++++-------------- 2 files changed, 22 insertions(+), 30 deletions(-) diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h index bd92e7f..755371f 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h @@ -162,6 +162,10 @@ protected: /// 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 + ProgramStatePair assumeDualImpl(ProgramStateRef &State, + AssumeFunction &Assume); }; std::unique_ptr diff --git a/clang/lib/StaticAnalyzer/Core/ConstraintManager.cpp b/clang/lib/StaticAnalyzer/Core/ConstraintManager.cpp index 8a3ee5f..096266f 100644 --- a/clang/lib/StaticAnalyzer/Core/ConstraintManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/ConstraintManager.cpp @@ -42,12 +42,14 @@ ConditionTruthVal ConstraintManager::checkNull(ProgramStateRef State, return {}; } +template 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()); @@ -63,7 +65,7 @@ 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); } @@ -72,35 +74,21 @@ ConstraintManager::assumeDual(ProgramStateRef State, DefinedSVal Cond) { } 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, -- 2.7.4