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