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