xref: /openbsd-src/gnu/llvm/clang/lib/Analysis/FlowSensitive/Transfer.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
1*12c85518Srobert //===-- Transfer.cpp --------------------------------------------*- C++ -*-===//
2*12c85518Srobert //
3*12c85518Srobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*12c85518Srobert // See https://llvm.org/LICENSE.txt for license information.
5*12c85518Srobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*12c85518Srobert //
7*12c85518Srobert //===----------------------------------------------------------------------===//
8*12c85518Srobert //
9*12c85518Srobert //  This file defines transfer functions that evaluate program statements and
10*12c85518Srobert //  update an environment accordingly.
11*12c85518Srobert //
12*12c85518Srobert //===----------------------------------------------------------------------===//
13*12c85518Srobert 
14*12c85518Srobert #include "clang/Analysis/FlowSensitive/Transfer.h"
15*12c85518Srobert #include "clang/AST/Decl.h"
16*12c85518Srobert #include "clang/AST/DeclBase.h"
17*12c85518Srobert #include "clang/AST/DeclCXX.h"
18*12c85518Srobert #include "clang/AST/Expr.h"
19*12c85518Srobert #include "clang/AST/ExprCXX.h"
20*12c85518Srobert #include "clang/AST/OperationKinds.h"
21*12c85518Srobert #include "clang/AST/Stmt.h"
22*12c85518Srobert #include "clang/AST/StmtVisitor.h"
23*12c85518Srobert #include "clang/Analysis/FlowSensitive/ControlFlowContext.h"
24*12c85518Srobert #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
25*12c85518Srobert #include "clang/Analysis/FlowSensitive/NoopAnalysis.h"
26*12c85518Srobert #include "clang/Analysis/FlowSensitive/Value.h"
27*12c85518Srobert #include "clang/Basic/Builtins.h"
28*12c85518Srobert #include "clang/Basic/OperatorKinds.h"
29*12c85518Srobert #include "llvm/ADT/STLExtras.h"
30*12c85518Srobert #include "llvm/Support/Casting.h"
31*12c85518Srobert #include "llvm/Support/ErrorHandling.h"
32*12c85518Srobert #include <cassert>
33*12c85518Srobert #include <memory>
34*12c85518Srobert #include <tuple>
35*12c85518Srobert 
36*12c85518Srobert namespace clang {
37*12c85518Srobert namespace dataflow {
38*12c85518Srobert 
evaluateBooleanEquality(const Expr & LHS,const Expr & RHS,Environment & Env)39*12c85518Srobert static BoolValue &evaluateBooleanEquality(const Expr &LHS, const Expr &RHS,
40*12c85518Srobert                                           Environment &Env) {
41*12c85518Srobert   if (auto *LHSValue =
42*12c85518Srobert           dyn_cast_or_null<BoolValue>(Env.getValue(LHS, SkipPast::Reference)))
43*12c85518Srobert     if (auto *RHSValue =
44*12c85518Srobert             dyn_cast_or_null<BoolValue>(Env.getValue(RHS, SkipPast::Reference)))
45*12c85518Srobert       return Env.makeIff(*LHSValue, *RHSValue);
46*12c85518Srobert 
47*12c85518Srobert   return Env.makeAtomicBoolValue();
48*12c85518Srobert }
49*12c85518Srobert 
50*12c85518Srobert // Functionally updates `V` such that any instances of `TopBool` are replaced
51*12c85518Srobert // with fresh atomic bools. Note: This implementation assumes that `B` is a
52*12c85518Srobert // tree; if `B` is a DAG, it will lose any sharing between subvalues that was
53*12c85518Srobert // present in the original .
54*12c85518Srobert static BoolValue &unpackValue(BoolValue &V, Environment &Env);
55*12c85518Srobert 
56*12c85518Srobert template <typename Derived, typename M>
unpackBinaryBoolValue(Environment & Env,BoolValue & B,M build)57*12c85518Srobert BoolValue &unpackBinaryBoolValue(Environment &Env, BoolValue &B, M build) {
58*12c85518Srobert   auto &V = *cast<Derived>(&B);
59*12c85518Srobert   BoolValue &Left = V.getLeftSubValue();
60*12c85518Srobert   BoolValue &Right = V.getRightSubValue();
61*12c85518Srobert   BoolValue &ULeft = unpackValue(Left, Env);
62*12c85518Srobert   BoolValue &URight = unpackValue(Right, Env);
63*12c85518Srobert 
64*12c85518Srobert   if (&ULeft == &Left && &URight == &Right)
65*12c85518Srobert     return V;
66*12c85518Srobert 
67*12c85518Srobert   return (Env.*build)(ULeft, URight);
68*12c85518Srobert }
69*12c85518Srobert 
unpackValue(BoolValue & V,Environment & Env)70*12c85518Srobert static BoolValue &unpackValue(BoolValue &V, Environment &Env) {
71*12c85518Srobert   switch (V.getKind()) {
72*12c85518Srobert   case Value::Kind::Integer:
73*12c85518Srobert   case Value::Kind::Reference:
74*12c85518Srobert   case Value::Kind::Pointer:
75*12c85518Srobert   case Value::Kind::Struct:
76*12c85518Srobert     llvm_unreachable("BoolValue cannot have any of these kinds.");
77*12c85518Srobert 
78*12c85518Srobert   case Value::Kind::AtomicBool:
79*12c85518Srobert     return V;
80*12c85518Srobert 
81*12c85518Srobert   case Value::Kind::TopBool:
82*12c85518Srobert     // Unpack `TopBool` into a fresh atomic bool.
83*12c85518Srobert     return Env.makeAtomicBoolValue();
84*12c85518Srobert 
85*12c85518Srobert   case Value::Kind::Negation: {
86*12c85518Srobert     auto &N = *cast<NegationValue>(&V);
87*12c85518Srobert     BoolValue &Sub = N.getSubVal();
88*12c85518Srobert     BoolValue &USub = unpackValue(Sub, Env);
89*12c85518Srobert 
90*12c85518Srobert     if (&USub == &Sub)
91*12c85518Srobert       return V;
92*12c85518Srobert     return Env.makeNot(USub);
93*12c85518Srobert   }
94*12c85518Srobert   case Value::Kind::Conjunction:
95*12c85518Srobert     return unpackBinaryBoolValue<ConjunctionValue>(Env, V,
96*12c85518Srobert                                                    &Environment::makeAnd);
97*12c85518Srobert   case Value::Kind::Disjunction:
98*12c85518Srobert     return unpackBinaryBoolValue<DisjunctionValue>(Env, V,
99*12c85518Srobert                                                    &Environment::makeOr);
100*12c85518Srobert   case Value::Kind::Implication:
101*12c85518Srobert     return unpackBinaryBoolValue<ImplicationValue>(
102*12c85518Srobert         Env, V, &Environment::makeImplication);
103*12c85518Srobert   case Value::Kind::Biconditional:
104*12c85518Srobert     return unpackBinaryBoolValue<BiconditionalValue>(Env, V,
105*12c85518Srobert                                                      &Environment::makeIff);
106*12c85518Srobert   }
107*12c85518Srobert   llvm_unreachable("All reachable cases in switch return");
108*12c85518Srobert }
109*12c85518Srobert 
110*12c85518Srobert // Unpacks the value (if any) associated with `E` and updates `E` to the new
111*12c85518Srobert // value, if any unpacking occured.
maybeUnpackLValueExpr(const Expr & E,Environment & Env)112*12c85518Srobert static Value *maybeUnpackLValueExpr(const Expr &E, Environment &Env) {
113*12c85518Srobert   // FIXME: this is too flexible: it _allows_ a reference, while it should
114*12c85518Srobert   // _require_ one, since lvalues should always be wrapped in `ReferenceValue`.
115*12c85518Srobert   auto *Loc = Env.getStorageLocation(E, SkipPast::Reference);
116*12c85518Srobert   if (Loc == nullptr)
117*12c85518Srobert     return nullptr;
118*12c85518Srobert   auto *Val = Env.getValue(*Loc);
119*12c85518Srobert 
120*12c85518Srobert   auto *B = dyn_cast_or_null<BoolValue>(Val);
121*12c85518Srobert   if (B == nullptr)
122*12c85518Srobert     return Val;
123*12c85518Srobert 
124*12c85518Srobert   auto &UnpackedVal = unpackValue(*B, Env);
125*12c85518Srobert   if (&UnpackedVal == Val)
126*12c85518Srobert     return Val;
127*12c85518Srobert   Env.setValue(*Loc, UnpackedVal);
128*12c85518Srobert   return &UnpackedVal;
129*12c85518Srobert }
130*12c85518Srobert 
131*12c85518Srobert class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
132*12c85518Srobert public:
TransferVisitor(const StmtToEnvMap & StmtToEnv,Environment & Env)133*12c85518Srobert   TransferVisitor(const StmtToEnvMap &StmtToEnv, Environment &Env)
134*12c85518Srobert       : StmtToEnv(StmtToEnv), Env(Env) {}
135*12c85518Srobert 
VisitBinaryOperator(const BinaryOperator * S)136*12c85518Srobert   void VisitBinaryOperator(const BinaryOperator *S) {
137*12c85518Srobert     const Expr *LHS = S->getLHS();
138*12c85518Srobert     assert(LHS != nullptr);
139*12c85518Srobert 
140*12c85518Srobert     const Expr *RHS = S->getRHS();
141*12c85518Srobert     assert(RHS != nullptr);
142*12c85518Srobert 
143*12c85518Srobert     switch (S->getOpcode()) {
144*12c85518Srobert     case BO_Assign: {
145*12c85518Srobert       auto *LHSLoc = Env.getStorageLocation(*LHS, SkipPast::Reference);
146*12c85518Srobert       if (LHSLoc == nullptr)
147*12c85518Srobert         break;
148*12c85518Srobert 
149*12c85518Srobert       auto *RHSVal = Env.getValue(*RHS, SkipPast::Reference);
150*12c85518Srobert       if (RHSVal == nullptr)
151*12c85518Srobert         break;
152*12c85518Srobert 
153*12c85518Srobert       // Assign a value to the storage location of the left-hand side.
154*12c85518Srobert       Env.setValue(*LHSLoc, *RHSVal);
155*12c85518Srobert 
156*12c85518Srobert       // Assign a storage location for the whole expression.
157*12c85518Srobert       Env.setStorageLocation(*S, *LHSLoc);
158*12c85518Srobert       break;
159*12c85518Srobert     }
160*12c85518Srobert     case BO_LAnd:
161*12c85518Srobert     case BO_LOr: {
162*12c85518Srobert       BoolValue &LHSVal = getLogicOperatorSubExprValue(*LHS);
163*12c85518Srobert       BoolValue &RHSVal = getLogicOperatorSubExprValue(*RHS);
164*12c85518Srobert 
165*12c85518Srobert       auto &Loc = Env.createStorageLocation(*S);
166*12c85518Srobert       Env.setStorageLocation(*S, Loc);
167*12c85518Srobert       if (S->getOpcode() == BO_LAnd)
168*12c85518Srobert         Env.setValue(Loc, Env.makeAnd(LHSVal, RHSVal));
169*12c85518Srobert       else
170*12c85518Srobert         Env.setValue(Loc, Env.makeOr(LHSVal, RHSVal));
171*12c85518Srobert       break;
172*12c85518Srobert     }
173*12c85518Srobert     case BO_NE:
174*12c85518Srobert     case BO_EQ: {
175*12c85518Srobert       auto &LHSEqRHSValue = evaluateBooleanEquality(*LHS, *RHS, Env);
176*12c85518Srobert       auto &Loc = Env.createStorageLocation(*S);
177*12c85518Srobert       Env.setStorageLocation(*S, Loc);
178*12c85518Srobert       Env.setValue(Loc, S->getOpcode() == BO_EQ ? LHSEqRHSValue
179*12c85518Srobert                                                 : Env.makeNot(LHSEqRHSValue));
180*12c85518Srobert       break;
181*12c85518Srobert     }
182*12c85518Srobert     case BO_Comma: {
183*12c85518Srobert       if (auto *Loc = Env.getStorageLocation(*RHS, SkipPast::None))
184*12c85518Srobert         Env.setStorageLocation(*S, *Loc);
185*12c85518Srobert       break;
186*12c85518Srobert     }
187*12c85518Srobert     default:
188*12c85518Srobert       break;
189*12c85518Srobert     }
190*12c85518Srobert   }
191*12c85518Srobert 
VisitDeclRefExpr(const DeclRefExpr * S)192*12c85518Srobert   void VisitDeclRefExpr(const DeclRefExpr *S) {
193*12c85518Srobert     const ValueDecl *VD = S->getDecl();
194*12c85518Srobert     assert(VD != nullptr);
195*12c85518Srobert     auto *DeclLoc = Env.getStorageLocation(*VD, SkipPast::None);
196*12c85518Srobert     if (DeclLoc == nullptr)
197*12c85518Srobert       return;
198*12c85518Srobert 
199*12c85518Srobert     if (VD->getType()->isReferenceType()) {
200*12c85518Srobert       assert(isa_and_nonnull<ReferenceValue>(Env.getValue((*DeclLoc))) &&
201*12c85518Srobert              "reference-typed declarations map to `ReferenceValue`s");
202*12c85518Srobert       Env.setStorageLocation(*S, *DeclLoc);
203*12c85518Srobert     } else {
204*12c85518Srobert       auto &Loc = Env.createStorageLocation(*S);
205*12c85518Srobert       auto &Val = Env.takeOwnership(std::make_unique<ReferenceValue>(*DeclLoc));
206*12c85518Srobert       Env.setStorageLocation(*S, Loc);
207*12c85518Srobert       Env.setValue(Loc, Val);
208*12c85518Srobert     }
209*12c85518Srobert   }
210*12c85518Srobert 
VisitDeclStmt(const DeclStmt * S)211*12c85518Srobert   void VisitDeclStmt(const DeclStmt *S) {
212*12c85518Srobert     // Group decls are converted into single decls in the CFG so the cast below
213*12c85518Srobert     // is safe.
214*12c85518Srobert     const auto &D = *cast<VarDecl>(S->getSingleDecl());
215*12c85518Srobert 
216*12c85518Srobert     // Static local vars are already initialized in `Environment`.
217*12c85518Srobert     if (D.hasGlobalStorage())
218*12c85518Srobert       return;
219*12c85518Srobert 
220*12c85518Srobert     // The storage location for `D` could have been created earlier, before the
221*12c85518Srobert     // variable's declaration statement (for example, in the case of
222*12c85518Srobert     // BindingDecls).
223*12c85518Srobert     auto *MaybeLoc = Env.getStorageLocation(D, SkipPast::None);
224*12c85518Srobert     if (MaybeLoc == nullptr) {
225*12c85518Srobert       MaybeLoc = &Env.createStorageLocation(D);
226*12c85518Srobert       Env.setStorageLocation(D, *MaybeLoc);
227*12c85518Srobert     }
228*12c85518Srobert     auto &Loc = *MaybeLoc;
229*12c85518Srobert 
230*12c85518Srobert     const Expr *InitExpr = D.getInit();
231*12c85518Srobert     if (InitExpr == nullptr) {
232*12c85518Srobert       // No initializer expression - associate `Loc` with a new value.
233*12c85518Srobert       if (Value *Val = Env.createValue(D.getType()))
234*12c85518Srobert         Env.setValue(Loc, *Val);
235*12c85518Srobert       return;
236*12c85518Srobert     }
237*12c85518Srobert 
238*12c85518Srobert     if (D.getType()->isReferenceType()) {
239*12c85518Srobert       // Initializing a reference variable - do not create a reference to
240*12c85518Srobert       // reference.
241*12c85518Srobert       if (auto *InitExprLoc =
242*12c85518Srobert               Env.getStorageLocation(*InitExpr, SkipPast::Reference)) {
243*12c85518Srobert         auto &Val =
244*12c85518Srobert             Env.takeOwnership(std::make_unique<ReferenceValue>(*InitExprLoc));
245*12c85518Srobert         Env.setValue(Loc, Val);
246*12c85518Srobert       }
247*12c85518Srobert     } else if (auto *InitExprVal = Env.getValue(*InitExpr, SkipPast::None)) {
248*12c85518Srobert       Env.setValue(Loc, *InitExprVal);
249*12c85518Srobert     }
250*12c85518Srobert 
251*12c85518Srobert     if (Env.getValue(Loc) == nullptr) {
252*12c85518Srobert       // We arrive here in (the few) cases where an expression is intentionally
253*12c85518Srobert       // "uninterpreted". There are two ways to handle this situation: propagate
254*12c85518Srobert       // the status, so that uninterpreted initializers result in uninterpreted
255*12c85518Srobert       // variables, or provide a default value. We choose the latter so that
256*12c85518Srobert       // later refinements of the variable can be used for reasoning about the
257*12c85518Srobert       // surrounding code.
258*12c85518Srobert       //
259*12c85518Srobert       // FIXME. If and when we interpret all language cases, change this to
260*12c85518Srobert       // assert that `InitExpr` is interpreted, rather than supplying a default
261*12c85518Srobert       // value (assuming we don't update the environment API to return
262*12c85518Srobert       // references).
263*12c85518Srobert       if (Value *Val = Env.createValue(D.getType()))
264*12c85518Srobert         Env.setValue(Loc, *Val);
265*12c85518Srobert     }
266*12c85518Srobert 
267*12c85518Srobert     if (const auto *Decomp = dyn_cast<DecompositionDecl>(&D)) {
268*12c85518Srobert       // If VarDecl is a DecompositionDecl, evaluate each of its bindings. This
269*12c85518Srobert       // needs to be evaluated after initializing the values in the storage for
270*12c85518Srobert       // VarDecl, as the bindings refer to them.
271*12c85518Srobert       // FIXME: Add support for ArraySubscriptExpr.
272*12c85518Srobert       // FIXME: Consider adding AST nodes used in BindingDecls to the CFG.
273*12c85518Srobert       for (const auto *B : Decomp->bindings()) {
274*12c85518Srobert         if (auto *ME = dyn_cast_or_null<MemberExpr>(B->getBinding())) {
275*12c85518Srobert           auto *DE = dyn_cast_or_null<DeclRefExpr>(ME->getBase());
276*12c85518Srobert           if (DE == nullptr)
277*12c85518Srobert             continue;
278*12c85518Srobert 
279*12c85518Srobert           // ME and its base haven't been visited because they aren't included
280*12c85518Srobert           // in the statements of the CFG basic block.
281*12c85518Srobert           VisitDeclRefExpr(DE);
282*12c85518Srobert           VisitMemberExpr(ME);
283*12c85518Srobert 
284*12c85518Srobert           if (auto *Loc = Env.getStorageLocation(*ME, SkipPast::Reference))
285*12c85518Srobert             Env.setStorageLocation(*B, *Loc);
286*12c85518Srobert         } else if (auto *VD = B->getHoldingVar()) {
287*12c85518Srobert           // Holding vars are used to back the BindingDecls of tuple-like
288*12c85518Srobert           // types. The holding var declarations appear *after* this statement,
289*12c85518Srobert           // so we have to create a location for them here to share with `B`. We
290*12c85518Srobert           // don't visit the binding, because we know it will be a DeclRefExpr
291*12c85518Srobert           // to `VD`.
292*12c85518Srobert           auto &VDLoc = Env.createStorageLocation(*VD);
293*12c85518Srobert           Env.setStorageLocation(*VD, VDLoc);
294*12c85518Srobert           Env.setStorageLocation(*B, VDLoc);
295*12c85518Srobert         }
296*12c85518Srobert       }
297*12c85518Srobert     }
298*12c85518Srobert   }
299*12c85518Srobert 
VisitImplicitCastExpr(const ImplicitCastExpr * S)300*12c85518Srobert   void VisitImplicitCastExpr(const ImplicitCastExpr *S) {
301*12c85518Srobert     const Expr *SubExpr = S->getSubExpr();
302*12c85518Srobert     assert(SubExpr != nullptr);
303*12c85518Srobert 
304*12c85518Srobert     switch (S->getCastKind()) {
305*12c85518Srobert     case CK_IntegralToBoolean: {
306*12c85518Srobert       // This cast creates a new, boolean value from the integral value. We
307*12c85518Srobert       // model that with a fresh value in the environment, unless it's already a
308*12c85518Srobert       // boolean.
309*12c85518Srobert       auto &Loc = Env.createStorageLocation(*S);
310*12c85518Srobert       Env.setStorageLocation(*S, Loc);
311*12c85518Srobert       if (auto *SubExprVal = dyn_cast_or_null<BoolValue>(
312*12c85518Srobert               Env.getValue(*SubExpr, SkipPast::Reference)))
313*12c85518Srobert         Env.setValue(Loc, *SubExprVal);
314*12c85518Srobert       else
315*12c85518Srobert         // FIXME: If integer modeling is added, then update this code to create
316*12c85518Srobert         // the boolean based on the integer model.
317*12c85518Srobert         Env.setValue(Loc, Env.makeAtomicBoolValue());
318*12c85518Srobert       break;
319*12c85518Srobert     }
320*12c85518Srobert 
321*12c85518Srobert     case CK_LValueToRValue: {
322*12c85518Srobert       // When an L-value is used as an R-value, it may result in sharing, so we
323*12c85518Srobert       // need to unpack any nested `Top`s.
324*12c85518Srobert       auto *SubExprVal = maybeUnpackLValueExpr(*SubExpr, Env);
325*12c85518Srobert       if (SubExprVal == nullptr)
326*12c85518Srobert         break;
327*12c85518Srobert 
328*12c85518Srobert       auto &ExprLoc = Env.createStorageLocation(*S);
329*12c85518Srobert       Env.setStorageLocation(*S, ExprLoc);
330*12c85518Srobert       Env.setValue(ExprLoc, *SubExprVal);
331*12c85518Srobert       break;
332*12c85518Srobert     }
333*12c85518Srobert 
334*12c85518Srobert     case CK_IntegralCast:
335*12c85518Srobert       // FIXME: This cast creates a new integral value from the
336*12c85518Srobert       // subexpression. But, because we don't model integers, we don't
337*12c85518Srobert       // distinguish between this new value and the underlying one. If integer
338*12c85518Srobert       // modeling is added, then update this code to create a fresh location and
339*12c85518Srobert       // value.
340*12c85518Srobert     case CK_UncheckedDerivedToBase:
341*12c85518Srobert     case CK_ConstructorConversion:
342*12c85518Srobert     case CK_UserDefinedConversion:
343*12c85518Srobert       // FIXME: Add tests that excercise CK_UncheckedDerivedToBase,
344*12c85518Srobert       // CK_ConstructorConversion, and CK_UserDefinedConversion.
345*12c85518Srobert     case CK_NoOp: {
346*12c85518Srobert       // FIXME: Consider making `Environment::getStorageLocation` skip noop
347*12c85518Srobert       // expressions (this and other similar expressions in the file) instead of
348*12c85518Srobert       // assigning them storage locations.
349*12c85518Srobert       auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
350*12c85518Srobert       if (SubExprLoc == nullptr)
351*12c85518Srobert         break;
352*12c85518Srobert 
353*12c85518Srobert       Env.setStorageLocation(*S, *SubExprLoc);
354*12c85518Srobert       break;
355*12c85518Srobert     }
356*12c85518Srobert     case CK_NullToPointer:
357*12c85518Srobert     case CK_NullToMemberPointer: {
358*12c85518Srobert       auto &Loc = Env.createStorageLocation(S->getType());
359*12c85518Srobert       Env.setStorageLocation(*S, Loc);
360*12c85518Srobert 
361*12c85518Srobert       auto &NullPointerVal =
362*12c85518Srobert           Env.getOrCreateNullPointerValue(S->getType()->getPointeeType());
363*12c85518Srobert       Env.setValue(Loc, NullPointerVal);
364*12c85518Srobert       break;
365*12c85518Srobert     }
366*12c85518Srobert     default:
367*12c85518Srobert       break;
368*12c85518Srobert     }
369*12c85518Srobert   }
370*12c85518Srobert 
VisitUnaryOperator(const UnaryOperator * S)371*12c85518Srobert   void VisitUnaryOperator(const UnaryOperator *S) {
372*12c85518Srobert     const Expr *SubExpr = S->getSubExpr();
373*12c85518Srobert     assert(SubExpr != nullptr);
374*12c85518Srobert 
375*12c85518Srobert     switch (S->getOpcode()) {
376*12c85518Srobert     case UO_Deref: {
377*12c85518Srobert       // Skip past a reference to handle dereference of a dependent pointer.
378*12c85518Srobert       const auto *SubExprVal = cast_or_null<PointerValue>(
379*12c85518Srobert           Env.getValue(*SubExpr, SkipPast::Reference));
380*12c85518Srobert       if (SubExprVal == nullptr)
381*12c85518Srobert         break;
382*12c85518Srobert 
383*12c85518Srobert       auto &Loc = Env.createStorageLocation(*S);
384*12c85518Srobert       Env.setStorageLocation(*S, Loc);
385*12c85518Srobert       Env.setValue(Loc, Env.takeOwnership(std::make_unique<ReferenceValue>(
386*12c85518Srobert                             SubExprVal->getPointeeLoc())));
387*12c85518Srobert       break;
388*12c85518Srobert     }
389*12c85518Srobert     case UO_AddrOf: {
390*12c85518Srobert       // Do not form a pointer to a reference. If `SubExpr` is assigned a
391*12c85518Srobert       // `ReferenceValue` then form a value that points to the location of its
392*12c85518Srobert       // pointee.
393*12c85518Srobert       StorageLocation *PointeeLoc =
394*12c85518Srobert           Env.getStorageLocation(*SubExpr, SkipPast::Reference);
395*12c85518Srobert       if (PointeeLoc == nullptr)
396*12c85518Srobert         break;
397*12c85518Srobert 
398*12c85518Srobert       auto &PointerLoc = Env.createStorageLocation(*S);
399*12c85518Srobert       auto &PointerVal =
400*12c85518Srobert           Env.takeOwnership(std::make_unique<PointerValue>(*PointeeLoc));
401*12c85518Srobert       Env.setStorageLocation(*S, PointerLoc);
402*12c85518Srobert       Env.setValue(PointerLoc, PointerVal);
403*12c85518Srobert       break;
404*12c85518Srobert     }
405*12c85518Srobert     case UO_LNot: {
406*12c85518Srobert       auto *SubExprVal =
407*12c85518Srobert           dyn_cast_or_null<BoolValue>(Env.getValue(*SubExpr, SkipPast::None));
408*12c85518Srobert       if (SubExprVal == nullptr)
409*12c85518Srobert         break;
410*12c85518Srobert 
411*12c85518Srobert       auto &ExprLoc = Env.createStorageLocation(*S);
412*12c85518Srobert       Env.setStorageLocation(*S, ExprLoc);
413*12c85518Srobert       Env.setValue(ExprLoc, Env.makeNot(*SubExprVal));
414*12c85518Srobert       break;
415*12c85518Srobert     }
416*12c85518Srobert     default:
417*12c85518Srobert       break;
418*12c85518Srobert     }
419*12c85518Srobert   }
420*12c85518Srobert 
VisitCXXThisExpr(const CXXThisExpr * S)421*12c85518Srobert   void VisitCXXThisExpr(const CXXThisExpr *S) {
422*12c85518Srobert     auto *ThisPointeeLoc = Env.getThisPointeeStorageLocation();
423*12c85518Srobert     if (ThisPointeeLoc == nullptr)
424*12c85518Srobert       // Unions are not supported yet, and will not have a location for the
425*12c85518Srobert       // `this` expression's pointee.
426*12c85518Srobert       return;
427*12c85518Srobert 
428*12c85518Srobert     auto &Loc = Env.createStorageLocation(*S);
429*12c85518Srobert     Env.setStorageLocation(*S, Loc);
430*12c85518Srobert     Env.setValue(Loc, Env.takeOwnership(
431*12c85518Srobert                           std::make_unique<PointerValue>(*ThisPointeeLoc)));
432*12c85518Srobert   }
433*12c85518Srobert 
VisitReturnStmt(const ReturnStmt * S)434*12c85518Srobert   void VisitReturnStmt(const ReturnStmt *S) {
435*12c85518Srobert     if (!Env.getAnalysisOptions().ContextSensitiveOpts)
436*12c85518Srobert       return;
437*12c85518Srobert 
438*12c85518Srobert     auto *Ret = S->getRetValue();
439*12c85518Srobert     if (Ret == nullptr)
440*12c85518Srobert       return;
441*12c85518Srobert 
442*12c85518Srobert     auto *Val = Env.getValue(*Ret, SkipPast::None);
443*12c85518Srobert     if (Val == nullptr)
444*12c85518Srobert       return;
445*12c85518Srobert 
446*12c85518Srobert     // FIXME: Support reference-type returns.
447*12c85518Srobert     if (Val->getKind() == Value::Kind::Reference)
448*12c85518Srobert       return;
449*12c85518Srobert 
450*12c85518Srobert     auto *Loc = Env.getReturnStorageLocation();
451*12c85518Srobert     assert(Loc != nullptr);
452*12c85518Srobert     // FIXME: Support reference-type returns.
453*12c85518Srobert     if (Loc->getType()->isReferenceType())
454*12c85518Srobert       return;
455*12c85518Srobert 
456*12c85518Srobert     // FIXME: Model NRVO.
457*12c85518Srobert     Env.setValue(*Loc, *Val);
458*12c85518Srobert   }
459*12c85518Srobert 
VisitMemberExpr(const MemberExpr * S)460*12c85518Srobert   void VisitMemberExpr(const MemberExpr *S) {
461*12c85518Srobert     ValueDecl *Member = S->getMemberDecl();
462*12c85518Srobert     assert(Member != nullptr);
463*12c85518Srobert 
464*12c85518Srobert     // FIXME: Consider assigning pointer values to function member expressions.
465*12c85518Srobert     if (Member->isFunctionOrFunctionTemplate())
466*12c85518Srobert       return;
467*12c85518Srobert 
468*12c85518Srobert     // FIXME: if/when we add support for modeling enums, use that support here.
469*12c85518Srobert     if (isa<EnumConstantDecl>(Member))
470*12c85518Srobert       return;
471*12c85518Srobert 
472*12c85518Srobert     if (auto *D = dyn_cast<VarDecl>(Member)) {
473*12c85518Srobert       if (D->hasGlobalStorage()) {
474*12c85518Srobert         auto *VarDeclLoc = Env.getStorageLocation(*D, SkipPast::None);
475*12c85518Srobert         if (VarDeclLoc == nullptr)
476*12c85518Srobert           return;
477*12c85518Srobert 
478*12c85518Srobert         if (VarDeclLoc->getType()->isReferenceType()) {
479*12c85518Srobert           assert(isa_and_nonnull<ReferenceValue>(Env.getValue((*VarDeclLoc))) &&
480*12c85518Srobert                  "reference-typed declarations map to `ReferenceValue`s");
481*12c85518Srobert           Env.setStorageLocation(*S, *VarDeclLoc);
482*12c85518Srobert         } else {
483*12c85518Srobert           auto &Loc = Env.createStorageLocation(*S);
484*12c85518Srobert           Env.setStorageLocation(*S, Loc);
485*12c85518Srobert           Env.setValue(Loc, Env.takeOwnership(
486*12c85518Srobert                                 std::make_unique<ReferenceValue>(*VarDeclLoc)));
487*12c85518Srobert         }
488*12c85518Srobert         return;
489*12c85518Srobert       }
490*12c85518Srobert     }
491*12c85518Srobert 
492*12c85518Srobert     // The receiver can be either a value or a pointer to a value. Skip past the
493*12c85518Srobert     // indirection to handle both cases.
494*12c85518Srobert     auto *BaseLoc = cast_or_null<AggregateStorageLocation>(
495*12c85518Srobert         Env.getStorageLocation(*S->getBase(), SkipPast::ReferenceThenPointer));
496*12c85518Srobert     if (BaseLoc == nullptr)
497*12c85518Srobert       return;
498*12c85518Srobert 
499*12c85518Srobert     auto &MemberLoc = BaseLoc->getChild(*Member);
500*12c85518Srobert     if (MemberLoc.getType()->isReferenceType()) {
501*12c85518Srobert       // Based on its type, `MemberLoc` must be mapped either to nothing or to a
502*12c85518Srobert       // `ReferenceValue`. For the former, we won't set a storage location for
503*12c85518Srobert       // this expression, so as to maintain an invariant lvalue expressions;
504*12c85518Srobert       // namely, that their location maps to a `ReferenceValue`.  In this,
505*12c85518Srobert       // lvalues are unlike other expressions, where it is valid for their
506*12c85518Srobert       // location to map to nothing (because they are not modeled).
507*12c85518Srobert       //
508*12c85518Srobert       // Note: we need this invariant for lvalues so that, when accessing a
509*12c85518Srobert       // value, we can distinguish an rvalue from an lvalue. An alternative
510*12c85518Srobert       // design, which takes the expression's value category into account, would
511*12c85518Srobert       // avoid the need for this invariant.
512*12c85518Srobert       if (auto *V = Env.getValue(MemberLoc)) {
513*12c85518Srobert         assert(isa<ReferenceValue>(V) &&
514*12c85518Srobert                "reference-typed declarations map to `ReferenceValue`s");
515*12c85518Srobert         Env.setStorageLocation(*S, MemberLoc);
516*12c85518Srobert       }
517*12c85518Srobert     } else {
518*12c85518Srobert       auto &Loc = Env.createStorageLocation(*S);
519*12c85518Srobert       Env.setStorageLocation(*S, Loc);
520*12c85518Srobert       Env.setValue(
521*12c85518Srobert           Loc, Env.takeOwnership(std::make_unique<ReferenceValue>(MemberLoc)));
522*12c85518Srobert     }
523*12c85518Srobert   }
524*12c85518Srobert 
VisitCXXDefaultInitExpr(const CXXDefaultInitExpr * S)525*12c85518Srobert   void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *S) {
526*12c85518Srobert     const Expr *InitExpr = S->getExpr();
527*12c85518Srobert     assert(InitExpr != nullptr);
528*12c85518Srobert 
529*12c85518Srobert     Value *InitExprVal = Env.getValue(*InitExpr, SkipPast::None);
530*12c85518Srobert     if (InitExprVal == nullptr)
531*12c85518Srobert       return;
532*12c85518Srobert 
533*12c85518Srobert     const FieldDecl *Field = S->getField();
534*12c85518Srobert     assert(Field != nullptr);
535*12c85518Srobert 
536*12c85518Srobert     auto &ThisLoc =
537*12c85518Srobert         *cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation());
538*12c85518Srobert     auto &FieldLoc = ThisLoc.getChild(*Field);
539*12c85518Srobert     Env.setValue(FieldLoc, *InitExprVal);
540*12c85518Srobert   }
541*12c85518Srobert 
VisitCXXConstructExpr(const CXXConstructExpr * S)542*12c85518Srobert   void VisitCXXConstructExpr(const CXXConstructExpr *S) {
543*12c85518Srobert     const CXXConstructorDecl *ConstructorDecl = S->getConstructor();
544*12c85518Srobert     assert(ConstructorDecl != nullptr);
545*12c85518Srobert 
546*12c85518Srobert     if (ConstructorDecl->isCopyOrMoveConstructor()) {
547*12c85518Srobert       assert(S->getNumArgs() == 1);
548*12c85518Srobert 
549*12c85518Srobert       const Expr *Arg = S->getArg(0);
550*12c85518Srobert       assert(Arg != nullptr);
551*12c85518Srobert 
552*12c85518Srobert       if (S->isElidable()) {
553*12c85518Srobert         auto *ArgLoc = Env.getStorageLocation(*Arg, SkipPast::Reference);
554*12c85518Srobert         if (ArgLoc == nullptr)
555*12c85518Srobert           return;
556*12c85518Srobert 
557*12c85518Srobert         Env.setStorageLocation(*S, *ArgLoc);
558*12c85518Srobert       } else if (auto *ArgVal = Env.getValue(*Arg, SkipPast::Reference)) {
559*12c85518Srobert         auto &Loc = Env.createStorageLocation(*S);
560*12c85518Srobert         Env.setStorageLocation(*S, Loc);
561*12c85518Srobert         Env.setValue(Loc, *ArgVal);
562*12c85518Srobert       }
563*12c85518Srobert       return;
564*12c85518Srobert     }
565*12c85518Srobert 
566*12c85518Srobert     auto &Loc = Env.createStorageLocation(*S);
567*12c85518Srobert     Env.setStorageLocation(*S, Loc);
568*12c85518Srobert     if (Value *Val = Env.createValue(S->getType()))
569*12c85518Srobert       Env.setValue(Loc, *Val);
570*12c85518Srobert 
571*12c85518Srobert     transferInlineCall(S, ConstructorDecl);
572*12c85518Srobert   }
573*12c85518Srobert 
VisitCXXOperatorCallExpr(const CXXOperatorCallExpr * S)574*12c85518Srobert   void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) {
575*12c85518Srobert     if (S->getOperator() == OO_Equal) {
576*12c85518Srobert       assert(S->getNumArgs() == 2);
577*12c85518Srobert 
578*12c85518Srobert       const Expr *Arg0 = S->getArg(0);
579*12c85518Srobert       assert(Arg0 != nullptr);
580*12c85518Srobert 
581*12c85518Srobert       const Expr *Arg1 = S->getArg(1);
582*12c85518Srobert       assert(Arg1 != nullptr);
583*12c85518Srobert 
584*12c85518Srobert       // Evaluate only copy and move assignment operators.
585*12c85518Srobert       auto *Arg0Type = Arg0->getType()->getUnqualifiedDesugaredType();
586*12c85518Srobert       auto *Arg1Type = Arg1->getType()->getUnqualifiedDesugaredType();
587*12c85518Srobert       if (Arg0Type != Arg1Type)
588*12c85518Srobert         return;
589*12c85518Srobert 
590*12c85518Srobert       auto *ObjectLoc = Env.getStorageLocation(*Arg0, SkipPast::Reference);
591*12c85518Srobert       if (ObjectLoc == nullptr)
592*12c85518Srobert         return;
593*12c85518Srobert 
594*12c85518Srobert       auto *Val = Env.getValue(*Arg1, SkipPast::Reference);
595*12c85518Srobert       if (Val == nullptr)
596*12c85518Srobert         return;
597*12c85518Srobert 
598*12c85518Srobert       // Assign a value to the storage location of the object.
599*12c85518Srobert       Env.setValue(*ObjectLoc, *Val);
600*12c85518Srobert 
601*12c85518Srobert       // FIXME: Add a test for the value of the whole expression.
602*12c85518Srobert       // Assign a storage location for the whole expression.
603*12c85518Srobert       Env.setStorageLocation(*S, *ObjectLoc);
604*12c85518Srobert     }
605*12c85518Srobert   }
606*12c85518Srobert 
VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr * S)607*12c85518Srobert   void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *S) {
608*12c85518Srobert     if (S->getCastKind() == CK_ConstructorConversion) {
609*12c85518Srobert       const Expr *SubExpr = S->getSubExpr();
610*12c85518Srobert       assert(SubExpr != nullptr);
611*12c85518Srobert 
612*12c85518Srobert       auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
613*12c85518Srobert       if (SubExprLoc == nullptr)
614*12c85518Srobert         return;
615*12c85518Srobert 
616*12c85518Srobert       Env.setStorageLocation(*S, *SubExprLoc);
617*12c85518Srobert     }
618*12c85518Srobert   }
619*12c85518Srobert 
VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr * S)620*12c85518Srobert   void VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *S) {
621*12c85518Srobert     auto &Loc = Env.createStorageLocation(*S);
622*12c85518Srobert     Env.setStorageLocation(*S, Loc);
623*12c85518Srobert     if (Value *Val = Env.createValue(S->getType()))
624*12c85518Srobert       Env.setValue(Loc, *Val);
625*12c85518Srobert   }
626*12c85518Srobert 
VisitCallExpr(const CallExpr * S)627*12c85518Srobert   void VisitCallExpr(const CallExpr *S) {
628*12c85518Srobert     // Of clang's builtins, only `__builtin_expect` is handled explicitly, since
629*12c85518Srobert     // others (like trap, debugtrap, and unreachable) are handled by CFG
630*12c85518Srobert     // construction.
631*12c85518Srobert     if (S->isCallToStdMove()) {
632*12c85518Srobert       assert(S->getNumArgs() == 1);
633*12c85518Srobert 
634*12c85518Srobert       const Expr *Arg = S->getArg(0);
635*12c85518Srobert       assert(Arg != nullptr);
636*12c85518Srobert 
637*12c85518Srobert       auto *ArgLoc = Env.getStorageLocation(*Arg, SkipPast::None);
638*12c85518Srobert       if (ArgLoc == nullptr)
639*12c85518Srobert         return;
640*12c85518Srobert 
641*12c85518Srobert       Env.setStorageLocation(*S, *ArgLoc);
642*12c85518Srobert     } else if (S->getDirectCallee() != nullptr &&
643*12c85518Srobert                S->getDirectCallee()->getBuiltinID() ==
644*12c85518Srobert                    Builtin::BI__builtin_expect) {
645*12c85518Srobert       assert(S->getNumArgs() > 0);
646*12c85518Srobert       assert(S->getArg(0) != nullptr);
647*12c85518Srobert       // `__builtin_expect` returns by-value, so strip away any potential
648*12c85518Srobert       // references in the argument.
649*12c85518Srobert       auto *ArgLoc = Env.getStorageLocation(*S->getArg(0), SkipPast::Reference);
650*12c85518Srobert       if (ArgLoc == nullptr)
651*12c85518Srobert         return;
652*12c85518Srobert       Env.setStorageLocation(*S, *ArgLoc);
653*12c85518Srobert     } else if (const FunctionDecl *F = S->getDirectCallee()) {
654*12c85518Srobert       transferInlineCall(S, F);
655*12c85518Srobert     }
656*12c85518Srobert   }
657*12c85518Srobert 
VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr * S)658*12c85518Srobert   void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *S) {
659*12c85518Srobert     const Expr *SubExpr = S->getSubExpr();
660*12c85518Srobert     assert(SubExpr != nullptr);
661*12c85518Srobert 
662*12c85518Srobert     auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
663*12c85518Srobert     if (SubExprLoc == nullptr)
664*12c85518Srobert       return;
665*12c85518Srobert 
666*12c85518Srobert     Env.setStorageLocation(*S, *SubExprLoc);
667*12c85518Srobert   }
668*12c85518Srobert 
VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr * S)669*12c85518Srobert   void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *S) {
670*12c85518Srobert     const Expr *SubExpr = S->getSubExpr();
671*12c85518Srobert     assert(SubExpr != nullptr);
672*12c85518Srobert 
673*12c85518Srobert     auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
674*12c85518Srobert     if (SubExprLoc == nullptr)
675*12c85518Srobert       return;
676*12c85518Srobert 
677*12c85518Srobert     Env.setStorageLocation(*S, *SubExprLoc);
678*12c85518Srobert   }
679*12c85518Srobert 
VisitCXXStaticCastExpr(const CXXStaticCastExpr * S)680*12c85518Srobert   void VisitCXXStaticCastExpr(const CXXStaticCastExpr *S) {
681*12c85518Srobert     if (S->getCastKind() == CK_NoOp) {
682*12c85518Srobert       const Expr *SubExpr = S->getSubExpr();
683*12c85518Srobert       assert(SubExpr != nullptr);
684*12c85518Srobert 
685*12c85518Srobert       auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
686*12c85518Srobert       if (SubExprLoc == nullptr)
687*12c85518Srobert         return;
688*12c85518Srobert 
689*12c85518Srobert       Env.setStorageLocation(*S, *SubExprLoc);
690*12c85518Srobert     }
691*12c85518Srobert   }
692*12c85518Srobert 
VisitConditionalOperator(const ConditionalOperator * S)693*12c85518Srobert   void VisitConditionalOperator(const ConditionalOperator *S) {
694*12c85518Srobert     // FIXME: Revisit this once flow conditions are added to the framework. For
695*12c85518Srobert     // `a = b ? c : d` we can add `b => a == c && !b => a == d` to the flow
696*12c85518Srobert     // condition.
697*12c85518Srobert     auto &Loc = Env.createStorageLocation(*S);
698*12c85518Srobert     Env.setStorageLocation(*S, Loc);
699*12c85518Srobert     if (Value *Val = Env.createValue(S->getType()))
700*12c85518Srobert       Env.setValue(Loc, *Val);
701*12c85518Srobert   }
702*12c85518Srobert 
VisitInitListExpr(const InitListExpr * S)703*12c85518Srobert   void VisitInitListExpr(const InitListExpr *S) {
704*12c85518Srobert     QualType Type = S->getType();
705*12c85518Srobert 
706*12c85518Srobert     auto &Loc = Env.createStorageLocation(*S);
707*12c85518Srobert     Env.setStorageLocation(*S, Loc);
708*12c85518Srobert 
709*12c85518Srobert     auto *Val = Env.createValue(Type);
710*12c85518Srobert     if (Val == nullptr)
711*12c85518Srobert       return;
712*12c85518Srobert 
713*12c85518Srobert     Env.setValue(Loc, *Val);
714*12c85518Srobert 
715*12c85518Srobert     if (Type->isStructureOrClassType()) {
716*12c85518Srobert       for (auto It : llvm::zip(Type->getAsRecordDecl()->fields(), S->inits())) {
717*12c85518Srobert         const FieldDecl *Field = std::get<0>(It);
718*12c85518Srobert         assert(Field != nullptr);
719*12c85518Srobert 
720*12c85518Srobert         const Expr *Init = std::get<1>(It);
721*12c85518Srobert         assert(Init != nullptr);
722*12c85518Srobert 
723*12c85518Srobert         if (Value *InitVal = Env.getValue(*Init, SkipPast::None))
724*12c85518Srobert           cast<StructValue>(Val)->setChild(*Field, *InitVal);
725*12c85518Srobert       }
726*12c85518Srobert     }
727*12c85518Srobert     // FIXME: Implement array initialization.
728*12c85518Srobert   }
729*12c85518Srobert 
VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr * S)730*12c85518Srobert   void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *S) {
731*12c85518Srobert     auto &Loc = Env.createStorageLocation(*S);
732*12c85518Srobert     Env.setStorageLocation(*S, Loc);
733*12c85518Srobert     Env.setValue(Loc, Env.getBoolLiteralValue(S->getValue()));
734*12c85518Srobert   }
735*12c85518Srobert 
VisitParenExpr(const ParenExpr * S)736*12c85518Srobert   void VisitParenExpr(const ParenExpr *S) {
737*12c85518Srobert     // The CFG does not contain `ParenExpr` as top-level statements in basic
738*12c85518Srobert     // blocks, however manual traversal to sub-expressions may encounter them.
739*12c85518Srobert     // Redirect to the sub-expression.
740*12c85518Srobert     auto *SubExpr = S->getSubExpr();
741*12c85518Srobert     assert(SubExpr != nullptr);
742*12c85518Srobert     Visit(SubExpr);
743*12c85518Srobert   }
744*12c85518Srobert 
VisitExprWithCleanups(const ExprWithCleanups * S)745*12c85518Srobert   void VisitExprWithCleanups(const ExprWithCleanups *S) {
746*12c85518Srobert     // The CFG does not contain `ExprWithCleanups` as top-level statements in
747*12c85518Srobert     // basic blocks, however manual traversal to sub-expressions may encounter
748*12c85518Srobert     // them. Redirect to the sub-expression.
749*12c85518Srobert     auto *SubExpr = S->getSubExpr();
750*12c85518Srobert     assert(SubExpr != nullptr);
751*12c85518Srobert     Visit(SubExpr);
752*12c85518Srobert   }
753*12c85518Srobert 
754*12c85518Srobert private:
getLogicOperatorSubExprValue(const Expr & SubExpr)755*12c85518Srobert   BoolValue &getLogicOperatorSubExprValue(const Expr &SubExpr) {
756*12c85518Srobert     // `SubExpr` and its parent logic operator might be part of different basic
757*12c85518Srobert     // blocks. We try to access the value that is assigned to `SubExpr` in the
758*12c85518Srobert     // corresponding environment.
759*12c85518Srobert     if (const Environment *SubExprEnv = StmtToEnv.getEnvironment(SubExpr)) {
760*12c85518Srobert       if (auto *Val = dyn_cast_or_null<BoolValue>(
761*12c85518Srobert               SubExprEnv->getValue(SubExpr, SkipPast::Reference)))
762*12c85518Srobert         return *Val;
763*12c85518Srobert     }
764*12c85518Srobert 
765*12c85518Srobert     if (Env.getStorageLocation(SubExpr, SkipPast::None) == nullptr) {
766*12c85518Srobert       // Sub-expressions that are logic operators are not added in basic blocks
767*12c85518Srobert       // (e.g. see CFG for `bool d = a && (b || c);`). If `SubExpr` is a logic
768*12c85518Srobert       // operator, it may not have been evaluated and assigned a value yet. In
769*12c85518Srobert       // that case, we need to first visit `SubExpr` and then try to get the
770*12c85518Srobert       // value that gets assigned to it.
771*12c85518Srobert       Visit(&SubExpr);
772*12c85518Srobert     }
773*12c85518Srobert 
774*12c85518Srobert     if (auto *Val = dyn_cast_or_null<BoolValue>(
775*12c85518Srobert             Env.getValue(SubExpr, SkipPast::Reference)))
776*12c85518Srobert       return *Val;
777*12c85518Srobert 
778*12c85518Srobert     // If the value of `SubExpr` is still unknown, we create a fresh symbolic
779*12c85518Srobert     // boolean value for it.
780*12c85518Srobert     return Env.makeAtomicBoolValue();
781*12c85518Srobert   }
782*12c85518Srobert 
783*12c85518Srobert   // If context sensitivity is enabled, try to analyze the body of the callee
784*12c85518Srobert   // `F` of `S`. The type `E` must be either `CallExpr` or `CXXConstructExpr`.
785*12c85518Srobert   template <typename E>
transferInlineCall(const E * S,const FunctionDecl * F)786*12c85518Srobert   void transferInlineCall(const E *S, const FunctionDecl *F) {
787*12c85518Srobert     const auto &Options = Env.getAnalysisOptions();
788*12c85518Srobert     if (!(Options.ContextSensitiveOpts &&
789*12c85518Srobert           Env.canDescend(Options.ContextSensitiveOpts->Depth, F)))
790*12c85518Srobert       return;
791*12c85518Srobert 
792*12c85518Srobert     const ControlFlowContext *CFCtx = Env.getControlFlowContext(F);
793*12c85518Srobert     if (!CFCtx)
794*12c85518Srobert       return;
795*12c85518Srobert 
796*12c85518Srobert     // FIXME: We don't support context-sensitive analysis of recursion, so
797*12c85518Srobert     // we should return early here if `F` is the same as the `FunctionDecl`
798*12c85518Srobert     // holding `S` itself.
799*12c85518Srobert 
800*12c85518Srobert     auto ExitBlock = CFCtx->getCFG().getExit().getBlockID();
801*12c85518Srobert 
802*12c85518Srobert     if (const auto *NonConstructExpr = dyn_cast<CallExpr>(S)) {
803*12c85518Srobert       // Note that it is important for the storage location of `S` to be set
804*12c85518Srobert       // before `pushCall`, because the latter uses it to set the storage
805*12c85518Srobert       // location for `return`.
806*12c85518Srobert       auto &ReturnLoc = Env.createStorageLocation(*S);
807*12c85518Srobert       Env.setStorageLocation(*S, ReturnLoc);
808*12c85518Srobert     }
809*12c85518Srobert     auto CalleeEnv = Env.pushCall(S);
810*12c85518Srobert 
811*12c85518Srobert     // FIXME: Use the same analysis as the caller for the callee. Note,
812*12c85518Srobert     // though, that doing so would require support for changing the analysis's
813*12c85518Srobert     // ASTContext.
814*12c85518Srobert     assert(CFCtx->getDecl() != nullptr &&
815*12c85518Srobert            "ControlFlowContexts in the environment should always carry a decl");
816*12c85518Srobert     auto Analysis = NoopAnalysis(CFCtx->getDecl()->getASTContext(),
817*12c85518Srobert                                  DataflowAnalysisOptions{Options});
818*12c85518Srobert 
819*12c85518Srobert     auto BlockToOutputState =
820*12c85518Srobert         dataflow::runDataflowAnalysis(*CFCtx, Analysis, CalleeEnv);
821*12c85518Srobert     assert(BlockToOutputState);
822*12c85518Srobert     assert(ExitBlock < BlockToOutputState->size());
823*12c85518Srobert 
824*12c85518Srobert     auto ExitState = (*BlockToOutputState)[ExitBlock];
825*12c85518Srobert     assert(ExitState);
826*12c85518Srobert 
827*12c85518Srobert     Env.popCall(ExitState->Env);
828*12c85518Srobert   }
829*12c85518Srobert 
830*12c85518Srobert   const StmtToEnvMap &StmtToEnv;
831*12c85518Srobert   Environment &Env;
832*12c85518Srobert };
833*12c85518Srobert 
transfer(const StmtToEnvMap & StmtToEnv,const Stmt & S,Environment & Env)834*12c85518Srobert void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env) {
835*12c85518Srobert   TransferVisitor(StmtToEnv, Env).Visit(&S);
836*12c85518Srobert }
837*12c85518Srobert 
838*12c85518Srobert } // namespace dataflow
839*12c85518Srobert } // namespace clang
840