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