mirror of
https://github.com/Gericom/teak-llvm.git
synced 2025-06-28 07:49:01 -04:00

to reflect the new license. We understand that people may be surprised that we're moving the header entirely to discuss the new license. We checked this carefully with the Foundation's lawyer and we believe this is the correct approach. Essentially, all code in the project is now made available by the LLVM project under our new license, so you will see that the license headers include that license only. Some of our contributors have contributed code under our old license, and accordingly, we have retained a copy of our old license notice in the top-level files in each project and repository. llvm-svn: 351636
133 lines
4.6 KiB
C++
133 lines
4.6 KiB
C++
//== SimpleConstraintManager.cpp --------------------------------*- C++ -*--==//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines SimpleConstraintManager, a class that provides a
|
|
// simplified constraint manager interface, compared to ConstraintManager.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h"
|
|
#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
|
|
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
|
|
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
|
|
|
|
namespace clang {
|
|
|
|
namespace ento {
|
|
|
|
SimpleConstraintManager::~SimpleConstraintManager() {}
|
|
|
|
ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef State,
|
|
DefinedSVal Cond,
|
|
bool Assumption) {
|
|
// If we have a Loc value, cast it to a bool NonLoc first.
|
|
if (Optional<Loc> LV = Cond.getAs<Loc>()) {
|
|
SValBuilder &SVB = State->getStateManager().getSValBuilder();
|
|
QualType T;
|
|
const MemRegion *MR = LV->getAsRegion();
|
|
if (const TypedRegion *TR = dyn_cast_or_null<TypedRegion>(MR))
|
|
T = TR->getLocationType();
|
|
else
|
|
T = SVB.getContext().VoidPtrTy;
|
|
|
|
Cond = SVB.evalCast(*LV, SVB.getContext().BoolTy, T).castAs<DefinedSVal>();
|
|
}
|
|
|
|
return assume(State, Cond.castAs<NonLoc>(), Assumption);
|
|
}
|
|
|
|
ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef State,
|
|
NonLoc Cond, bool Assumption) {
|
|
State = assumeAux(State, Cond, Assumption);
|
|
if (NotifyAssumeClients && SU)
|
|
return SU->processAssume(State, Cond, Assumption);
|
|
return State;
|
|
}
|
|
|
|
ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef State,
|
|
NonLoc Cond,
|
|
bool Assumption) {
|
|
|
|
// We cannot reason about SymSymExprs, and can only reason about some
|
|
// SymIntExprs.
|
|
if (!canReasonAbout(Cond)) {
|
|
// Just add the constraint to the expression without trying to simplify.
|
|
SymbolRef Sym = Cond.getAsSymExpr();
|
|
assert(Sym);
|
|
return assumeSymUnsupported(State, Sym, Assumption);
|
|
}
|
|
|
|
switch (Cond.getSubKind()) {
|
|
default:
|
|
llvm_unreachable("'Assume' not implemented for this NonLoc");
|
|
|
|
case nonloc::SymbolValKind: {
|
|
nonloc::SymbolVal SV = Cond.castAs<nonloc::SymbolVal>();
|
|
SymbolRef Sym = SV.getSymbol();
|
|
assert(Sym);
|
|
return assumeSym(State, Sym, Assumption);
|
|
}
|
|
|
|
case nonloc::ConcreteIntKind: {
|
|
bool b = Cond.castAs<nonloc::ConcreteInt>().getValue() != 0;
|
|
bool isFeasible = b ? Assumption : !Assumption;
|
|
return isFeasible ? State : nullptr;
|
|
}
|
|
|
|
case nonloc::PointerToMemberKind: {
|
|
bool IsNull = !Cond.castAs<nonloc::PointerToMember>().isNullMemberPointer();
|
|
bool IsFeasible = IsNull ? Assumption : !Assumption;
|
|
return IsFeasible ? State : nullptr;
|
|
}
|
|
|
|
case nonloc::LocAsIntegerKind:
|
|
return assume(State, Cond.castAs<nonloc::LocAsInteger>().getLoc(),
|
|
Assumption);
|
|
} // end switch
|
|
}
|
|
|
|
ProgramStateRef SimpleConstraintManager::assumeInclusiveRange(
|
|
ProgramStateRef State, NonLoc Value, const llvm::APSInt &From,
|
|
const llvm::APSInt &To, bool InRange) {
|
|
|
|
assert(From.isUnsigned() == To.isUnsigned() &&
|
|
From.getBitWidth() == To.getBitWidth() &&
|
|
"Values should have same types!");
|
|
|
|
if (!canReasonAbout(Value)) {
|
|
// Just add the constraint to the expression without trying to simplify.
|
|
SymbolRef Sym = Value.getAsSymExpr();
|
|
assert(Sym);
|
|
return assumeSymInclusiveRange(State, Sym, From, To, InRange);
|
|
}
|
|
|
|
switch (Value.getSubKind()) {
|
|
default:
|
|
llvm_unreachable("'assumeInclusiveRange' is not implemented"
|
|
"for this NonLoc");
|
|
|
|
case nonloc::LocAsIntegerKind:
|
|
case nonloc::SymbolValKind: {
|
|
if (SymbolRef Sym = Value.getAsSymbol())
|
|
return assumeSymInclusiveRange(State, Sym, From, To, InRange);
|
|
return State;
|
|
} // end switch
|
|
|
|
case nonloc::ConcreteIntKind: {
|
|
const llvm::APSInt &IntVal = Value.castAs<nonloc::ConcreteInt>().getValue();
|
|
bool IsInRange = IntVal >= From && IntVal <= To;
|
|
bool isFeasible = (IsInRange == InRange);
|
|
return isFeasible ? State : nullptr;
|
|
}
|
|
} // end switch
|
|
}
|
|
|
|
} // end of namespace ento
|
|
|
|
} // end of namespace clang
|