1*67e74705SXin Li //== BodyFarm.cpp - Factory for conjuring up fake bodies ----------*- C++ -*-//
2*67e74705SXin Li //
3*67e74705SXin Li // The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li //
10*67e74705SXin Li // BodyFarm is a factory for creating faux implementations for functions/methods
11*67e74705SXin Li // for analysis purposes.
12*67e74705SXin Li //
13*67e74705SXin Li //===----------------------------------------------------------------------===//
14*67e74705SXin Li
15*67e74705SXin Li #include "BodyFarm.h"
16*67e74705SXin Li #include "clang/AST/ASTContext.h"
17*67e74705SXin Li #include "clang/AST/Decl.h"
18*67e74705SXin Li #include "clang/AST/Expr.h"
19*67e74705SXin Li #include "clang/AST/ExprObjC.h"
20*67e74705SXin Li #include "clang/Analysis/CodeInjector.h"
21*67e74705SXin Li #include "llvm/ADT/StringSwitch.h"
22*67e74705SXin Li
23*67e74705SXin Li using namespace clang;
24*67e74705SXin Li
25*67e74705SXin Li //===----------------------------------------------------------------------===//
26*67e74705SXin Li // Helper creation functions for constructing faux ASTs.
27*67e74705SXin Li //===----------------------------------------------------------------------===//
28*67e74705SXin Li
isDispatchBlock(QualType Ty)29*67e74705SXin Li static bool isDispatchBlock(QualType Ty) {
30*67e74705SXin Li // Is it a block pointer?
31*67e74705SXin Li const BlockPointerType *BPT = Ty->getAs<BlockPointerType>();
32*67e74705SXin Li if (!BPT)
33*67e74705SXin Li return false;
34*67e74705SXin Li
35*67e74705SXin Li // Check if the block pointer type takes no arguments and
36*67e74705SXin Li // returns void.
37*67e74705SXin Li const FunctionProtoType *FT =
38*67e74705SXin Li BPT->getPointeeType()->getAs<FunctionProtoType>();
39*67e74705SXin Li return FT && FT->getReturnType()->isVoidType() && FT->getNumParams() == 0;
40*67e74705SXin Li }
41*67e74705SXin Li
42*67e74705SXin Li namespace {
43*67e74705SXin Li class ASTMaker {
44*67e74705SXin Li public:
ASTMaker(ASTContext & C)45*67e74705SXin Li ASTMaker(ASTContext &C) : C(C) {}
46*67e74705SXin Li
47*67e74705SXin Li /// Create a new BinaryOperator representing a simple assignment.
48*67e74705SXin Li BinaryOperator *makeAssignment(const Expr *LHS, const Expr *RHS, QualType Ty);
49*67e74705SXin Li
50*67e74705SXin Li /// Create a new BinaryOperator representing a comparison.
51*67e74705SXin Li BinaryOperator *makeComparison(const Expr *LHS, const Expr *RHS,
52*67e74705SXin Li BinaryOperator::Opcode Op);
53*67e74705SXin Li
54*67e74705SXin Li /// Create a new compound stmt using the provided statements.
55*67e74705SXin Li CompoundStmt *makeCompound(ArrayRef<Stmt*>);
56*67e74705SXin Li
57*67e74705SXin Li /// Create a new DeclRefExpr for the referenced variable.
58*67e74705SXin Li DeclRefExpr *makeDeclRefExpr(const VarDecl *D);
59*67e74705SXin Li
60*67e74705SXin Li /// Create a new UnaryOperator representing a dereference.
61*67e74705SXin Li UnaryOperator *makeDereference(const Expr *Arg, QualType Ty);
62*67e74705SXin Li
63*67e74705SXin Li /// Create an implicit cast for an integer conversion.
64*67e74705SXin Li Expr *makeIntegralCast(const Expr *Arg, QualType Ty);
65*67e74705SXin Li
66*67e74705SXin Li /// Create an implicit cast to a builtin boolean type.
67*67e74705SXin Li ImplicitCastExpr *makeIntegralCastToBoolean(const Expr *Arg);
68*67e74705SXin Li
69*67e74705SXin Li // Create an implicit cast for lvalue-to-rvaluate conversions.
70*67e74705SXin Li ImplicitCastExpr *makeLvalueToRvalue(const Expr *Arg, QualType Ty);
71*67e74705SXin Li
72*67e74705SXin Li /// Create an Objective-C bool literal.
73*67e74705SXin Li ObjCBoolLiteralExpr *makeObjCBool(bool Val);
74*67e74705SXin Li
75*67e74705SXin Li /// Create an Objective-C ivar reference.
76*67e74705SXin Li ObjCIvarRefExpr *makeObjCIvarRef(const Expr *Base, const ObjCIvarDecl *IVar);
77*67e74705SXin Li
78*67e74705SXin Li /// Create a Return statement.
79*67e74705SXin Li ReturnStmt *makeReturn(const Expr *RetVal);
80*67e74705SXin Li
81*67e74705SXin Li private:
82*67e74705SXin Li ASTContext &C;
83*67e74705SXin Li };
84*67e74705SXin Li }
85*67e74705SXin Li
makeAssignment(const Expr * LHS,const Expr * RHS,QualType Ty)86*67e74705SXin Li BinaryOperator *ASTMaker::makeAssignment(const Expr *LHS, const Expr *RHS,
87*67e74705SXin Li QualType Ty) {
88*67e74705SXin Li return new (C) BinaryOperator(const_cast<Expr*>(LHS), const_cast<Expr*>(RHS),
89*67e74705SXin Li BO_Assign, Ty, VK_RValue,
90*67e74705SXin Li OK_Ordinary, SourceLocation(), false);
91*67e74705SXin Li }
92*67e74705SXin Li
makeComparison(const Expr * LHS,const Expr * RHS,BinaryOperator::Opcode Op)93*67e74705SXin Li BinaryOperator *ASTMaker::makeComparison(const Expr *LHS, const Expr *RHS,
94*67e74705SXin Li BinaryOperator::Opcode Op) {
95*67e74705SXin Li assert(BinaryOperator::isLogicalOp(Op) ||
96*67e74705SXin Li BinaryOperator::isComparisonOp(Op));
97*67e74705SXin Li return new (C) BinaryOperator(const_cast<Expr*>(LHS),
98*67e74705SXin Li const_cast<Expr*>(RHS),
99*67e74705SXin Li Op,
100*67e74705SXin Li C.getLogicalOperationType(),
101*67e74705SXin Li VK_RValue,
102*67e74705SXin Li OK_Ordinary, SourceLocation(), false);
103*67e74705SXin Li }
104*67e74705SXin Li
makeCompound(ArrayRef<Stmt * > Stmts)105*67e74705SXin Li CompoundStmt *ASTMaker::makeCompound(ArrayRef<Stmt *> Stmts) {
106*67e74705SXin Li return new (C) CompoundStmt(C, Stmts, SourceLocation(), SourceLocation());
107*67e74705SXin Li }
108*67e74705SXin Li
makeDeclRefExpr(const VarDecl * D)109*67e74705SXin Li DeclRefExpr *ASTMaker::makeDeclRefExpr(const VarDecl *D) {
110*67e74705SXin Li DeclRefExpr *DR =
111*67e74705SXin Li DeclRefExpr::Create(/* Ctx = */ C,
112*67e74705SXin Li /* QualifierLoc = */ NestedNameSpecifierLoc(),
113*67e74705SXin Li /* TemplateKWLoc = */ SourceLocation(),
114*67e74705SXin Li /* D = */ const_cast<VarDecl*>(D),
115*67e74705SXin Li /* RefersToEnclosingVariableOrCapture = */ false,
116*67e74705SXin Li /* NameLoc = */ SourceLocation(),
117*67e74705SXin Li /* T = */ D->getType(),
118*67e74705SXin Li /* VK = */ VK_LValue);
119*67e74705SXin Li return DR;
120*67e74705SXin Li }
121*67e74705SXin Li
makeDereference(const Expr * Arg,QualType Ty)122*67e74705SXin Li UnaryOperator *ASTMaker::makeDereference(const Expr *Arg, QualType Ty) {
123*67e74705SXin Li return new (C) UnaryOperator(const_cast<Expr*>(Arg), UO_Deref, Ty,
124*67e74705SXin Li VK_LValue, OK_Ordinary, SourceLocation());
125*67e74705SXin Li }
126*67e74705SXin Li
makeLvalueToRvalue(const Expr * Arg,QualType Ty)127*67e74705SXin Li ImplicitCastExpr *ASTMaker::makeLvalueToRvalue(const Expr *Arg, QualType Ty) {
128*67e74705SXin Li return ImplicitCastExpr::Create(C, Ty, CK_LValueToRValue,
129*67e74705SXin Li const_cast<Expr*>(Arg), nullptr, VK_RValue);
130*67e74705SXin Li }
131*67e74705SXin Li
makeIntegralCast(const Expr * Arg,QualType Ty)132*67e74705SXin Li Expr *ASTMaker::makeIntegralCast(const Expr *Arg, QualType Ty) {
133*67e74705SXin Li if (Arg->getType() == Ty)
134*67e74705SXin Li return const_cast<Expr*>(Arg);
135*67e74705SXin Li
136*67e74705SXin Li return ImplicitCastExpr::Create(C, Ty, CK_IntegralCast,
137*67e74705SXin Li const_cast<Expr*>(Arg), nullptr, VK_RValue);
138*67e74705SXin Li }
139*67e74705SXin Li
makeIntegralCastToBoolean(const Expr * Arg)140*67e74705SXin Li ImplicitCastExpr *ASTMaker::makeIntegralCastToBoolean(const Expr *Arg) {
141*67e74705SXin Li return ImplicitCastExpr::Create(C, C.BoolTy, CK_IntegralToBoolean,
142*67e74705SXin Li const_cast<Expr*>(Arg), nullptr, VK_RValue);
143*67e74705SXin Li }
144*67e74705SXin Li
makeObjCBool(bool Val)145*67e74705SXin Li ObjCBoolLiteralExpr *ASTMaker::makeObjCBool(bool Val) {
146*67e74705SXin Li QualType Ty = C.getBOOLDecl() ? C.getBOOLType() : C.ObjCBuiltinBoolTy;
147*67e74705SXin Li return new (C) ObjCBoolLiteralExpr(Val, Ty, SourceLocation());
148*67e74705SXin Li }
149*67e74705SXin Li
makeObjCIvarRef(const Expr * Base,const ObjCIvarDecl * IVar)150*67e74705SXin Li ObjCIvarRefExpr *ASTMaker::makeObjCIvarRef(const Expr *Base,
151*67e74705SXin Li const ObjCIvarDecl *IVar) {
152*67e74705SXin Li return new (C) ObjCIvarRefExpr(const_cast<ObjCIvarDecl*>(IVar),
153*67e74705SXin Li IVar->getType(), SourceLocation(),
154*67e74705SXin Li SourceLocation(), const_cast<Expr*>(Base),
155*67e74705SXin Li /*arrow=*/true, /*free=*/false);
156*67e74705SXin Li }
157*67e74705SXin Li
158*67e74705SXin Li
makeReturn(const Expr * RetVal)159*67e74705SXin Li ReturnStmt *ASTMaker::makeReturn(const Expr *RetVal) {
160*67e74705SXin Li return new (C) ReturnStmt(SourceLocation(), const_cast<Expr*>(RetVal),
161*67e74705SXin Li nullptr);
162*67e74705SXin Li }
163*67e74705SXin Li
164*67e74705SXin Li //===----------------------------------------------------------------------===//
165*67e74705SXin Li // Creation functions for faux ASTs.
166*67e74705SXin Li //===----------------------------------------------------------------------===//
167*67e74705SXin Li
168*67e74705SXin Li typedef Stmt *(*FunctionFarmer)(ASTContext &C, const FunctionDecl *D);
169*67e74705SXin Li
170*67e74705SXin Li /// Create a fake body for dispatch_once.
create_dispatch_once(ASTContext & C,const FunctionDecl * D)171*67e74705SXin Li static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
172*67e74705SXin Li // Check if we have at least two parameters.
173*67e74705SXin Li if (D->param_size() != 2)
174*67e74705SXin Li return nullptr;
175*67e74705SXin Li
176*67e74705SXin Li // Check if the first parameter is a pointer to integer type.
177*67e74705SXin Li const ParmVarDecl *Predicate = D->getParamDecl(0);
178*67e74705SXin Li QualType PredicateQPtrTy = Predicate->getType();
179*67e74705SXin Li const PointerType *PredicatePtrTy = PredicateQPtrTy->getAs<PointerType>();
180*67e74705SXin Li if (!PredicatePtrTy)
181*67e74705SXin Li return nullptr;
182*67e74705SXin Li QualType PredicateTy = PredicatePtrTy->getPointeeType();
183*67e74705SXin Li if (!PredicateTy->isIntegerType())
184*67e74705SXin Li return nullptr;
185*67e74705SXin Li
186*67e74705SXin Li // Check if the second parameter is the proper block type.
187*67e74705SXin Li const ParmVarDecl *Block = D->getParamDecl(1);
188*67e74705SXin Li QualType Ty = Block->getType();
189*67e74705SXin Li if (!isDispatchBlock(Ty))
190*67e74705SXin Li return nullptr;
191*67e74705SXin Li
192*67e74705SXin Li // Everything checks out. Create a fakse body that checks the predicate,
193*67e74705SXin Li // sets it, and calls the block. Basically, an AST dump of:
194*67e74705SXin Li //
195*67e74705SXin Li // void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block) {
196*67e74705SXin Li // if (!*predicate) {
197*67e74705SXin Li // *predicate = 1;
198*67e74705SXin Li // block();
199*67e74705SXin Li // }
200*67e74705SXin Li // }
201*67e74705SXin Li
202*67e74705SXin Li ASTMaker M(C);
203*67e74705SXin Li
204*67e74705SXin Li // (1) Create the call.
205*67e74705SXin Li DeclRefExpr *DR = M.makeDeclRefExpr(Block);
206*67e74705SXin Li ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty);
207*67e74705SXin Li CallExpr *CE = new (C) CallExpr(C, ICE, None, C.VoidTy, VK_RValue,
208*67e74705SXin Li SourceLocation());
209*67e74705SXin Li
210*67e74705SXin Li // (2) Create the assignment to the predicate.
211*67e74705SXin Li IntegerLiteral *IL =
212*67e74705SXin Li IntegerLiteral::Create(C, llvm::APInt(C.getTypeSize(C.IntTy), (uint64_t) 1),
213*67e74705SXin Li C.IntTy, SourceLocation());
214*67e74705SXin Li BinaryOperator *B =
215*67e74705SXin Li M.makeAssignment(
216*67e74705SXin Li M.makeDereference(
217*67e74705SXin Li M.makeLvalueToRvalue(
218*67e74705SXin Li M.makeDeclRefExpr(Predicate), PredicateQPtrTy),
219*67e74705SXin Li PredicateTy),
220*67e74705SXin Li M.makeIntegralCast(IL, PredicateTy),
221*67e74705SXin Li PredicateTy);
222*67e74705SXin Li
223*67e74705SXin Li // (3) Create the compound statement.
224*67e74705SXin Li Stmt *Stmts[] = { B, CE };
225*67e74705SXin Li CompoundStmt *CS = M.makeCompound(Stmts);
226*67e74705SXin Li
227*67e74705SXin Li // (4) Create the 'if' condition.
228*67e74705SXin Li ImplicitCastExpr *LValToRval =
229*67e74705SXin Li M.makeLvalueToRvalue(
230*67e74705SXin Li M.makeDereference(
231*67e74705SXin Li M.makeLvalueToRvalue(
232*67e74705SXin Li M.makeDeclRefExpr(Predicate),
233*67e74705SXin Li PredicateQPtrTy),
234*67e74705SXin Li PredicateTy),
235*67e74705SXin Li PredicateTy);
236*67e74705SXin Li
237*67e74705SXin Li UnaryOperator *UO = new (C) UnaryOperator(LValToRval, UO_LNot, C.IntTy,
238*67e74705SXin Li VK_RValue, OK_Ordinary,
239*67e74705SXin Li SourceLocation());
240*67e74705SXin Li
241*67e74705SXin Li // (5) Create the 'if' statement.
242*67e74705SXin Li IfStmt *If = new (C) IfStmt(C, SourceLocation(), false, nullptr, nullptr,
243*67e74705SXin Li UO, CS);
244*67e74705SXin Li return If;
245*67e74705SXin Li }
246*67e74705SXin Li
247*67e74705SXin Li /// Create a fake body for dispatch_sync.
create_dispatch_sync(ASTContext & C,const FunctionDecl * D)248*67e74705SXin Li static Stmt *create_dispatch_sync(ASTContext &C, const FunctionDecl *D) {
249*67e74705SXin Li // Check if we have at least two parameters.
250*67e74705SXin Li if (D->param_size() != 2)
251*67e74705SXin Li return nullptr;
252*67e74705SXin Li
253*67e74705SXin Li // Check if the second parameter is a block.
254*67e74705SXin Li const ParmVarDecl *PV = D->getParamDecl(1);
255*67e74705SXin Li QualType Ty = PV->getType();
256*67e74705SXin Li if (!isDispatchBlock(Ty))
257*67e74705SXin Li return nullptr;
258*67e74705SXin Li
259*67e74705SXin Li // Everything checks out. Create a fake body that just calls the block.
260*67e74705SXin Li // This is basically just an AST dump of:
261*67e74705SXin Li //
262*67e74705SXin Li // void dispatch_sync(dispatch_queue_t queue, void (^block)(void)) {
263*67e74705SXin Li // block();
264*67e74705SXin Li // }
265*67e74705SXin Li //
266*67e74705SXin Li ASTMaker M(C);
267*67e74705SXin Li DeclRefExpr *DR = M.makeDeclRefExpr(PV);
268*67e74705SXin Li ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty);
269*67e74705SXin Li CallExpr *CE = new (C) CallExpr(C, ICE, None, C.VoidTy, VK_RValue,
270*67e74705SXin Li SourceLocation());
271*67e74705SXin Li return CE;
272*67e74705SXin Li }
273*67e74705SXin Li
create_OSAtomicCompareAndSwap(ASTContext & C,const FunctionDecl * D)274*67e74705SXin Li static Stmt *create_OSAtomicCompareAndSwap(ASTContext &C, const FunctionDecl *D)
275*67e74705SXin Li {
276*67e74705SXin Li // There are exactly 3 arguments.
277*67e74705SXin Li if (D->param_size() != 3)
278*67e74705SXin Li return nullptr;
279*67e74705SXin Li
280*67e74705SXin Li // Signature:
281*67e74705SXin Li // _Bool OSAtomicCompareAndSwapPtr(void *__oldValue,
282*67e74705SXin Li // void *__newValue,
283*67e74705SXin Li // void * volatile *__theValue)
284*67e74705SXin Li // Generate body:
285*67e74705SXin Li // if (oldValue == *theValue) {
286*67e74705SXin Li // *theValue = newValue;
287*67e74705SXin Li // return YES;
288*67e74705SXin Li // }
289*67e74705SXin Li // else return NO;
290*67e74705SXin Li
291*67e74705SXin Li QualType ResultTy = D->getReturnType();
292*67e74705SXin Li bool isBoolean = ResultTy->isBooleanType();
293*67e74705SXin Li if (!isBoolean && !ResultTy->isIntegralType(C))
294*67e74705SXin Li return nullptr;
295*67e74705SXin Li
296*67e74705SXin Li const ParmVarDecl *OldValue = D->getParamDecl(0);
297*67e74705SXin Li QualType OldValueTy = OldValue->getType();
298*67e74705SXin Li
299*67e74705SXin Li const ParmVarDecl *NewValue = D->getParamDecl(1);
300*67e74705SXin Li QualType NewValueTy = NewValue->getType();
301*67e74705SXin Li
302*67e74705SXin Li assert(OldValueTy == NewValueTy);
303*67e74705SXin Li
304*67e74705SXin Li const ParmVarDecl *TheValue = D->getParamDecl(2);
305*67e74705SXin Li QualType TheValueTy = TheValue->getType();
306*67e74705SXin Li const PointerType *PT = TheValueTy->getAs<PointerType>();
307*67e74705SXin Li if (!PT)
308*67e74705SXin Li return nullptr;
309*67e74705SXin Li QualType PointeeTy = PT->getPointeeType();
310*67e74705SXin Li
311*67e74705SXin Li ASTMaker M(C);
312*67e74705SXin Li // Construct the comparison.
313*67e74705SXin Li Expr *Comparison =
314*67e74705SXin Li M.makeComparison(
315*67e74705SXin Li M.makeLvalueToRvalue(M.makeDeclRefExpr(OldValue), OldValueTy),
316*67e74705SXin Li M.makeLvalueToRvalue(
317*67e74705SXin Li M.makeDereference(
318*67e74705SXin Li M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
319*67e74705SXin Li PointeeTy),
320*67e74705SXin Li PointeeTy),
321*67e74705SXin Li BO_EQ);
322*67e74705SXin Li
323*67e74705SXin Li // Construct the body of the IfStmt.
324*67e74705SXin Li Stmt *Stmts[2];
325*67e74705SXin Li Stmts[0] =
326*67e74705SXin Li M.makeAssignment(
327*67e74705SXin Li M.makeDereference(
328*67e74705SXin Li M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
329*67e74705SXin Li PointeeTy),
330*67e74705SXin Li M.makeLvalueToRvalue(M.makeDeclRefExpr(NewValue), NewValueTy),
331*67e74705SXin Li NewValueTy);
332*67e74705SXin Li
333*67e74705SXin Li Expr *BoolVal = M.makeObjCBool(true);
334*67e74705SXin Li Expr *RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
335*67e74705SXin Li : M.makeIntegralCast(BoolVal, ResultTy);
336*67e74705SXin Li Stmts[1] = M.makeReturn(RetVal);
337*67e74705SXin Li CompoundStmt *Body = M.makeCompound(Stmts);
338*67e74705SXin Li
339*67e74705SXin Li // Construct the else clause.
340*67e74705SXin Li BoolVal = M.makeObjCBool(false);
341*67e74705SXin Li RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
342*67e74705SXin Li : M.makeIntegralCast(BoolVal, ResultTy);
343*67e74705SXin Li Stmt *Else = M.makeReturn(RetVal);
344*67e74705SXin Li
345*67e74705SXin Li /// Construct the If.
346*67e74705SXin Li Stmt *If = new (C) IfStmt(C, SourceLocation(), false, nullptr, nullptr,
347*67e74705SXin Li Comparison, Body, SourceLocation(), Else);
348*67e74705SXin Li
349*67e74705SXin Li return If;
350*67e74705SXin Li }
351*67e74705SXin Li
getBody(const FunctionDecl * D)352*67e74705SXin Li Stmt *BodyFarm::getBody(const FunctionDecl *D) {
353*67e74705SXin Li D = D->getCanonicalDecl();
354*67e74705SXin Li
355*67e74705SXin Li Optional<Stmt *> &Val = Bodies[D];
356*67e74705SXin Li if (Val.hasValue())
357*67e74705SXin Li return Val.getValue();
358*67e74705SXin Li
359*67e74705SXin Li Val = nullptr;
360*67e74705SXin Li
361*67e74705SXin Li if (D->getIdentifier() == nullptr)
362*67e74705SXin Li return nullptr;
363*67e74705SXin Li
364*67e74705SXin Li StringRef Name = D->getName();
365*67e74705SXin Li if (Name.empty())
366*67e74705SXin Li return nullptr;
367*67e74705SXin Li
368*67e74705SXin Li FunctionFarmer FF;
369*67e74705SXin Li
370*67e74705SXin Li if (Name.startswith("OSAtomicCompareAndSwap") ||
371*67e74705SXin Li Name.startswith("objc_atomicCompareAndSwap")) {
372*67e74705SXin Li FF = create_OSAtomicCompareAndSwap;
373*67e74705SXin Li }
374*67e74705SXin Li else {
375*67e74705SXin Li FF = llvm::StringSwitch<FunctionFarmer>(Name)
376*67e74705SXin Li .Case("dispatch_sync", create_dispatch_sync)
377*67e74705SXin Li .Case("dispatch_once", create_dispatch_once)
378*67e74705SXin Li .Default(nullptr);
379*67e74705SXin Li }
380*67e74705SXin Li
381*67e74705SXin Li if (FF) { Val = FF(C, D); }
382*67e74705SXin Li else if (Injector) { Val = Injector->getBody(D); }
383*67e74705SXin Li return Val.getValue();
384*67e74705SXin Li }
385*67e74705SXin Li
findBackingIvar(const ObjCPropertyDecl * Prop)386*67e74705SXin Li static const ObjCIvarDecl *findBackingIvar(const ObjCPropertyDecl *Prop) {
387*67e74705SXin Li const ObjCIvarDecl *IVar = Prop->getPropertyIvarDecl();
388*67e74705SXin Li
389*67e74705SXin Li if (IVar)
390*67e74705SXin Li return IVar;
391*67e74705SXin Li
392*67e74705SXin Li // When a readonly property is shadowed in a class extensions with a
393*67e74705SXin Li // a readwrite property, the instance variable belongs to the shadowing
394*67e74705SXin Li // property rather than the shadowed property. If there is no instance
395*67e74705SXin Li // variable on a readonly property, check to see whether the property is
396*67e74705SXin Li // shadowed and if so try to get the instance variable from shadowing
397*67e74705SXin Li // property.
398*67e74705SXin Li if (!Prop->isReadOnly())
399*67e74705SXin Li return nullptr;
400*67e74705SXin Li
401*67e74705SXin Li auto *Container = cast<ObjCContainerDecl>(Prop->getDeclContext());
402*67e74705SXin Li const ObjCInterfaceDecl *PrimaryInterface = nullptr;
403*67e74705SXin Li if (auto *InterfaceDecl = dyn_cast<ObjCInterfaceDecl>(Container)) {
404*67e74705SXin Li PrimaryInterface = InterfaceDecl;
405*67e74705SXin Li } else if (auto *CategoryDecl = dyn_cast<ObjCCategoryDecl>(Container)) {
406*67e74705SXin Li PrimaryInterface = CategoryDecl->getClassInterface();
407*67e74705SXin Li } else if (auto *ImplDecl = dyn_cast<ObjCImplDecl>(Container)) {
408*67e74705SXin Li PrimaryInterface = ImplDecl->getClassInterface();
409*67e74705SXin Li } else {
410*67e74705SXin Li return nullptr;
411*67e74705SXin Li }
412*67e74705SXin Li
413*67e74705SXin Li // FindPropertyVisibleInPrimaryClass() looks first in class extensions, so it
414*67e74705SXin Li // is guaranteed to find the shadowing property, if it exists, rather than
415*67e74705SXin Li // the shadowed property.
416*67e74705SXin Li auto *ShadowingProp = PrimaryInterface->FindPropertyVisibleInPrimaryClass(
417*67e74705SXin Li Prop->getIdentifier(), Prop->getQueryKind());
418*67e74705SXin Li if (ShadowingProp && ShadowingProp != Prop) {
419*67e74705SXin Li IVar = ShadowingProp->getPropertyIvarDecl();
420*67e74705SXin Li }
421*67e74705SXin Li
422*67e74705SXin Li return IVar;
423*67e74705SXin Li }
424*67e74705SXin Li
createObjCPropertyGetter(ASTContext & Ctx,const ObjCPropertyDecl * Prop)425*67e74705SXin Li static Stmt *createObjCPropertyGetter(ASTContext &Ctx,
426*67e74705SXin Li const ObjCPropertyDecl *Prop) {
427*67e74705SXin Li // First, find the backing ivar.
428*67e74705SXin Li const ObjCIvarDecl *IVar = findBackingIvar(Prop);
429*67e74705SXin Li if (!IVar)
430*67e74705SXin Li return nullptr;
431*67e74705SXin Li
432*67e74705SXin Li // Ignore weak variables, which have special behavior.
433*67e74705SXin Li if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak)
434*67e74705SXin Li return nullptr;
435*67e74705SXin Li
436*67e74705SXin Li // Look to see if Sema has synthesized a body for us. This happens in
437*67e74705SXin Li // Objective-C++ because the return value may be a C++ class type with a
438*67e74705SXin Li // non-trivial copy constructor. We can only do this if we can find the
439*67e74705SXin Li // @synthesize for this property, though (or if we know it's been auto-
440*67e74705SXin Li // synthesized).
441*67e74705SXin Li const ObjCImplementationDecl *ImplDecl =
442*67e74705SXin Li IVar->getContainingInterface()->getImplementation();
443*67e74705SXin Li if (ImplDecl) {
444*67e74705SXin Li for (const auto *I : ImplDecl->property_impls()) {
445*67e74705SXin Li if (I->getPropertyDecl() != Prop)
446*67e74705SXin Li continue;
447*67e74705SXin Li
448*67e74705SXin Li if (I->getGetterCXXConstructor()) {
449*67e74705SXin Li ASTMaker M(Ctx);
450*67e74705SXin Li return M.makeReturn(I->getGetterCXXConstructor());
451*67e74705SXin Li }
452*67e74705SXin Li }
453*67e74705SXin Li }
454*67e74705SXin Li
455*67e74705SXin Li // Sanity check that the property is the same type as the ivar, or a
456*67e74705SXin Li // reference to it, and that it is either an object pointer or trivially
457*67e74705SXin Li // copyable.
458*67e74705SXin Li if (!Ctx.hasSameUnqualifiedType(IVar->getType(),
459*67e74705SXin Li Prop->getType().getNonReferenceType()))
460*67e74705SXin Li return nullptr;
461*67e74705SXin Li if (!IVar->getType()->isObjCLifetimeType() &&
462*67e74705SXin Li !IVar->getType().isTriviallyCopyableType(Ctx))
463*67e74705SXin Li return nullptr;
464*67e74705SXin Li
465*67e74705SXin Li // Generate our body:
466*67e74705SXin Li // return self->_ivar;
467*67e74705SXin Li ASTMaker M(Ctx);
468*67e74705SXin Li
469*67e74705SXin Li const VarDecl *selfVar = Prop->getGetterMethodDecl()->getSelfDecl();
470*67e74705SXin Li
471*67e74705SXin Li Expr *loadedIVar =
472*67e74705SXin Li M.makeObjCIvarRef(
473*67e74705SXin Li M.makeLvalueToRvalue(
474*67e74705SXin Li M.makeDeclRefExpr(selfVar),
475*67e74705SXin Li selfVar->getType()),
476*67e74705SXin Li IVar);
477*67e74705SXin Li
478*67e74705SXin Li if (!Prop->getType()->isReferenceType())
479*67e74705SXin Li loadedIVar = M.makeLvalueToRvalue(loadedIVar, IVar->getType());
480*67e74705SXin Li
481*67e74705SXin Li return M.makeReturn(loadedIVar);
482*67e74705SXin Li }
483*67e74705SXin Li
getBody(const ObjCMethodDecl * D)484*67e74705SXin Li Stmt *BodyFarm::getBody(const ObjCMethodDecl *D) {
485*67e74705SXin Li // We currently only know how to synthesize property accessors.
486*67e74705SXin Li if (!D->isPropertyAccessor())
487*67e74705SXin Li return nullptr;
488*67e74705SXin Li
489*67e74705SXin Li D = D->getCanonicalDecl();
490*67e74705SXin Li
491*67e74705SXin Li Optional<Stmt *> &Val = Bodies[D];
492*67e74705SXin Li if (Val.hasValue())
493*67e74705SXin Li return Val.getValue();
494*67e74705SXin Li Val = nullptr;
495*67e74705SXin Li
496*67e74705SXin Li const ObjCPropertyDecl *Prop = D->findPropertyDecl();
497*67e74705SXin Li if (!Prop)
498*67e74705SXin Li return nullptr;
499*67e74705SXin Li
500*67e74705SXin Li // For now, we only synthesize getters.
501*67e74705SXin Li // Synthesizing setters would cause false negatives in the
502*67e74705SXin Li // RetainCountChecker because the method body would bind the parameter
503*67e74705SXin Li // to an instance variable, causing it to escape. This would prevent
504*67e74705SXin Li // warning in the following common scenario:
505*67e74705SXin Li //
506*67e74705SXin Li // id foo = [[NSObject alloc] init];
507*67e74705SXin Li // self.foo = foo; // We should warn that foo leaks here.
508*67e74705SXin Li //
509*67e74705SXin Li if (D->param_size() != 0)
510*67e74705SXin Li return nullptr;
511*67e74705SXin Li
512*67e74705SXin Li Val = createObjCPropertyGetter(C, Prop);
513*67e74705SXin Li
514*67e74705SXin Li return Val.getValue();
515*67e74705SXin Li }
516*67e74705SXin Li
517