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" 2055fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/ADT/StringSwitch.h" 21a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 22a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenekusing namespace clang; 23a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 240a4c0988c237678f4b5ba7375e51d24d2c55d67fTed Kremenek//===----------------------------------------------------------------------===// 250a4c0988c237678f4b5ba7375e51d24d2c55d67fTed Kremenek// Helper creation functions for constructing faux ASTs. 260a4c0988c237678f4b5ba7375e51d24d2c55d67fTed Kremenek//===----------------------------------------------------------------------===// 27a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 28cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenekstatic bool isDispatchBlock(QualType Ty) { 29cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // Is it a block pointer? 30cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek const BlockPointerType *BPT = Ty->getAs<BlockPointerType>(); 31cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek if (!BPT) 32cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek return false; 33cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek 34cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // Check if the block pointer type takes no arguments and 35cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // returns void. 36cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek const FunctionProtoType *FT = 37cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek BPT->getPointeeType()->getAs<FunctionProtoType>(); 38651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!FT || !FT->getReturnType()->isVoidType() || FT->getNumParams() != 0) 39cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek return false; 40cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek 41cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek return true; 42cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek} 43cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek 44016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremeneknamespace { 45016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenekclass ASTMaker { 46016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenekpublic: 47016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek ASTMaker(ASTContext &C) : C(C) {} 48016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek 49b80e5bb7c7c47e06f2ff9c2f9d4b6b138db180e2Ted Kremenek /// Create a new BinaryOperator representing a simple assignment. 50b80e5bb7c7c47e06f2ff9c2f9d4b6b138db180e2Ted Kremenek BinaryOperator *makeAssignment(const Expr *LHS, const Expr *RHS, QualType Ty); 51b80e5bb7c7c47e06f2ff9c2f9d4b6b138db180e2Ted Kremenek 5248fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek /// Create a new BinaryOperator representing a comparison. 5348fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek BinaryOperator *makeComparison(const Expr *LHS, const Expr *RHS, 5448fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek BinaryOperator::Opcode Op); 5548fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 5648fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek /// Create a new compound stmt using the provided statements. 5748fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek CompoundStmt *makeCompound(ArrayRef<Stmt*>); 5848fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 59a6d62a10a6e1b8aa3c8294d8cac842c3720df7ffTed Kremenek /// Create a new DeclRefExpr for the referenced variable. 60016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek DeclRefExpr *makeDeclRefExpr(const VarDecl *D); 61016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek 620b5c5e487bbbdeb2a7688e6c753d3b2a7c337604Ted Kremenek /// Create a new UnaryOperator representing a dereference. 630b5c5e487bbbdeb2a7688e6c753d3b2a7c337604Ted Kremenek UnaryOperator *makeDereference(const Expr *Arg, QualType Ty); 640b5c5e487bbbdeb2a7688e6c753d3b2a7c337604Ted Kremenek 65a6d62a10a6e1b8aa3c8294d8cac842c3720df7ffTed Kremenek /// Create an implicit cast for an integer conversion. 665dbd990d7978fb990b61a9bcf1b71314a3e743feTed Kremenek Expr *makeIntegralCast(const Expr *Arg, QualType Ty); 67a6d62a10a6e1b8aa3c8294d8cac842c3720df7ffTed Kremenek 6848fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek /// Create an implicit cast to a builtin boolean type. 6948fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek ImplicitCastExpr *makeIntegralCastToBoolean(const Expr *Arg); 7048fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 719ba05cd2e24e600ab59b2ed893ae598abbbc9a36Ted Kremenek // Create an implicit cast for lvalue-to-rvaluate conversions. 729ba05cd2e24e600ab59b2ed893ae598abbbc9a36Ted Kremenek ImplicitCastExpr *makeLvalueToRvalue(const Expr *Arg, QualType Ty); 739ba05cd2e24e600ab59b2ed893ae598abbbc9a36Ted Kremenek 7448fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek /// Create an Objective-C bool literal. 7548fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek ObjCBoolLiteralExpr *makeObjCBool(bool Val); 76651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 77651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines /// Create an Objective-C ivar reference. 78651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCIvarRefExpr *makeObjCIvarRef(const Expr *Base, const ObjCIvarDecl *IVar); 7948fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 8048fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek /// Create a Return statement. 8148fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek ReturnStmt *makeReturn(const Expr *RetVal); 8248fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 83016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenekprivate: 84016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek ASTContext &C; 85016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek}; 86016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek} 87016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek 88b80e5bb7c7c47e06f2ff9c2f9d4b6b138db180e2Ted KremenekBinaryOperator *ASTMaker::makeAssignment(const Expr *LHS, const Expr *RHS, 89b80e5bb7c7c47e06f2ff9c2f9d4b6b138db180e2Ted Kremenek QualType Ty) { 90b80e5bb7c7c47e06f2ff9c2f9d4b6b138db180e2Ted Kremenek return new (C) BinaryOperator(const_cast<Expr*>(LHS), const_cast<Expr*>(RHS), 91b80e5bb7c7c47e06f2ff9c2f9d4b6b138db180e2Ted Kremenek BO_Assign, Ty, VK_RValue, 92be9af1288881110e406b87914162eaa59f1e5918Lang Hames OK_Ordinary, SourceLocation(), false); 93b80e5bb7c7c47e06f2ff9c2f9d4b6b138db180e2Ted Kremenek} 94b80e5bb7c7c47e06f2ff9c2f9d4b6b138db180e2Ted Kremenek 9548fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted KremenekBinaryOperator *ASTMaker::makeComparison(const Expr *LHS, const Expr *RHS, 9648fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek BinaryOperator::Opcode Op) { 9748fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek assert(BinaryOperator::isLogicalOp(Op) || 9848fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek BinaryOperator::isComparisonOp(Op)); 9948fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek return new (C) BinaryOperator(const_cast<Expr*>(LHS), 10048fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek const_cast<Expr*>(RHS), 10148fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek Op, 10248fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek C.getLogicalOperationType(), 10348fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek VK_RValue, 10448fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek OK_Ordinary, SourceLocation(), false); 10548fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek} 10648fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 10748fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted KremenekCompoundStmt *ASTMaker::makeCompound(ArrayRef<Stmt *> Stmts) { 108d36aa359e2f45cd22c7366a015ad94de08044dbbNico Weber return new (C) CompoundStmt(C, Stmts, SourceLocation(), SourceLocation()); 10948fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek} 11048fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 111016c33d7bbca20c096ad8c7400b70f33aadfb224Ted KremenekDeclRefExpr *ASTMaker::makeDeclRefExpr(const VarDecl *D) { 112016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek DeclRefExpr *DR = 113016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek DeclRefExpr::Create(/* Ctx = */ C, 114016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek /* QualifierLoc = */ NestedNameSpecifierLoc(), 115016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek /* TemplateKWLoc = */ SourceLocation(), 116016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek /* D = */ const_cast<VarDecl*>(D), 117016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek /* isEnclosingLocal = */ false, 118016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek /* NameLoc = */ SourceLocation(), 119016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek /* T = */ D->getType(), 120016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek /* VK = */ VK_LValue); 121016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek return DR; 122016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek} 123016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek 1240b5c5e487bbbdeb2a7688e6c753d3b2a7c337604Ted KremenekUnaryOperator *ASTMaker::makeDereference(const Expr *Arg, QualType Ty) { 1250b5c5e487bbbdeb2a7688e6c753d3b2a7c337604Ted Kremenek return new (C) UnaryOperator(const_cast<Expr*>(Arg), UO_Deref, Ty, 1260b5c5e487bbbdeb2a7688e6c753d3b2a7c337604Ted Kremenek VK_LValue, OK_Ordinary, SourceLocation()); 1270b5c5e487bbbdeb2a7688e6c753d3b2a7c337604Ted Kremenek} 1280b5c5e487bbbdeb2a7688e6c753d3b2a7c337604Ted Kremenek 1299ba05cd2e24e600ab59b2ed893ae598abbbc9a36Ted KremenekImplicitCastExpr *ASTMaker::makeLvalueToRvalue(const Expr *Arg, QualType Ty) { 1309ba05cd2e24e600ab59b2ed893ae598abbbc9a36Ted Kremenek return ImplicitCastExpr::Create(C, Ty, CK_LValueToRValue, 1316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const_cast<Expr*>(Arg), nullptr, VK_RValue); 1329ba05cd2e24e600ab59b2ed893ae598abbbc9a36Ted Kremenek} 1339ba05cd2e24e600ab59b2ed893ae598abbbc9a36Ted Kremenek 1345dbd990d7978fb990b61a9bcf1b71314a3e743feTed KremenekExpr *ASTMaker::makeIntegralCast(const Expr *Arg, QualType Ty) { 1355dbd990d7978fb990b61a9bcf1b71314a3e743feTed Kremenek if (Arg->getType() == Ty) 1365dbd990d7978fb990b61a9bcf1b71314a3e743feTed Kremenek return const_cast<Expr*>(Arg); 1376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 138a6d62a10a6e1b8aa3c8294d8cac842c3720df7ffTed Kremenek return ImplicitCastExpr::Create(C, Ty, CK_IntegralCast, 1396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const_cast<Expr*>(Arg), nullptr, VK_RValue); 140a6d62a10a6e1b8aa3c8294d8cac842c3720df7ffTed Kremenek} 141a6d62a10a6e1b8aa3c8294d8cac842c3720df7ffTed Kremenek 14248fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted KremenekImplicitCastExpr *ASTMaker::makeIntegralCastToBoolean(const Expr *Arg) { 14348fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek return ImplicitCastExpr::Create(C, C.BoolTy, CK_IntegralToBoolean, 1446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const_cast<Expr*>(Arg), nullptr, VK_RValue); 14548fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek} 14648fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 14748fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted KremenekObjCBoolLiteralExpr *ASTMaker::makeObjCBool(bool Val) { 14848fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek QualType Ty = C.getBOOLDecl() ? C.getBOOLType() : C.ObjCBuiltinBoolTy; 14948fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek return new (C) ObjCBoolLiteralExpr(Val, Ty, SourceLocation()); 15048fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek} 15148fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 152651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesObjCIvarRefExpr *ASTMaker::makeObjCIvarRef(const Expr *Base, 153651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const ObjCIvarDecl *IVar) { 154651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return new (C) ObjCIvarRefExpr(const_cast<ObjCIvarDecl*>(IVar), 155651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines IVar->getType(), SourceLocation(), 156651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SourceLocation(), const_cast<Expr*>(Base), 157651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines /*arrow=*/true, /*free=*/false); 158651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 159651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 160651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 16148fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted KremenekReturnStmt *ASTMaker::makeReturn(const Expr *RetVal) { 1626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return new (C) ReturnStmt(SourceLocation(), const_cast<Expr*>(RetVal), 1636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines nullptr); 16448fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek} 16548fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 1660a4c0988c237678f4b5ba7375e51d24d2c55d67fTed Kremenek//===----------------------------------------------------------------------===// 1670a4c0988c237678f4b5ba7375e51d24d2c55d67fTed Kremenek// Creation functions for faux ASTs. 1680a4c0988c237678f4b5ba7375e51d24d2c55d67fTed Kremenek//===----------------------------------------------------------------------===// 1690a4c0988c237678f4b5ba7375e51d24d2c55d67fTed Kremenek 1700a4c0988c237678f4b5ba7375e51d24d2c55d67fTed Kremenektypedef Stmt *(*FunctionFarmer)(ASTContext &C, const FunctionDecl *D); 1710a4c0988c237678f4b5ba7375e51d24d2c55d67fTed Kremenek 172cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek/// Create a fake body for dispatch_once. 173cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenekstatic Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) { 174cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // Check if we have at least two parameters. 175cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek if (D->param_size() != 2) 1766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 177cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek 178cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // Check if the first parameter is a pointer to integer type. 179cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek const ParmVarDecl *Predicate = D->getParamDecl(0); 180cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek QualType PredicateQPtrTy = Predicate->getType(); 181cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek const PointerType *PredicatePtrTy = PredicateQPtrTy->getAs<PointerType>(); 182cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek if (!PredicatePtrTy) 1836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 184cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek QualType PredicateTy = PredicatePtrTy->getPointeeType(); 185cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek if (!PredicateTy->isIntegerType()) 1866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 1876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 188cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // Check if the second parameter is the proper block type. 189cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek const ParmVarDecl *Block = D->getParamDecl(1); 190cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek QualType Ty = Block->getType(); 191cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek if (!isDispatchBlock(Ty)) 1926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 1936bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 194cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // Everything checks out. Create a fakse body that checks the predicate, 195cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // sets it, and calls the block. Basically, an AST dump of: 196cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // 197cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block) { 198cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // if (!*predicate) { 199cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // *predicate = 1; 200cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // block(); 201cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // } 202cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // } 203cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek 204016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek ASTMaker M(C); 205016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek 206cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // (1) Create the call. 207016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek DeclRefExpr *DR = M.makeDeclRefExpr(Block); 2089ba05cd2e24e600ab59b2ed893ae598abbbc9a36Ted Kremenek ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty); 2095543169296beeb183b9c9392debc774fcf493eebDmitri Gribenko CallExpr *CE = new (C) CallExpr(C, ICE, None, C.VoidTy, VK_RValue, 2105543169296beeb183b9c9392debc774fcf493eebDmitri Gribenko SourceLocation()); 211cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek 212cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // (2) Create the assignment to the predicate. 213cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek IntegerLiteral *IL = 214cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek IntegerLiteral::Create(C, llvm::APInt(C.getTypeSize(C.IntTy), (uint64_t) 1), 215cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek C.IntTy, SourceLocation()); 216fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek BinaryOperator *B = 217fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek M.makeAssignment( 218fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek M.makeDereference( 219fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek M.makeLvalueToRvalue( 220fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek M.makeDeclRefExpr(Predicate), PredicateQPtrTy), 221fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek PredicateTy), 222fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek M.makeIntegralCast(IL, PredicateTy), 223fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek PredicateTy); 224fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek 225cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // (3) Create the compound statement. 226cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek Stmt *Stmts[2]; 227cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek Stmts[0] = B; 22848fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek Stmts[1] = CE; 22948fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek CompoundStmt *CS = M.makeCompound(ArrayRef<Stmt*>(Stmts, 2)); 230cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek 231cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // (4) Create the 'if' condition. 232fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek ImplicitCastExpr *LValToRval = 233fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek M.makeLvalueToRvalue( 234fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek M.makeDereference( 235fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek M.makeLvalueToRvalue( 236fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek M.makeDeclRefExpr(Predicate), 237fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek PredicateQPtrTy), 238fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek PredicateTy), 239fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek PredicateTy); 240fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek 241fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek UnaryOperator *UO = new (C) UnaryOperator(LValToRval, UO_LNot, C.IntTy, 242fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek VK_RValue, OK_Ordinary, 243fcf8eba0c78634243383f92a77381e919e7e27efTed Kremenek SourceLocation()); 244cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek 245cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek // (5) Create the 'if' statement. 2466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines IfStmt *If = new (C) IfStmt(C, SourceLocation(), nullptr, UO, CS); 247cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek return If; 248cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek} 249cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek 250a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek/// Create a fake body for dispatch_sync. 251a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenekstatic Stmt *create_dispatch_sync(ASTContext &C, const FunctionDecl *D) { 252a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek // Check if we have at least two parameters. 253a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek if (D->param_size() != 2) 2546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 2556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 256a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek // Check if the second parameter is a block. 257a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek const ParmVarDecl *PV = D->getParamDecl(1); 258a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek QualType Ty = PV->getType(); 259cc85d217d329aa3c78aa3f57a238e5b7931ee2c5Ted Kremenek if (!isDispatchBlock(Ty)) 2606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 2616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 262a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek // Everything checks out. Create a fake body that just calls the block. 263a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek // This is basically just an AST dump of: 264a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek // 265a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek // void dispatch_sync(dispatch_queue_t queue, void (^block)(void)) { 266a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek // block(); 267a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek // } 268016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek // 269016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek ASTMaker M(C); 270016c33d7bbca20c096ad8c7400b70f33aadfb224Ted Kremenek DeclRefExpr *DR = M.makeDeclRefExpr(PV); 2710b5c5e487bbbdeb2a7688e6c753d3b2a7c337604Ted Kremenek ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty); 2725543169296beeb183b9c9392debc774fcf493eebDmitri Gribenko CallExpr *CE = new (C) CallExpr(C, ICE, None, C.VoidTy, VK_RValue, 2735543169296beeb183b9c9392debc774fcf493eebDmitri Gribenko SourceLocation()); 274a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek return CE; 275a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek} 276a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 27748fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenekstatic Stmt *create_OSAtomicCompareAndSwap(ASTContext &C, const FunctionDecl *D) 27848fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek{ 27948fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek // There are exactly 3 arguments. 28048fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek if (D->param_size() != 3) 2816bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 2826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 283ef95aea4fe779730de23ac84536cfd135b13a4b4Anna Zaks // Signature: 284ef95aea4fe779730de23ac84536cfd135b13a4b4Anna Zaks // _Bool OSAtomicCompareAndSwapPtr(void *__oldValue, 285ef95aea4fe779730de23ac84536cfd135b13a4b4Anna Zaks // void *__newValue, 286ef95aea4fe779730de23ac84536cfd135b13a4b4Anna Zaks // void * volatile *__theValue) 287ef95aea4fe779730de23ac84536cfd135b13a4b4Anna Zaks // Generate body: 28848fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek // if (oldValue == *theValue) { 28948fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek // *theValue = newValue; 29048fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek // return YES; 29148fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek // } 29248fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek // else return NO; 293651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 294651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines QualType ResultTy = D->getReturnType(); 2955dbd990d7978fb990b61a9bcf1b71314a3e743feTed Kremenek bool isBoolean = ResultTy->isBooleanType(); 2965dbd990d7978fb990b61a9bcf1b71314a3e743feTed Kremenek if (!isBoolean && !ResultTy->isIntegralType(C)) 2976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 2986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 29948fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek const ParmVarDecl *OldValue = D->getParamDecl(0); 30048fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek QualType OldValueTy = OldValue->getType(); 30148fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 30248fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek const ParmVarDecl *NewValue = D->getParamDecl(1); 30348fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek QualType NewValueTy = NewValue->getType(); 30448fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 30548fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek assert(OldValueTy == NewValueTy); 30648fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 30748fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek const ParmVarDecl *TheValue = D->getParamDecl(2); 30848fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek QualType TheValueTy = TheValue->getType(); 30948fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek const PointerType *PT = TheValueTy->getAs<PointerType>(); 31048fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek if (!PT) 3116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 31248fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek QualType PointeeTy = PT->getPointeeType(); 31348fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 31448fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek ASTMaker M(C); 31548fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek // Construct the comparison. 31648fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek Expr *Comparison = 31748fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek M.makeComparison( 31848fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek M.makeLvalueToRvalue(M.makeDeclRefExpr(OldValue), OldValueTy), 31948fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek M.makeLvalueToRvalue( 32048fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek M.makeDereference( 32148fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy), 32248fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek PointeeTy), 32348fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek PointeeTy), 32448fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek BO_EQ); 32548fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 32648fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek // Construct the body of the IfStmt. 32748fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek Stmt *Stmts[2]; 32848fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek Stmts[0] = 32948fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek M.makeAssignment( 33048fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek M.makeDereference( 33148fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy), 33248fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek PointeeTy), 33348fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek M.makeLvalueToRvalue(M.makeDeclRefExpr(NewValue), NewValueTy), 33448fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek NewValueTy); 3355dbd990d7978fb990b61a9bcf1b71314a3e743feTed Kremenek 3365dbd990d7978fb990b61a9bcf1b71314a3e743feTed Kremenek Expr *BoolVal = M.makeObjCBool(true); 3375dbd990d7978fb990b61a9bcf1b71314a3e743feTed Kremenek Expr *RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal) 3385dbd990d7978fb990b61a9bcf1b71314a3e743feTed Kremenek : M.makeIntegralCast(BoolVal, ResultTy); 3395dbd990d7978fb990b61a9bcf1b71314a3e743feTed Kremenek Stmts[1] = M.makeReturn(RetVal); 34048fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek CompoundStmt *Body = M.makeCompound(ArrayRef<Stmt*>(Stmts, 2)); 34148fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 34248fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek // Construct the else clause. 3435dbd990d7978fb990b61a9bcf1b71314a3e743feTed Kremenek BoolVal = M.makeObjCBool(false); 3445dbd990d7978fb990b61a9bcf1b71314a3e743feTed Kremenek RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal) 3455dbd990d7978fb990b61a9bcf1b71314a3e743feTed Kremenek : M.makeIntegralCast(BoolVal, ResultTy); 3465dbd990d7978fb990b61a9bcf1b71314a3e743feTed Kremenek Stmt *Else = M.makeReturn(RetVal); 34748fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 34848fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek /// Construct the If. 34948fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek Stmt *If = 3506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines new (C) IfStmt(C, SourceLocation(), nullptr, Comparison, Body, 35148fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek SourceLocation(), Else); 3526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 35348fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek return If; 35448fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek} 35548fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 356a43df9539644bf1c258e12710cd69d79b0b078cdTed KremenekStmt *BodyFarm::getBody(const FunctionDecl *D) { 357a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek D = D->getCanonicalDecl(); 358a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 359dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie Optional<Stmt *> &Val = Bodies[D]; 360a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek if (Val.hasValue()) 361a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek return Val.getValue(); 3626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 3636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Val = nullptr; 3646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 3656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (D->getIdentifier() == nullptr) 3666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 367a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 368a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek StringRef Name = D->getName(); 369a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek if (Name.empty()) 3706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 37148fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 37248fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek FunctionFarmer FF; 37348fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek 37448fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek if (Name.startswith("OSAtomicCompareAndSwap") || 37548fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek Name.startswith("objc_atomicCompareAndSwap")) { 37648fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek FF = create_OSAtomicCompareAndSwap; 37748fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek } 37848fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek else { 37948fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek FF = llvm::StringSwitch<FunctionFarmer>(Name) 38048fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek .Case("dispatch_sync", create_dispatch_sync) 38148fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek .Case("dispatch_once", create_dispatch_once) 3826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines .Default(nullptr); 383a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek } 384a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 38548fa1361505c51cdc5e78deffdbdd7c334cca5d0Ted Kremenek if (FF) { Val = FF(C, D); } 386a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek return Val.getValue(); 387a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek} 388a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 389651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic Stmt *createObjCPropertyGetter(ASTContext &Ctx, 390651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const ObjCPropertyDecl *Prop) { 391651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // First, find the backing ivar. 392651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const ObjCIvarDecl *IVar = Prop->getPropertyIvarDecl(); 393651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!IVar) 3946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 395651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 396651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Ignore weak variables, which have special behavior. 397651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak) 3986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 399651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 400651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Look to see if Sema has synthesized a body for us. This happens in 401651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Objective-C++ because the return value may be a C++ class type with a 402651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // non-trivial copy constructor. We can only do this if we can find the 403651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // @synthesize for this property, though (or if we know it's been auto- 404651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // synthesized). 405651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const ObjCImplementationDecl *ImplDecl = 406651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines IVar->getContainingInterface()->getImplementation(); 407651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (ImplDecl) { 408651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto *I : ImplDecl->property_impls()) { 409651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (I->getPropertyDecl() != Prop) 410651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 411651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 412651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (I->getGetterCXXConstructor()) { 413651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ASTMaker M(Ctx); 414651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return M.makeReturn(I->getGetterCXXConstructor()); 415651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 416651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 417651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 418651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 419651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Sanity check that the property is the same type as the ivar, or a 420651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // reference to it, and that it is either an object pointer or trivially 421651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // copyable. 422651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!Ctx.hasSameUnqualifiedType(IVar->getType(), 423651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Prop->getType().getNonReferenceType())) 4246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 425651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!IVar->getType()->isObjCLifetimeType() && 426651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines !IVar->getType().isTriviallyCopyableType(Ctx)) 4276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 428651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 429651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Generate our body: 430651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // return self->_ivar; 431651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ASTMaker M(Ctx); 432651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 433651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const VarDecl *selfVar = Prop->getGetterMethodDecl()->getSelfDecl(); 434651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 435651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Expr *loadedIVar = 436651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines M.makeObjCIvarRef( 437651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines M.makeLvalueToRvalue( 438651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines M.makeDeclRefExpr(selfVar), 439651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines selfVar->getType()), 440651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines IVar); 441651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 442651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!Prop->getType()->isReferenceType()) 443651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines loadedIVar = M.makeLvalueToRvalue(loadedIVar, IVar->getType()); 444651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 445651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return M.makeReturn(loadedIVar); 446651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 447651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 448651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesStmt *BodyFarm::getBody(const ObjCMethodDecl *D) { 449651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // We currently only know how to synthesize property accessors. 450651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!D->isPropertyAccessor()) 4516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 452651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 453651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines D = D->getCanonicalDecl(); 454651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 455651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Optional<Stmt *> &Val = Bodies[D]; 456651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Val.hasValue()) 457651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return Val.getValue(); 4586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Val = nullptr; 459651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 460651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const ObjCPropertyDecl *Prop = D->findPropertyDecl(); 461651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!Prop) 4626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 463651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 464651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // For now, we only synthesize getters. 465651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (D->param_size() != 0) 4666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 467651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 468651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Val = createObjCPropertyGetter(C, Prop); 469651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 470651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return Val.getValue(); 471651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 472651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 473