clang 20.0.0git
SimpleSValBuilder.cpp
Go to the documentation of this file.
1// SimpleSValBuilder.cpp - A basic SValBuilder -----------------------*- 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 SimpleSValBuilder, a basic implementation of SValBuilder.
10//
11//===----------------------------------------------------------------------===//
12
19#include <optional>
20
21using namespace clang;
22using namespace ento;
23
24namespace {
25class SimpleSValBuilder : public SValBuilder {
26
27 // Query the constraint manager whether the SVal has only one possible
28 // (integer) value. If that is the case, the value is returned. Otherwise,
29 // returns NULL.
30 // This is an implementation detail. Checkers should use `getKnownValue()`
31 // instead.
32 static const llvm::APSInt *getConstValue(ProgramStateRef state, SVal V);
33
34 // Helper function that returns the value stored in a nonloc::ConcreteInt or
35 // loc::ConcreteInt.
36 static const llvm::APSInt *getConcreteValue(SVal V);
37
38 // With one `simplifySValOnce` call, a compound symbols might collapse to
39 // simpler symbol tree that is still possible to further simplify. Thus, we
40 // do the simplification on a new symbol tree until we reach the simplest
41 // form, i.e. the fixpoint.
42 // Consider the following symbol `(b * b) * b * b` which has this tree:
43 // *
44 // / \
45 // * b
46 // / \
47 // / b
48 // (b * b)
49 // Now, if the `b * b == 1` new constraint is added then during the first
50 // iteration we have the following transformations:
51 // * *
52 // / \ / \
53 // * b --> b b
54 // / \
55 // / b
56 // 1
57 // We need another iteration to reach the final result `1`.
58 SVal simplifyUntilFixpoint(ProgramStateRef State, SVal Val);
59
60 // Recursively descends into symbolic expressions and replaces symbols
61 // with their known values (in the sense of the getConstValue() method).
62 // We traverse the symbol tree and query the constraint values for the
63 // sub-trees and if a value is a constant we do the constant folding.
64 SVal simplifySValOnce(ProgramStateRef State, SVal V);
65
66public:
67 SimpleSValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context,
68 ProgramStateManager &stateMgr)
69 : SValBuilder(alloc, context, stateMgr) {}
70 ~SimpleSValBuilder() override {}
71
73 NonLoc lhs, NonLoc rhs, QualType resultTy) override;
75 Loc lhs, Loc rhs, QualType resultTy) override;
77 Loc lhs, NonLoc rhs, QualType resultTy) override;
78
79 /// Evaluates a given SVal by recursively evaluating and
80 /// simplifying the children SVals. If the SVal has only one possible
81 /// (integer) value, that value is returned. Otherwise, returns NULL.
82 const llvm::APSInt *getKnownValue(ProgramStateRef state, SVal V) override;
83
84 /// Evaluates a given SVal by recursively evaluating and simplifying the
85 /// children SVals, then returns its minimal possible (integer) value. If the
86 /// constraint manager cannot provide a meaningful answer, this returns NULL.
87 const llvm::APSInt *getMinValue(ProgramStateRef state, SVal V) override;
88
89 /// Evaluates a given SVal by recursively evaluating and simplifying the
90 /// children SVals, then returns its maximal possible (integer) value. If the
91 /// constraint manager cannot provide a meaningful answer, this returns NULL.
92 const llvm::APSInt *getMaxValue(ProgramStateRef state, SVal V) override;
93
94 SVal simplifySVal(ProgramStateRef State, SVal V) override;
95
96 SVal MakeSymIntVal(const SymExpr *LHS, BinaryOperator::Opcode op,
97 const llvm::APSInt &RHS, QualType resultTy);
98};
99} // end anonymous namespace
100
101SValBuilder *ento::createSimpleSValBuilder(llvm::BumpPtrAllocator &alloc,
102 ASTContext &context,
103 ProgramStateManager &stateMgr) {
104 return new SimpleSValBuilder(alloc, context, stateMgr);
105}
106
107// Checks if the negation the value and flipping sign preserve
108// the semantics on the operation in the resultType
109static bool isNegationValuePreserving(const llvm::APSInt &Value,
110 APSIntType ResultType) {
111 const unsigned ValueBits = Value.getSignificantBits();
112 if (ValueBits == ResultType.getBitWidth()) {
113 // The value is the lowest negative value that is representable
114 // in signed integer with bitWith of result type. The
115 // negation is representable if resultType is unsigned.
116 return ResultType.isUnsigned();
117 }
118
119 // If resultType bitWith is higher that number of bits required
120 // to represent RHS, the sign flip produce same value.
121 return ValueBits < ResultType.getBitWidth();
122}
123
124//===----------------------------------------------------------------------===//
125// Transfer function for binary operators.
126//===----------------------------------------------------------------------===//
127
128SVal SimpleSValBuilder::MakeSymIntVal(const SymExpr *LHS,
130 const llvm::APSInt &RHS,
131 QualType resultTy) {