1a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek//== BodyFarm.cpp - Factory for conjuring up fake bodies ----------*- C++ -*-// 2a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek// 3a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek// The LLVM Compiler Infrastructure 4a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek// 5a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek// This file is distributed under the University of Illinois Open Source 6a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek// License. See LICENSE.TXT for details. 7a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek// 8a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek//===----------------------------------------------------------------------===// 9a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek// 10a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek// BodyFarm is a factory for creating faux implementations for functions/methods 11a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek// for analysis purposes. 12a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek// 13a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek//===----------------------------------------------------------------------===// 14a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 1555fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "BodyFarm.h" 16a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek#include "clang/AST/ASTContext.h" 17a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek#include "clang/AST/Decl.h" 1855fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/AST/Expr.h" 1948fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek#include "clang/AST/ExprObjC.h" 200e2c34f92f00628d48968dfea096d36381f494cbStephen Hines#include "clang/Analysis/CodeInjector.h" 2155fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/ADT/StringSwitch.h" 22a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 23a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenekusing namespace clang; 24a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 250a4c0988c237678f4b5ba7375e51d24d2c55d67fTed Kremenek//===----------------------------------------------------------------------===// 260a4c0988c237678f4b5ba7375e51d24d2c55d67fTed Kremenek// Helper creation functions for constructing faux ASTs. 270a4c0988c237678f4b5ba7375e51d24d2c55d67fTed Kremenek//===----------------------------------------------------------------------===// 28a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 29cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenekstatic bool isDispatchBlock(QualType Ty) { 30cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // Is it a block pointer? 31cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek const BlockPointerType *BPT = Ty->getAs<BlockPointerType>(); 32cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek if (!BPT) 33cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek return false; 34cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek 35cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // Check if the block pointer type takes no arguments and 36cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // returns void. 37cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek const FunctionProtoType *FT = 38cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek BPT->getPointeeType()->getAs<FunctionProtoType>(); 3987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return FT && FT->getReturnType()->isVoidType() && FT->getNumParams() == 0; 40cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek} 41cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek 42016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremeneknamespace { 43016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenekclass ASTMaker { 44016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenekpublic: 45016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek ASTMaker(ASTContext &C) : C(C) {} 46016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek 47b80e5bb7c7c47e06f2ff9c2f9d4b6b138db180e2Ted Kremenek /// Create a new BinaryOperator representing a simple assignment. 48b80e5bb7c7c47e06f2ff9c2f9d4b6b138db180e2Ted Kremenek BinaryOperator *makeAssignment(const Expr *LHS, const Expr *RHS, QualType Ty); 49b80e5bb7c7c47e06f2ff9c2f9d4b6b138db180e2Ted Kremenek 5048fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek /// Create a new BinaryOperator representing a comparison. 5148fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek BinaryOperator *makeComparison(const Expr *LHS, const Expr *RHS, 5248fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek BinaryOperator::Opcode Op); 5348fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 5448fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek /// Create a new compound stmt using the provided statements. 5548fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek CompoundStmt *makeCompound(ArrayRef<Stmt*>); 5648fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 57a6d62a10a6e1b8aa3c8294d8cac842c3720df7ffTed Kremenek /// Create a new DeclRefExpr for the referenced variable. 58016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek DeclRefExpr *makeDeclRefExpr(const VarDecl *D); 59016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek 600b5c5e487bbbdeb2a7688e6c753d3b2a7c337604Ted Kremenek /// Create a new UnaryOperator representing a dereference. 610b5c5e487bbbdeb2a7688e6c753d3b2a7c337604Ted Kremenek UnaryOperator *makeDereference(const Expr *Arg, QualType Ty); 620b5c5e487bbbdeb2a7688e6c753d3b2a7c337604Ted Kremenek 63a6d62a10a6e1b8aa3c8294d8cac842c3720df7ffTed Kremenek /// Create an implicit cast for an integer conversion. 645dbd990d7978fb990b61a9bcf1b71314a3e743feTed Kremenek Expr *makeIntegralCast(const Expr *Arg, QualType Ty); 65a6d62a10a6e1b8aa3c8294d8cac842c3720df7ffTed Kremenek 6648fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek /// Create an implicit cast to a builtin boolean type. 6748fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek ImplicitCastExpr *makeIntegralCastToBoolean(const Expr *Arg); 6848fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 699ba05cd2e24e600ab59b2ed893ae598abbbc9a36Ted Kremenek // Create an implicit cast for lvalue-to-rvaluate conversions. 709ba05cd2e24e600ab59b2ed893ae598abbbc9a36Ted Kremenek ImplicitCastExpr *makeLvalueToRvalue(const Expr *Arg, QualType Ty); 719ba05cd2e24e600ab59b2ed893ae598abbbc9a36Ted Kremenek 7248fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek /// Create an Objective-C bool literal. 7348fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek ObjCBoolLiteralExpr *makeObjCBool(bool Val); 74651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 75651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines /// Create an Objective-C ivar reference. 76651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCIvarRefExpr *makeObjCIvarRef(const Expr *Base, const ObjCIvarDecl *IVar); 7748fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 7848fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek /// Create a Return statement. 7948fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek ReturnStmt *makeReturn(const Expr *RetVal); 8048fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 81016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenekprivate: 82016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek ASTContext &C; 83016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek}; 84016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek} 85016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek 86b80e5bb7c7c47e06f2ff9c2f9d4b6b138db180e2Ted KremenekBinaryOperator *ASTMaker::makeAssignment(const Expr *LHS, const Expr *RHS, 87b80e5bb7c7c47e06f2ff9c2f9d4b6b138db180e2Ted Kremenek QualType Ty) { 88b80e5bb7c7c47e06f2ff9c2f9d4b6b138db180e2Ted Kremenek return new (C) BinaryOperator(const_cast<Expr*>(LHS), const_cast<Expr*>(RHS), 89b80e5bb7c7c47e06f2ff9c2f9d4b6b138db180e2Ted Kremenek BO_Assign, Ty, VK_RValue, 90be9af1288881110e406b87914162eaa59f1e5918Lang Hames OK_Ordinary, SourceLocation(), false); 91b80e5bb7c7c47e06f2ff9c2f9d4b6b138db180e2Ted Kremenek} 92b80e5bb7c7c47e06f2ff9c2f9d4b6b138db180e2Ted Kremenek 9348fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted KremenekBinaryOperator *ASTMaker::makeComparison(const Expr *LHS, const Expr *RHS, 9448fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek BinaryOperator::Opcode Op) { 9548fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek assert(BinaryOperator::isLogicalOp(Op) || 9648fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek BinaryOperator::isComparisonOp(Op)); 9748fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek return new (C) BinaryOperator(const_cast<Expr*>(LHS), 9848fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek const_cast<Expr*>(RHS), 9948fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek Op, 10048fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek C.getLogicalOperationType(), 10148fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek VK_RValue, 10248fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek OK_Ordinary, SourceLocation(), false); 10348fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek} 10448fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 10548fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted KremenekCompoundStmt *ASTMaker::makeCompound(ArrayRef<Stmt *> Stmts) { 106d36aa359e2f45cd22c7366a015ad94de08044dbbNico Weber return new (C) CompoundStmt(C, Stmts, SourceLocation(), SourceLocation()); 10748fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek} 10848fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 109016c33d7bbca20c096ad8c7400b70f33aadfb224Ted KremenekDeclRefExpr *ASTMaker::makeDeclRefExpr(const VarDecl *D) { 110016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek DeclRefExpr *DR = 111016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek DeclRefExpr::Create(/* Ctx = */ C, 112016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek /* QualifierLoc = */ NestedNameSpecifierLoc(), 113016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek /* TemplateKWLoc = */ SourceLocation(), 114016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek /* D = */ const_cast<VarDecl*>(D), 1150e2c34f92f00628d48968dfea096d36381f494cbStephen Hines /* RefersToEnclosingVariableOrCapture = */ false, 116016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek /* NameLoc = */ SourceLocation(), 117016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek /* T = */ D->getType(), 118016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek /* VK = */ VK_LValue); 119016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek return DR; 120016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek} 121016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek 1220b5c5e487bbbdeb2a7688e6c753d3b2a7c337604Ted KremenekUnaryOperator *ASTMaker::makeDereference(const Expr *Arg, QualType Ty) { 1230b5c5e487bbbdeb2a7688e6c753d3b2a7c337604Ted Kremenek return new (C) UnaryOperator(const_cast<Expr*>(Arg), UO_Deref, Ty, 1240b5c5e487bbbdeb2a7688e6c753d3b2a7c337604Ted Kremenek VK_LValue, OK_Ordinary, SourceLocation()); 1250b5c5e487bbbdeb2a7688e6c753d3b2a7c337604Ted Kremenek} 1260b5c5e487bbbdeb2a7688e6c753d3b2a7c337604Ted Kremenek 1279ba05cd2e24e600ab59b2ed893ae598abbbc9a36Ted KremenekImplicitCastExpr *ASTMaker::makeLvalueToRvalue(const Expr *Arg, QualType Ty) { 1289ba05cd2e24e600ab59b2ed893ae598abbbc9a36Ted Kremenek return ImplicitCastExpr::Create(C, Ty, CK_LValueToRValue, 1296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const_cast<Expr*>(Arg), nullptr, VK_RValue); 1309ba05cd2e24e600ab59b2ed893ae598abbbc9a36Ted Kremenek} 1319ba05cd2e24e600ab59b2ed893ae598abbbc9a36Ted Kremenek 1325dbd990d7978fb990b61a9bcf1b71314a3e743feTed KremenekExpr *ASTMaker::makeIntegralCast(const Expr *Arg, QualType Ty) { 1335dbd990d7978fb990b61a9bcf1b71314a3e743feTed Kremenek if (Arg->getType() == Ty) 1345dbd990d7978fb990b61a9bcf1b71314a3e743feTed Kremenek return const_cast<Expr*>(Arg); 1356bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 136a6d62a10a6e1b8aa3c8294d8cac842c3720df7ffTed Kremenek return ImplicitCastExpr::Create(C, Ty, CK_IntegralCast, 1376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const_cast<Expr*>(Arg), nullptr, VK_RValue); 138a6d62a10a6e1b8aa3c8294d8cac842c3720df7ffTed Kremenek} 139a6d62a10a6e1b8aa3c8294d8cac842c3720df7ffTed Kremenek 14048fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted KremenekImplicitCastExpr *ASTMaker::makeIntegralCastToBoolean(const Expr *Arg) { 14148fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek return ImplicitCastExpr::Create(C, C.BoolTy, CK_IntegralToBoolean, 1426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const_cast<Expr*>(Arg), nullptr, VK_RValue); 14348fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek} 14448fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 14548fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted KremenekObjCBoolLiteralExpr *ASTMaker::makeObjCBool(bool Val) { 14648fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek QualType Ty = C.getBOOLDecl() ? C.getBOOLType() : C.ObjCBuiltinBoolTy; 14748fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek return new (C) ObjCBoolLiteralExpr(Val, Ty, SourceLocation()); 14848fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek} 14948fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 150651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesObjCIvarRefExpr *ASTMaker::makeObjCIvarRef(const Expr *Base, 151651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const ObjCIvarDecl *IVar) { 152651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return new (C) ObjCIvarRefExpr(const_cast<ObjCIvarDecl*>(IVar), 153651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines IVar->getType(), SourceLocation(), 154651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SourceLocation(), const_cast<Expr*>(Base), 155651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines /*arrow=*/true, /*free=*/false); 156651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 157651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 158651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 15948fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted KremenekReturnStmt *ASTMaker::makeReturn(const Expr *RetVal) { 1606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return new (C) ReturnStmt(SourceLocation(), const_cast<Expr*>(RetVal), 1616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines nullptr); 16248fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek} 16348fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 1640a4c0988c237678f4b5ba7375e51d24d2c55d67fTed Kremenek//===----------------------------------------------------------------------===// 1650a4c0988c237678f4b5ba7375e51d24d2c55d67fTed Kremenek// Creation functions for faux ASTs. 1660a4c0988c237678f4b5ba7375e51d24d2c55d67fTed Kremenek//===----------------------------------------------------------------------===// 1670a4c0988c237678f4b5ba7375e51d24d2c55d67fTed Kremenek 1680a4c0988c237678f4b5ba7375e51d24d2c55d67fTed Kremenektypedef Stmt *(*FunctionFarmer)(ASTContext &C, const FunctionDecl *D); 1690a4c0988c237678f4b5ba7375e51d24d2c55d67fTed Kremenek 170cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek/// Create a fake body for dispatch_once. 171cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenekstatic Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) { 172cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // Check if we have at least two parameters. 173cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek if (D->param_size() != 2) 1746bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 175cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek 176cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // Check if the first parameter is a pointer to integer type. 177cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek const ParmVarDecl *Predicate = D->getParamDecl(0); 178cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek QualType PredicateQPtrTy = Predicate->getType(); 179cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek const PointerType *PredicatePtrTy = PredicateQPtrTy->getAs<PointerType>(); 180cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek if (!PredicatePtrTy) 1816bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 182cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek QualType PredicateTy = PredicatePtrTy->getPointeeType(); 183cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek if (!PredicateTy->isIntegerType()) 1846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 1856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 186cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // Check if the second parameter is the proper block type. 187cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek const ParmVarDecl *Block = D->getParamDecl(1); 188cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek QualType Ty = Block->getType(); 189cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek if (!isDispatchBlock(Ty)) 1906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 1916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 192cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // Everything checks out. Create a fakse body that checks the predicate, 193cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // sets it, and calls the block. Basically, an AST dump of: 194cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // 195cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block) { 196cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // if (!*predicate) { 197cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // *predicate = 1; 198cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // block(); 199cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // } 200cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // } 201cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek 202016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek ASTMaker M(C); 203016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek 204cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // (1) Create the call. 205016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek DeclRefExpr *DR = M.makeDeclRefExpr(Block); 2069ba05cd2e24e600ab59b2ed893ae598abbbc9a36Ted Kremenek ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty); 2075543169296beeb183b9c9392debc774fcf493eebDmitri Gribenko CallExpr *CE = new (C) CallExpr(C, ICE, None, C.VoidTy, VK_RValue, 2085543169296beeb183b9c9392debc774fcf493eebDmitri Gribenko SourceLocation()); 209cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek 210cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // (2) Create the assignment to the predicate. 211cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek IntegerLiteral *IL = 212cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek IntegerLiteral::Create(C, llvm::APInt(C.getTypeSize(C.IntTy), (uint64_t) 1), 213cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek C.IntTy, SourceLocation()); 214fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek BinaryOperator *B = 215fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek M.makeAssignment( 216fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek M.makeDereference( 217fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek M.makeLvalueToRvalue( 218fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek M.makeDeclRefExpr(Predicate), PredicateQPtrTy), 219fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek PredicateTy), 220fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek M.makeIntegralCast(IL, PredicateTy), 221fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek PredicateTy); 222fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek 223cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // (3) Create the compound statement. 224176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Stmt *Stmts[] = { B, CE }; 225176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CompoundStmt *CS = M.makeCompound(Stmts); 226cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek 227cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // (4) Create the 'if' condition. 228fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek ImplicitCastExpr *LValToRval = 229fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek M.makeLvalueToRvalue( 230fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek M.makeDereference( 231fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek M.makeLvalueToRvalue( 232fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek M.makeDeclRefExpr(Predicate), 233fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek PredicateQPtrTy), 234fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek PredicateTy), 235fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek PredicateTy); 236fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek 237fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek UnaryOperator *UO = new (C) UnaryOperator(LValToRval, UO_LNot, C.IntTy, 238fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek VK_RValue, OK_Ordinary, 239fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek SourceLocation()); 240cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek 241cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // (5) Create the 'if' statement. 2424967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar IfStmt *If = new (C) IfStmt(C, SourceLocation(), false, nullptr, nullptr, 2434967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar UO, CS); 244cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek return If; 245cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek} 246cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek 247a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek/// Create a fake body for dispatch_sync. 248a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenekstatic Stmt *create_dispatch_sync(ASTContext &C, const FunctionDecl *D) { 249a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek // Check if we have at least two parameters. 250a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek if (D->param_size() != 2) 2516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 2526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 253a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek // Check if the second parameter is a block. 254a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek const ParmVarDecl *PV = D->getParamDecl(1); 255a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek QualType Ty = PV->getType(); 256cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek if (!isDispatchBlock(Ty)) 2576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 2586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 259a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek // Everything checks out. Create a fake body that just calls the block. 260a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek // This is basically just an AST dump of: 261a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek // 262a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek // void dispatch_sync(dispatch_queue_t queue, void (^block)(void)) { 263a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek // block(); 264a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek // } 265016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek // 266016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek ASTMaker M(C); 267016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek DeclRefExpr *DR = M.makeDeclRefExpr(PV); 2680b5c5e487bbbdeb2a7688e6c753d3b2a7c337604Ted Kremenek ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty); 2695543169296beeb183b9c9392debc774fcf493eebDmitri Gribenko CallExpr *CE = new (C) CallExpr(C, ICE, None, C.VoidTy, VK_RValue, 2705543169296beeb183b9c9392debc774fcf493eebDmitri Gribenko SourceLocation()); 271a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek return CE; 272a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek} 273a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 27448fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenekstatic Stmt *create_OSAtomicCompareAndSwap(ASTContext &C, const FunctionDecl *D) 27548fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek{ 27648fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek // There are exactly 3 arguments. 27748fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek if (D->param_size() != 3) 2786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 2796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 280ef95aea4fe779730de23ac84536cfd135b13a4b4Anna Zaks // Signature: 281ef95aea4fe779730de23ac84536cfd135b13a4b4Anna Zaks // _Bool OSAtomicCompareAndSwapPtr(void *__oldValue, 282ef95aea4fe779730de23ac84536cfd135b13a4b4Anna Zaks // void *__newValue, 283ef95aea4fe779730de23ac84536cfd135b13a4b4Anna Zaks // void * volatile *__theValue) 284ef95aea4fe779730de23ac84536cfd135b13a4b4Anna Zaks // Generate body: 28548fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek // if (oldValue == *theValue) { 28648fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek // *theValue = newValue; 28748fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek // return YES; 28848fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek // } 28948fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek // else return NO; 290651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 291651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines QualType ResultTy = D->getReturnType(); 2925dbd990d7978fb990b61a9bcf1b71314a3e743feTed Kremenek bool isBoolean = ResultTy->isBooleanType(); 2935dbd990d7978fb990b61a9bcf1b71314a3e743feTed Kremenek if (!isBoolean && !ResultTy->isIntegralType(C)) 2946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 2956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 29648fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek const ParmVarDecl *OldValue = D->getParamDecl(0); 29748fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek QualType OldValueTy = OldValue->getType(); 29848fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 29948fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek const ParmVarDecl *NewValue = D->getParamDecl(1); 30048fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek QualType NewValueTy = NewValue->getType(); 30148fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 30248fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek assert(OldValueTy == NewValueTy); 30348fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 30448fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek const ParmVarDecl *TheValue = D->getParamDecl(2); 30548fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek QualType TheValueTy = TheValue->getType(); 30648fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek const PointerType *PT = TheValueTy->getAs<PointerType>(); 30748fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek if (!PT) 3086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 30948fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek QualType PointeeTy = PT->getPointeeType(); 31048fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 31148fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek ASTMaker M(C); 31248fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek // Construct the comparison. 31348fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek Expr *Comparison = 31448fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek M.makeComparison( 31548fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek M.makeLvalueToRvalue(M.makeDeclRefExpr(OldValue), OldValueTy), 31648fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek M.makeLvalueToRvalue( 31748fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek M.makeDereference( 31848fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy), 31948fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek PointeeTy), 32048fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek PointeeTy), 32148fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek BO_EQ); 32248fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 32348fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek // Construct the body of the IfStmt. 32448fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek Stmt *Stmts[2]; 32548fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek Stmts[0] = 32648fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek M.makeAssignment( 32748fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek M.makeDereference( 32848fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy), 32948fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek PointeeTy), 33048fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek M.makeLvalueToRvalue(M.makeDeclRefExpr(NewValue), NewValueTy), 33148fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek NewValueTy); 3325dbd990d7978fb990b61a9bcf1b71314a3e743feTed Kremenek 3335dbd990d7978fb990b61a9bcf1b71314a3e743feTed Kremenek Expr *BoolVal = M.makeObjCBool(true); 3345dbd990d7978fb990b61a9bcf1b71314a3e743feTed Kremenek Expr *RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal) 3355dbd990d7978fb990b61a9bcf1b71314a3e743feTed Kremenek : M.makeIntegralCast(BoolVal, ResultTy); 3365dbd990d7978fb990b61a9bcf1b71314a3e743feTed Kremenek Stmts[1] = M.makeReturn(RetVal); 337176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CompoundStmt *Body = M.makeCompound(Stmts); 33848fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 33948fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek // Construct the else clause. 3405dbd990d7978fb990b61a9bcf1b71314a3e743feTed Kremenek BoolVal = M.makeObjCBool(false); 3415dbd990d7978fb990b61a9bcf1b71314a3e743feTed Kremenek RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal) 3425dbd990d7978fb990b61a9bcf1b71314a3e743feTed Kremenek : M.makeIntegralCast(BoolVal, ResultTy); 3435dbd990d7978fb990b61a9bcf1b71314a3e743feTed Kremenek Stmt *Else = M.makeReturn(RetVal); 34448fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 34548fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek /// Construct the If. 3464967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Stmt *If = new (C) IfStmt(C, SourceLocation(), false, nullptr, nullptr, 3474967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Comparison, Body, SourceLocation(), Else); 3486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 34948fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek return If; 35048fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek} 35148fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 352a43df9539644bf1c258e12710cd69d79b0b078cdTed KremenekStmt *BodyFarm::getBody(const FunctionDecl *D) { 353a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek D = D->getCanonicalDecl(); 354a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 355dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie Optional<Stmt *> &Val = Bodies[D]; 356a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek if (Val.hasValue()) 357a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek return Val.getValue(); 3586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 3596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Val = nullptr; 3606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 3616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (D->getIdentifier() == nullptr) 3626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 363a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 364a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek StringRef Name = D->getName(); 365a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek if (Name.empty()) 3666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 36748fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 36848fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek FunctionFarmer FF; 36948fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 37048fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek if (Name.startswith("OSAtomicCompareAndSwap") || 37148fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek Name.startswith("objc_atomicCompareAndSwap")) { 37248fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek FF = create_OSAtomicCompareAndSwap; 37348fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek } 37448fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek else { 37548fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek FF = llvm::StringSwitch<FunctionFarmer>(Name) 37648fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek .Case("dispatch_sync", create_dispatch_sync) 37748fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek .Case("dispatch_once", create_dispatch_once) 3786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines .Default(nullptr); 379a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek } 380a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 38148fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek if (FF) { Val = FF(C, D); } 382176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines else if (Injector) { Val = Injector->getBody(D); } 383a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek return Val.getValue(); 384a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek} 385a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 3864967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarstatic const ObjCIvarDecl *findBackingIvar(const ObjCPropertyDecl *Prop) { 3874967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar const ObjCIvarDecl *IVar = Prop->getPropertyIvarDecl(); 3884967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 3894967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (IVar) 3904967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return IVar; 3914967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 3924967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // When a readonly property is shadowed in a class extensions with a 3934967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // a readwrite property, the instance variable belongs to the shadowing 3944967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // property rather than the shadowed property. If there is no instance 3954967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // variable on a readonly property, check to see whether the property is 3964967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // shadowed and if so try to get the instance variable from shadowing 3974967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // property. 3984967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (!Prop->isReadOnly()) 3994967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return nullptr; 4004967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 4014967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar auto *Container = cast<ObjCContainerDecl>(Prop->getDeclContext()); 4024967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar const ObjCInterfaceDecl *PrimaryInterface = nullptr; 4034967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (auto *InterfaceDecl = dyn_cast<ObjCInterfaceDecl>(Container)) { 4044967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar PrimaryInterface = InterfaceDecl; 4054967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } else if (auto *CategoryDecl = dyn_cast<ObjCCategoryDecl>(Container)) { 4064967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar PrimaryInterface = CategoryDecl->getClassInterface(); 4074967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } else if (auto *ImplDecl = dyn_cast<ObjCImplDecl>(Container)) { 4084967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar PrimaryInterface = ImplDecl->getClassInterface(); 4094967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } else { 4104967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return nullptr; 4114967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 4124967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 4134967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // FindPropertyVisibleInPrimaryClass() looks first in class extensions, so it 4144967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // is guaranteed to find the shadowing property, if it exists, rather than 4154967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // the shadowed property. 4164967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar auto *ShadowingProp = PrimaryInterface->FindPropertyVisibleInPrimaryClass( 4174967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Prop->getIdentifier(), Prop->getQueryKind()); 4184967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (ShadowingProp && ShadowingProp != Prop) { 4194967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar IVar = ShadowingProp->getPropertyIvarDecl(); 4204967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 4214967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 4224967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return IVar; 4234967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar} 4244967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 425651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic Stmt *createObjCPropertyGetter(ASTContext &Ctx, 426651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const ObjCPropertyDecl *Prop) { 427651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // First, find the backing ivar. 4284967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar const ObjCIvarDecl *IVar = findBackingIvar(Prop); 429651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!IVar) 4306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 431651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 432651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Ignore weak variables, which have special behavior. 433651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak) 4346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 435651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 436651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Look to see if Sema has synthesized a body for us. This happens in 437651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Objective-C++ because the return value may be a C++ class type with a 438651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // non-trivial copy constructor. We can only do this if we can find the 439651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // @synthesize for this property, though (or if we know it's been auto- 440651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // synthesized). 441651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const ObjCImplementationDecl *ImplDecl = 442651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines IVar->getContainingInterface()->getImplementation(); 443651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (ImplDecl) { 444651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto *I : ImplDecl->property_impls()) { 445651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (I->getPropertyDecl() != Prop) 446651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 447651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 448651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (I->getGetterCXXConstructor()) { 449651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ASTMaker M(Ctx); 450651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return M.makeReturn(I->getGetterCXXConstructor()); 451651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 452651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 453651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 454651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 455651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Sanity check that the property is the same type as the ivar, or a 456651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // reference to it, and that it is either an object pointer or trivially 457651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // copyable. 458651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!Ctx.hasSameUnqualifiedType(IVar->getType(), 459651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Prop->getType().getNonReferenceType())) 4606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 461651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!IVar->getType()->isObjCLifetimeType() && 462651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines !IVar->getType().isTriviallyCopyableType(Ctx)) 4636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 464651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 465651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Generate our body: 466651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // return self->_ivar; 467651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ASTMaker M(Ctx); 468651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 469651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const VarDecl *selfVar = Prop->getGetterMethodDecl()->getSelfDecl(); 470651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 471651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Expr *loadedIVar = 472651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines M.makeObjCIvarRef( 473651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines M.makeLvalueToRvalue( 474651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines M.makeDeclRefExpr(selfVar), 475651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines selfVar->getType()), 476651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines IVar); 477651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 478651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!Prop->getType()->isReferenceType()) 479651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines loadedIVar = M.makeLvalueToRvalue(loadedIVar, IVar->getType()); 480651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 481651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return M.makeReturn(loadedIVar); 482651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 483651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 484651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesStmt *BodyFarm::getBody(const ObjCMethodDecl *D) { 485651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // We currently only know how to synthesize property accessors. 486651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!D->isPropertyAccessor()) 4876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 488651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 489651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines D = D->getCanonicalDecl(); 490651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 491651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Optional<Stmt *> &Val = Bodies[D]; 492651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Val.hasValue()) 493651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return Val.getValue(); 4946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Val = nullptr; 495651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 496651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const ObjCPropertyDecl *Prop = D->findPropertyDecl(); 497651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!Prop) 4986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 499651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 500651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // For now, we only synthesize getters. 5014967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // Synthesizing setters would cause false negatives in the 5024967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // RetainCountChecker because the method body would bind the parameter 5034967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // to an instance variable, causing it to escape. This would prevent 5044967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // warning in the following common scenario: 5054967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // 5064967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // id foo = [[NSObject alloc] init]; 5074967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // self.foo = foo; // We should warn that foo leaks here. 5084967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar // 509651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (D->param_size() != 0) 5106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 511651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 512651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Val = createObjCPropertyGetter(C, Prop); 513651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 514651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return Val.getValue(); 515651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 516651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 517