xref: /netbsd-src/external/apache2/llvm/dist/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
1 // SValBuilder.h - Construction of SVals from evaluating expressions -*- 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 SValBuilder, a class that defines the interface for
10 //  "symbolical evaluators" which construct an SVal from an expression.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALBUILDER_H
15 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALBUILDER_H
16 
17 #include "clang/AST/ASTContext.h"
18 #include "clang/AST/DeclarationName.h"
19 #include "clang/AST/Expr.h"
20 #include "clang/AST/ExprObjC.h"
21 #include "clang/AST/Type.h"
22 #include "clang/Basic/LLVM.h"
23 #include "clang/Basic/LangOptions.h"
24 #include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
25 #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
26 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
27 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
28 #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
29 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
30 #include "llvm/ADT/ImmutableList.h"
31 #include "llvm/ADT/Optional.h"
32 #include <cstdint>
33 
34 namespace clang {
35 
36 class BlockDecl;
37 class CXXBoolLiteralExpr;
38 class CXXMethodDecl;
39 class CXXRecordDecl;
40 class DeclaratorDecl;
41 class FunctionDecl;
42 class LocationContext;
43 class StackFrameContext;
44 class Stmt;
45 
46 namespace ento {
47 
48 class ConditionTruthVal;
49 class ProgramStateManager;
50 class StoreRef;
51 
52 class SValBuilder {
53   virtual void anchor();
54 
55 protected:
56   ASTContext &Context;
57 
58   /// Manager of APSInt values.
59   BasicValueFactory BasicVals;
60 
61   /// Manages the creation of symbols.
62   SymbolManager SymMgr;
63 
64   /// Manages the creation of memory regions.
65   MemRegionManager MemMgr;
66 
67   ProgramStateManager &StateMgr;
68 
69   /// The scalar type to use for array indices.
70   const QualType ArrayIndexTy;
71 
72   /// The width of the scalar type used for array indices.
73   const unsigned ArrayIndexWidth;
74 
75   SVal evalCastKind(UndefinedVal V, QualType CastTy, QualType OriginalTy);
76   SVal evalCastKind(UnknownVal V, QualType CastTy, QualType OriginalTy);
77   SVal evalCastKind(Loc V, QualType CastTy, QualType OriginalTy);
78   SVal evalCastKind(NonLoc V, QualType CastTy, QualType OriginalTy);
79   SVal evalCastSubKind(loc::ConcreteInt V, QualType CastTy,
80                        QualType OriginalTy);
81   SVal evalCastSubKind(loc::GotoLabel V, QualType CastTy, QualType OriginalTy);
82   SVal evalCastSubKind(loc::MemRegionVal V, QualType CastTy,
83                        QualType OriginalTy);
84   SVal evalCastSubKind(nonloc::CompoundVal V, QualType CastTy,
85                        QualType OriginalTy);
86   SVal evalCastSubKind(nonloc::ConcreteInt V, QualType CastTy,
87                        QualType OriginalTy);
88   SVal evalCastSubKind(nonloc::LazyCompoundVal V, QualType CastTy,
89                        QualType OriginalTy);
90   SVal evalCastSubKind(nonloc::LocAsInteger V, QualType CastTy,
91                        QualType OriginalTy);
92   SVal evalCastSubKind(nonloc::SymbolVal V, QualType CastTy,
93                        QualType OriginalTy);
94   SVal evalCastSubKind(nonloc::PointerToMember V, QualType CastTy,
95                        QualType OriginalTy);
96 
97 public:
SValBuilder(llvm::BumpPtrAllocator & alloc,ASTContext & context,ProgramStateManager & stateMgr)98   SValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context,
99               ProgramStateManager &stateMgr)
100       : Context(context), BasicVals(context, alloc),
101         SymMgr(context, BasicVals, alloc), MemMgr(context, alloc),
102         StateMgr(stateMgr), ArrayIndexTy(context.LongLongTy),
103         ArrayIndexWidth(context.getTypeSize(ArrayIndexTy)) {}
104 
105   virtual ~SValBuilder() = default;
106 
haveSameType(const SymExpr * Sym1,const SymExpr * Sym2)107   bool haveSameType(const SymExpr *Sym1, const SymExpr *Sym2) {
108     return haveSameType(Sym1->getType(), Sym2->getType());
109   }
110 
haveSameType(QualType Ty1,QualType Ty2)111   bool haveSameType(QualType Ty1, QualType Ty2) {
112     // FIXME: Remove the second disjunct when we support symbolic
113     // truncation/extension.
114     return (Context.getCanonicalType(Ty1) == Context.getCanonicalType(Ty2) ||
115             (Ty1->isIntegralOrEnumerationType() &&
116              Ty2->isIntegralOrEnumerationType()));
117   }
118 
119   SVal evalCast(SVal V, QualType CastTy, QualType OriginalTy);
120 
121   // Handles casts of type CK_IntegralCast.
122   SVal evalIntegralCast(ProgramStateRef state, SVal val, QualType castTy,
123                         QualType originalType);
124 
125   virtual SVal evalMinus(NonLoc val) = 0;
126 
127   virtual SVal evalComplement(NonLoc val) = 0;
128 
129   /// Create a new value which represents a binary expression with two non-
130   /// location operands.
131   virtual SVal evalBinOpNN(ProgramStateRef state, BinaryOperator::Opcode op,
132                            NonLoc lhs, NonLoc rhs, QualType resultTy) = 0;
133 
134   /// Create a new value which represents a binary expression with two memory
135   /// location operands.
136   virtual SVal evalBinOpLL(ProgramStateRef state, BinaryOperator::Opcode op,
137                            Loc lhs, Loc rhs, QualType resultTy) = 0;
138 
139   /// Create a new value which represents a binary expression with a memory
140   /// location and non-location operands. For example, this would be used to
141   /// evaluate a pointer arithmetic operation.
142   virtual SVal evalBinOpLN(ProgramStateRef state, BinaryOperator::Opcode op,
143                            Loc lhs, NonLoc rhs, QualType resultTy) = 0;
144 
145   /// Evaluates a given SVal. If the SVal has only one possible (integer) value,
146   /// that value is returned. Otherwise, returns NULL.
147   virtual const llvm::APSInt *getKnownValue(ProgramStateRef state, SVal val) = 0;
148 
149   /// Simplify symbolic expressions within a given SVal. Return an SVal
150   /// that represents the same value, but is hopefully easier to work with
151   /// than the original SVal.
152   virtual SVal simplifySVal(ProgramStateRef State, SVal Val) = 0;
153 
154   /// Constructs a symbolic expression for two non-location values.
155   SVal makeSymExprValNN(BinaryOperator::Opcode op,
156                         NonLoc lhs, NonLoc rhs, QualType resultTy);
157 
158   SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
159                  SVal lhs, SVal rhs, QualType type);
160 
161   /// \return Whether values in \p lhs and \p rhs are equal at \p state.
162   ConditionTruthVal areEqual(ProgramStateRef state, SVal lhs, SVal rhs);
163 
164   SVal evalEQ(ProgramStateRef state, SVal lhs, SVal rhs);
165 
166   DefinedOrUnknownSVal evalEQ(ProgramStateRef state, DefinedOrUnknownSVal lhs,
167                               DefinedOrUnknownSVal rhs);
168 
getContext()169   ASTContext &getContext() { return Context; }
getContext()170   const ASTContext &getContext() const { return Context; }
171 
getStateManager()172   ProgramStateManager &getStateManager() { return StateMgr; }
173 
getConditionType()174   QualType getConditionType() const {
175     return Context.getLangOpts().CPlusPlus ? Context.BoolTy : Context.IntTy;
176   }
177 
getArrayIndexType()178   QualType getArrayIndexType() const {
179     return ArrayIndexTy;
180   }
181 
getBasicValueFactory()182   BasicValueFactory &getBasicValueFactory() { return BasicVals; }
getBasicValueFactory()183   const BasicValueFactory &getBasicValueFactory() const { return BasicVals; }
184 
getSymbolManager()185   SymbolManager &getSymbolManager() { return SymMgr; }
getSymbolManager()186   const SymbolManager &getSymbolManager() const { return SymMgr; }
187 
getRegionManager()188   MemRegionManager &getRegionManager() { return MemMgr; }
getRegionManager()189   const MemRegionManager &getRegionManager() const { return MemMgr; }
190 
191   // Forwarding methods to SymbolManager.
192 
193   const SymbolConjured* conjureSymbol(const Stmt *stmt,
194                                       const LocationContext *LCtx,
195                                       QualType type,
196                                       unsigned visitCount,
197                                       const void *symbolTag = nullptr) {
198     return SymMgr.conjureSymbol(stmt, LCtx, type, visitCount, symbolTag);
199   }
200 
201   const SymbolConjured* conjureSymbol(const Expr *expr,
202                                       const LocationContext *LCtx,
203                                       unsigned visitCount,
204                                       const void *symbolTag = nullptr) {
205     return SymMgr.conjureSymbol(expr, LCtx, visitCount, symbolTag);
206   }
207 
208   /// Construct an SVal representing '0' for the specified type.
209   DefinedOrUnknownSVal makeZeroVal(QualType type);
210 
211   /// Make a unique symbol for value of region.
212   DefinedOrUnknownSVal getRegionValueSymbolVal(const TypedValueRegion *region);
213 
214   /// Create a new symbol with a unique 'name'.
215   ///
216   /// We resort to conjured symbols when we cannot construct a derived symbol.
217   /// The advantage of symbols derived/built from other symbols is that we
218   /// preserve the relation between related(or even equivalent) expressions, so
219   /// conjured symbols should be used sparingly.
220   DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag,
221                                         const Expr *expr,
222                                         const LocationContext *LCtx,
223                                         unsigned count);
224   DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag,
225                                         const Expr *expr,
226                                         const LocationContext *LCtx,
227                                         QualType type,
228                                         unsigned count);
229   DefinedOrUnknownSVal conjureSymbolVal(const Stmt *stmt,
230                                         const LocationContext *LCtx,
231                                         QualType type,
232                                         unsigned visitCount);
233 
234   /// Conjure a symbol representing heap allocated memory region.
235   ///
236   /// Note, the expression should represent a location.
237   DefinedOrUnknownSVal getConjuredHeapSymbolVal(const Expr *E,
238                                                 const LocationContext *LCtx,
239                                                 unsigned Count);
240 
241   DefinedOrUnknownSVal getDerivedRegionValueSymbolVal(
242       SymbolRef parentSymbol, const TypedValueRegion *region);
243 
244   DefinedSVal getMetadataSymbolVal(const void *symbolTag,
245                                    const MemRegion *region,
246                                    const Expr *expr, QualType type,
247                                    const LocationContext *LCtx,
248                                    unsigned count);
249 
250   DefinedSVal getMemberPointer(const NamedDecl *ND);
251 
252   DefinedSVal getFunctionPointer(const FunctionDecl *func);
253 
254   DefinedSVal getBlockPointer(const BlockDecl *block, CanQualType locTy,
255                               const LocationContext *locContext,
256                               unsigned blockCount);
257 
258   /// Returns the value of \p E, if it can be determined in a non-path-sensitive
259   /// manner.
260   ///
261   /// If \p E is not a constant or cannot be modeled, returns \c None.
262   Optional<SVal> getConstantVal(const Expr *E);
263 
makeCompoundVal(QualType type,llvm::ImmutableList<SVal> vals)264   NonLoc makeCompoundVal(QualType type, llvm::ImmutableList<SVal> vals) {
265     return nonloc::CompoundVal(BasicVals.getCompoundValData(type, vals));
266   }
267 
makeLazyCompoundVal(const StoreRef & store,const TypedValueRegion * region)268   NonLoc makeLazyCompoundVal(const StoreRef &store,
269                              const TypedValueRegion *region) {
270     return nonloc::LazyCompoundVal(
271         BasicVals.getLazyCompoundValData(store, region));
272   }
273 
makePointerToMember(const DeclaratorDecl * DD)274   NonLoc makePointerToMember(const DeclaratorDecl *DD) {
275     return nonloc::PointerToMember(DD);
276   }
277 
makePointerToMember(const PointerToMemberData * PTMD)278   NonLoc makePointerToMember(const PointerToMemberData *PTMD) {
279     return nonloc::PointerToMember(PTMD);
280   }
281 
makeZeroArrayIndex()282   NonLoc makeZeroArrayIndex() {
283     return nonloc::ConcreteInt(BasicVals.getValue(0, ArrayIndexTy));
284   }
285 
makeArrayIndex(uint64_t idx)286   NonLoc makeArrayIndex(uint64_t idx) {
287     return nonloc::ConcreteInt(BasicVals.getValue(idx, ArrayIndexTy));
288   }
289 
290   SVal convertToArrayIndex(SVal val);
291 
makeIntVal(const IntegerLiteral * integer)292   nonloc::ConcreteInt makeIntVal(const IntegerLiteral* integer) {
293     return nonloc::ConcreteInt(
294         BasicVals.getValue(integer->getValue(),
295                      integer->getType()->isUnsignedIntegerOrEnumerationType()));
296   }
297 
makeBoolVal(const ObjCBoolLiteralExpr * boolean)298   nonloc::ConcreteInt makeBoolVal(const ObjCBoolLiteralExpr *boolean) {
299     return makeTruthVal(boolean->getValue(), boolean->getType());
300   }
301 
302   nonloc::ConcreteInt makeBoolVal(const CXXBoolLiteralExpr *boolean);
303 
makeIntVal(const llvm::APSInt & integer)304   nonloc::ConcreteInt makeIntVal(const llvm::APSInt& integer) {
305     return nonloc::ConcreteInt(BasicVals.getValue(integer));
306   }
307 
makeIntLocVal(const llvm::APSInt & integer)308   loc::ConcreteInt makeIntLocVal(const llvm::APSInt &integer) {
309     return loc::ConcreteInt(BasicVals.getValue(integer));
310   }
311 
makeIntVal(const llvm::APInt & integer,bool isUnsigned)312   NonLoc makeIntVal(const llvm::APInt& integer, bool isUnsigned) {
313     return nonloc::ConcreteInt(BasicVals.getValue(integer, isUnsigned));
314   }
315 
makeIntVal(uint64_t integer,QualType type)316   DefinedSVal makeIntVal(uint64_t integer, QualType type) {
317     if (Loc::isLocType(type))
318       return loc::ConcreteInt(BasicVals.getValue(integer, type));
319 
320     return nonloc::ConcreteInt(BasicVals.getValue(integer, type));
321   }
322 
makeIntVal(uint64_t integer,bool isUnsigned)323   NonLoc makeIntVal(uint64_t integer, bool isUnsigned) {
324     return nonloc::ConcreteInt(BasicVals.getIntValue(integer, isUnsigned));
325   }
326 
makeIntValWithPtrWidth(uint64_t integer,bool isUnsigned)327   NonLoc makeIntValWithPtrWidth(uint64_t integer, bool isUnsigned) {
328     return nonloc::ConcreteInt(
329         BasicVals.getIntWithPtrWidth(integer, isUnsigned));
330   }
331 
makeLocAsInteger(Loc loc,unsigned bits)332   NonLoc makeLocAsInteger(Loc loc, unsigned bits) {
333     return nonloc::LocAsInteger(BasicVals.getPersistentSValWithData(loc, bits));
334   }
335 
336   NonLoc makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
337                     const llvm::APSInt& rhs, QualType type);
338 
339   NonLoc makeNonLoc(const llvm::APSInt& rhs, BinaryOperator::Opcode op,
340                     const SymExpr *lhs, QualType type);
341 
342   NonLoc makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
343                     const SymExpr *rhs, QualType type);
344 
345   /// Create a NonLoc value for cast.
346   NonLoc makeNonLoc(const SymExpr *operand, QualType fromTy, QualType toTy);
347 
makeTruthVal(bool b,QualType type)348   nonloc::ConcreteInt makeTruthVal(bool b, QualType type) {
349     return nonloc::ConcreteInt(BasicVals.getTruthValue(b, type));
350   }
351 
makeTruthVal(bool b)352   nonloc::ConcreteInt makeTruthVal(bool b) {
353     return nonloc::ConcreteInt(BasicVals.getTruthValue(b));
354   }
355 
356   /// Create NULL pointer, with proper pointer bit-width for given address
357   /// space.
358   /// \param type pointer type.
makeNullWithType(QualType type)359   Loc makeNullWithType(QualType type) {
360     return loc::ConcreteInt(BasicVals.getZeroWithTypeSize(type));
361   }
362 
makeNull()363   Loc makeNull() {
364     return loc::ConcreteInt(BasicVals.getZeroWithPtrWidth());
365   }
366 
makeLoc(SymbolRef sym)367   Loc makeLoc(SymbolRef sym) {
368     return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
369   }
370 
makeLoc(const MemRegion * region)371   Loc makeLoc(const MemRegion* region) {
372     return loc::MemRegionVal(region);
373   }
374 
makeLoc(const AddrLabelExpr * expr)375   Loc makeLoc(const AddrLabelExpr *expr) {
376     return loc::GotoLabel(expr->getLabel());
377   }
378 
makeLoc(const llvm::APSInt & integer)379   Loc makeLoc(const llvm::APSInt& integer) {
380     return loc::ConcreteInt(BasicVals.getValue(integer));
381   }
382 
383   /// Make an SVal that represents the given symbol. This follows the convention
384   /// of representing Loc-type symbols (symbolic pointers and references)
385   /// as Loc values wrapping the symbol rather than as plain symbol values.
makeSymbolVal(SymbolRef Sym)386   SVal makeSymbolVal(SymbolRef Sym) {
387     if (Loc::isLocType(Sym->getType()))
388       return makeLoc(Sym);
389     return nonloc::SymbolVal(Sym);
390   }
391 
392   /// Return a memory region for the 'this' object reference.
393   loc::MemRegionVal getCXXThis(const CXXMethodDecl *D,
394                                const StackFrameContext *SFC);
395 
396   /// Return a memory region for the 'this' object reference.
397   loc::MemRegionVal getCXXThis(const CXXRecordDecl *D,
398                                const StackFrameContext *SFC);
399 };
400 
401 SValBuilder* createSimpleSValBuilder(llvm::BumpPtrAllocator &alloc,
402                                      ASTContext &context,
403                                      ProgramStateManager &stateMgr);
404 
405 } // namespace ento
406 
407 } // namespace clang
408 
409 #endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALBUILDER_H
410