xref: /freebsd/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/Transfer.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
104eeddc0SDimitry Andric //===-- Transfer.cpp --------------------------------------------*- C++ -*-===//
204eeddc0SDimitry Andric //
304eeddc0SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
404eeddc0SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
504eeddc0SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
604eeddc0SDimitry Andric //
704eeddc0SDimitry Andric //===----------------------------------------------------------------------===//
804eeddc0SDimitry Andric //
904eeddc0SDimitry Andric //  This file defines transfer functions that evaluate program statements and
1004eeddc0SDimitry Andric //  update an environment accordingly.
1104eeddc0SDimitry Andric //
1204eeddc0SDimitry Andric //===----------------------------------------------------------------------===//
1304eeddc0SDimitry Andric 
1404eeddc0SDimitry Andric #include "clang/Analysis/FlowSensitive/Transfer.h"
1504eeddc0SDimitry Andric #include "clang/AST/Decl.h"
1604eeddc0SDimitry Andric #include "clang/AST/DeclBase.h"
1704eeddc0SDimitry Andric #include "clang/AST/DeclCXX.h"
1804eeddc0SDimitry Andric #include "clang/AST/Expr.h"
1904eeddc0SDimitry Andric #include "clang/AST/ExprCXX.h"
2004eeddc0SDimitry Andric #include "clang/AST/OperationKinds.h"
2104eeddc0SDimitry Andric #include "clang/AST/Stmt.h"
2204eeddc0SDimitry Andric #include "clang/AST/StmtVisitor.h"
2304eeddc0SDimitry Andric #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
24*81ad6265SDimitry Andric #include "clang/Analysis/FlowSensitive/Value.h"
25*81ad6265SDimitry Andric #include "clang/Basic/Builtins.h"
2604eeddc0SDimitry Andric #include "clang/Basic/OperatorKinds.h"
2704eeddc0SDimitry Andric #include "llvm/ADT/STLExtras.h"
2804eeddc0SDimitry Andric #include "llvm/Support/Casting.h"
2904eeddc0SDimitry Andric #include <cassert>
3004eeddc0SDimitry Andric #include <memory>
3104eeddc0SDimitry Andric #include <tuple>
3204eeddc0SDimitry Andric 
3304eeddc0SDimitry Andric namespace clang {
3404eeddc0SDimitry Andric namespace dataflow {
3504eeddc0SDimitry Andric 
36*81ad6265SDimitry Andric static BoolValue &evaluateBooleanEquality(const Expr &LHS, const Expr &RHS,
37*81ad6265SDimitry Andric                                           Environment &Env) {
38*81ad6265SDimitry Andric   if (auto *LHSValue =
39*81ad6265SDimitry Andric           dyn_cast_or_null<BoolValue>(Env.getValue(LHS, SkipPast::Reference)))
40*81ad6265SDimitry Andric     if (auto *RHSValue =
41*81ad6265SDimitry Andric             dyn_cast_or_null<BoolValue>(Env.getValue(RHS, SkipPast::Reference)))
42*81ad6265SDimitry Andric       return Env.makeIff(*LHSValue, *RHSValue);
43*81ad6265SDimitry Andric 
44*81ad6265SDimitry Andric   return Env.makeAtomicBoolValue();
4504eeddc0SDimitry Andric }
4604eeddc0SDimitry Andric 
4704eeddc0SDimitry Andric class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
4804eeddc0SDimitry Andric public:
49*81ad6265SDimitry Andric   TransferVisitor(const StmtToEnvMap &StmtToEnv, Environment &Env)
50*81ad6265SDimitry Andric       : StmtToEnv(StmtToEnv), Env(Env) {}
5104eeddc0SDimitry Andric 
5204eeddc0SDimitry Andric   void VisitBinaryOperator(const BinaryOperator *S) {
53*81ad6265SDimitry Andric     const Expr *LHS = S->getLHS();
5404eeddc0SDimitry Andric     assert(LHS != nullptr);
55*81ad6265SDimitry Andric 
56*81ad6265SDimitry Andric     const Expr *RHS = S->getRHS();
57*81ad6265SDimitry Andric     assert(RHS != nullptr);
58*81ad6265SDimitry Andric 
59*81ad6265SDimitry Andric     switch (S->getOpcode()) {
60*81ad6265SDimitry Andric     case BO_Assign: {
6104eeddc0SDimitry Andric       auto *LHSLoc = Env.getStorageLocation(*LHS, SkipPast::Reference);
6204eeddc0SDimitry Andric       if (LHSLoc == nullptr)
63*81ad6265SDimitry Andric         break;
6404eeddc0SDimitry Andric 
65*81ad6265SDimitry Andric       auto *RHSVal = Env.getValue(*RHS, SkipPast::Reference);
6604eeddc0SDimitry Andric       if (RHSVal == nullptr)
67*81ad6265SDimitry Andric         break;
6804eeddc0SDimitry Andric 
6904eeddc0SDimitry Andric       // Assign a value to the storage location of the left-hand side.
7004eeddc0SDimitry Andric       Env.setValue(*LHSLoc, *RHSVal);
7104eeddc0SDimitry Andric 
7204eeddc0SDimitry Andric       // Assign a storage location for the whole expression.
7304eeddc0SDimitry Andric       Env.setStorageLocation(*S, *LHSLoc);
74*81ad6265SDimitry Andric       break;
7504eeddc0SDimitry Andric     }
76*81ad6265SDimitry Andric     case BO_LAnd:
77*81ad6265SDimitry Andric     case BO_LOr: {
78*81ad6265SDimitry Andric       BoolValue &LHSVal = getLogicOperatorSubExprValue(*LHS);
79*81ad6265SDimitry Andric       BoolValue &RHSVal = getLogicOperatorSubExprValue(*RHS);
80*81ad6265SDimitry Andric 
81*81ad6265SDimitry Andric       auto &Loc = Env.createStorageLocation(*S);
82*81ad6265SDimitry Andric       Env.setStorageLocation(*S, Loc);
83*81ad6265SDimitry Andric       if (S->getOpcode() == BO_LAnd)
84*81ad6265SDimitry Andric         Env.setValue(Loc, Env.makeAnd(LHSVal, RHSVal));
85*81ad6265SDimitry Andric       else
86*81ad6265SDimitry Andric         Env.setValue(Loc, Env.makeOr(LHSVal, RHSVal));
87*81ad6265SDimitry Andric       break;
88*81ad6265SDimitry Andric     }
89*81ad6265SDimitry Andric     case BO_NE:
90*81ad6265SDimitry Andric     case BO_EQ: {
91*81ad6265SDimitry Andric       auto &LHSEqRHSValue = evaluateBooleanEquality(*LHS, *RHS, Env);
92*81ad6265SDimitry Andric       auto &Loc = Env.createStorageLocation(*S);
93*81ad6265SDimitry Andric       Env.setStorageLocation(*S, Loc);
94*81ad6265SDimitry Andric       Env.setValue(Loc, S->getOpcode() == BO_EQ ? LHSEqRHSValue
95*81ad6265SDimitry Andric                                                 : Env.makeNot(LHSEqRHSValue));
96*81ad6265SDimitry Andric       break;
97*81ad6265SDimitry Andric     }
98*81ad6265SDimitry Andric     case BO_Comma: {
99*81ad6265SDimitry Andric       if (auto *Loc = Env.getStorageLocation(*RHS, SkipPast::None))
100*81ad6265SDimitry Andric         Env.setStorageLocation(*S, *Loc);
101*81ad6265SDimitry Andric       break;
102*81ad6265SDimitry Andric     }
103*81ad6265SDimitry Andric     default:
104*81ad6265SDimitry Andric       break;
105*81ad6265SDimitry Andric     }
10604eeddc0SDimitry Andric   }
10704eeddc0SDimitry Andric 
10804eeddc0SDimitry Andric   void VisitDeclRefExpr(const DeclRefExpr *S) {
10904eeddc0SDimitry Andric     assert(S->getDecl() != nullptr);
11004eeddc0SDimitry Andric     auto *DeclLoc = Env.getStorageLocation(*S->getDecl(), SkipPast::None);
11104eeddc0SDimitry Andric     if (DeclLoc == nullptr)
11204eeddc0SDimitry Andric       return;
11304eeddc0SDimitry Andric 
11404eeddc0SDimitry Andric     if (S->getDecl()->getType()->isReferenceType()) {
11504eeddc0SDimitry Andric       Env.setStorageLocation(*S, *DeclLoc);
11604eeddc0SDimitry Andric     } else {
11704eeddc0SDimitry Andric       auto &Loc = Env.createStorageLocation(*S);
11804eeddc0SDimitry Andric       auto &Val = Env.takeOwnership(std::make_unique<ReferenceValue>(*DeclLoc));
11904eeddc0SDimitry Andric       Env.setStorageLocation(*S, Loc);
12004eeddc0SDimitry Andric       Env.setValue(Loc, Val);
12104eeddc0SDimitry Andric     }
12204eeddc0SDimitry Andric   }
12304eeddc0SDimitry Andric 
12404eeddc0SDimitry Andric   void VisitDeclStmt(const DeclStmt *S) {
12504eeddc0SDimitry Andric     // Group decls are converted into single decls in the CFG so the cast below
12604eeddc0SDimitry Andric     // is safe.
12704eeddc0SDimitry Andric     const auto &D = *cast<VarDecl>(S->getSingleDecl());
128*81ad6265SDimitry Andric 
129*81ad6265SDimitry Andric     // Static local vars are already initialized in `Environment`.
130*81ad6265SDimitry Andric     if (D.hasGlobalStorage())
131*81ad6265SDimitry Andric       return;
132*81ad6265SDimitry Andric 
13304eeddc0SDimitry Andric     auto &Loc = Env.createStorageLocation(D);
13404eeddc0SDimitry Andric     Env.setStorageLocation(D, Loc);
13504eeddc0SDimitry Andric 
13604eeddc0SDimitry Andric     const Expr *InitExpr = D.getInit();
13704eeddc0SDimitry Andric     if (InitExpr == nullptr) {
13804eeddc0SDimitry Andric       // No initializer expression - associate `Loc` with a new value.
13904eeddc0SDimitry Andric       if (Value *Val = Env.createValue(D.getType()))
14004eeddc0SDimitry Andric         Env.setValue(Loc, *Val);
14104eeddc0SDimitry Andric       return;
14204eeddc0SDimitry Andric     }
14304eeddc0SDimitry Andric 
14404eeddc0SDimitry Andric     if (D.getType()->isReferenceType()) {
14504eeddc0SDimitry Andric       // Initializing a reference variable - do not create a reference to
14604eeddc0SDimitry Andric       // reference.
14704eeddc0SDimitry Andric       if (auto *InitExprLoc =
14804eeddc0SDimitry Andric               Env.getStorageLocation(*InitExpr, SkipPast::Reference)) {
14904eeddc0SDimitry Andric         auto &Val =
15004eeddc0SDimitry Andric             Env.takeOwnership(std::make_unique<ReferenceValue>(*InitExprLoc));
15104eeddc0SDimitry Andric         Env.setValue(Loc, Val);
15204eeddc0SDimitry Andric       }
153*81ad6265SDimitry Andric     } else if (auto *InitExprVal = Env.getValue(*InitExpr, SkipPast::None)) {
154*81ad6265SDimitry Andric       Env.setValue(Loc, *InitExprVal);
15504eeddc0SDimitry Andric     }
15604eeddc0SDimitry Andric 
157*81ad6265SDimitry Andric     if (Env.getValue(Loc) == nullptr) {
158*81ad6265SDimitry Andric       // We arrive here in (the few) cases where an expression is intentionally
159*81ad6265SDimitry Andric       // "uninterpreted". There are two ways to handle this situation: propagate
160*81ad6265SDimitry Andric       // the status, so that uninterpreted initializers result in uninterpreted
161*81ad6265SDimitry Andric       // variables, or provide a default value. We choose the latter so that
162*81ad6265SDimitry Andric       // later refinements of the variable can be used for reasoning about the
163*81ad6265SDimitry Andric       // surrounding code.
164*81ad6265SDimitry Andric       //
165*81ad6265SDimitry Andric       // FIXME. If and when we interpret all language cases, change this to
166*81ad6265SDimitry Andric       // assert that `InitExpr` is interpreted, rather than supplying a default
167*81ad6265SDimitry Andric       // value (assuming we don't update the environment API to return
168*81ad6265SDimitry Andric       // references).
16904eeddc0SDimitry Andric       if (Value *Val = Env.createValue(D.getType()))
17004eeddc0SDimitry Andric         Env.setValue(Loc, *Val);
171*81ad6265SDimitry Andric     }
172*81ad6265SDimitry Andric 
173*81ad6265SDimitry Andric     if (const auto *Decomp = dyn_cast<DecompositionDecl>(&D)) {
174*81ad6265SDimitry Andric       // If VarDecl is a DecompositionDecl, evaluate each of its bindings. This
175*81ad6265SDimitry Andric       // needs to be evaluated after initializing the values in the storage for
176*81ad6265SDimitry Andric       // VarDecl, as the bindings refer to them.
177*81ad6265SDimitry Andric       // FIXME: Add support for ArraySubscriptExpr.
178*81ad6265SDimitry Andric       // FIXME: Consider adding AST nodes that are used for structured bindings
179*81ad6265SDimitry Andric       // to the CFG.
180*81ad6265SDimitry Andric       for (const auto *B : Decomp->bindings()) {
181*81ad6265SDimitry Andric         auto *ME = dyn_cast_or_null<MemberExpr>(B->getBinding());
182*81ad6265SDimitry Andric         if (ME == nullptr)
183*81ad6265SDimitry Andric           continue;
184*81ad6265SDimitry Andric 
185*81ad6265SDimitry Andric         auto *DE = dyn_cast_or_null<DeclRefExpr>(ME->getBase());
186*81ad6265SDimitry Andric         if (DE == nullptr)
187*81ad6265SDimitry Andric           continue;
188*81ad6265SDimitry Andric 
189*81ad6265SDimitry Andric         // ME and its base haven't been visited because they aren't included in
190*81ad6265SDimitry Andric         // the statements of the CFG basic block.
191*81ad6265SDimitry Andric         VisitDeclRefExpr(DE);
192*81ad6265SDimitry Andric         VisitMemberExpr(ME);
193*81ad6265SDimitry Andric 
194*81ad6265SDimitry Andric         if (auto *Loc = Env.getStorageLocation(*ME, SkipPast::Reference))
195*81ad6265SDimitry Andric           Env.setStorageLocation(*B, *Loc);
196*81ad6265SDimitry Andric       }
19704eeddc0SDimitry Andric     }
19804eeddc0SDimitry Andric   }
19904eeddc0SDimitry Andric 
20004eeddc0SDimitry Andric   void VisitImplicitCastExpr(const ImplicitCastExpr *S) {
201*81ad6265SDimitry Andric     const Expr *SubExpr = S->getSubExpr();
20204eeddc0SDimitry Andric     assert(SubExpr != nullptr);
20304eeddc0SDimitry Andric 
20404eeddc0SDimitry Andric     switch (S->getCastKind()) {
205*81ad6265SDimitry Andric     case CK_IntegralToBoolean: {
206*81ad6265SDimitry Andric       // This cast creates a new, boolean value from the integral value. We
207*81ad6265SDimitry Andric       // model that with a fresh value in the environment, unless it's already a
208*81ad6265SDimitry Andric       // boolean.
209*81ad6265SDimitry Andric       auto &Loc = Env.createStorageLocation(*S);
210*81ad6265SDimitry Andric       Env.setStorageLocation(*S, Loc);
211*81ad6265SDimitry Andric       if (auto *SubExprVal = dyn_cast_or_null<BoolValue>(
212*81ad6265SDimitry Andric               Env.getValue(*SubExpr, SkipPast::Reference)))
213*81ad6265SDimitry Andric         Env.setValue(Loc, *SubExprVal);
214*81ad6265SDimitry Andric       else
215*81ad6265SDimitry Andric         // FIXME: If integer modeling is added, then update this code to create
216*81ad6265SDimitry Andric         // the boolean based on the integer model.
217*81ad6265SDimitry Andric         Env.setValue(Loc, Env.makeAtomicBoolValue());
218*81ad6265SDimitry Andric       break;
219*81ad6265SDimitry Andric     }
220*81ad6265SDimitry Andric 
22104eeddc0SDimitry Andric     case CK_LValueToRValue: {
22204eeddc0SDimitry Andric       auto *SubExprVal = Env.getValue(*SubExpr, SkipPast::Reference);
22304eeddc0SDimitry Andric       if (SubExprVal == nullptr)
22404eeddc0SDimitry Andric         break;
22504eeddc0SDimitry Andric 
22604eeddc0SDimitry Andric       auto &ExprLoc = Env.createStorageLocation(*S);
22704eeddc0SDimitry Andric       Env.setStorageLocation(*S, ExprLoc);
22804eeddc0SDimitry Andric       Env.setValue(ExprLoc, *SubExprVal);
22904eeddc0SDimitry Andric       break;
23004eeddc0SDimitry Andric     }
231*81ad6265SDimitry Andric 
232*81ad6265SDimitry Andric     case CK_IntegralCast:
233*81ad6265SDimitry Andric       // FIXME: This cast creates a new integral value from the
234*81ad6265SDimitry Andric       // subexpression. But, because we don't model integers, we don't
235*81ad6265SDimitry Andric       // distinguish between this new value and the underlying one. If integer
236*81ad6265SDimitry Andric       // modeling is added, then update this code to create a fresh location and
237*81ad6265SDimitry Andric       // value.
238*81ad6265SDimitry Andric     case CK_UncheckedDerivedToBase:
239*81ad6265SDimitry Andric     case CK_ConstructorConversion:
240*81ad6265SDimitry Andric     case CK_UserDefinedConversion:
241*81ad6265SDimitry Andric       // FIXME: Add tests that excercise CK_UncheckedDerivedToBase,
242*81ad6265SDimitry Andric       // CK_ConstructorConversion, and CK_UserDefinedConversion.
24304eeddc0SDimitry Andric     case CK_NoOp: {
24404eeddc0SDimitry Andric       // FIXME: Consider making `Environment::getStorageLocation` skip noop
24504eeddc0SDimitry Andric       // expressions (this and other similar expressions in the file) instead of
24604eeddc0SDimitry Andric       // assigning them storage locations.
24704eeddc0SDimitry Andric       auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
24804eeddc0SDimitry Andric       if (SubExprLoc == nullptr)
24904eeddc0SDimitry Andric         break;
25004eeddc0SDimitry Andric 
25104eeddc0SDimitry Andric       Env.setStorageLocation(*S, *SubExprLoc);
25204eeddc0SDimitry Andric       break;
25304eeddc0SDimitry Andric     }
254*81ad6265SDimitry Andric     case CK_NullToPointer:
255*81ad6265SDimitry Andric     case CK_NullToMemberPointer: {
256*81ad6265SDimitry Andric       auto &Loc = Env.createStorageLocation(S->getType());
257*81ad6265SDimitry Andric       Env.setStorageLocation(*S, Loc);
258*81ad6265SDimitry Andric 
259*81ad6265SDimitry Andric       auto &NullPointerVal =
260*81ad6265SDimitry Andric           Env.getOrCreateNullPointerValue(S->getType()->getPointeeType());
261*81ad6265SDimitry Andric       Env.setValue(Loc, NullPointerVal);
262*81ad6265SDimitry Andric       break;
263*81ad6265SDimitry Andric     }
26404eeddc0SDimitry Andric     default:
26504eeddc0SDimitry Andric       break;
26604eeddc0SDimitry Andric     }
26704eeddc0SDimitry Andric   }
26804eeddc0SDimitry Andric 
26904eeddc0SDimitry Andric   void VisitUnaryOperator(const UnaryOperator *S) {
270*81ad6265SDimitry Andric     const Expr *SubExpr = S->getSubExpr();
27104eeddc0SDimitry Andric     assert(SubExpr != nullptr);
27204eeddc0SDimitry Andric 
27304eeddc0SDimitry Andric     switch (S->getOpcode()) {
27404eeddc0SDimitry Andric     case UO_Deref: {
27504eeddc0SDimitry Andric       // Skip past a reference to handle dereference of a dependent pointer.
27604eeddc0SDimitry Andric       const auto *SubExprVal = cast_or_null<PointerValue>(
27704eeddc0SDimitry Andric           Env.getValue(*SubExpr, SkipPast::Reference));
27804eeddc0SDimitry Andric       if (SubExprVal == nullptr)
27904eeddc0SDimitry Andric         break;
28004eeddc0SDimitry Andric 
28104eeddc0SDimitry Andric       auto &Loc = Env.createStorageLocation(*S);
28204eeddc0SDimitry Andric       Env.setStorageLocation(*S, Loc);
28304eeddc0SDimitry Andric       Env.setValue(Loc, Env.takeOwnership(std::make_unique<ReferenceValue>(
28404eeddc0SDimitry Andric                             SubExprVal->getPointeeLoc())));
28504eeddc0SDimitry Andric       break;
28604eeddc0SDimitry Andric     }
28704eeddc0SDimitry Andric     case UO_AddrOf: {
28804eeddc0SDimitry Andric       // Do not form a pointer to a reference. If `SubExpr` is assigned a
28904eeddc0SDimitry Andric       // `ReferenceValue` then form a value that points to the location of its
29004eeddc0SDimitry Andric       // pointee.
29104eeddc0SDimitry Andric       StorageLocation *PointeeLoc =
29204eeddc0SDimitry Andric           Env.getStorageLocation(*SubExpr, SkipPast::Reference);
29304eeddc0SDimitry Andric       if (PointeeLoc == nullptr)
29404eeddc0SDimitry Andric         break;
29504eeddc0SDimitry Andric 
29604eeddc0SDimitry Andric       auto &PointerLoc = Env.createStorageLocation(*S);
29704eeddc0SDimitry Andric       auto &PointerVal =
29804eeddc0SDimitry Andric           Env.takeOwnership(std::make_unique<PointerValue>(*PointeeLoc));
29904eeddc0SDimitry Andric       Env.setStorageLocation(*S, PointerLoc);
30004eeddc0SDimitry Andric       Env.setValue(PointerLoc, PointerVal);
30104eeddc0SDimitry Andric       break;
30204eeddc0SDimitry Andric     }
303*81ad6265SDimitry Andric     case UO_LNot: {
304*81ad6265SDimitry Andric       auto *SubExprVal =
305*81ad6265SDimitry Andric           dyn_cast_or_null<BoolValue>(Env.getValue(*SubExpr, SkipPast::None));
306*81ad6265SDimitry Andric       if (SubExprVal == nullptr)
307*81ad6265SDimitry Andric         break;
308*81ad6265SDimitry Andric 
309*81ad6265SDimitry Andric       auto &ExprLoc = Env.createStorageLocation(*S);
310*81ad6265SDimitry Andric       Env.setStorageLocation(*S, ExprLoc);
311*81ad6265SDimitry Andric       Env.setValue(ExprLoc, Env.makeNot(*SubExprVal));
312*81ad6265SDimitry Andric       break;
313*81ad6265SDimitry Andric     }
31404eeddc0SDimitry Andric     default:
31504eeddc0SDimitry Andric       break;
31604eeddc0SDimitry Andric     }
31704eeddc0SDimitry Andric   }
31804eeddc0SDimitry Andric 
31904eeddc0SDimitry Andric   void VisitCXXThisExpr(const CXXThisExpr *S) {
32004eeddc0SDimitry Andric     auto *ThisPointeeLoc = Env.getThisPointeeStorageLocation();
321*81ad6265SDimitry Andric     if (ThisPointeeLoc == nullptr)
322*81ad6265SDimitry Andric       // Unions are not supported yet, and will not have a location for the
323*81ad6265SDimitry Andric       // `this` expression's pointee.
324*81ad6265SDimitry Andric       return;
32504eeddc0SDimitry Andric 
32604eeddc0SDimitry Andric     auto &Loc = Env.createStorageLocation(*S);
32704eeddc0SDimitry Andric     Env.setStorageLocation(*S, Loc);
32804eeddc0SDimitry Andric     Env.setValue(Loc, Env.takeOwnership(
32904eeddc0SDimitry Andric                           std::make_unique<PointerValue>(*ThisPointeeLoc)));
33004eeddc0SDimitry Andric   }
33104eeddc0SDimitry Andric 
33204eeddc0SDimitry Andric   void VisitMemberExpr(const MemberExpr *S) {
33304eeddc0SDimitry Andric     ValueDecl *Member = S->getMemberDecl();
33404eeddc0SDimitry Andric     assert(Member != nullptr);
33504eeddc0SDimitry Andric 
33604eeddc0SDimitry Andric     // FIXME: Consider assigning pointer values to function member expressions.
33704eeddc0SDimitry Andric     if (Member->isFunctionOrFunctionTemplate())
33804eeddc0SDimitry Andric       return;
33904eeddc0SDimitry Andric 
340*81ad6265SDimitry Andric     if (auto *D = dyn_cast<VarDecl>(Member)) {
341*81ad6265SDimitry Andric       if (D->hasGlobalStorage()) {
342*81ad6265SDimitry Andric         auto *VarDeclLoc = Env.getStorageLocation(*D, SkipPast::None);
343*81ad6265SDimitry Andric         if (VarDeclLoc == nullptr)
344*81ad6265SDimitry Andric           return;
345*81ad6265SDimitry Andric 
346*81ad6265SDimitry Andric         if (VarDeclLoc->getType()->isReferenceType()) {
347*81ad6265SDimitry Andric           Env.setStorageLocation(*S, *VarDeclLoc);
348*81ad6265SDimitry Andric         } else {
349*81ad6265SDimitry Andric           auto &Loc = Env.createStorageLocation(*S);
350*81ad6265SDimitry Andric           Env.setStorageLocation(*S, Loc);
351*81ad6265SDimitry Andric           Env.setValue(Loc, Env.takeOwnership(
352*81ad6265SDimitry Andric                                 std::make_unique<ReferenceValue>(*VarDeclLoc)));
353*81ad6265SDimitry Andric         }
354*81ad6265SDimitry Andric         return;
355*81ad6265SDimitry Andric       }
356*81ad6265SDimitry Andric     }
357*81ad6265SDimitry Andric 
35804eeddc0SDimitry Andric     // The receiver can be either a value or a pointer to a value. Skip past the
35904eeddc0SDimitry Andric     // indirection to handle both cases.
36004eeddc0SDimitry Andric     auto *BaseLoc = cast_or_null<AggregateStorageLocation>(
36104eeddc0SDimitry Andric         Env.getStorageLocation(*S->getBase(), SkipPast::ReferenceThenPointer));
36204eeddc0SDimitry Andric     if (BaseLoc == nullptr)
36304eeddc0SDimitry Andric       return;
36404eeddc0SDimitry Andric 
36504eeddc0SDimitry Andric     // FIXME: Add support for union types.
36604eeddc0SDimitry Andric     if (BaseLoc->getType()->isUnionType())
36704eeddc0SDimitry Andric       return;
36804eeddc0SDimitry Andric 
36904eeddc0SDimitry Andric     auto &MemberLoc = BaseLoc->getChild(*Member);
37004eeddc0SDimitry Andric     if (MemberLoc.getType()->isReferenceType()) {
37104eeddc0SDimitry Andric       Env.setStorageLocation(*S, MemberLoc);
37204eeddc0SDimitry Andric     } else {
37304eeddc0SDimitry Andric       auto &Loc = Env.createStorageLocation(*S);
37404eeddc0SDimitry Andric       Env.setStorageLocation(*S, Loc);
37504eeddc0SDimitry Andric       Env.setValue(
37604eeddc0SDimitry Andric           Loc, Env.takeOwnership(std::make_unique<ReferenceValue>(MemberLoc)));
37704eeddc0SDimitry Andric     }
37804eeddc0SDimitry Andric   }
37904eeddc0SDimitry Andric 
38004eeddc0SDimitry Andric   void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *S) {
38104eeddc0SDimitry Andric     const Expr *InitExpr = S->getExpr();
38204eeddc0SDimitry Andric     assert(InitExpr != nullptr);
38304eeddc0SDimitry Andric 
38404eeddc0SDimitry Andric     Value *InitExprVal = Env.getValue(*InitExpr, SkipPast::None);
38504eeddc0SDimitry Andric     if (InitExprVal == nullptr)
38604eeddc0SDimitry Andric       return;
38704eeddc0SDimitry Andric 
38804eeddc0SDimitry Andric     const FieldDecl *Field = S->getField();
38904eeddc0SDimitry Andric     assert(Field != nullptr);
39004eeddc0SDimitry Andric 
39104eeddc0SDimitry Andric     auto &ThisLoc =
39204eeddc0SDimitry Andric         *cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation());
39304eeddc0SDimitry Andric     auto &FieldLoc = ThisLoc.getChild(*Field);
39404eeddc0SDimitry Andric     Env.setValue(FieldLoc, *InitExprVal);
39504eeddc0SDimitry Andric   }
39604eeddc0SDimitry Andric 
39704eeddc0SDimitry Andric   void VisitCXXConstructExpr(const CXXConstructExpr *S) {
39804eeddc0SDimitry Andric     const CXXConstructorDecl *ConstructorDecl = S->getConstructor();
39904eeddc0SDimitry Andric     assert(ConstructorDecl != nullptr);
40004eeddc0SDimitry Andric 
40104eeddc0SDimitry Andric     if (ConstructorDecl->isCopyOrMoveConstructor()) {
40204eeddc0SDimitry Andric       assert(S->getNumArgs() == 1);
40304eeddc0SDimitry Andric 
40404eeddc0SDimitry Andric       const Expr *Arg = S->getArg(0);
40504eeddc0SDimitry Andric       assert(Arg != nullptr);
40604eeddc0SDimitry Andric 
40704eeddc0SDimitry Andric       if (S->isElidable()) {
40804eeddc0SDimitry Andric         auto *ArgLoc = Env.getStorageLocation(*Arg, SkipPast::Reference);
40904eeddc0SDimitry Andric         if (ArgLoc == nullptr)
41004eeddc0SDimitry Andric           return;
41104eeddc0SDimitry Andric 
41204eeddc0SDimitry Andric         Env.setStorageLocation(*S, *ArgLoc);
41304eeddc0SDimitry Andric       } else if (auto *ArgVal = Env.getValue(*Arg, SkipPast::Reference)) {
41404eeddc0SDimitry Andric         auto &Loc = Env.createStorageLocation(*S);
41504eeddc0SDimitry Andric         Env.setStorageLocation(*S, Loc);
41604eeddc0SDimitry Andric         Env.setValue(Loc, *ArgVal);
41704eeddc0SDimitry Andric       }
41804eeddc0SDimitry Andric       return;
41904eeddc0SDimitry Andric     }
42004eeddc0SDimitry Andric 
42104eeddc0SDimitry Andric     auto &Loc = Env.createStorageLocation(*S);
42204eeddc0SDimitry Andric     Env.setStorageLocation(*S, Loc);
42304eeddc0SDimitry Andric     if (Value *Val = Env.createValue(S->getType()))
42404eeddc0SDimitry Andric       Env.setValue(Loc, *Val);
42504eeddc0SDimitry Andric   }
42604eeddc0SDimitry Andric 
42704eeddc0SDimitry Andric   void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) {
42804eeddc0SDimitry Andric     if (S->getOperator() == OO_Equal) {
42904eeddc0SDimitry Andric       assert(S->getNumArgs() == 2);
43004eeddc0SDimitry Andric 
43104eeddc0SDimitry Andric       const Expr *Arg0 = S->getArg(0);
43204eeddc0SDimitry Andric       assert(Arg0 != nullptr);
43304eeddc0SDimitry Andric 
43404eeddc0SDimitry Andric       const Expr *Arg1 = S->getArg(1);
43504eeddc0SDimitry Andric       assert(Arg1 != nullptr);
43604eeddc0SDimitry Andric 
43704eeddc0SDimitry Andric       // Evaluate only copy and move assignment operators.
43804eeddc0SDimitry Andric       auto *Arg0Type = Arg0->getType()->getUnqualifiedDesugaredType();
43904eeddc0SDimitry Andric       auto *Arg1Type = Arg1->getType()->getUnqualifiedDesugaredType();
44004eeddc0SDimitry Andric       if (Arg0Type != Arg1Type)
44104eeddc0SDimitry Andric         return;
44204eeddc0SDimitry Andric 
44304eeddc0SDimitry Andric       auto *ObjectLoc = Env.getStorageLocation(*Arg0, SkipPast::Reference);
44404eeddc0SDimitry Andric       if (ObjectLoc == nullptr)
44504eeddc0SDimitry Andric         return;
44604eeddc0SDimitry Andric 
44704eeddc0SDimitry Andric       auto *Val = Env.getValue(*Arg1, SkipPast::Reference);
44804eeddc0SDimitry Andric       if (Val == nullptr)
44904eeddc0SDimitry Andric         return;
45004eeddc0SDimitry Andric 
451*81ad6265SDimitry Andric       // Assign a value to the storage location of the object.
45204eeddc0SDimitry Andric       Env.setValue(*ObjectLoc, *Val);
453*81ad6265SDimitry Andric 
454*81ad6265SDimitry Andric       // FIXME: Add a test for the value of the whole expression.
455*81ad6265SDimitry Andric       // Assign a storage location for the whole expression.
456*81ad6265SDimitry Andric       Env.setStorageLocation(*S, *ObjectLoc);
45704eeddc0SDimitry Andric     }
45804eeddc0SDimitry Andric   }
45904eeddc0SDimitry Andric 
46004eeddc0SDimitry Andric   void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *S) {
46104eeddc0SDimitry Andric     if (S->getCastKind() == CK_ConstructorConversion) {
46204eeddc0SDimitry Andric       const Expr *SubExpr = S->getSubExpr();
46304eeddc0SDimitry Andric       assert(SubExpr != nullptr);
46404eeddc0SDimitry Andric 
46504eeddc0SDimitry Andric       auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
46604eeddc0SDimitry Andric       if (SubExprLoc == nullptr)
46704eeddc0SDimitry Andric         return;
46804eeddc0SDimitry Andric 
46904eeddc0SDimitry Andric       Env.setStorageLocation(*S, *SubExprLoc);
47004eeddc0SDimitry Andric     }
47104eeddc0SDimitry Andric   }
47204eeddc0SDimitry Andric 
47304eeddc0SDimitry Andric   void VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *S) {
47404eeddc0SDimitry Andric     auto &Loc = Env.createStorageLocation(*S);
47504eeddc0SDimitry Andric     Env.setStorageLocation(*S, Loc);
47604eeddc0SDimitry Andric     if (Value *Val = Env.createValue(S->getType()))
47704eeddc0SDimitry Andric       Env.setValue(Loc, *Val);
47804eeddc0SDimitry Andric   }
47904eeddc0SDimitry Andric 
48004eeddc0SDimitry Andric   void VisitCallExpr(const CallExpr *S) {
481*81ad6265SDimitry Andric     // Of clang's builtins, only `__builtin_expect` is handled explicitly, since
482*81ad6265SDimitry Andric     // others (like trap, debugtrap, and unreachable) are handled by CFG
483*81ad6265SDimitry Andric     // construction.
48404eeddc0SDimitry Andric     if (S->isCallToStdMove()) {
48504eeddc0SDimitry Andric       assert(S->getNumArgs() == 1);
48604eeddc0SDimitry Andric 
48704eeddc0SDimitry Andric       const Expr *Arg = S->getArg(0);
48804eeddc0SDimitry Andric       assert(Arg != nullptr);
48904eeddc0SDimitry Andric 
49004eeddc0SDimitry Andric       auto *ArgLoc = Env.getStorageLocation(*Arg, SkipPast::None);
49104eeddc0SDimitry Andric       if (ArgLoc == nullptr)
49204eeddc0SDimitry Andric         return;
49304eeddc0SDimitry Andric 
49404eeddc0SDimitry Andric       Env.setStorageLocation(*S, *ArgLoc);
495*81ad6265SDimitry Andric     } else if (S->getDirectCallee() != nullptr &&
496*81ad6265SDimitry Andric                S->getDirectCallee()->getBuiltinID() ==
497*81ad6265SDimitry Andric                    Builtin::BI__builtin_expect) {
498*81ad6265SDimitry Andric       assert(S->getNumArgs() > 0);
499*81ad6265SDimitry Andric       assert(S->getArg(0) != nullptr);
500*81ad6265SDimitry Andric       // `__builtin_expect` returns by-value, so strip away any potential
501*81ad6265SDimitry Andric       // references in the argument.
502*81ad6265SDimitry Andric       auto *ArgLoc = Env.getStorageLocation(*S->getArg(0), SkipPast::Reference);
503*81ad6265SDimitry Andric       if (ArgLoc == nullptr)
504*81ad6265SDimitry Andric         return;
505*81ad6265SDimitry Andric       Env.setStorageLocation(*S, *ArgLoc);
50604eeddc0SDimitry Andric     }
50704eeddc0SDimitry Andric   }
50804eeddc0SDimitry Andric 
50904eeddc0SDimitry Andric   void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *S) {
51004eeddc0SDimitry Andric     const Expr *SubExpr = S->getSubExpr();
51104eeddc0SDimitry Andric     assert(SubExpr != nullptr);
51204eeddc0SDimitry Andric 
51304eeddc0SDimitry Andric     auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
51404eeddc0SDimitry Andric     if (SubExprLoc == nullptr)
51504eeddc0SDimitry Andric       return;
51604eeddc0SDimitry Andric 
51704eeddc0SDimitry Andric     Env.setStorageLocation(*S, *SubExprLoc);
51804eeddc0SDimitry Andric   }
51904eeddc0SDimitry Andric 
52004eeddc0SDimitry Andric   void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *S) {
52104eeddc0SDimitry Andric     const Expr *SubExpr = S->getSubExpr();
52204eeddc0SDimitry Andric     assert(SubExpr != nullptr);
52304eeddc0SDimitry Andric 
52404eeddc0SDimitry Andric     auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
52504eeddc0SDimitry Andric     if (SubExprLoc == nullptr)
52604eeddc0SDimitry Andric       return;
52704eeddc0SDimitry Andric 
52804eeddc0SDimitry Andric     Env.setStorageLocation(*S, *SubExprLoc);
52904eeddc0SDimitry Andric   }
53004eeddc0SDimitry Andric 
53104eeddc0SDimitry Andric   void VisitCXXStaticCastExpr(const CXXStaticCastExpr *S) {
53204eeddc0SDimitry Andric     if (S->getCastKind() == CK_NoOp) {
53304eeddc0SDimitry Andric       const Expr *SubExpr = S->getSubExpr();
53404eeddc0SDimitry Andric       assert(SubExpr != nullptr);
53504eeddc0SDimitry Andric 
53604eeddc0SDimitry Andric       auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
53704eeddc0SDimitry Andric       if (SubExprLoc == nullptr)
53804eeddc0SDimitry Andric         return;
53904eeddc0SDimitry Andric 
54004eeddc0SDimitry Andric       Env.setStorageLocation(*S, *SubExprLoc);
54104eeddc0SDimitry Andric     }
54204eeddc0SDimitry Andric   }
54304eeddc0SDimitry Andric 
54404eeddc0SDimitry Andric   void VisitConditionalOperator(const ConditionalOperator *S) {
54504eeddc0SDimitry Andric     // FIXME: Revisit this once flow conditions are added to the framework. For
54604eeddc0SDimitry Andric     // `a = b ? c : d` we can add `b => a == c && !b => a == d` to the flow
54704eeddc0SDimitry Andric     // condition.
54804eeddc0SDimitry Andric     auto &Loc = Env.createStorageLocation(*S);
54904eeddc0SDimitry Andric     Env.setStorageLocation(*S, Loc);
55004eeddc0SDimitry Andric     if (Value *Val = Env.createValue(S->getType()))
55104eeddc0SDimitry Andric       Env.setValue(Loc, *Val);
55204eeddc0SDimitry Andric   }
55304eeddc0SDimitry Andric 
55404eeddc0SDimitry Andric   void VisitInitListExpr(const InitListExpr *S) {
55504eeddc0SDimitry Andric     QualType Type = S->getType();
55604eeddc0SDimitry Andric 
55704eeddc0SDimitry Andric     auto &Loc = Env.createStorageLocation(*S);
55804eeddc0SDimitry Andric     Env.setStorageLocation(*S, Loc);
55904eeddc0SDimitry Andric 
56004eeddc0SDimitry Andric     auto *Val = Env.createValue(Type);
56104eeddc0SDimitry Andric     if (Val == nullptr)
56204eeddc0SDimitry Andric       return;
56304eeddc0SDimitry Andric 
56404eeddc0SDimitry Andric     Env.setValue(Loc, *Val);
56504eeddc0SDimitry Andric 
56604eeddc0SDimitry Andric     if (Type->isStructureOrClassType()) {
56704eeddc0SDimitry Andric       for (auto IT : llvm::zip(Type->getAsRecordDecl()->fields(), S->inits())) {
56804eeddc0SDimitry Andric         const FieldDecl *Field = std::get<0>(IT);
56904eeddc0SDimitry Andric         assert(Field != nullptr);
57004eeddc0SDimitry Andric 
57104eeddc0SDimitry Andric         const Expr *Init = std::get<1>(IT);
57204eeddc0SDimitry Andric         assert(Init != nullptr);
57304eeddc0SDimitry Andric 
57404eeddc0SDimitry Andric         if (Value *InitVal = Env.getValue(*Init, SkipPast::None))
57504eeddc0SDimitry Andric           cast<StructValue>(Val)->setChild(*Field, *InitVal);
57604eeddc0SDimitry Andric       }
57704eeddc0SDimitry Andric     }
57804eeddc0SDimitry Andric     // FIXME: Implement array initialization.
57904eeddc0SDimitry Andric   }
58004eeddc0SDimitry Andric 
58104eeddc0SDimitry Andric   void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *S) {
58204eeddc0SDimitry Andric     auto &Loc = Env.createStorageLocation(*S);
58304eeddc0SDimitry Andric     Env.setStorageLocation(*S, Loc);
58404eeddc0SDimitry Andric     Env.setValue(Loc, Env.getBoolLiteralValue(S->getValue()));
58504eeddc0SDimitry Andric   }
58604eeddc0SDimitry Andric 
587*81ad6265SDimitry Andric   void VisitParenExpr(const ParenExpr *S) {
588*81ad6265SDimitry Andric     // The CFG does not contain `ParenExpr` as top-level statements in basic
589*81ad6265SDimitry Andric     // blocks, however manual traversal to sub-expressions may encounter them.
590*81ad6265SDimitry Andric     // Redirect to the sub-expression.
591*81ad6265SDimitry Andric     auto *SubExpr = S->getSubExpr();
592*81ad6265SDimitry Andric     assert(SubExpr != nullptr);
593*81ad6265SDimitry Andric     Visit(SubExpr);
594*81ad6265SDimitry Andric   }
595*81ad6265SDimitry Andric 
596*81ad6265SDimitry Andric   void VisitExprWithCleanups(const ExprWithCleanups *S) {
597*81ad6265SDimitry Andric     // The CFG does not contain `ExprWithCleanups` as top-level statements in
598*81ad6265SDimitry Andric     // basic blocks, however manual traversal to sub-expressions may encounter
599*81ad6265SDimitry Andric     // them. Redirect to the sub-expression.
600*81ad6265SDimitry Andric     auto *SubExpr = S->getSubExpr();
601*81ad6265SDimitry Andric     assert(SubExpr != nullptr);
602*81ad6265SDimitry Andric     Visit(SubExpr);
603*81ad6265SDimitry Andric   }
604*81ad6265SDimitry Andric 
60504eeddc0SDimitry Andric private:
606*81ad6265SDimitry Andric   BoolValue &getLogicOperatorSubExprValue(const Expr &SubExpr) {
607*81ad6265SDimitry Andric     // `SubExpr` and its parent logic operator might be part of different basic
608*81ad6265SDimitry Andric     // blocks. We try to access the value that is assigned to `SubExpr` in the
609*81ad6265SDimitry Andric     // corresponding environment.
610*81ad6265SDimitry Andric     if (const Environment *SubExprEnv = StmtToEnv.getEnvironment(SubExpr)) {
611*81ad6265SDimitry Andric       if (auto *Val = dyn_cast_or_null<BoolValue>(
612*81ad6265SDimitry Andric               SubExprEnv->getValue(SubExpr, SkipPast::Reference)))
613*81ad6265SDimitry Andric         return *Val;
614*81ad6265SDimitry Andric     }
615*81ad6265SDimitry Andric 
616*81ad6265SDimitry Andric     if (Env.getStorageLocation(SubExpr, SkipPast::None) == nullptr) {
617*81ad6265SDimitry Andric       // Sub-expressions that are logic operators are not added in basic blocks
618*81ad6265SDimitry Andric       // (e.g. see CFG for `bool d = a && (b || c);`). If `SubExpr` is a logic
619*81ad6265SDimitry Andric       // operator, it may not have been evaluated and assigned a value yet. In
620*81ad6265SDimitry Andric       // that case, we need to first visit `SubExpr` and then try to get the
621*81ad6265SDimitry Andric       // value that gets assigned to it.
622*81ad6265SDimitry Andric       Visit(&SubExpr);
623*81ad6265SDimitry Andric     }
624*81ad6265SDimitry Andric 
625*81ad6265SDimitry Andric     if (auto *Val = dyn_cast_or_null<BoolValue>(
626*81ad6265SDimitry Andric             Env.getValue(SubExpr, SkipPast::Reference)))
627*81ad6265SDimitry Andric       return *Val;
628*81ad6265SDimitry Andric 
629*81ad6265SDimitry Andric     // If the value of `SubExpr` is still unknown, we create a fresh symbolic
630*81ad6265SDimitry Andric     // boolean value for it.
631*81ad6265SDimitry Andric     return Env.makeAtomicBoolValue();
632*81ad6265SDimitry Andric   }
633*81ad6265SDimitry Andric 
634*81ad6265SDimitry Andric   const StmtToEnvMap &StmtToEnv;
63504eeddc0SDimitry Andric   Environment &Env;
63604eeddc0SDimitry Andric };
63704eeddc0SDimitry Andric 
638*81ad6265SDimitry Andric void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env) {
639*81ad6265SDimitry Andric   TransferVisitor(StmtToEnv, Env).Visit(&S);
64004eeddc0SDimitry Andric }
64104eeddc0SDimitry Andric 
64204eeddc0SDimitry Andric } // namespace dataflow
64304eeddc0SDimitry Andric } // namespace clang
644