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