[Clang] Warning as error Array Comparisons from C++26 (#118872)
[llvm-project.git] / clang / lib / StaticAnalyzer / Core / SimpleConstraintManager.cpp
blob8ca2cdb9d3ab7a7109ae156525d8392260ebff47
1 //== SimpleConstraintManager.cpp --------------------------------*- C++ -*--==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines SimpleConstraintManager, a class that provides a
10 // simplified constraint manager interface, compared to ConstraintManager.
12 //===----------------------------------------------------------------------===//
14 #include "clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h"
15 #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
16 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
17 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
18 #include <optional>
20 namespace clang {
22 namespace ento {
24 SimpleConstraintManager::~SimpleConstraintManager() {}
26 ProgramStateRef SimpleConstraintManager::assumeInternal(ProgramStateRef State,
27 DefinedSVal Cond,
28 bool Assumption) {
29 // If we have a Loc value, cast it to a bool NonLoc first.
30 if (std::optional<Loc> LV = Cond.getAs<Loc>()) {
31 SValBuilder &SVB = State->getStateManager().getSValBuilder();
32 QualType T;
33 const MemRegion *MR = LV->getAsRegion();
34 if (const TypedRegion *TR = dyn_cast_or_null<TypedRegion>(MR))
35 T = TR->getLocationType();
36 else
37 T = SVB.getContext().VoidPtrTy;
39 Cond = SVB.evalCast(*LV, SVB.getContext().BoolTy, T).castAs<DefinedSVal>();
42 return assume(State, Cond.castAs<NonLoc>(), Assumption);
45 ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef State,
46 NonLoc Cond, bool Assumption) {
47 State = assumeAux(State, Cond, Assumption);
48 if (EE)
49 return EE->processAssume(State, Cond, Assumption);
50 return State;
53 ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef State,
54 NonLoc Cond,
55 bool Assumption) {
57 // We cannot reason about SymSymExprs, and can only reason about some
58 // SymIntExprs.
59 if (!canReasonAbout(Cond)) {
60 // Just add the constraint to the expression without trying to simplify.
61 SymbolRef Sym = Cond.getAsSymbol();
62 assert(Sym);
63 return assumeSymUnsupported(State, Sym, Assumption);
66 switch (Cond.getKind()) {
67 default:
68 llvm_unreachable("'Assume' not implemented for this NonLoc");
70 case nonloc::SymbolValKind: {
71 nonloc::SymbolVal SV = Cond.castAs<nonloc::SymbolVal>();
72 SymbolRef Sym = SV.getSymbol();
73 assert(Sym);
74 return assumeSym(State, Sym, Assumption);
77 case nonloc::ConcreteIntKind: {
78 bool b = Cond.castAs<nonloc::ConcreteInt>().getValue() != 0;
79 bool isFeasible = b ? Assumption : !Assumption;
80 return isFeasible ? State : nullptr;
83 case nonloc::PointerToMemberKind: {
84 bool IsNull = !Cond.castAs<nonloc::PointerToMember>().isNullMemberPointer();
85 bool IsFeasible = IsNull ? Assumption : !Assumption;
86 return IsFeasible ? State : nullptr;
89 case nonloc::LocAsIntegerKind:
90 return assumeInternal(State, Cond.castAs<nonloc::LocAsInteger>().getLoc(),
91 Assumption);
92 } // end switch
95 ProgramStateRef SimpleConstraintManager::assumeInclusiveRangeInternal(
96 ProgramStateRef State, NonLoc Value, const llvm::APSInt &From,
97 const llvm::APSInt &To, bool InRange) {
99 assert(From.isUnsigned() == To.isUnsigned() &&
100 From.getBitWidth() == To.getBitWidth() &&
101 "Values should have same types!");
103 if (!canReasonAbout(Value)) {
104 // Just add the constraint to the expression without trying to simplify.
105 SymbolRef Sym = Value.getAsSymbol();
106 assert(Sym);
107 return assumeSymInclusiveRange(State, Sym, From, To, InRange);
110 switch (Value.getKind()) {
111 default:
112 llvm_unreachable("'assumeInclusiveRange' is not implemented"
113 "for this NonLoc");
115 case nonloc::LocAsIntegerKind:
116 case nonloc::SymbolValKind: {
117 if (SymbolRef Sym = Value.getAsSymbol())
118 return assumeSymInclusiveRange(State, Sym, From, To, InRange);
119 return State;
120 } // end switch
122 case nonloc::ConcreteIntKind: {
123 const llvm::APSInt &IntVal = Value.castAs<nonloc::ConcreteInt>().getValue();
124 bool IsInRange = IntVal >= From && IntVal <= To;
125 bool isFeasible = (IsInRange == InRange);
126 return isFeasible ? State : nullptr;
128 } // end switch
131 } // end of namespace ento
133 } // end of namespace clang