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