1 //===-- DataflowEnvironment.cpp ---------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines an Environment class that is used by dataflow analyses
10 // that run over Control-Flow Graphs (CFGs) to keep track of the state of the
11 // program at given program points.
13 //===----------------------------------------------------------------------===//
15 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
16 #include "clang/AST/Decl.h"
17 #include "clang/AST/DeclCXX.h"
18 #include "clang/AST/Type.h"
19 #include "clang/Analysis/FlowSensitive/DataflowLattice.h"
20 #include "clang/Analysis/FlowSensitive/Value.h"
21 #include "llvm/ADT/DenseMap.h"
22 #include "llvm/ADT/DenseSet.h"
23 #include "llvm/ADT/MapVector.h"
24 #include "llvm/ADT/STLExtras.h"
25 #include "llvm/Support/ErrorHandling.h"
32 // FIXME: convert these to parameters of the analysis or environment. Current
33 // settings have been experimentaly validated, but only for a particular
35 static constexpr int MaxCompositeValueDepth
= 3;
36 static constexpr int MaxCompositeValueSize
= 1000;
38 /// Returns a map consisting of key-value entries that are present in both maps.
39 template <typename K
, typename V
>
40 llvm::DenseMap
<K
, V
> intersectDenseMaps(const llvm::DenseMap
<K
, V
> &Map1
,
41 const llvm::DenseMap
<K
, V
> &Map2
) {
42 llvm::DenseMap
<K
, V
> Result
;
43 for (auto &Entry
: Map1
) {
44 auto It
= Map2
.find(Entry
.first
);
45 if (It
!= Map2
.end() && Entry
.second
== It
->second
)
46 Result
.insert({Entry
.first
, Entry
.second
});
51 // Whether to consider equivalent two values with an unknown relation.
53 // FIXME: this function is a hack enabling unsoundness to support
54 // convergence. Once we have widening support for the reference/pointer and
55 // struct built-in models, this should be unconditionally `false` (and inlined
56 // as such at its call sites).
57 static bool equateUnknownValues(Value::Kind K
) {
59 case Value::Kind::Integer
:
60 case Value::Kind::Pointer
:
61 case Value::Kind::Record
:
68 static bool compareDistinctValues(QualType Type
, Value
&Val1
,
69 const Environment
&Env1
, Value
&Val2
,
70 const Environment
&Env2
,
71 Environment::ValueModel
&Model
) {
72 // Note: Potentially costly, but, for booleans, we could check whether both
73 // can be proven equivalent in their respective environments.
75 // FIXME: move the reference/pointers logic from `areEquivalentValues` to here
76 // and implement separate, join/widen specific handling for
77 // reference/pointers.
78 switch (Model
.compare(Type
, Val1
, Env1
, Val2
, Env2
)) {
79 case ComparisonResult::Same
:
81 case ComparisonResult::Different
:
83 case ComparisonResult::Unknown
:
84 return equateUnknownValues(Val1
.getKind());
86 llvm_unreachable("All cases covered in switch");
89 /// Attempts to merge distinct values `Val1` and `Val2` in `Env1` and `Env2`,
90 /// respectively, of the same type `Type`. Merging generally produces a single
91 /// value that (soundly) approximates the two inputs, although the actual
92 /// meaning depends on `Model`.
93 static Value
*mergeDistinctValues(QualType Type
, Value
&Val1
,
94 const Environment
&Env1
, Value
&Val2
,
95 const Environment
&Env2
,
96 Environment
&MergedEnv
,
97 Environment::ValueModel
&Model
) {
98 // Join distinct boolean values preserving information about the constraints
99 // in the respective path conditions.
100 if (isa
<BoolValue
>(&Val1
) && isa
<BoolValue
>(&Val2
)) {
101 // FIXME: Checking both values should be unnecessary, since they should have
102 // a consistent shape. However, right now we can end up with BoolValue's in
103 // integer-typed variables due to our incorrect handling of
104 // boolean-to-integer casts (we just propagate the BoolValue to the result
105 // of the cast). So, a join can encounter an integer in one branch but a
106 // bool in the other.
109 // std::optional<bool> o;
111 // if (o.has_value())
114 auto &Expr1
= cast
<BoolValue
>(Val1
).formula();
115 auto &Expr2
= cast
<BoolValue
>(Val2
).formula();
116 auto &A
= MergedEnv
.arena();
117 auto &MergedVal
= A
.makeAtomRef(A
.makeAtom());
118 MergedEnv
.addToFlowCondition(
119 A
.makeOr(A
.makeAnd(A
.makeAtomRef(Env1
.getFlowConditionToken()),
120 A
.makeEquals(MergedVal
, Expr1
)),
121 A
.makeAnd(A
.makeAtomRef(Env2
.getFlowConditionToken()),
122 A
.makeEquals(MergedVal
, Expr2
))));
123 return &A
.makeBoolValue(MergedVal
);
126 Value
*MergedVal
= nullptr;
127 if (auto *RecordVal1
= dyn_cast
<RecordValue
>(&Val1
)) {
128 auto *RecordVal2
= cast
<RecordValue
>(&Val2
);
130 if (&RecordVal1
->getLoc() == &RecordVal2
->getLoc())
131 // `RecordVal1` and `RecordVal2` may have different properties associated
132 // with them. Create a new `RecordValue` with the same location but
133 // without any properties so that we soundly approximate both values. If a
134 // particular analysis needs to merge properties, it should do so in
135 // `DataflowAnalysis::merge()`.
136 MergedVal
= &MergedEnv
.create
<RecordValue
>(RecordVal1
->getLoc());
138 // If the locations for the two records are different, need to create a
139 // completely new value.
140 MergedVal
= MergedEnv
.createValue(Type
);
142 MergedVal
= MergedEnv
.createValue(Type
);
145 // FIXME: Consider destroying `MergedValue` immediately if `ValueModel::merge`
146 // returns false to avoid storing unneeded values in `DACtx`.
148 if (Model
.merge(Type
, Val1
, Env1
, Val2
, Env2
, *MergedVal
, MergedEnv
))
154 // When widening does not change `Current`, return value will equal `&Prev`.
155 static Value
&widenDistinctValues(QualType Type
, Value
&Prev
,
156 const Environment
&PrevEnv
, Value
&Current
,
157 Environment
&CurrentEnv
,
158 Environment::ValueModel
&Model
) {
159 // Boolean-model widening.
160 if (isa
<BoolValue
>(&Prev
)) {
161 assert(isa
<BoolValue
>(Current
));
162 // Widen to Top, because we know they are different values. If previous was
163 // already Top, re-use that to (implicitly) indicate that no change occured.
164 if (isa
<TopBoolValue
>(Prev
))
166 return CurrentEnv
.makeTopBoolValue();
169 // FIXME: Add other built-in model widening.
171 // Custom-model widening.
172 if (auto *W
= Model
.widen(Type
, Prev
, PrevEnv
, Current
, CurrentEnv
))
175 return equateUnknownValues(Prev
.getKind()) ? Prev
: Current
;
178 // Returns whether the values in `Map1` and `Map2` compare equal for those
179 // keys that `Map1` and `Map2` have in common.
180 template <typename Key
>
181 bool compareKeyToValueMaps(const llvm::MapVector
<Key
, Value
*> &Map1
,
182 const llvm::MapVector
<Key
, Value
*> &Map2
,
183 const Environment
&Env1
, const Environment
&Env2
,
184 Environment::ValueModel
&Model
) {
185 for (auto &Entry
: Map1
) {
187 assert(K
!= nullptr);
189 Value
*Val
= Entry
.second
;
190 assert(Val
!= nullptr);
192 auto It
= Map2
.find(K
);
193 if (It
== Map2
.end())
195 assert(It
->second
!= nullptr);
197 if (!areEquivalentValues(*Val
, *It
->second
) &&
198 !compareDistinctValues(K
->getType(), *Val
, Env1
, *It
->second
, Env2
,
206 // Perform a join on either `LocToVal` or `ExprToVal`. `Key` must be either
207 // `const StorageLocation *` or `const Expr *`.
208 template <typename Key
>
209 llvm::MapVector
<Key
, Value
*>
210 joinKeyToValueMap(const llvm::MapVector
<Key
, Value
*> &Map1
,
211 const llvm::MapVector
<Key
, Value
*> &Map2
,
212 const Environment
&Env1
, const Environment
&Env2
,
213 Environment
&JoinedEnv
, Environment::ValueModel
&Model
) {
214 llvm::MapVector
<Key
, Value
*> MergedMap
;
215 for (auto &Entry
: Map1
) {
217 assert(K
!= nullptr);
219 Value
*Val
= Entry
.second
;
220 assert(Val
!= nullptr);
222 auto It
= Map2
.find(K
);
223 if (It
== Map2
.end())
225 assert(It
->second
!= nullptr);
227 if (areEquivalentValues(*Val
, *It
->second
)) {
228 MergedMap
.insert({K
, Val
});
232 if (Value
*MergedVal
= mergeDistinctValues(
233 K
->getType(), *Val
, Env1
, *It
->second
, Env2
, JoinedEnv
, Model
)) {
234 MergedMap
.insert({K
, MergedVal
});
241 // Perform widening on either `LocToVal` or `ExprToVal`. `Key` must be either
242 // `const StorageLocation *` or `const Expr *`.
243 template <typename Key
>
244 llvm::MapVector
<Key
, Value
*>
245 widenKeyToValueMap(const llvm::MapVector
<Key
, Value
*> &CurMap
,
246 const llvm::MapVector
<Key
, Value
*> &PrevMap
,
247 Environment
&CurEnv
, const Environment
&PrevEnv
,
248 Environment::ValueModel
&Model
, LatticeJoinEffect
&Effect
) {
249 llvm::MapVector
<Key
, Value
*> WidenedMap
;
250 for (auto &Entry
: CurMap
) {
252 assert(K
!= nullptr);
254 Value
*Val
= Entry
.second
;
255 assert(Val
!= nullptr);
257 auto PrevIt
= PrevMap
.find(K
);
258 if (PrevIt
== PrevMap
.end())
260 assert(PrevIt
->second
!= nullptr);
262 if (areEquivalentValues(*Val
, *PrevIt
->second
)) {
263 WidenedMap
.insert({K
, Val
});
267 Value
&WidenedVal
= widenDistinctValues(K
->getType(), *PrevIt
->second
,
268 PrevEnv
, *Val
, CurEnv
, Model
);
269 WidenedMap
.insert({K
, &WidenedVal
});
270 if (&WidenedVal
!= PrevIt
->second
)
271 Effect
= LatticeJoinEffect::Changed
;
277 /// Initializes a global storage value.
278 static void insertIfGlobal(const Decl
&D
,
279 llvm::DenseSet
<const VarDecl
*> &Vars
) {
280 if (auto *V
= dyn_cast
<VarDecl
>(&D
))
281 if (V
->hasGlobalStorage())
285 static void insertIfFunction(const Decl
&D
,
286 llvm::DenseSet
<const FunctionDecl
*> &Funcs
) {
287 if (auto *FD
= dyn_cast
<FunctionDecl
>(&D
))
291 static MemberExpr
*getMemberForAccessor(const CXXMemberCallExpr
&C
) {
292 if (!C
.getMethodDecl())
294 auto *Body
= dyn_cast_or_null
<CompoundStmt
>(C
.getMethodDecl()->getBody());
295 if (!Body
|| Body
->size() != 1)
297 if (auto *RS
= dyn_cast
<ReturnStmt
>(*Body
->body_begin()))
298 if (auto *Return
= RS
->getRetValue())
299 return dyn_cast
<MemberExpr
>(Return
->IgnoreParenImpCasts());
304 getFieldsGlobalsAndFuncs(const Decl
&D
, FieldSet
&Fields
,
305 llvm::DenseSet
<const VarDecl
*> &Vars
,
306 llvm::DenseSet
<const FunctionDecl
*> &Funcs
) {
307 insertIfGlobal(D
, Vars
);
308 insertIfFunction(D
, Funcs
);
309 if (const auto *Decomp
= dyn_cast
<DecompositionDecl
>(&D
))
310 for (const auto *B
: Decomp
->bindings())
311 if (auto *ME
= dyn_cast_or_null
<MemberExpr
>(B
->getBinding()))
312 // FIXME: should we be using `E->getFoundDecl()`?
313 if (const auto *FD
= dyn_cast
<FieldDecl
>(ME
->getMemberDecl()))
317 /// Traverses `S` and inserts into `Fields`, `Vars` and `Funcs` any fields,
318 /// global variables and functions that are declared in or referenced from
321 getFieldsGlobalsAndFuncs(const Stmt
&S
, FieldSet
&Fields
,
322 llvm::DenseSet
<const VarDecl
*> &Vars
,
323 llvm::DenseSet
<const FunctionDecl
*> &Funcs
) {
324 for (auto *Child
: S
.children())
325 if (Child
!= nullptr)
326 getFieldsGlobalsAndFuncs(*Child
, Fields
, Vars
, Funcs
);
327 if (const auto *DefaultInit
= dyn_cast
<CXXDefaultInitExpr
>(&S
))
328 getFieldsGlobalsAndFuncs(*DefaultInit
->getExpr(), Fields
, Vars
, Funcs
);
330 if (auto *DS
= dyn_cast
<DeclStmt
>(&S
)) {
331 if (DS
->isSingleDecl())
332 getFieldsGlobalsAndFuncs(*DS
->getSingleDecl(), Fields
, Vars
, Funcs
);
334 for (auto *D
: DS
->getDeclGroup())
335 getFieldsGlobalsAndFuncs(*D
, Fields
, Vars
, Funcs
);
336 } else if (auto *E
= dyn_cast
<DeclRefExpr
>(&S
)) {
337 insertIfGlobal(*E
->getDecl(), Vars
);
338 insertIfFunction(*E
->getDecl(), Funcs
);
339 } else if (const auto *C
= dyn_cast
<CXXMemberCallExpr
>(&S
)) {
340 // If this is a method that returns a member variable but does nothing else,
341 // model the field of the return value.
342 if (MemberExpr
*E
= getMemberForAccessor(*C
))
343 if (const auto *FD
= dyn_cast
<FieldDecl
>(E
->getMemberDecl()))
345 } else if (auto *E
= dyn_cast
<MemberExpr
>(&S
)) {
346 // FIXME: should we be using `E->getFoundDecl()`?
347 const ValueDecl
*VD
= E
->getMemberDecl();
348 insertIfGlobal(*VD
, Vars
);
349 insertIfFunction(*VD
, Funcs
);
350 if (const auto *FD
= dyn_cast
<FieldDecl
>(VD
))
352 } else if (auto *InitList
= dyn_cast
<InitListExpr
>(&S
)) {
353 if (RecordDecl
*RD
= InitList
->getType()->getAsRecordDecl())
354 for (const auto *FD
: getFieldsForInitListExpr(RD
))
359 // FIXME: Add support for resetting globals after function calls to enable
360 // the implementation of sound analyses.
361 void Environment::initFieldsGlobalsAndFuncs(const FunctionDecl
*FuncDecl
) {
362 assert(FuncDecl
->getBody() != nullptr);
365 llvm::DenseSet
<const VarDecl
*> Vars
;
366 llvm::DenseSet
<const FunctionDecl
*> Funcs
;
368 // Look for global variable and field references in the
369 // constructor-initializers.
370 if (const auto *CtorDecl
= dyn_cast
<CXXConstructorDecl
>(FuncDecl
)) {
371 for (const auto *Init
: CtorDecl
->inits()) {
372 if (Init
->isMemberInitializer()) {
373 Fields
.insert(Init
->getMember());
374 } else if (Init
->isIndirectMemberInitializer()) {
375 for (const auto *I
: Init
->getIndirectMember()->chain())
376 Fields
.insert(cast
<FieldDecl
>(I
));
378 const Expr
*E
= Init
->getInit();
379 assert(E
!= nullptr);
380 getFieldsGlobalsAndFuncs(*E
, Fields
, Vars
, Funcs
);
382 // Add all fields mentioned in default member initializers.
383 for (const FieldDecl
*F
: CtorDecl
->getParent()->fields())
384 if (const auto *I
= F
->getInClassInitializer())
385 getFieldsGlobalsAndFuncs(*I
, Fields
, Vars
, Funcs
);
387 getFieldsGlobalsAndFuncs(*FuncDecl
->getBody(), Fields
, Vars
, Funcs
);
389 // These have to be added before the lines that follow to ensure that
390 // `create*` work correctly for structs.
391 DACtx
->addModeledFields(Fields
);
393 for (const VarDecl
*D
: Vars
) {
394 if (getStorageLocation(*D
) != nullptr)
397 setStorageLocation(*D
, createObject(*D
));
400 for (const FunctionDecl
*FD
: Funcs
) {
401 if (getStorageLocation(*FD
) != nullptr)
403 auto &Loc
= createStorageLocation(FD
->getType());
404 setStorageLocation(*FD
, Loc
);
408 Environment::Environment(DataflowAnalysisContext
&DACtx
)
410 FlowConditionToken(DACtx
.arena().makeFlowConditionToken()) {}
412 Environment
Environment::fork() const {
413 Environment
Copy(*this);
414 Copy
.FlowConditionToken
= DACtx
->forkFlowCondition(FlowConditionToken
);
418 Environment::Environment(DataflowAnalysisContext
&DACtx
,
419 const DeclContext
&DeclCtx
)
420 : Environment(DACtx
) {
421 CallStack
.push_back(&DeclCtx
);
423 if (const auto *FuncDecl
= dyn_cast
<FunctionDecl
>(&DeclCtx
)) {
424 assert(FuncDecl
->getBody() != nullptr);
426 initFieldsGlobalsAndFuncs(FuncDecl
);
428 for (const auto *ParamDecl
: FuncDecl
->parameters()) {
429 assert(ParamDecl
!= nullptr);
430 setStorageLocation(*ParamDecl
, createObject(*ParamDecl
, nullptr));
434 if (const auto *MethodDecl
= dyn_cast
<CXXMethodDecl
>(&DeclCtx
)) {
435 auto *Parent
= MethodDecl
->getParent();
436 assert(Parent
!= nullptr);
438 if (Parent
->isLambda()) {
439 for (auto Capture
: Parent
->captures()) {
440 if (Capture
.capturesVariable()) {
441 const auto *VarDecl
= Capture
.getCapturedVar();
442 assert(VarDecl
!= nullptr);
443 setStorageLocation(*VarDecl
, createObject(*VarDecl
, nullptr));
444 } else if (Capture
.capturesThis()) {
445 const auto *SurroundingMethodDecl
=
446 cast
<CXXMethodDecl
>(DeclCtx
.getNonClosureAncestor());
447 QualType ThisPointeeType
=
448 SurroundingMethodDecl
->getFunctionObjectParameterType();
450 &cast
<RecordValue
>(createValue(ThisPointeeType
))->getLoc();
453 } else if (MethodDecl
->isImplicitObjectMemberFunction()) {
454 QualType ThisPointeeType
= MethodDecl
->getFunctionObjectParameterType();
456 &cast
<RecordValue
>(createValue(ThisPointeeType
))->getLoc();
461 bool Environment::canDescend(unsigned MaxDepth
,
462 const DeclContext
*Callee
) const {
463 return CallStack
.size() <= MaxDepth
&& !llvm::is_contained(CallStack
, Callee
);
466 Environment
Environment::pushCall(const CallExpr
*Call
) const {
467 Environment
Env(*this);
469 if (const auto *MethodCall
= dyn_cast
<CXXMemberCallExpr
>(Call
)) {
470 if (const Expr
*Arg
= MethodCall
->getImplicitObjectArgument()) {
471 if (!isa
<CXXThisExpr
>(Arg
))
473 cast
<RecordStorageLocation
>(getStorageLocation(*Arg
));
474 // Otherwise (when the argument is `this`), retain the current
475 // environment's `ThisPointeeLoc`.
479 Env
.pushCallInternal(Call
->getDirectCallee(),
480 llvm::ArrayRef(Call
->getArgs(), Call
->getNumArgs()));
485 Environment
Environment::pushCall(const CXXConstructExpr
*Call
) const {
486 Environment
Env(*this);
488 Env
.ThisPointeeLoc
= &Env
.getResultObjectLocation(*Call
);
490 Env
.pushCallInternal(Call
->getConstructor(),
491 llvm::ArrayRef(Call
->getArgs(), Call
->getNumArgs()));
496 void Environment::pushCallInternal(const FunctionDecl
*FuncDecl
,
497 ArrayRef
<const Expr
*> Args
) {
498 // Canonicalize to the definition of the function. This ensures that we're
499 // putting arguments into the same `ParamVarDecl`s` that the callee will later
500 // be retrieving them from.
501 assert(FuncDecl
->getDefinition() != nullptr);
502 FuncDecl
= FuncDecl
->getDefinition();
504 CallStack
.push_back(FuncDecl
);
506 initFieldsGlobalsAndFuncs(FuncDecl
);
508 const auto *ParamIt
= FuncDecl
->param_begin();
510 // FIXME: Parameters don't always map to arguments 1:1; examples include
511 // overloaded operators implemented as member functions, and parameter packs.
512 for (unsigned ArgIndex
= 0; ArgIndex
< Args
.size(); ++ParamIt
, ++ArgIndex
) {
513 assert(ParamIt
!= FuncDecl
->param_end());
514 const VarDecl
*Param
= *ParamIt
;
515 setStorageLocation(*Param
, createObject(*Param
, Args
[ArgIndex
]));
519 void Environment::popCall(const CallExpr
*Call
, const Environment
&CalleeEnv
) {
520 // We ignore some entries of `CalleeEnv`:
521 // - `DACtx` because is already the same in both
522 // - We don't want the callee's `DeclCtx`, `ReturnVal`, `ReturnLoc` or
523 // `ThisPointeeLoc` because they don't apply to us.
524 // - `DeclToLoc`, `ExprToLoc`, and `ExprToVal` capture information from the
525 // callee's local scope, so when popping that scope, we do not propagate
527 this->LocToVal
= std::move(CalleeEnv
.LocToVal
);
528 this->FlowConditionToken
= std::move(CalleeEnv
.FlowConditionToken
);
530 if (Call
->isGLValue()) {
531 if (CalleeEnv
.ReturnLoc
!= nullptr)
532 setStorageLocation(*Call
, *CalleeEnv
.ReturnLoc
);
533 } else if (!Call
->getType()->isVoidType()) {
534 if (CalleeEnv
.ReturnVal
!= nullptr)
535 setValue(*Call
, *CalleeEnv
.ReturnVal
);
539 void Environment::popCall(const CXXConstructExpr
*Call
,
540 const Environment
&CalleeEnv
) {
541 // See also comment in `popCall(const CallExpr *, const Environment &)` above.
542 this->LocToVal
= std::move(CalleeEnv
.LocToVal
);
543 this->FlowConditionToken
= std::move(CalleeEnv
.FlowConditionToken
);
545 if (Value
*Val
= CalleeEnv
.getValue(*CalleeEnv
.ThisPointeeLoc
)) {
546 setValue(*Call
, *Val
);
550 bool Environment::equivalentTo(const Environment
&Other
,
551 Environment::ValueModel
&Model
) const {
552 assert(DACtx
== Other
.DACtx
);
554 if (ReturnVal
!= Other
.ReturnVal
)
557 if (ReturnLoc
!= Other
.ReturnLoc
)
560 if (ThisPointeeLoc
!= Other
.ThisPointeeLoc
)
563 if (DeclToLoc
!= Other
.DeclToLoc
)
566 if (ExprToLoc
!= Other
.ExprToLoc
)
569 if (!compareKeyToValueMaps(ExprToVal
, Other
.ExprToVal
, *this, Other
, Model
))
572 if (!compareKeyToValueMaps(LocToVal
, Other
.LocToVal
, *this, Other
, Model
))
578 LatticeJoinEffect
Environment::widen(const Environment
&PrevEnv
,
579 Environment::ValueModel
&Model
) {
580 assert(DACtx
== PrevEnv
.DACtx
);
581 assert(ReturnVal
== PrevEnv
.ReturnVal
);
582 assert(ReturnLoc
== PrevEnv
.ReturnLoc
);
583 assert(ThisPointeeLoc
== PrevEnv
.ThisPointeeLoc
);
584 assert(CallStack
== PrevEnv
.CallStack
);
586 auto Effect
= LatticeJoinEffect::Unchanged
;
588 // By the API, `PrevEnv` is a previous version of the environment for the same
589 // block, so we have some guarantees about its shape. In particular, it will
590 // be the result of a join or widen operation on previous values for this
591 // block. For `DeclToLoc`, `ExprToVal`, and `ExprToLoc`, join guarantees that
592 // these maps are subsets of the maps in `PrevEnv`. So, as long as we maintain
593 // this property here, we don't need change their current values to widen.
594 assert(DeclToLoc
.size() <= PrevEnv
.DeclToLoc
.size());
595 assert(ExprToVal
.size() <= PrevEnv
.ExprToVal
.size());
596 assert(ExprToLoc
.size() <= PrevEnv
.ExprToLoc
.size());
598 ExprToVal
= widenKeyToValueMap(ExprToVal
, PrevEnv
.ExprToVal
, *this, PrevEnv
,
601 LocToVal
= widenKeyToValueMap(LocToVal
, PrevEnv
.LocToVal
, *this, PrevEnv
,
603 if (DeclToLoc
.size() != PrevEnv
.DeclToLoc
.size() ||
604 ExprToLoc
.size() != PrevEnv
.ExprToLoc
.size() ||
605 ExprToVal
.size() != PrevEnv
.ExprToVal
.size() ||
606 LocToVal
.size() != PrevEnv
.LocToVal
.size())
607 Effect
= LatticeJoinEffect::Changed
;
612 Environment
Environment::join(const Environment
&EnvA
, const Environment
&EnvB
,
613 Environment::ValueModel
&Model
) {
614 assert(EnvA
.DACtx
== EnvB
.DACtx
);
615 assert(EnvA
.ThisPointeeLoc
== EnvB
.ThisPointeeLoc
);
616 assert(EnvA
.CallStack
== EnvB
.CallStack
);
618 Environment
JoinedEnv(*EnvA
.DACtx
);
620 JoinedEnv
.CallStack
= EnvA
.CallStack
;
621 JoinedEnv
.ThisPointeeLoc
= EnvA
.ThisPointeeLoc
;
623 if (EnvA
.ReturnVal
== nullptr || EnvB
.ReturnVal
== nullptr) {
624 // `ReturnVal` might not always get set -- for example if we have a return
625 // statement of the form `return some_other_func()` and we decide not to
626 // analyze `some_other_func()`.
627 // In this case, we can't say anything about the joined return value -- we
628 // don't simply want to propagate the return value that we do have, because
629 // it might not be the correct one.
630 // This occurs for example in the test `ContextSensitiveMutualRecursion`.
631 JoinedEnv
.ReturnVal
= nullptr;
632 } else if (areEquivalentValues(*EnvA
.ReturnVal
, *EnvB
.ReturnVal
)) {
633 JoinedEnv
.ReturnVal
= EnvA
.ReturnVal
;
635 assert(!EnvA
.CallStack
.empty());
636 // FIXME: Make `CallStack` a vector of `FunctionDecl` so we don't need this
638 auto *Func
= dyn_cast
<FunctionDecl
>(EnvA
.CallStack
.back());
639 assert(Func
!= nullptr);
640 if (Value
*MergedVal
=
641 mergeDistinctValues(Func
->getReturnType(), *EnvA
.ReturnVal
, EnvA
,
642 *EnvB
.ReturnVal
, EnvB
, JoinedEnv
, Model
))
643 JoinedEnv
.ReturnVal
= MergedVal
;
646 if (EnvA
.ReturnLoc
== EnvB
.ReturnLoc
)
647 JoinedEnv
.ReturnLoc
= EnvA
.ReturnLoc
;
649 JoinedEnv
.ReturnLoc
= nullptr;
651 JoinedEnv
.DeclToLoc
= intersectDenseMaps(EnvA
.DeclToLoc
, EnvB
.DeclToLoc
);
653 JoinedEnv
.ExprToLoc
= intersectDenseMaps(EnvA
.ExprToLoc
, EnvB
.ExprToLoc
);
655 // FIXME: update join to detect backedges and simplify the flow condition
657 JoinedEnv
.FlowConditionToken
= EnvA
.DACtx
->joinFlowConditions(
658 EnvA
.FlowConditionToken
, EnvB
.FlowConditionToken
);
660 JoinedEnv
.ExprToVal
= joinKeyToValueMap(EnvA
.ExprToVal
, EnvB
.ExprToVal
, EnvA
,
661 EnvB
, JoinedEnv
, Model
);
663 JoinedEnv
.LocToVal
= joinKeyToValueMap(EnvA
.LocToVal
, EnvB
.LocToVal
, EnvA
,
664 EnvB
, JoinedEnv
, Model
);
669 StorageLocation
&Environment::createStorageLocation(QualType Type
) {
670 return DACtx
->createStorageLocation(Type
);
673 StorageLocation
&Environment::createStorageLocation(const ValueDecl
&D
) {
674 // Evaluated declarations are always assigned the same storage locations to
675 // ensure that the environment stabilizes across loop iterations. Storage
676 // locations for evaluated declarations are stored in the analysis context.
677 return DACtx
->getStableStorageLocation(D
);
680 StorageLocation
&Environment::createStorageLocation(const Expr
&E
) {
681 // Evaluated expressions are always assigned the same storage locations to
682 // ensure that the environment stabilizes across loop iterations. Storage
683 // locations for evaluated expressions are stored in the analysis context.
684 return DACtx
->getStableStorageLocation(E
);
687 void Environment::setStorageLocation(const ValueDecl
&D
, StorageLocation
&Loc
) {
688 assert(!DeclToLoc
.contains(&D
));
689 DeclToLoc
[&D
] = &Loc
;
692 StorageLocation
*Environment::getStorageLocation(const ValueDecl
&D
) const {
693 auto It
= DeclToLoc
.find(&D
);
694 if (It
== DeclToLoc
.end())
697 StorageLocation
*Loc
= It
->second
;
702 void Environment::removeDecl(const ValueDecl
&D
) { DeclToLoc
.erase(&D
); }
704 void Environment::setStorageLocation(const Expr
&E
, StorageLocation
&Loc
) {
705 // `DeclRefExpr`s to builtin function types aren't glvalues, for some reason,
706 // but we still want to be able to associate a `StorageLocation` with them,
707 // so allow these as an exception.
708 assert(E
.isGLValue() ||
709 E
.getType()->isSpecificBuiltinType(BuiltinType::BuiltinFn
));
710 setStorageLocationInternal(E
, Loc
);
713 StorageLocation
*Environment::getStorageLocation(const Expr
&E
) const {
714 // See comment in `setStorageLocation()`.
715 assert(E
.isGLValue() ||
716 E
.getType()->isSpecificBuiltinType(BuiltinType::BuiltinFn
));
717 return getStorageLocationInternal(E
);
720 RecordStorageLocation
*Environment::getThisPointeeStorageLocation() const {
721 return ThisPointeeLoc
;
724 RecordStorageLocation
&
725 Environment::getResultObjectLocation(const Expr
&RecordPRValue
) {
726 assert(RecordPRValue
.getType()->isRecordType());
727 assert(RecordPRValue
.isPRValue());
729 if (StorageLocation
*ExistingLoc
= getStorageLocationInternal(RecordPRValue
))
730 return *cast
<RecordStorageLocation
>(ExistingLoc
);
731 auto &Loc
= cast
<RecordStorageLocation
>(
732 DACtx
->getStableStorageLocation(RecordPRValue
));
733 setStorageLocationInternal(RecordPRValue
, Loc
);
737 PointerValue
&Environment::getOrCreateNullPointerValue(QualType PointeeType
) {
738 return DACtx
->getOrCreateNullPointerValue(PointeeType
);
741 void Environment::setValue(const StorageLocation
&Loc
, Value
&Val
) {
742 assert(!isa
<RecordValue
>(&Val
) || &cast
<RecordValue
>(&Val
)->getLoc() == &Loc
);
744 LocToVal
[&Loc
] = &Val
;
747 void Environment::setValue(const Expr
&E
, Value
&Val
) {
748 assert(E
.isPRValue());
749 ExprToVal
[&E
] = &Val
;
752 Value
*Environment::getValue(const StorageLocation
&Loc
) const {
753 return LocToVal
.lookup(&Loc
);
756 Value
*Environment::getValue(const ValueDecl
&D
) const {
757 auto *Loc
= getStorageLocation(D
);
760 return getValue(*Loc
);
763 Value
*Environment::getValue(const Expr
&E
) const {
765 auto It
= ExprToVal
.find(&ignoreCFGOmittedNodes(E
));
766 return It
== ExprToVal
.end() ? nullptr : It
->second
;
769 auto It
= ExprToLoc
.find(&ignoreCFGOmittedNodes(E
));
770 if (It
== ExprToLoc
.end())
772 return getValue(*It
->second
);
775 Value
*Environment::createValue(QualType Type
) {
776 llvm::DenseSet
<QualType
> Visited
;
777 int CreatedValuesCount
= 0;
778 Value
*Val
= createValueUnlessSelfReferential(Type
, Visited
, /*Depth=*/0,
780 if (CreatedValuesCount
> MaxCompositeValueSize
) {
781 llvm::errs() << "Attempting to initialize a huge value of type: " << Type
787 void Environment::setStorageLocationInternal(const Expr
&E
,
788 StorageLocation
&Loc
) {
789 const Expr
&CanonE
= ignoreCFGOmittedNodes(E
);
790 assert(!ExprToLoc
.contains(&CanonE
));
791 ExprToLoc
[&CanonE
] = &Loc
;
794 StorageLocation
*Environment::getStorageLocationInternal(const Expr
&E
) const {
795 auto It
= ExprToLoc
.find(&ignoreCFGOmittedNodes(E
));
796 return It
== ExprToLoc
.end() ? nullptr : &*It
->second
;
799 Value
*Environment::createValueUnlessSelfReferential(
800 QualType Type
, llvm::DenseSet
<QualType
> &Visited
, int Depth
,
801 int &CreatedValuesCount
) {
802 assert(!Type
.isNull());
803 assert(!Type
->isReferenceType());
805 // Allow unlimited fields at depth 1; only cap at deeper nesting levels.
806 if ((Depth
> 1 && CreatedValuesCount
> MaxCompositeValueSize
) ||
807 Depth
> MaxCompositeValueDepth
)
810 if (Type
->isBooleanType()) {
811 CreatedValuesCount
++;
812 return &makeAtomicBoolValue();
815 if (Type
->isIntegerType()) {
816 // FIXME: consider instead `return nullptr`, given that we do nothing useful
817 // with integers, and so distinguishing them serves no purpose, but could
818 // prevent convergence.
819 CreatedValuesCount
++;
820 return &arena().create
<IntegerValue
>();
823 if (Type
->isPointerType()) {
824 CreatedValuesCount
++;
825 QualType PointeeType
= Type
->getPointeeType();
826 StorageLocation
&PointeeLoc
=
827 createLocAndMaybeValue(PointeeType
, Visited
, Depth
, CreatedValuesCount
);
829 return &arena().create
<PointerValue
>(PointeeLoc
);
832 if (Type
->isRecordType()) {
833 CreatedValuesCount
++;
834 llvm::DenseMap
<const ValueDecl
*, StorageLocation
*> FieldLocs
;
835 for (const FieldDecl
*Field
: DACtx
->getModeledFields(Type
)) {
836 assert(Field
!= nullptr);
838 QualType FieldType
= Field
->getType();
841 {Field
, &createLocAndMaybeValue(FieldType
, Visited
, Depth
+ 1,
842 CreatedValuesCount
)});
845 RecordStorageLocation
&Loc
=
846 arena().create
<RecordStorageLocation
>(Type
, std::move(FieldLocs
));
847 RecordValue
&RecordVal
= create
<RecordValue
>(Loc
);
849 // As we already have a storage location for the `RecordValue`, we can and
850 // should associate them in the environment.
851 setValue(Loc
, RecordVal
);
860 Environment::createLocAndMaybeValue(QualType Ty
,
861 llvm::DenseSet
<QualType
> &Visited
,
862 int Depth
, int &CreatedValuesCount
) {
863 if (!Visited
.insert(Ty
.getCanonicalType()).second
)
864 return createStorageLocation(Ty
.getNonReferenceType());
865 Value
*Val
= createValueUnlessSelfReferential(
866 Ty
.getNonReferenceType(), Visited
, Depth
, CreatedValuesCount
);
867 Visited
.erase(Ty
.getCanonicalType());
869 Ty
= Ty
.getNonReferenceType();
872 return createStorageLocation(Ty
);
874 if (Ty
->isRecordType())
875 return cast
<RecordValue
>(Val
)->getLoc();
877 StorageLocation
&Loc
= createStorageLocation(Ty
);
882 StorageLocation
&Environment::createObjectInternal(const ValueDecl
*D
,
884 const Expr
*InitExpr
) {
885 if (Ty
->isReferenceType()) {
886 // Although variables of reference type always need to be initialized, it
887 // can happen that we can't see the initializer, so `InitExpr` may still
890 if (auto *InitExprLoc
= getStorageLocation(*InitExpr
))
894 // Even though we have an initializer, we might not get an
895 // InitExprLoc, for example if the InitExpr is a CallExpr for which we
896 // don't have a function body. In this case, we just invent a storage
897 // location and value -- it's the best we can do.
898 return createObjectInternal(D
, Ty
.getNonReferenceType(), nullptr);
901 Value
*Val
= nullptr;
903 // In the (few) cases where an expression is intentionally
904 // "uninterpreted", `InitExpr` is not associated with a value. There are
905 // two ways to handle this situation: propagate the status, so that
906 // uninterpreted initializers result in uninterpreted variables, or
907 // provide a default value. We choose the latter so that later refinements
908 // of the variable can be used for reasoning about the surrounding code.
909 // For this reason, we let this case be handled by the `createValue()`
912 // FIXME. If and when we interpret all language cases, change this to
913 // assert that `InitExpr` is interpreted, rather than supplying a
914 // default value (assuming we don't update the environment API to return
916 Val
= getValue(*InitExpr
);
918 Val
= createValue(Ty
);
920 if (Ty
->isRecordType())
921 return cast
<RecordValue
>(Val
)->getLoc();
923 StorageLocation
&Loc
=
924 D
? createStorageLocation(*D
) : createStorageLocation(Ty
);
932 void Environment::assume(const Formula
&F
) {
933 DACtx
->addFlowConditionConstraint(FlowConditionToken
, F
);
936 bool Environment::proves(const Formula
&F
) const {
937 return DACtx
->flowConditionImplies(FlowConditionToken
, F
);
940 bool Environment::allows(const Formula
&F
) const {
941 return DACtx
->flowConditionAllows(FlowConditionToken
, F
);
944 void Environment::dump(raw_ostream
&OS
) const {
945 // FIXME: add printing for remaining fields and allow caller to decide what
946 // fields are printed.
947 OS
<< "DeclToLoc:\n";
948 for (auto [D
, L
] : DeclToLoc
)
949 OS
<< " [" << D
->getNameAsString() << ", " << L
<< "]\n";
951 OS
<< "ExprToLoc:\n";
952 for (auto [E
, L
] : ExprToLoc
)
953 OS
<< " [" << E
<< ", " << L
<< "]\n";
955 OS
<< "ExprToVal:\n";
956 for (auto [E
, V
] : ExprToVal
)
957 OS
<< " [" << E
<< ", " << V
<< ": " << *V
<< "]\n";
960 for (auto [L
, V
] : LocToVal
) {
961 OS
<< " [" << L
<< ", " << V
<< ": " << *V
<< "]\n";
964 OS
<< "FlowConditionToken:\n";
965 DACtx
->dumpFlowCondition(FlowConditionToken
, OS
);
968 void Environment::dump() const {
972 RecordStorageLocation
*getImplicitObjectLocation(const CXXMemberCallExpr
&MCE
,
973 const Environment
&Env
) {
974 Expr
*ImplicitObject
= MCE
.getImplicitObjectArgument();
975 if (ImplicitObject
== nullptr)
977 if (ImplicitObject
->getType()->isPointerType()) {
978 if (auto *Val
= cast_or_null
<PointerValue
>(Env
.getValue(*ImplicitObject
)))
979 return &cast
<RecordStorageLocation
>(Val
->getPointeeLoc());
982 return cast_or_null
<RecordStorageLocation
>(
983 Env
.getStorageLocation(*ImplicitObject
));
986 RecordStorageLocation
*getBaseObjectLocation(const MemberExpr
&ME
,
987 const Environment
&Env
) {
988 Expr
*Base
= ME
.getBase();
992 if (auto *Val
= cast_or_null
<PointerValue
>(Env
.getValue(*Base
)))
993 return &cast
<RecordStorageLocation
>(Val
->getPointeeLoc());
996 return cast_or_null
<RecordStorageLocation
>(Env
.getStorageLocation(*Base
));
999 std::vector
<FieldDecl
*> getFieldsForInitListExpr(const RecordDecl
*RD
) {
1000 // Unnamed bitfields are only used for padding and do not appear in
1001 // `InitListExpr`'s inits. However, those fields do appear in `RecordDecl`'s
1002 // field list, and we thus need to remove them before mapping inits to
1003 // fields to avoid mapping inits to the wrongs fields.
1004 std::vector
<FieldDecl
*> Fields
;
1006 RD
->fields(), std::back_inserter(Fields
),
1007 [](const FieldDecl
*Field
) { return !Field
->isUnnamedBitfield(); });
1011 RecordValue
&refreshRecordValue(RecordStorageLocation
&Loc
, Environment
&Env
) {
1012 auto &NewVal
= Env
.create
<RecordValue
>(Loc
);
1013 Env
.setValue(Loc
, NewVal
);
1017 RecordValue
&refreshRecordValue(const Expr
&Expr
, Environment
&Env
) {
1018 assert(Expr
.getType()->isRecordType());
1020 if (Expr
.isPRValue()) {
1021 if (auto *ExistingVal
= cast_or_null
<RecordValue
>(Env
.getValue(Expr
))) {
1022 auto &NewVal
= Env
.create
<RecordValue
>(ExistingVal
->getLoc());
1023 Env
.setValue(Expr
, NewVal
);
1027 auto &NewVal
= *cast
<RecordValue
>(Env
.createValue(Expr
.getType()));
1028 Env
.setValue(Expr
, NewVal
);
1033 cast_or_null
<RecordStorageLocation
>(Env
.getStorageLocation(Expr
))) {
1034 auto &NewVal
= Env
.create
<RecordValue
>(*Loc
);
1035 Env
.setValue(*Loc
, NewVal
);
1039 auto &NewVal
= *cast
<RecordValue
>(Env
.createValue(Expr
.getType()));
1040 Env
.setStorageLocation(Expr
, NewVal
.getLoc());
1044 } // namespace dataflow
1045 } // namespace clang