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