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