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