xref: /freebsd/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/Transfer.cpp (revision 942815c54820783d3d4f7f6faa71ab7919b5f0e5)
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/Value.h"
27 #include "clang/Basic/Builtins.h"
28 #include "clang/Basic/OperatorKinds.h"
29 #include "llvm/ADT/STLExtras.h"
30 #include "llvm/Support/Casting.h"
31 #include <cassert>
32 #include <memory>
33 #include <tuple>
34 
35 namespace clang {
36 namespace dataflow {
37 
38 static BoolValue &evaluateBooleanEquality(const Expr &LHS, const Expr &RHS,
39                                           Environment &Env) {
40   if (auto *LHSValue =
41           dyn_cast_or_null<BoolValue>(Env.getValue(LHS, SkipPast::Reference)))
42     if (auto *RHSValue =
43             dyn_cast_or_null<BoolValue>(Env.getValue(RHS, SkipPast::Reference)))
44       return Env.makeIff(*LHSValue, *RHSValue);
45 
46   return Env.makeAtomicBoolValue();
47 }
48 
49 class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
50 public:
51   TransferVisitor(const StmtToEnvMap &StmtToEnv, Environment &Env,
52                   TransferOptions Options)
53       : StmtToEnv(StmtToEnv), Env(Env), Options(Options) {}
54 
55   void VisitBinaryOperator(const BinaryOperator *S) {
56     const Expr *LHS = S->getLHS();
57     assert(LHS != nullptr);
58 
59     const Expr *RHS = S->getRHS();
60     assert(RHS != nullptr);
61 
62     switch (S->getOpcode()) {
63     case BO_Assign: {
64       auto *LHSLoc = Env.getStorageLocation(*LHS, SkipPast::Reference);
65       if (LHSLoc == nullptr)
66         break;
67 
68       auto *RHSVal = Env.getValue(*RHS, SkipPast::Reference);
69       if (RHSVal == nullptr)
70         break;
71 
72       // Assign a value to the storage location of the left-hand side.
73       Env.setValue(*LHSLoc, *RHSVal);
74 
75       // Assign a storage location for the whole expression.
76       Env.setStorageLocation(*S, *LHSLoc);
77       break;
78     }
79     case BO_LAnd:
80     case BO_LOr: {
81       BoolValue &LHSVal = getLogicOperatorSubExprValue(*LHS);
82       BoolValue &RHSVal = getLogicOperatorSubExprValue(*RHS);
83 
84       auto &Loc = Env.createStorageLocation(*S);
85       Env.setStorageLocation(*S, Loc);
86       if (S->getOpcode() == BO_LAnd)
87         Env.setValue(Loc, Env.makeAnd(LHSVal, RHSVal));
88       else
89         Env.setValue(Loc, Env.makeOr(LHSVal, RHSVal));
90       break;
91     }
92     case BO_NE:
93     case BO_EQ: {
94       auto &LHSEqRHSValue = evaluateBooleanEquality(*LHS, *RHS, Env);
95       auto &Loc = Env.createStorageLocation(*S);
96       Env.setStorageLocation(*S, Loc);
97       Env.setValue(Loc, S->getOpcode() == BO_EQ ? LHSEqRHSValue
98                                                 : Env.makeNot(LHSEqRHSValue));
99       break;
100     }
101     case BO_Comma: {
102       if (auto *Loc = Env.getStorageLocation(*RHS, SkipPast::None))
103         Env.setStorageLocation(*S, *Loc);
104       break;
105     }
106     default:
107       break;
108     }
109   }
110 
111   void VisitDeclRefExpr(const DeclRefExpr *S) {
112     assert(S->getDecl() != nullptr);
113     auto *DeclLoc = Env.getStorageLocation(*S->getDecl(), SkipPast::None);
114     if (DeclLoc == nullptr)
115       return;
116 
117     if (S->getDecl()->getType()->isReferenceType()) {
118       Env.setStorageLocation(*S, *DeclLoc);
119     } else {
120       auto &Loc = Env.createStorageLocation(*S);
121       auto &Val = Env.takeOwnership(std::make_unique<ReferenceValue>(*DeclLoc));
122       Env.setStorageLocation(*S, Loc);
123       Env.setValue(Loc, Val);
124     }
125   }
126 
127   void VisitDeclStmt(const DeclStmt *S) {
128     // Group decls are converted into single decls in the CFG so the cast below
129     // is safe.
130     const auto &D = *cast<VarDecl>(S->getSingleDecl());
131 
132     // Static local vars are already initialized in `Environment`.
133     if (D.hasGlobalStorage())
134       return;
135 
136     auto &Loc = Env.createStorageLocation(D);
137     Env.setStorageLocation(D, Loc);
138 
139     const Expr *InitExpr = D.getInit();
140     if (InitExpr == nullptr) {
141       // No initializer expression - associate `Loc` with a new value.
142       if (Value *Val = Env.createValue(D.getType()))
143         Env.setValue(Loc, *Val);
144       return;
145     }
146 
147     if (D.getType()->isReferenceType()) {
148       // Initializing a reference variable - do not create a reference to
149       // reference.
150       if (auto *InitExprLoc =
151               Env.getStorageLocation(*InitExpr, SkipPast::Reference)) {
152         auto &Val =
153             Env.takeOwnership(std::make_unique<ReferenceValue>(*InitExprLoc));
154         Env.setValue(Loc, Val);
155       }
156     } else if (auto *InitExprVal = Env.getValue(*InitExpr, SkipPast::None)) {
157       Env.setValue(Loc, *InitExprVal);
158     }
159 
160     if (Env.getValue(Loc) == nullptr) {
161       // We arrive here in (the few) cases where an expression is intentionally
162       // "uninterpreted". There are two ways to handle this situation: propagate
163       // the status, so that uninterpreted initializers result in uninterpreted
164       // variables, or provide a default value. We choose the latter so that
165       // later refinements of the variable can be used for reasoning about the
166       // surrounding code.
167       //
168       // FIXME. If and when we interpret all language cases, change this to
169       // assert that `InitExpr` is interpreted, rather than supplying a default
170       // value (assuming we don't update the environment API to return
171       // references).
172       if (Value *Val = Env.createValue(D.getType()))
173         Env.setValue(Loc, *Val);
174     }
175 
176     if (const auto *Decomp = dyn_cast<DecompositionDecl>(&D)) {
177       // If VarDecl is a DecompositionDecl, evaluate each of its bindings. This
178       // needs to be evaluated after initializing the values in the storage for
179       // VarDecl, as the bindings refer to them.
180       // FIXME: Add support for ArraySubscriptExpr.
181       // FIXME: Consider adding AST nodes that are used for structured bindings
182       // to the CFG.
183       for (const auto *B : Decomp->bindings()) {
184         auto *ME = dyn_cast_or_null<MemberExpr>(B->getBinding());
185         if (ME == nullptr)
186           continue;
187 
188         auto *DE = dyn_cast_or_null<DeclRefExpr>(ME->getBase());
189         if (DE == nullptr)
190           continue;
191 
192         // ME and its base haven't been visited because they aren't included in
193         // the statements of the CFG basic block.
194         VisitDeclRefExpr(DE);
195         VisitMemberExpr(ME);
196 
197         if (auto *Loc = Env.getStorageLocation(*ME, SkipPast::Reference))
198           Env.setStorageLocation(*B, *Loc);
199       }
200     }
201   }
202 
203   void VisitImplicitCastExpr(const ImplicitCastExpr *S) {
204     const Expr *SubExpr = S->getSubExpr();
205     assert(SubExpr != nullptr);
206 
207     switch (S->getCastKind()) {
208     case CK_IntegralToBoolean: {
209       // This cast creates a new, boolean value from the integral value. We
210       // model that with a fresh value in the environment, unless it's already a
211       // boolean.
212       auto &Loc = Env.createStorageLocation(*S);
213       Env.setStorageLocation(*S, Loc);
214       if (auto *SubExprVal = dyn_cast_or_null<BoolValue>(
215               Env.getValue(*SubExpr, SkipPast::Reference)))
216         Env.setValue(Loc, *SubExprVal);
217       else
218         // FIXME: If integer modeling is added, then update this code to create
219         // the boolean based on the integer model.
220         Env.setValue(Loc, Env.makeAtomicBoolValue());
221       break;
222     }
223 
224     case CK_LValueToRValue: {
225       auto *SubExprVal = Env.getValue(*SubExpr, SkipPast::Reference);
226       if (SubExprVal == nullptr)
227         break;
228 
229       auto &ExprLoc = Env.createStorageLocation(*S);
230       Env.setStorageLocation(*S, ExprLoc);
231       Env.setValue(ExprLoc, *SubExprVal);
232       break;
233     }
234 
235     case CK_IntegralCast:
236       // FIXME: This cast creates a new integral value from the
237       // subexpression. But, because we don't model integers, we don't
238       // distinguish between this new value and the underlying one. If integer
239       // modeling is added, then update this code to create a fresh location and
240       // value.
241     case CK_UncheckedDerivedToBase:
242     case CK_ConstructorConversion:
243     case CK_UserDefinedConversion:
244       // FIXME: Add tests that excercise CK_UncheckedDerivedToBase,
245       // CK_ConstructorConversion, and CK_UserDefinedConversion.
246     case CK_NoOp: {
247       // FIXME: Consider making `Environment::getStorageLocation` skip noop
248       // expressions (this and other similar expressions in the file) instead of
249       // assigning them storage locations.
250       auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
251       if (SubExprLoc == nullptr)
252         break;
253 
254       Env.setStorageLocation(*S, *SubExprLoc);
255       break;
256     }
257     case CK_NullToPointer:
258     case CK_NullToMemberPointer: {
259       auto &Loc = Env.createStorageLocation(S->getType());
260       Env.setStorageLocation(*S, Loc);
261 
262       auto &NullPointerVal =
263           Env.getOrCreateNullPointerValue(S->getType()->getPointeeType());
264       Env.setValue(Loc, NullPointerVal);
265       break;
266     }
267     default:
268       break;
269     }
270   }
271 
272   void VisitUnaryOperator(const UnaryOperator *S) {
273     const Expr *SubExpr = S->getSubExpr();
274     assert(SubExpr != nullptr);
275 
276     switch (S->getOpcode()) {
277     case UO_Deref: {
278       // Skip past a reference to handle dereference of a dependent pointer.
279       const auto *SubExprVal = cast_or_null<PointerValue>(
280           Env.getValue(*SubExpr, SkipPast::Reference));
281       if (SubExprVal == nullptr)
282         break;
283 
284       auto &Loc = Env.createStorageLocation(*S);
285       Env.setStorageLocation(*S, Loc);
286       Env.setValue(Loc, Env.takeOwnership(std::make_unique<ReferenceValue>(
287                             SubExprVal->getPointeeLoc())));
288       break;
289     }
290     case UO_AddrOf: {
291       // Do not form a pointer to a reference. If `SubExpr` is assigned a
292       // `ReferenceValue` then form a value that points to the location of its
293       // pointee.
294       StorageLocation *PointeeLoc =
295           Env.getStorageLocation(*SubExpr, SkipPast::Reference);
296       if (PointeeLoc == nullptr)
297         break;
298 
299       auto &PointerLoc = Env.createStorageLocation(*S);
300       auto &PointerVal =
301           Env.takeOwnership(std::make_unique<PointerValue>(*PointeeLoc));
302       Env.setStorageLocation(*S, PointerLoc);
303       Env.setValue(PointerLoc, PointerVal);
304       break;
305     }
306     case UO_LNot: {
307       auto *SubExprVal =
308           dyn_cast_or_null<BoolValue>(Env.getValue(*SubExpr, SkipPast::None));
309       if (SubExprVal == nullptr)
310         break;
311 
312       auto &ExprLoc = Env.createStorageLocation(*S);
313       Env.setStorageLocation(*S, ExprLoc);
314       Env.setValue(ExprLoc, Env.makeNot(*SubExprVal));
315       break;
316     }
317     default:
318       break;
319     }
320   }
321 
322   void VisitCXXThisExpr(const CXXThisExpr *S) {
323     auto *ThisPointeeLoc = Env.getThisPointeeStorageLocation();
324     if (ThisPointeeLoc == nullptr)
325       // Unions are not supported yet, and will not have a location for the
326       // `this` expression's pointee.
327       return;
328 
329     auto &Loc = Env.createStorageLocation(*S);
330     Env.setStorageLocation(*S, Loc);
331     Env.setValue(Loc, Env.takeOwnership(
332                           std::make_unique<PointerValue>(*ThisPointeeLoc)));
333   }
334 
335   void VisitMemberExpr(const MemberExpr *S) {
336     ValueDecl *Member = S->getMemberDecl();
337     assert(Member != nullptr);
338 
339     // FIXME: Consider assigning pointer values to function member expressions.
340     if (Member->isFunctionOrFunctionTemplate())
341       return;
342 
343     if (auto *D = dyn_cast<VarDecl>(Member)) {
344       if (D->hasGlobalStorage()) {
345         auto *VarDeclLoc = Env.getStorageLocation(*D, SkipPast::None);
346         if (VarDeclLoc == nullptr)
347           return;
348 
349         if (VarDeclLoc->getType()->isReferenceType()) {
350           Env.setStorageLocation(*S, *VarDeclLoc);
351         } else {
352           auto &Loc = Env.createStorageLocation(*S);
353           Env.setStorageLocation(*S, Loc);
354           Env.setValue(Loc, Env.takeOwnership(
355                                 std::make_unique<ReferenceValue>(*VarDeclLoc)));
356         }
357         return;
358       }
359     }
360 
361     // The receiver can be either a value or a pointer to a value. Skip past the
362     // indirection to handle both cases.
363     auto *BaseLoc = cast_or_null<AggregateStorageLocation>(
364         Env.getStorageLocation(*S->getBase(), SkipPast::ReferenceThenPointer));
365     if (BaseLoc == nullptr)
366       return;
367 
368     // FIXME: Add support for union types.
369     if (BaseLoc->getType()->isUnionType())
370       return;
371 
372     auto &MemberLoc = BaseLoc->getChild(*Member);
373     if (MemberLoc.getType()->isReferenceType()) {
374       Env.setStorageLocation(*S, MemberLoc);
375     } else {
376       auto &Loc = Env.createStorageLocation(*S);
377       Env.setStorageLocation(*S, Loc);
378       Env.setValue(
379           Loc, Env.takeOwnership(std::make_unique<ReferenceValue>(MemberLoc)));
380     }
381   }
382 
383   void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *S) {
384     const Expr *InitExpr = S->getExpr();
385     assert(InitExpr != nullptr);
386 
387     Value *InitExprVal = Env.getValue(*InitExpr, SkipPast::None);
388     if (InitExprVal == nullptr)
389       return;
390 
391     const FieldDecl *Field = S->getField();
392     assert(Field != nullptr);
393 
394     auto &ThisLoc =
395         *cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation());
396     auto &FieldLoc = ThisLoc.getChild(*Field);
397     Env.setValue(FieldLoc, *InitExprVal);
398   }
399 
400   void VisitCXXConstructExpr(const CXXConstructExpr *S) {
401     const CXXConstructorDecl *ConstructorDecl = S->getConstructor();
402     assert(ConstructorDecl != nullptr);
403 
404     if (ConstructorDecl->isCopyOrMoveConstructor()) {
405       assert(S->getNumArgs() == 1);
406 
407       const Expr *Arg = S->getArg(0);
408       assert(Arg != nullptr);
409 
410       if (S->isElidable()) {
411         auto *ArgLoc = Env.getStorageLocation(*Arg, SkipPast::Reference);
412         if (ArgLoc == nullptr)
413           return;
414 
415         Env.setStorageLocation(*S, *ArgLoc);
416       } else if (auto *ArgVal = Env.getValue(*Arg, SkipPast::Reference)) {
417         auto &Loc = Env.createStorageLocation(*S);
418         Env.setStorageLocation(*S, Loc);
419         Env.setValue(Loc, *ArgVal);
420       }
421       return;
422     }
423 
424     auto &Loc = Env.createStorageLocation(*S);
425     Env.setStorageLocation(*S, Loc);
426     if (Value *Val = Env.createValue(S->getType()))
427       Env.setValue(Loc, *Val);
428   }
429 
430   void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) {
431     if (S->getOperator() == OO_Equal) {
432       assert(S->getNumArgs() == 2);
433 
434       const Expr *Arg0 = S->getArg(0);
435       assert(Arg0 != nullptr);
436 
437       const Expr *Arg1 = S->getArg(1);
438       assert(Arg1 != nullptr);
439 
440       // Evaluate only copy and move assignment operators.
441       auto *Arg0Type = Arg0->getType()->getUnqualifiedDesugaredType();
442       auto *Arg1Type = Arg1->getType()->getUnqualifiedDesugaredType();
443       if (Arg0Type != Arg1Type)
444         return;
445 
446       auto *ObjectLoc = Env.getStorageLocation(*Arg0, SkipPast::Reference);
447       if (ObjectLoc == nullptr)
448         return;
449 
450       auto *Val = Env.getValue(*Arg1, SkipPast::Reference);
451       if (Val == nullptr)
452         return;
453 
454       // Assign a value to the storage location of the object.
455       Env.setValue(*ObjectLoc, *Val);
456 
457       // FIXME: Add a test for the value of the whole expression.
458       // Assign a storage location for the whole expression.
459       Env.setStorageLocation(*S, *ObjectLoc);
460     }
461   }
462 
463   void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *S) {
464     if (S->getCastKind() == CK_ConstructorConversion) {
465       const Expr *SubExpr = S->getSubExpr();
466       assert(SubExpr != nullptr);
467 
468       auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
469       if (SubExprLoc == nullptr)
470         return;
471 
472       Env.setStorageLocation(*S, *SubExprLoc);
473     }
474   }
475 
476   void VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *S) {
477     auto &Loc = Env.createStorageLocation(*S);
478     Env.setStorageLocation(*S, Loc);
479     if (Value *Val = Env.createValue(S->getType()))
480       Env.setValue(Loc, *Val);
481   }
482 
483   void VisitCallExpr(const CallExpr *S) {
484     // Of clang's builtins, only `__builtin_expect` is handled explicitly, since
485     // others (like trap, debugtrap, and unreachable) are handled by CFG
486     // construction.
487     if (S->isCallToStdMove()) {
488       assert(S->getNumArgs() == 1);
489 
490       const Expr *Arg = S->getArg(0);
491       assert(Arg != nullptr);
492 
493       auto *ArgLoc = Env.getStorageLocation(*Arg, SkipPast::None);
494       if (ArgLoc == nullptr)
495         return;
496 
497       Env.setStorageLocation(*S, *ArgLoc);
498     } else if (S->getDirectCallee() != nullptr &&
499                S->getDirectCallee()->getBuiltinID() ==
500                    Builtin::BI__builtin_expect) {
501       assert(S->getNumArgs() > 0);
502       assert(S->getArg(0) != nullptr);
503       // `__builtin_expect` returns by-value, so strip away any potential
504       // references in the argument.
505       auto *ArgLoc = Env.getStorageLocation(*S->getArg(0), SkipPast::Reference);
506       if (ArgLoc == nullptr)
507         return;
508       Env.setStorageLocation(*S, *ArgLoc);
509     } else if (const FunctionDecl *F = S->getDirectCallee()) {
510       // This case is for context-sensitive analysis, which we only do if we
511       // have the callee body available in the translation unit.
512       if (!Options.ContextSensitive || F->getBody() == nullptr)
513         return;
514 
515       auto &ASTCtx = F->getASTContext();
516 
517       // FIXME: Cache these CFGs.
518       auto CFCtx = ControlFlowContext::build(F, F->getBody(), &ASTCtx);
519       // FIXME: Handle errors here and below.
520       assert(CFCtx);
521       auto ExitBlock = CFCtx->getCFG().getExit().getBlockID();
522 
523       auto CalleeEnv = Env.pushCall(S);
524 
525       // FIXME: Use the same analysis as the caller for the callee.
526       DataflowAnalysisOptions Options;
527       auto Analysis = NoopAnalysis(ASTCtx, Options);
528 
529       auto BlockToOutputState =
530           dataflow::runDataflowAnalysis(*CFCtx, Analysis, CalleeEnv);
531       assert(BlockToOutputState);
532       assert(ExitBlock < BlockToOutputState->size());
533 
534       auto ExitState = (*BlockToOutputState)[ExitBlock];
535       assert(ExitState);
536 
537       Env = ExitState->Env;
538     }
539   }
540 
541   void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *S) {
542     const Expr *SubExpr = S->getSubExpr();
543     assert(SubExpr != nullptr);
544 
545     auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
546     if (SubExprLoc == nullptr)
547       return;
548 
549     Env.setStorageLocation(*S, *SubExprLoc);
550   }
551 
552   void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *S) {
553     const Expr *SubExpr = S->getSubExpr();
554     assert(SubExpr != nullptr);
555 
556     auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
557     if (SubExprLoc == nullptr)
558       return;
559 
560     Env.setStorageLocation(*S, *SubExprLoc);
561   }
562 
563   void VisitCXXStaticCastExpr(const CXXStaticCastExpr *S) {
564     if (S->getCastKind() == CK_NoOp) {
565       const Expr *SubExpr = S->getSubExpr();
566       assert(SubExpr != nullptr);
567 
568       auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
569       if (SubExprLoc == nullptr)
570         return;
571 
572       Env.setStorageLocation(*S, *SubExprLoc);
573     }
574   }
575 
576   void VisitConditionalOperator(const ConditionalOperator *S) {
577     // FIXME: Revisit this once flow conditions are added to the framework. For
578     // `a = b ? c : d` we can add `b => a == c && !b => a == d` to the flow
579     // condition.
580     auto &Loc = Env.createStorageLocation(*S);
581     Env.setStorageLocation(*S, Loc);
582     if (Value *Val = Env.createValue(S->getType()))
583       Env.setValue(Loc, *Val);
584   }
585 
586   void VisitInitListExpr(const InitListExpr *S) {
587     QualType Type = S->getType();
588 
589     auto &Loc = Env.createStorageLocation(*S);
590     Env.setStorageLocation(*S, Loc);
591 
592     auto *Val = Env.createValue(Type);
593     if (Val == nullptr)
594       return;
595 
596     Env.setValue(Loc, *Val);
597 
598     if (Type->isStructureOrClassType()) {
599       for (auto It : llvm::zip(Type->getAsRecordDecl()->fields(), S->inits())) {
600         const FieldDecl *Field = std::get<0>(It);
601         assert(Field != nullptr);
602 
603         const Expr *Init = std::get<1>(It);
604         assert(Init != nullptr);
605 
606         if (Value *InitVal = Env.getValue(*Init, SkipPast::None))
607           cast<StructValue>(Val)->setChild(*Field, *InitVal);
608       }
609     }
610     // FIXME: Implement array initialization.
611   }
612 
613   void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *S) {
614     auto &Loc = Env.createStorageLocation(*S);
615     Env.setStorageLocation(*S, Loc);
616     Env.setValue(Loc, Env.getBoolLiteralValue(S->getValue()));
617   }
618 
619   void VisitParenExpr(const ParenExpr *S) {
620     // The CFG does not contain `ParenExpr` as top-level statements in basic
621     // blocks, however manual traversal to sub-expressions may encounter them.
622     // Redirect to the sub-expression.
623     auto *SubExpr = S->getSubExpr();
624     assert(SubExpr != nullptr);
625     Visit(SubExpr);
626   }
627 
628   void VisitExprWithCleanups(const ExprWithCleanups *S) {
629     // The CFG does not contain `ExprWithCleanups` as top-level statements in
630     // basic blocks, however manual traversal to sub-expressions may encounter
631     // them. Redirect to the sub-expression.
632     auto *SubExpr = S->getSubExpr();
633     assert(SubExpr != nullptr);
634     Visit(SubExpr);
635   }
636 
637 private:
638   BoolValue &getLogicOperatorSubExprValue(const Expr &SubExpr) {
639     // `SubExpr` and its parent logic operator might be part of different basic
640     // blocks. We try to access the value that is assigned to `SubExpr` in the
641     // corresponding environment.
642     if (const Environment *SubExprEnv = StmtToEnv.getEnvironment(SubExpr)) {
643       if (auto *Val = dyn_cast_or_null<BoolValue>(
644               SubExprEnv->getValue(SubExpr, SkipPast::Reference)))
645         return *Val;
646     }
647 
648     if (Env.getStorageLocation(SubExpr, SkipPast::None) == nullptr) {
649       // Sub-expressions that are logic operators are not added in basic blocks
650       // (e.g. see CFG for `bool d = a && (b || c);`). If `SubExpr` is a logic
651       // operator, it may not have been evaluated and assigned a value yet. In
652       // that case, we need to first visit `SubExpr` and then try to get the
653       // value that gets assigned to it.
654       Visit(&SubExpr);
655     }
656 
657     if (auto *Val = dyn_cast_or_null<BoolValue>(
658             Env.getValue(SubExpr, SkipPast::Reference)))
659       return *Val;
660 
661     // If the value of `SubExpr` is still unknown, we create a fresh symbolic
662     // boolean value for it.
663     return Env.makeAtomicBoolValue();
664   }
665 
666   const StmtToEnvMap &StmtToEnv;
667   Environment &Env;
668   TransferOptions Options;
669 };
670 
671 void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env,
672               TransferOptions Options) {
673   TransferVisitor(StmtToEnv, Env, Options).Visit(&S);
674 }
675 
676 } // namespace dataflow
677 } // namespace clang
678