xref: /llvm-project/clang/lib/Analysis/FlowSensitive/Transfer.cpp (revision e8fce95887ecfd87a83db8dbb0cc55966b004d6f)
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/ASTOps.h"
24 #include "clang/Analysis/FlowSensitive/AdornedCFG.h"
25 #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
26 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
27 #include "clang/Analysis/FlowSensitive/NoopAnalysis.h"
28 #include "clang/Analysis/FlowSensitive/RecordOps.h"
29 #include "clang/Analysis/FlowSensitive/Value.h"
30 #include "clang/Basic/Builtins.h"
31 #include "clang/Basic/OperatorKinds.h"
32 #include "llvm/Support/Casting.h"
33 #include "llvm/Support/Debug.h"
34 #include <assert.h>
35 #include <cassert>
36 
37 #define DEBUG_TYPE "dataflow"
38 
39 namespace clang {
40 namespace dataflow {
41 
42 const Environment *StmtToEnvMap::getEnvironment(const Stmt &S) const {
43   auto BlockIt = ACFG.getStmtToBlock().find(&ignoreCFGOmittedNodes(S));
44   assert(BlockIt != ACFG.getStmtToBlock().end());
45   if (!ACFG.isBlockReachable(*BlockIt->getSecond()))
46     return nullptr;
47   if (BlockIt->getSecond()->getBlockID() == CurBlockID)
48     return &CurState.Env;
49   const auto &State = BlockToState[BlockIt->getSecond()->getBlockID()];
50   if (!(State))
51     return nullptr;
52   return &State->Env;
53 }
54 
55 static BoolValue &evaluateBooleanEquality(const Expr &LHS, const Expr &RHS,
56                                           Environment &Env) {
57   Value *LHSValue = Env.getValue(LHS);
58   Value *RHSValue = Env.getValue(RHS);
59 
60   if (LHSValue == RHSValue)
61     return Env.getBoolLiteralValue(true);
62 
63   if (auto *LHSBool = dyn_cast_or_null<BoolValue>(LHSValue))
64     if (auto *RHSBool = dyn_cast_or_null<BoolValue>(RHSValue))
65       return Env.makeIff(*LHSBool, *RHSBool);
66 
67   return Env.makeAtomicBoolValue();
68 }
69 
70 static BoolValue &unpackValue(BoolValue &V, Environment &Env) {
71   if (auto *Top = llvm::dyn_cast<TopBoolValue>(&V)) {
72     auto &A = Env.getDataflowAnalysisContext().arena();
73     return A.makeBoolValue(A.makeAtomRef(Top->getAtom()));
74   }
75   return V;
76 }
77 
78 // Unpacks the value (if any) associated with `E` and updates `E` to the new
79 // value, if any unpacking occured. Also, does the lvalue-to-rvalue conversion,
80 // by skipping past the reference.
81 static Value *maybeUnpackLValueExpr(const Expr &E, Environment &Env) {
82   auto *Loc = Env.getStorageLocation(E);
83   if (Loc == nullptr)
84     return nullptr;
85   auto *Val = Env.getValue(*Loc);
86 
87   auto *B = dyn_cast_or_null<BoolValue>(Val);
88   if (B == nullptr)
89     return Val;
90 
91   auto &UnpackedVal = unpackValue(*B, Env);
92   if (&UnpackedVal == Val)
93     return Val;
94   Env.setValue(*Loc, UnpackedVal);
95   return &UnpackedVal;
96 }
97 
98 static void propagateValue(const Expr &From, const Expr &To, Environment &Env) {
99   if (From.getType()->isRecordType())
100     return;
101   if (auto *Val = Env.getValue(From))
102     Env.setValue(To, *Val);
103 }
104 
105 static void propagateStorageLocation(const Expr &From, const Expr &To,
106                                      Environment &Env) {
107   if (auto *Loc = Env.getStorageLocation(From))
108     Env.setStorageLocation(To, *Loc);
109 }
110 
111 // Propagates the value or storage location of `From` to `To` in cases where
112 // `From` may be either a glvalue or a prvalue. `To` must be a glvalue iff
113 // `From` is a glvalue.
114 static void propagateValueOrStorageLocation(const Expr &From, const Expr &To,
115                                             Environment &Env) {
116   assert(From.isGLValue() == To.isGLValue());
117   if (From.isGLValue())
118     propagateStorageLocation(From, To, Env);
119   else
120     propagateValue(From, To, Env);
121 }
122 
123 namespace {
124 
125 class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
126 public:
127   TransferVisitor(const StmtToEnvMap &StmtToEnv, Environment &Env)
128       : StmtToEnv(StmtToEnv), Env(Env) {}
129 
130   void VisitBinaryOperator(const BinaryOperator *S) {
131     const Expr *LHS = S->getLHS();
132     assert(LHS != nullptr);
133 
134     const Expr *RHS = S->getRHS();
135     assert(RHS != nullptr);
136 
137     switch (S->getOpcode()) {
138     case BO_Assign: {
139       auto *LHSLoc = Env.getStorageLocation(*LHS);
140       if (LHSLoc == nullptr)
141         break;
142 
143       auto *RHSVal = Env.getValue(*RHS);
144       if (RHSVal == nullptr)
145         break;
146 
147       // Assign a value to the storage location of the left-hand side.
148       Env.setValue(*LHSLoc, *RHSVal);
149 
150       // Assign a storage location for the whole expression.
151       Env.setStorageLocation(*S, *LHSLoc);
152       break;
153     }
154     case BO_LAnd:
155     case BO_LOr: {
156       BoolValue &LHSVal = getLogicOperatorSubExprValue(*LHS);
157       BoolValue &RHSVal = getLogicOperatorSubExprValue(*RHS);
158 
159       if (S->getOpcode() == BO_LAnd)
160         Env.setValue(*S, Env.makeAnd(LHSVal, RHSVal));
161       else
162         Env.setValue(*S, Env.makeOr(LHSVal, RHSVal));
163       break;
164     }
165     case BO_NE:
166     case BO_EQ: {
167       auto &LHSEqRHSValue = evaluateBooleanEquality(*LHS, *RHS, Env);
168       Env.setValue(*S, S->getOpcode() == BO_EQ ? LHSEqRHSValue
169                                                : Env.makeNot(LHSEqRHSValue));
170       break;
171     }
172     case BO_Comma: {
173       propagateValueOrStorageLocation(*RHS, *S, Env);
174       break;
175     }
176     default:
177       break;
178     }
179   }
180 
181   void VisitDeclRefExpr(const DeclRefExpr *S) {
182     const ValueDecl *VD = S->getDecl();
183     assert(VD != nullptr);
184 
185     // Some `DeclRefExpr`s aren't glvalues, so we can't associate them with a
186     // `StorageLocation`, and there's also no sensible `Value` that we can
187     // assign to them. Examples:
188     // - Non-static member variables
189     // - Non static member functions
190     //   Note: Member operators are an exception to this, but apparently only
191     //   if the `DeclRefExpr` is used within the callee of a
192     //   `CXXOperatorCallExpr`. In other cases, for example when applying the
193     //   address-of operator, the `DeclRefExpr` is a prvalue.
194     if (!S->isGLValue())
195       return;
196 
197     auto *DeclLoc = Env.getStorageLocation(*VD);
198     if (DeclLoc == nullptr)
199       return;
200 
201     Env.setStorageLocation(*S, *DeclLoc);
202   }
203 
204   void VisitDeclStmt(const DeclStmt *S) {
205     // Group decls are converted into single decls in the CFG so the cast below
206     // is safe.
207     const auto &D = *cast<VarDecl>(S->getSingleDecl());
208 
209     ProcessVarDecl(D);
210   }
211 
212   void ProcessVarDecl(const VarDecl &D) {
213     // Static local vars are already initialized in `Environment`.
214     if (D.hasGlobalStorage())
215       return;
216 
217     // If this is the holding variable for a `BindingDecl`, we may already
218     // have a storage location set up -- so check. (See also explanation below
219     // where we process the `BindingDecl`.)
220     if (D.getType()->isReferenceType() && Env.getStorageLocation(D) != nullptr)
221       return;
222 
223     assert(Env.getStorageLocation(D) == nullptr);
224 
225     Env.setStorageLocation(D, Env.createObject(D));
226 
227     // `DecompositionDecl` must be handled after we've interpreted the loc
228     // itself, because the binding expression refers back to the
229     // `DecompositionDecl` (even though it has no written name).
230     if (const auto *Decomp = dyn_cast<DecompositionDecl>(&D)) {
231       // If VarDecl is a DecompositionDecl, evaluate each of its bindings. This
232       // needs to be evaluated after initializing the values in the storage for
233       // VarDecl, as the bindings refer to them.
234       // FIXME: Add support for ArraySubscriptExpr.
235       // FIXME: Consider adding AST nodes used in BindingDecls to the CFG.
236       for (const auto *B : Decomp->bindings()) {
237         if (auto *ME = dyn_cast_or_null<MemberExpr>(B->getBinding())) {
238           auto *DE = dyn_cast_or_null<DeclRefExpr>(ME->getBase());
239           if (DE == nullptr)
240             continue;
241 
242           // ME and its base haven't been visited because they aren't included
243           // in the statements of the CFG basic block.
244           VisitDeclRefExpr(DE);
245           VisitMemberExpr(ME);
246 
247           if (auto *Loc = Env.getStorageLocation(*ME))
248             Env.setStorageLocation(*B, *Loc);
249         } else if (auto *VD = B->getHoldingVar()) {
250           // Holding vars are used to back the `BindingDecl`s of tuple-like
251           // types. The holding var declarations appear after the
252           // `DecompositionDecl`, so we have to explicitly process them here
253           // to know their storage location. They will be processed a second
254           // time when we visit their `VarDecl`s, so we have code that protects
255           // against this above.
256           ProcessVarDecl(*VD);
257           auto *VDLoc = Env.getStorageLocation(*VD);
258           assert(VDLoc != nullptr);
259           Env.setStorageLocation(*B, *VDLoc);
260         }
261       }
262     }
263   }
264 
265   void VisitImplicitCastExpr(const ImplicitCastExpr *S) {
266     const Expr *SubExpr = S->getSubExpr();
267     assert(SubExpr != nullptr);
268 
269     switch (S->getCastKind()) {
270     case CK_IntegralToBoolean: {
271       // This cast creates a new, boolean value from the integral value. We
272       // model that with a fresh value in the environment, unless it's already a
273       // boolean.
274       if (auto *SubExprVal =
275               dyn_cast_or_null<BoolValue>(Env.getValue(*SubExpr)))
276         Env.setValue(*S, *SubExprVal);
277       else
278         // FIXME: If integer modeling is added, then update this code to create
279         // the boolean based on the integer model.
280         Env.setValue(*S, Env.makeAtomicBoolValue());
281       break;
282     }
283 
284     case CK_LValueToRValue: {
285       // When an L-value is used as an R-value, it may result in sharing, so we
286       // need to unpack any nested `Top`s.
287       auto *SubExprVal = maybeUnpackLValueExpr(*SubExpr, Env);
288       if (SubExprVal == nullptr)
289         break;
290 
291       Env.setValue(*S, *SubExprVal);
292       break;
293     }
294 
295     case CK_IntegralCast:
296       // FIXME: This cast creates a new integral value from the
297       // subexpression. But, because we don't model integers, we don't
298       // distinguish between this new value and the underlying one. If integer
299       // modeling is added, then update this code to create a fresh location and
300       // value.
301     case CK_UncheckedDerivedToBase:
302     case CK_ConstructorConversion:
303     case CK_UserDefinedConversion:
304       // FIXME: Add tests that excercise CK_UncheckedDerivedToBase,
305       // CK_ConstructorConversion, and CK_UserDefinedConversion.
306     case CK_NoOp: {
307       // FIXME: Consider making `Environment::getStorageLocation` skip noop
308       // expressions (this and other similar expressions in the file) instead
309       // of assigning them storage locations.
310       propagateValueOrStorageLocation(*SubExpr, *S, Env);
311       break;
312     }
313     case CK_NullToPointer: {
314       auto &NullPointerVal =
315           Env.getOrCreateNullPointerValue(S->getType()->getPointeeType());
316       Env.setValue(*S, NullPointerVal);
317       break;
318     }
319     case CK_NullToMemberPointer:
320       // FIXME: Implement pointers to members. For now, don't associate a value
321       // with this expression.
322       break;
323     case CK_FunctionToPointerDecay: {
324       StorageLocation *PointeeLoc = Env.getStorageLocation(*SubExpr);
325       if (PointeeLoc == nullptr)
326         break;
327 
328       Env.setValue(*S, Env.create<PointerValue>(*PointeeLoc));
329       break;
330     }
331     case CK_BuiltinFnToFnPtr:
332       // Despite its name, the result type of `BuiltinFnToFnPtr` is a function,
333       // not a function pointer. In addition, builtin functions can only be
334       // called directly; it is not legal to take their address. We therefore
335       // don't need to create a value or storage location for them.
336       break;
337     default:
338       break;
339     }
340   }
341 
342   void VisitUnaryOperator(const UnaryOperator *S) {
343     const Expr *SubExpr = S->getSubExpr();
344     assert(SubExpr != nullptr);
345 
346     switch (S->getOpcode()) {
347     case UO_Deref: {
348       const auto *SubExprVal = Env.get<PointerValue>(*SubExpr);
349       if (SubExprVal == nullptr)
350         break;
351 
352       Env.setStorageLocation(*S, SubExprVal->getPointeeLoc());
353       break;
354     }
355     case UO_AddrOf: {
356       // FIXME: Model pointers to members.
357       if (S->getType()->isMemberPointerType())
358         break;
359 
360       if (StorageLocation *PointeeLoc = Env.getStorageLocation(*SubExpr))
361         Env.setValue(*S, Env.create<PointerValue>(*PointeeLoc));
362       break;
363     }
364     case UO_LNot: {
365       auto *SubExprVal = dyn_cast_or_null<BoolValue>(Env.getValue(*SubExpr));
366       if (SubExprVal == nullptr)
367         break;
368 
369       Env.setValue(*S, Env.makeNot(*SubExprVal));
370       break;
371     }
372     default:
373       break;
374     }
375   }
376 
377   void VisitCXXThisExpr(const CXXThisExpr *S) {
378     auto *ThisPointeeLoc = Env.getThisPointeeStorageLocation();
379     if (ThisPointeeLoc == nullptr)
380       // Unions are not supported yet, and will not have a location for the
381       // `this` expression's pointee.
382       return;
383 
384     Env.setValue(*S, Env.create<PointerValue>(*ThisPointeeLoc));
385   }
386 
387   void VisitCXXNewExpr(const CXXNewExpr *S) {
388     if (Value *Val = Env.createValue(S->getType()))
389       Env.setValue(*S, *Val);
390   }
391 
392   void VisitCXXDeleteExpr(const CXXDeleteExpr *S) {
393     // Empty method.
394     // We consciously don't do anything on deletes.  Diagnosing double deletes
395     // (for example) should be done by a specific analysis, not by the
396     // framework.
397   }
398 
399   void VisitReturnStmt(const ReturnStmt *S) {
400     if (!Env.getDataflowAnalysisContext().getOptions().ContextSensitiveOpts)
401       return;
402 
403     auto *Ret = S->getRetValue();
404     if (Ret == nullptr)
405       return;
406 
407     if (Ret->isPRValue()) {
408       if (Ret->getType()->isRecordType())
409         return;
410 
411       auto *Val = Env.getValue(*Ret);
412       if (Val == nullptr)
413         return;
414 
415       // FIXME: Model NRVO.
416       Env.setReturnValue(Val);
417     } else {
418       auto *Loc = Env.getStorageLocation(*Ret);
419       if (Loc == nullptr)
420         return;
421 
422       // FIXME: Model NRVO.
423       Env.setReturnStorageLocation(Loc);
424     }
425   }
426 
427   void VisitMemberExpr(const MemberExpr *S) {
428     ValueDecl *Member = S->getMemberDecl();
429     assert(Member != nullptr);
430 
431     // FIXME: Consider assigning pointer values to function member expressions.
432     if (Member->isFunctionOrFunctionTemplate())
433       return;
434 
435     // FIXME: if/when we add support for modeling enums, use that support here.
436     if (isa<EnumConstantDecl>(Member))
437       return;
438 
439     if (auto *D = dyn_cast<VarDecl>(Member)) {
440       if (D->hasGlobalStorage()) {
441         auto *VarDeclLoc = Env.getStorageLocation(*D);
442         if (VarDeclLoc == nullptr)
443           return;
444 
445         Env.setStorageLocation(*S, *VarDeclLoc);
446         return;
447       }
448     }
449 
450     RecordStorageLocation *BaseLoc = getBaseObjectLocation(*S, Env);
451     if (BaseLoc == nullptr)
452       return;
453 
454     auto *MemberLoc = BaseLoc->getChild(*Member);
455     if (MemberLoc == nullptr)
456       return;
457     Env.setStorageLocation(*S, *MemberLoc);
458   }
459 
460   void VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *S) {
461     const Expr *ArgExpr = S->getExpr();
462     assert(ArgExpr != nullptr);
463     propagateValueOrStorageLocation(*ArgExpr, *S, Env);
464 
465     if (S->isPRValue() && S->getType()->isRecordType()) {
466       auto &Loc = Env.getResultObjectLocation(*S);
467       Env.initializeFieldsWithValues(Loc);
468     }
469   }
470 
471   void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *S) {
472     const Expr *InitExpr = S->getExpr();
473     assert(InitExpr != nullptr);
474 
475     // If this is a prvalue of record type, the handler for `*InitExpr` (if one
476     // exists) will initialize the result object; there is no value to propgate
477     // here.
478     if (S->getType()->isRecordType() && S->isPRValue())
479       return;
480 
481     propagateValueOrStorageLocation(*InitExpr, *S, Env);
482   }
483 
484   void VisitCXXConstructExpr(const CXXConstructExpr *S) {
485     const CXXConstructorDecl *ConstructorDecl = S->getConstructor();
486     assert(ConstructorDecl != nullptr);
487 
488     // `CXXConstructExpr` can have array type if default-initializing an array
489     // of records. We don't handle this specifically beyond potentially inlining
490     // the call.
491     if (!S->getType()->isRecordType()) {
492       transferInlineCall(S, ConstructorDecl);
493       return;
494     }
495 
496     RecordStorageLocation &Loc = Env.getResultObjectLocation(*S);
497 
498     if (ConstructorDecl->isCopyOrMoveConstructor()) {
499       // It is permissible for a copy/move constructor to have additional
500       // parameters as long as they have default arguments defined for them.
501       assert(S->getNumArgs() != 0);
502 
503       const Expr *Arg = S->getArg(0);
504       assert(Arg != nullptr);
505 
506       auto *ArgLoc = Env.get<RecordStorageLocation>(*Arg);
507       if (ArgLoc == nullptr)
508         return;
509 
510       // Even if the copy/move constructor call is elidable, we choose to copy
511       // the record in all cases (which isn't wrong, just potentially not
512       // optimal).
513       copyRecord(*ArgLoc, Loc, Env);
514       return;
515     }
516 
517     Env.initializeFieldsWithValues(Loc, S->getType());
518 
519     transferInlineCall(S, ConstructorDecl);
520   }
521 
522   void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) {
523     if (S->getOperator() == OO_Equal) {
524       assert(S->getNumArgs() == 2);
525 
526       const Expr *Arg0 = S->getArg(0);
527       assert(Arg0 != nullptr);
528 
529       const Expr *Arg1 = S->getArg(1);
530       assert(Arg1 != nullptr);
531 
532       // Evaluate only copy and move assignment operators.
533       const auto *Method =
534           dyn_cast_or_null<CXXMethodDecl>(S->getDirectCallee());
535       if (!Method)
536         return;
537       if (!Method->isCopyAssignmentOperator() &&
538           !Method->isMoveAssignmentOperator())
539         return;
540 
541       RecordStorageLocation *LocSrc = nullptr;
542       if (Arg1->isPRValue()) {
543         LocSrc = &Env.getResultObjectLocation(*Arg1);
544       } else {
545         LocSrc = Env.get<RecordStorageLocation>(*Arg1);
546       }
547       auto *LocDst = Env.get<RecordStorageLocation>(*Arg0);
548 
549       if (LocSrc == nullptr || LocDst == nullptr)
550         return;
551 
552       copyRecord(*LocSrc, *LocDst, Env);
553 
554       // If the expr is a glvalue, we can reasonably assume the operator is
555       // returning T& and thus we can assign it `LocDst`.
556       if (S->isGLValue()) {
557         Env.setStorageLocation(*S, *LocDst);
558       } else if (S->getType()->isRecordType()) {
559         // Assume that the assignment returns the assigned value.
560         copyRecord(*LocDst, Env.getResultObjectLocation(*S), Env);
561       }
562 
563       return;
564     }
565 
566     // `CXXOperatorCallExpr` can be a prvalue. Call `VisitCallExpr`() to
567     // initialize the prvalue's fields with values.
568     VisitCallExpr(S);
569   }
570 
571   void VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator *RBO) {
572     propagateValue(*RBO->getSemanticForm(), *RBO, Env);
573   }
574 
575   void VisitCallExpr(const CallExpr *S) {
576     // Of clang's builtins, only `__builtin_expect` is handled explicitly, since
577     // others (like trap, debugtrap, and unreachable) are handled by CFG
578     // construction.
579     if (S->isCallToStdMove()) {
580       assert(S->getNumArgs() == 1);
581 
582       const Expr *Arg = S->getArg(0);
583       assert(Arg != nullptr);
584 
585       auto *ArgLoc = Env.getStorageLocation(*Arg);
586       if (ArgLoc == nullptr)
587         return;
588 
589       Env.setStorageLocation(*S, *ArgLoc);
590     } else if (S->getDirectCallee() != nullptr &&
591                S->getDirectCallee()->getBuiltinID() ==
592                    Builtin::BI__builtin_expect) {
593       assert(S->getNumArgs() > 0);
594       assert(S->getArg(0) != nullptr);
595       auto *ArgVal = Env.getValue(*S->getArg(0));
596       if (ArgVal == nullptr)
597         return;
598       Env.setValue(*S, *ArgVal);
599     } else if (const FunctionDecl *F = S->getDirectCallee()) {
600       transferInlineCall(S, F);
601 
602       // If this call produces a prvalue of record type, initialize its fields
603       // with values.
604       if (S->getType()->isRecordType() && S->isPRValue()) {
605         RecordStorageLocation &Loc = Env.getResultObjectLocation(*S);
606         Env.initializeFieldsWithValues(Loc);
607       }
608     }
609   }
610 
611   void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *S) {
612     const Expr *SubExpr = S->getSubExpr();
613     assert(SubExpr != nullptr);
614 
615     StorageLocation &Loc = Env.createStorageLocation(*S);
616     Env.setStorageLocation(*S, Loc);
617 
618     if (SubExpr->getType()->isRecordType())
619       // Nothing else left to do -- we initialized the record when transferring
620       // `SubExpr`.
621       return;
622 
623     if (Value *SubExprVal = Env.getValue(*SubExpr))
624       Env.setValue(Loc, *SubExprVal);
625   }
626 
627   void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *S) {
628     const Expr *SubExpr = S->getSubExpr();
629     assert(SubExpr != nullptr);
630 
631     propagateValue(*SubExpr, *S, Env);
632   }
633 
634   void VisitCXXStaticCastExpr(const CXXStaticCastExpr *S) {
635     if (S->getCastKind() == CK_NoOp) {
636       const Expr *SubExpr = S->getSubExpr();
637       assert(SubExpr != nullptr);
638 
639       propagateValueOrStorageLocation(*SubExpr, *S, Env);
640     }
641   }
642 
643   void VisitConditionalOperator(const ConditionalOperator *S) {
644     // FIXME: Revisit this once flow conditions are added to the framework. For
645     // `a = b ? c : d` we can add `b => a == c && !b => a == d` to the flow
646     // condition.
647     // When we do this, we will need to retrieve the values of the operands from
648     // the environments for the basic blocks they are computed in, in a similar
649     // way to how this is done for short-circuited logical operators in
650     // `getLogicOperatorSubExprValue()`.
651     if (S->isGLValue())
652       Env.setStorageLocation(*S, Env.createObject(S->getType()));
653     else if (!S->getType()->isRecordType()) {
654       if (Value *Val = Env.createValue(S->getType()))
655         Env.setValue(*S, *Val);
656     }
657   }
658 
659   void VisitInitListExpr(const InitListExpr *S) {
660     QualType Type = S->getType();
661 
662     if (!Type->isRecordType()) {
663       // Until array initialization is implemented, we skip arrays and don't
664       // need to care about cases where `getNumInits() > 1`.
665       if (!Type->isArrayType() && S->getNumInits() == 1)
666         propagateValueOrStorageLocation(*S->getInit(0), *S, Env);
667       return;
668     }
669 
670     // If the initializer list is transparent, there's nothing to do.
671     if (S->isSemanticForm() && S->isTransparent())
672       return;
673 
674     RecordStorageLocation &Loc = Env.getResultObjectLocation(*S);
675 
676     // Initialization of base classes and fields of record type happens when we
677     // visit the nested `CXXConstructExpr` or `InitListExpr` for that base class
678     // or field. We therefore only need to deal with fields of non-record type
679     // here.
680 
681     RecordInitListHelper InitListHelper(S);
682 
683     for (auto [Field, Init] : InitListHelper.field_inits()) {
684       if (Field->getType()->isRecordType())
685         continue;
686       if (Field->getType()->isReferenceType()) {
687         assert(Field->getType().getCanonicalType()->getPointeeType() ==
688                Init->getType().getCanonicalType());
689         Loc.setChild(*Field, &Env.createObject(Field->getType(), Init));
690         continue;
691       }
692       assert(Field->getType().getCanonicalType().getUnqualifiedType() ==
693              Init->getType().getCanonicalType().getUnqualifiedType());
694       StorageLocation *FieldLoc = Loc.getChild(*Field);
695       // Locations for non-reference fields must always be non-null.
696       assert(FieldLoc != nullptr);
697       Value *Val = Env.getValue(*Init);
698       if (Val == nullptr && isa<ImplicitValueInitExpr>(Init) &&
699           Init->getType()->isPointerType())
700         Val =
701             &Env.getOrCreateNullPointerValue(Init->getType()->getPointeeType());
702       if (Val == nullptr)
703         Val = Env.createValue(Field->getType());
704       if (Val != nullptr)
705         Env.setValue(*FieldLoc, *Val);
706     }
707 
708     for (const auto &[FieldName, FieldLoc] : Loc.synthetic_fields()) {
709       QualType FieldType = FieldLoc->getType();
710       if (FieldType->isRecordType()) {
711         Env.initializeFieldsWithValues(*cast<RecordStorageLocation>(FieldLoc));
712       } else {
713         if (Value *Val = Env.createValue(FieldType))
714           Env.setValue(*FieldLoc, *Val);
715       }
716     }
717 
718     // FIXME: Implement array initialization.
719   }
720 
721   void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *S) {
722     Env.setValue(*S, Env.getBoolLiteralValue(S->getValue()));
723   }
724 
725   void VisitIntegerLiteral(const IntegerLiteral *S) {
726     Env.setValue(*S, Env.getIntLiteralValue(S->getValue()));
727   }
728 
729   void VisitParenExpr(const ParenExpr *S) {
730     // The CFG does not contain `ParenExpr` as top-level statements in basic
731     // blocks, however manual traversal to sub-expressions may encounter them.
732     // Redirect to the sub-expression.
733     auto *SubExpr = S->getSubExpr();
734     assert(SubExpr != nullptr);
735     Visit(SubExpr);
736   }
737 
738   void VisitExprWithCleanups(const ExprWithCleanups *S) {
739     // The CFG does not contain `ExprWithCleanups` as top-level statements in
740     // basic blocks, however manual traversal to sub-expressions may encounter
741     // them. Redirect to the sub-expression.
742     auto *SubExpr = S->getSubExpr();
743     assert(SubExpr != nullptr);
744     Visit(SubExpr);
745   }
746 
747 private:
748   /// Returns the value for the sub-expression `SubExpr` of a logic operator.
749   BoolValue &getLogicOperatorSubExprValue(const Expr &SubExpr) {
750     // `SubExpr` and its parent logic operator might be part of different basic
751     // blocks. We try to access the value that is assigned to `SubExpr` in the
752     // corresponding environment.
753     if (const Environment *SubExprEnv = StmtToEnv.getEnvironment(SubExpr))
754       if (auto *Val =
755               dyn_cast_or_null<BoolValue>(SubExprEnv->getValue(SubExpr)))
756         return *Val;
757 
758     // The sub-expression may lie within a basic block that isn't reachable,
759     // even if we need it to evaluate the current (reachable) expression
760     // (see https://discourse.llvm.org/t/70775). In this case, visit `SubExpr`
761     // within the current environment and then try to get the value that gets
762     // assigned to it.
763     if (Env.getValue(SubExpr) == nullptr)
764       Visit(&SubExpr);
765     if (auto *Val = dyn_cast_or_null<BoolValue>(Env.getValue(SubExpr)))
766       return *Val;
767 
768     // If the value of `SubExpr` is still unknown, we create a fresh symbolic
769     // boolean value for it.
770     return Env.makeAtomicBoolValue();
771   }
772 
773   // If context sensitivity is enabled, try to analyze the body of the callee
774   // `F` of `S`. The type `E` must be either `CallExpr` or `CXXConstructExpr`.
775   template <typename E>
776   void transferInlineCall(const E *S, const FunctionDecl *F) {
777     const auto &Options = Env.getDataflowAnalysisContext().getOptions();
778     if (!(Options.ContextSensitiveOpts &&
779           Env.canDescend(Options.ContextSensitiveOpts->Depth, F)))
780       return;
781 
782     const AdornedCFG *ACFG = Env.getDataflowAnalysisContext().getAdornedCFG(F);
783     if (!ACFG)
784       return;
785 
786     // FIXME: We don't support context-sensitive analysis of recursion, so
787     // we should return early here if `F` is the same as the `FunctionDecl`
788     // holding `S` itself.
789 
790     auto ExitBlock = ACFG->getCFG().getExit().getBlockID();
791 
792     auto CalleeEnv = Env.pushCall(S);
793 
794     // FIXME: Use the same analysis as the caller for the callee. Note,
795     // though, that doing so would require support for changing the analysis's
796     // ASTContext.
797     auto Analysis = NoopAnalysis(ACFG->getDecl().getASTContext(),
798                                  DataflowAnalysisOptions{Options});
799 
800     auto BlockToOutputState =
801         dataflow::runDataflowAnalysis(*ACFG, Analysis, CalleeEnv);
802     assert(BlockToOutputState);
803     assert(ExitBlock < BlockToOutputState->size());
804 
805     auto &ExitState = (*BlockToOutputState)[ExitBlock];
806     assert(ExitState);
807 
808     Env.popCall(S, ExitState->Env);
809   }
810 
811   const StmtToEnvMap &StmtToEnv;
812   Environment &Env;
813 };
814 
815 } // namespace
816 
817 void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env) {
818   TransferVisitor(StmtToEnv, Env).Visit(&S);
819 }
820 
821 } // namespace dataflow
822 } // namespace clang
823