blob: acab7c5e91a3f326610b175179e705627d296071 [file] [log] [blame]
Ted Kremenek14f779c2012-09-21 00:09:11 +00001//== BodyFarm.cpp - Factory for conjuring up fake bodies ----------*- C++ -*-//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// BodyFarm is a factory for creating faux implementations for functions/methods
11// for analysis purposes.
12//
13//===----------------------------------------------------------------------===//
14
Ted Kremenek14f779c2012-09-21 00:09:11 +000015#include "BodyFarm.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000016#include "clang/AST/ASTContext.h"
George Karpenkov657a5892017-09-30 00:03:22 +000017#include "clang/AST/CXXInheritance.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000018#include "clang/AST/Decl.h"
19#include "clang/AST/Expr.h"
George Karpenkov657a5892017-09-30 00:03:22 +000020#include "clang/AST/ExprCXX.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000021#include "clang/AST/ExprObjC.h"
George Karpenkov657a5892017-09-30 00:03:22 +000022#include "clang/AST/NestedNameSpecifier.h"
Chandler Carruth0d9593d2015-01-14 11:29:14 +000023#include "clang/Analysis/CodeInjector.h"
George Karpenkov657a5892017-09-30 00:03:22 +000024#include "clang/Basic/OperatorKinds.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000025#include "llvm/ADT/StringSwitch.h"
George Karpenkov657a5892017-09-30 00:03:22 +000026#include "llvm/Support/Debug.h"
27
28#define DEBUG_TYPE "body-farm"
Ted Kremenek14f779c2012-09-21 00:09:11 +000029
30using namespace clang;
31
Ted Kremenek2b5c83c2012-09-21 17:54:32 +000032//===----------------------------------------------------------------------===//
33// Helper creation functions for constructing faux ASTs.
34//===----------------------------------------------------------------------===//
Ted Kremenek14f779c2012-09-21 00:09:11 +000035
Ted Kremenekd81a4a12012-09-21 00:52:24 +000036static bool isDispatchBlock(QualType Ty) {
37 // Is it a block pointer?
38 const BlockPointerType *BPT = Ty->getAs<BlockPointerType>();
39 if (!BPT)
40 return false;
41
42 // Check if the block pointer type takes no arguments and
43 // returns void.
44 const FunctionProtoType *FT =
45 BPT->getPointeeType()->getAs<FunctionProtoType>();
Alexander Kornienko090360d2015-11-06 01:08:38 +000046 return FT && FT->getReturnType()->isVoidType() && FT->getNumParams() == 0;
Ted Kremenekd81a4a12012-09-21 00:52:24 +000047}
48
Ted Kremenek72418132012-09-21 17:54:35 +000049namespace {
50class ASTMaker {
51public:
52 ASTMaker(ASTContext &C) : C(C) {}
53
Ted Kremenekf465dc12012-09-21 18:33:54 +000054 /// Create a new BinaryOperator representing a simple assignment.
55 BinaryOperator *makeAssignment(const Expr *LHS, const Expr *RHS, QualType Ty);
56
Ted Kremenek089ffd02012-10-11 20:58:18 +000057 /// Create a new BinaryOperator representing a comparison.
58 BinaryOperator *makeComparison(const Expr *LHS, const Expr *RHS,
59 BinaryOperator::Opcode Op);
60
61 /// Create a new compound stmt using the provided statements.
62 CompoundStmt *makeCompound(ArrayRef<Stmt*>);
63
Ted Kremenek69bcb822012-09-21 18:13:23 +000064 /// Create a new DeclRefExpr for the referenced variable.
George Karpenkov657a5892017-09-30 00:03:22 +000065 DeclRefExpr *makeDeclRefExpr(const VarDecl *D,
66 bool RefersToEnclosingVariableOrCapture = false,
67 bool GetNonReferenceType = false);
Ted Kremenek72418132012-09-21 17:54:35 +000068
Ted Kremenekdff35532012-09-21 18:33:52 +000069 /// Create a new UnaryOperator representing a dereference.
70 UnaryOperator *makeDereference(const Expr *Arg, QualType Ty);
71
Ted Kremenek69bcb822012-09-21 18:13:23 +000072 /// Create an implicit cast for an integer conversion.
Ted Kremenek6fdefb52012-10-12 00:18:19 +000073 Expr *makeIntegralCast(const Expr *Arg, QualType Ty);
Ted Kremenek69bcb822012-09-21 18:13:23 +000074
Ted Kremenek089ffd02012-10-11 20:58:18 +000075 /// Create an implicit cast to a builtin boolean type.
76 ImplicitCastExpr *makeIntegralCastToBoolean(const Expr *Arg);
77
George Karpenkov657a5892017-09-30 00:03:22 +000078 /// Create an implicit cast for lvalue-to-rvaluate conversions.
Ted Kremenekca90ea52012-09-21 18:13:27 +000079 ImplicitCastExpr *makeLvalueToRvalue(const Expr *Arg, QualType Ty);
80
George Karpenkov657a5892017-09-30 00:03:22 +000081 /// Make RValue out of variable declaration, creating a temporary
82 /// DeclRefExpr in the process.
83 ImplicitCastExpr *
84 makeLvalueToRvalue(const VarDecl *Decl,
85 bool RefersToEnclosingVariableOrCapture = false,
86 bool GetNonReferenceType = false);
87
88 /// Create an implicit cast of the given type.
89 ImplicitCastExpr *makeImplicitCast(const Expr *Arg, QualType Ty,
90 CastKind CK = CK_LValueToRValue);
91
Ted Kremenek089ffd02012-10-11 20:58:18 +000092 /// Create an Objective-C bool literal.
93 ObjCBoolLiteralExpr *makeObjCBool(bool Val);
Jordan Rose1a866cd2014-01-10 20:06:06 +000094
95 /// Create an Objective-C ivar reference.
96 ObjCIvarRefExpr *makeObjCIvarRef(const Expr *Base, const ObjCIvarDecl *IVar);
Ted Kremenek089ffd02012-10-11 20:58:18 +000097
98 /// Create a Return statement.
99 ReturnStmt *makeReturn(const Expr *RetVal);
100
George Karpenkov657a5892017-09-30 00:03:22 +0000101 /// Create an integer literal.
102 IntegerLiteral *makeIntegerLiteral(uint64_t value);
103
104 /// Create a member expression.
105 MemberExpr *makeMemberExpression(Expr *base, ValueDecl *MemberDecl,
106 bool IsArrow = false,
107 ExprValueKind ValueKind = VK_LValue);
108
109 /// Returns a *first* member field of a record declaration with a given name.
110 /// \return an nullptr if no member with such a name exists.
111 NamedDecl *findMemberField(const CXXRecordDecl *RD, StringRef Name);
112
Ted Kremenek72418132012-09-21 17:54:35 +0000113private:
114 ASTContext &C;
115};
Alexander Kornienkoab9db512015-06-22 23:07:51 +0000116}
Ted Kremenek72418132012-09-21 17:54:35 +0000117
Ted Kremenekf465dc12012-09-21 18:33:54 +0000118BinaryOperator *ASTMaker::makeAssignment(const Expr *LHS, const Expr *RHS,
119 QualType Ty) {
120 return new (C) BinaryOperator(const_cast<Expr*>(LHS), const_cast<Expr*>(RHS),
121 BO_Assign, Ty, VK_RValue,
Adam Nemet484aa452017-03-27 19:17:25 +0000122 OK_Ordinary, SourceLocation(), FPOptions());
Ted Kremenekf465dc12012-09-21 18:33:54 +0000123}
124
Ted Kremenek089ffd02012-10-11 20:58:18 +0000125BinaryOperator *ASTMaker::makeComparison(const Expr *LHS, const Expr *RHS,
126 BinaryOperator::Opcode Op) {
127 assert(BinaryOperator::isLogicalOp(Op) ||
128 BinaryOperator::isComparisonOp(Op));
129 return new (C) BinaryOperator(const_cast<Expr*>(LHS),
130 const_cast<Expr*>(RHS),
131 Op,
132 C.getLogicalOperationType(),
133 VK_RValue,
Adam Nemet484aa452017-03-27 19:17:25 +0000134 OK_Ordinary, SourceLocation(), FPOptions());
Ted Kremenek089ffd02012-10-11 20:58:18 +0000135}
136
137CompoundStmt *ASTMaker::makeCompound(ArrayRef<Stmt *> Stmts) {
Nico Webera2a0eb92012-12-29 20:03:39 +0000138 return new (C) CompoundStmt(C, Stmts, SourceLocation(), SourceLocation());
Ted Kremenek089ffd02012-10-11 20:58:18 +0000139}
140
George Karpenkov657a5892017-09-30 00:03:22 +0000141DeclRefExpr *ASTMaker::makeDeclRefExpr(const VarDecl *D,
142 bool RefersToEnclosingVariableOrCapture,
143 bool GetNonReferenceType) {
144 auto Type = D->getType();
145 if (GetNonReferenceType)
146 Type = Type.getNonReferenceType();
147
148 DeclRefExpr *DR = DeclRefExpr::Create(
149 C, NestedNameSpecifierLoc(), SourceLocation(), const_cast<VarDecl *>(D),
150 RefersToEnclosingVariableOrCapture, SourceLocation(), Type, VK_LValue);
Ted Kremenek72418132012-09-21 17:54:35 +0000151 return DR;
152}
153
Ted Kremenekdff35532012-09-21 18:33:52 +0000154UnaryOperator *ASTMaker::makeDereference(const Expr *Arg, QualType Ty) {
155 return new (C) UnaryOperator(const_cast<Expr*>(Arg), UO_Deref, Ty,
156 VK_LValue, OK_Ordinary, SourceLocation());
157}
158
Ted Kremenekca90ea52012-09-21 18:13:27 +0000159ImplicitCastExpr *ASTMaker::makeLvalueToRvalue(const Expr *Arg, QualType Ty) {
George Karpenkov657a5892017-09-30 00:03:22 +0000160 return makeImplicitCast(Arg, Ty, CK_LValueToRValue);
161}
162
George Karpenkov657a5892017-09-30 00:03:22 +0000163ImplicitCastExpr *
164ASTMaker::makeLvalueToRvalue(const VarDecl *Arg,
165 bool RefersToEnclosingVariableOrCapture,
166 bool GetNonReferenceType) {
167 auto Type = Arg->getType();
168 if (GetNonReferenceType)
169 Type = Type.getNonReferenceType();
170 return makeLvalueToRvalue(makeDeclRefExpr(Arg,
171 RefersToEnclosingVariableOrCapture,
172 GetNonReferenceType),
173 Type);
174}
175
176ImplicitCastExpr *ASTMaker::makeImplicitCast(const Expr *Arg, QualType Ty,
177 CastKind CK) {
178 return ImplicitCastExpr::Create(C, Ty,
179 /* CastKind= */ CK,
180 /* Expr= */ const_cast<Expr *>(Arg),
181 /* CXXCastPath= */ nullptr,
182 /* ExprValueKind= */ VK_RValue);
Ted Kremenekca90ea52012-09-21 18:13:27 +0000183}
184
Ted Kremenek6fdefb52012-10-12 00:18:19 +0000185Expr *ASTMaker::makeIntegralCast(const Expr *Arg, QualType Ty) {
186 if (Arg->getType() == Ty)
187 return const_cast<Expr*>(Arg);
Craig Topper25542942014-05-20 04:30:07 +0000188
Ted Kremenek69bcb822012-09-21 18:13:23 +0000189 return ImplicitCastExpr::Create(C, Ty, CK_IntegralCast,
Craig Topper25542942014-05-20 04:30:07 +0000190 const_cast<Expr*>(Arg), nullptr, VK_RValue);
Ted Kremenek69bcb822012-09-21 18:13:23 +0000191}
192
Ted Kremenek089ffd02012-10-11 20:58:18 +0000193ImplicitCastExpr *ASTMaker::makeIntegralCastToBoolean(const Expr *Arg) {
194 return ImplicitCastExpr::Create(C, C.BoolTy, CK_IntegralToBoolean,
Craig Topper25542942014-05-20 04:30:07 +0000195 const_cast<Expr*>(Arg), nullptr, VK_RValue);
Ted Kremenek089ffd02012-10-11 20:58:18 +0000196}
197
198ObjCBoolLiteralExpr *ASTMaker::makeObjCBool(bool Val) {
199 QualType Ty = C.getBOOLDecl() ? C.getBOOLType() : C.ObjCBuiltinBoolTy;
200 return new (C) ObjCBoolLiteralExpr(Val, Ty, SourceLocation());
201}
202
Jordan Rose1a866cd2014-01-10 20:06:06 +0000203ObjCIvarRefExpr *ASTMaker::makeObjCIvarRef(const Expr *Base,
204 const ObjCIvarDecl *IVar) {
205 return new (C) ObjCIvarRefExpr(const_cast<ObjCIvarDecl*>(IVar),
206 IVar->getType(), SourceLocation(),
207 SourceLocation(), const_cast<Expr*>(Base),
208 /*arrow=*/true, /*free=*/false);
209}
210
211
Ted Kremenek089ffd02012-10-11 20:58:18 +0000212ReturnStmt *ASTMaker::makeReturn(const Expr *RetVal) {
Craig Topper25542942014-05-20 04:30:07 +0000213 return new (C) ReturnStmt(SourceLocation(), const_cast<Expr*>(RetVal),
214 nullptr);
Ted Kremenek089ffd02012-10-11 20:58:18 +0000215}
216
George Karpenkov657a5892017-09-30 00:03:22 +0000217IntegerLiteral *ASTMaker::makeIntegerLiteral(uint64_t value) {
218 return IntegerLiteral::Create(C,
219 llvm::APInt(
220 /*numBits=*/C.getTypeSize(C.IntTy), value),
221 /*QualType=*/C.IntTy, SourceLocation());
222}
223
224MemberExpr *ASTMaker::makeMemberExpression(Expr *base, ValueDecl *MemberDecl,
225 bool IsArrow,
226 ExprValueKind ValueKind) {
227
228 DeclAccessPair FoundDecl = DeclAccessPair::make(MemberDecl, AS_public);
229 return MemberExpr::Create(
230 C, base, IsArrow, SourceLocation(), NestedNameSpecifierLoc(),
231 SourceLocation(), MemberDecl, FoundDecl,
232 DeclarationNameInfo(MemberDecl->getDeclName(), SourceLocation()),
233 /* TemplateArgumentListInfo= */ nullptr, MemberDecl->getType(), ValueKind,
234 OK_Ordinary);
235}
236
237NamedDecl *ASTMaker::findMemberField(const CXXRecordDecl *RD, StringRef Name) {
238
239 CXXBasePaths Paths(
240 /* FindAmbiguities=*/false,
241 /* RecordPaths=*/false,
242 /* DetectVirtual= */ false);
243 const IdentifierInfo &II = C.Idents.get(Name);
244 DeclarationName DeclName = C.DeclarationNames.getIdentifier(&II);
245
246 DeclContextLookupResult Decls = RD->lookup(DeclName);
247 for (NamedDecl *FoundDecl : Decls)
248 if (!FoundDecl->getDeclContext()->isFunctionOrMethod())
249 return FoundDecl;
250
251 return nullptr;
252}
253
Ted Kremenek2b5c83c2012-09-21 17:54:32 +0000254//===----------------------------------------------------------------------===//
255// Creation functions for faux ASTs.
256//===----------------------------------------------------------------------===//
257
258typedef Stmt *(*FunctionFarmer)(ASTContext &C, const FunctionDecl *D);
259
George Karpenkov657a5892017-09-30 00:03:22 +0000260static CallExpr *
261create_call_once_funcptr_call(ASTContext &C, ASTMaker M,
262 const ParmVarDecl *Callback,
263 SmallVectorImpl<Expr *> &CallArgs) {
264
265 return new (C) CallExpr(
266 /*ASTContext=*/C,
267 /*StmtClass=*/M.makeLvalueToRvalue(/*Expr=*/Callback),
268 /*args=*/CallArgs,
269 /*QualType=*/C.VoidTy,
270 /*ExprValueType=*/VK_RValue,
271 /*SourceLocation=*/SourceLocation());
272}
273
274static CallExpr *
275create_call_once_lambda_call(ASTContext &C, ASTMaker M,
276 const ParmVarDecl *Callback, QualType CallbackType,
277 SmallVectorImpl<Expr *> &CallArgs) {
278
279 CXXRecordDecl *CallbackDecl = CallbackType->getAsCXXRecordDecl();
280
281 assert(CallbackDecl != nullptr);
282 assert(CallbackDecl->isLambda());
283 FunctionDecl *callOperatorDecl = CallbackDecl->getLambdaCallOperator();
284 assert(callOperatorDecl != nullptr);
285
286 DeclRefExpr *callOperatorDeclRef =
287 DeclRefExpr::Create(/* Ctx = */ C,
288 /* QualifierLoc = */ NestedNameSpecifierLoc(),
289 /* TemplateKWLoc = */ SourceLocation(),
290 const_cast<FunctionDecl *>(callOperatorDecl),
291 /* RefersToEnclosingVariableOrCapture= */ false,
292 /* NameLoc = */ SourceLocation(),
293 /* T = */ callOperatorDecl->getType(),
294 /* VK = */ VK_LValue);
295
296 CallArgs.insert(
297 CallArgs.begin(),
298 M.makeDeclRefExpr(Callback,
299 /* RefersToEnclosingVariableOrCapture= */ true,
300 /* GetNonReferenceType= */ true));
301
302 return new (C)
303 CXXOperatorCallExpr(/*AstContext=*/C, OO_Call, callOperatorDeclRef,
304 /*args=*/CallArgs,
305 /*QualType=*/C.VoidTy,
306 /*ExprValueType=*/VK_RValue,
307 /*SourceLocation=*/SourceLocation(), FPOptions());
308}
309
310/// Create a fake body for std::call_once.
311/// Emulates the following function body:
312///
313/// \code
314/// typedef struct once_flag_s {
315/// unsigned long __state = 0;
316/// } once_flag;
317/// template<class Callable>
318/// void call_once(once_flag& o, Callable func) {
319/// if (!o.__state) {
320/// func();
321/// }
322/// o.__state = 1;
323/// }
324/// \endcode
325static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) {
326 DEBUG(llvm::dbgs() << "Generating body for call_once\n");
327
328 // We need at least two parameters.
329 if (D->param_size() < 2)
330 return nullptr;
331
332 ASTMaker M(C);
333
334 const ParmVarDecl *Flag = D->getParamDecl(0);
335 const ParmVarDecl *Callback = D->getParamDecl(1);
336 QualType CallbackType = Callback->getType().getNonReferenceType();
337
338 SmallVector<Expr *, 5> CallArgs;
339
340 // All arguments past first two ones are passed to the callback.
341 for (unsigned int i = 2; i < D->getNumParams(); i++)
342 CallArgs.push_back(M.makeLvalueToRvalue(D->getParamDecl(i)));
343
344 CallExpr *CallbackCall;
345 if (CallbackType->getAsCXXRecordDecl() &&
346 CallbackType->getAsCXXRecordDecl()->isLambda()) {
347
348 CallbackCall =
349 create_call_once_lambda_call(C, M, Callback, CallbackType, CallArgs);
350 } else {
351
352 // Function pointer case.
353 CallbackCall = create_call_once_funcptr_call(C, M, Callback, CallArgs);
354 }
355
356 QualType FlagType = Flag->getType().getNonReferenceType();
357 DeclRefExpr *FlagDecl =
358 M.makeDeclRefExpr(Flag,
359 /* RefersToEnclosingVariableOrCapture=*/true,
360 /* GetNonReferenceType=*/true);
361
362 CXXRecordDecl *FlagCXXDecl = FlagType->getAsCXXRecordDecl();
363
364 // Note: here we are assuming libc++ implementation of call_once,
365 // which has a struct with a field `__state_`.
366 // Body farming might not work for other `call_once` implementations.
367 NamedDecl *FoundDecl = M.findMemberField(FlagCXXDecl, "__state_");
368 ValueDecl *FieldDecl;
369 if (FoundDecl) {
370 FieldDecl = dyn_cast<ValueDecl>(FoundDecl);
371 } else {
372 DEBUG(llvm::dbgs() << "No field __state_ found on std::once_flag struct, "
373 << "unable to synthesize call_once body, ignoring "
374 << "the call.\n");
375 return nullptr;
376 }
377
378 MemberExpr *Deref = M.makeMemberExpression(FlagDecl, FieldDecl);
379 assert(Deref->isLValue());
380 QualType DerefType = Deref->getType();
381
382 // Negation predicate.
383 UnaryOperator *FlagCheck = new (C) UnaryOperator(
384 /* input= */
385 M.makeImplicitCast(M.makeLvalueToRvalue(Deref, DerefType), DerefType,
386 CK_IntegralToBoolean),
387 /* opc= */ UO_LNot,
388 /* QualType= */ C.IntTy,
389 /* ExprValueKind= */ VK_RValue,
390 /* ExprObjectKind= */ OK_Ordinary, SourceLocation());
391
392 // Create assignment.
393 BinaryOperator *FlagAssignment = M.makeAssignment(
394 Deref, M.makeIntegralCast(M.makeIntegerLiteral(1), DerefType), DerefType);
395
396 IfStmt *Out = new (C)
397 IfStmt(C, SourceLocation(),
398 /* IsConstexpr= */ false,
399 /* init= */ nullptr,
400 /* var= */ nullptr,
401 /* cond= */ FlagCheck,
402 /* then= */ M.makeCompound({CallbackCall, FlagAssignment}));
403
404 return Out;
405}
406
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000407/// Create a fake body for dispatch_once.
408static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
409 // Check if we have at least two parameters.
410 if (D->param_size() != 2)
Craig Topper25542942014-05-20 04:30:07 +0000411 return nullptr;
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000412
413 // Check if the first parameter is a pointer to integer type.
414 const ParmVarDecl *Predicate = D->getParamDecl(0);
415 QualType PredicateQPtrTy = Predicate->getType();
416 const PointerType *PredicatePtrTy = PredicateQPtrTy->getAs<PointerType>();
417 if (!PredicatePtrTy)
Craig Topper25542942014-05-20 04:30:07 +0000418 return nullptr;
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000419 QualType PredicateTy = PredicatePtrTy->getPointeeType();
420 if (!PredicateTy->isIntegerType())
Craig Topper25542942014-05-20 04:30:07 +0000421 return nullptr;
422
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000423 // Check if the second parameter is the proper block type.
424 const ParmVarDecl *Block = D->getParamDecl(1);
425 QualType Ty = Block->getType();
426 if (!isDispatchBlock(Ty))
Craig Topper25542942014-05-20 04:30:07 +0000427 return nullptr;
428
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000429 // Everything checks out. Create a fakse body that checks the predicate,
430 // sets it, and calls the block. Basically, an AST dump of:
431 //
432 // void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block) {
433 // if (!*predicate) {
434 // *predicate = 1;
435 // block();
436 // }
437 // }
438
Ted Kremenek72418132012-09-21 17:54:35 +0000439 ASTMaker M(C);
440
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000441 // (1) Create the call.
George Karpenkov657a5892017-09-30 00:03:22 +0000442 CallExpr *CE = new (C) CallExpr(
443 /*ASTContext=*/C,
444 /*StmtClass=*/M.makeLvalueToRvalue(/*Expr=*/Block),
445 /*args=*/None,
446 /*QualType=*/C.VoidTy,
447 /*ExprValueType=*/VK_RValue,
448 /*SourceLocation=*/SourceLocation());
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000449
450 // (2) Create the assignment to the predicate.
George Karpenkov657a5892017-09-30 00:03:22 +0000451 IntegerLiteral *IL = M.makeIntegerLiteral(1);
452
Ted Kremeneke7ad5352012-09-21 18:33:56 +0000453 BinaryOperator *B =
454 M.makeAssignment(
455 M.makeDereference(
456 M.makeLvalueToRvalue(
457 M.makeDeclRefExpr(Predicate), PredicateQPtrTy),
458 PredicateTy),
459 M.makeIntegralCast(IL, PredicateTy),
460 PredicateTy);
461
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000462 // (3) Create the compound statement.
Craig Topper5fc8fc22014-08-27 06:28:36 +0000463 Stmt *Stmts[] = { B, CE };
464 CompoundStmt *CS = M.makeCompound(Stmts);
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000465
466 // (4) Create the 'if' condition.
Ted Kremeneke7ad5352012-09-21 18:33:56 +0000467 ImplicitCastExpr *LValToRval =
468 M.makeLvalueToRvalue(
469 M.makeDereference(
470 M.makeLvalueToRvalue(
471 M.makeDeclRefExpr(Predicate),
472 PredicateQPtrTy),
473 PredicateTy),
474 PredicateTy);
475
George Karpenkov657a5892017-09-30 00:03:22 +0000476 UnaryOperator *UO = new (C) UnaryOperator(
477 /* input= */ LValToRval,
478 /* opc= */ UO_LNot,
479 /* QualType= */ C.IntTy,
480 /* ExprValueKind= */ VK_RValue,
481 /* ExprObjectKind= */ OK_Ordinary, SourceLocation());
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000482
483 // (5) Create the 'if' statement.
George Karpenkov657a5892017-09-30 00:03:22 +0000484 IfStmt *If = new (C) IfStmt(C, SourceLocation(),
485 /* IsConstexpr= */ false,
486 /* init= */ nullptr,
487 /* var= */ nullptr,
488 /* cond= */ UO,
489 /* then= */ CS);
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000490 return If;
491}
492
Ted Kremenek14f779c2012-09-21 00:09:11 +0000493/// Create a fake body for dispatch_sync.
494static Stmt *create_dispatch_sync(ASTContext &C, const FunctionDecl *D) {
495 // Check if we have at least two parameters.
496 if (D->param_size() != 2)
Craig Topper25542942014-05-20 04:30:07 +0000497 return nullptr;
498
Ted Kremenek14f779c2012-09-21 00:09:11 +0000499 // Check if the second parameter is a block.
500 const ParmVarDecl *PV = D->getParamDecl(1);
501 QualType Ty = PV->getType();
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000502 if (!isDispatchBlock(Ty))
Craig Topper25542942014-05-20 04:30:07 +0000503 return nullptr;
504
Ted Kremenek14f779c2012-09-21 00:09:11 +0000505 // Everything checks out. Create a fake body that just calls the block.
506 // This is basically just an AST dump of:
507 //
508 // void dispatch_sync(dispatch_queue_t queue, void (^block)(void)) {
509 // block();
510 // }
Ted Kremenek72418132012-09-21 17:54:35 +0000511 //
512 ASTMaker M(C);
513 DeclRefExpr *DR = M.makeDeclRefExpr(PV);
Ted Kremenekdff35532012-09-21 18:33:52 +0000514 ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty);
Dmitri Gribenko44ebbd52013-05-05 00:41:58 +0000515 CallExpr *CE = new (C) CallExpr(C, ICE, None, C.VoidTy, VK_RValue,
516 SourceLocation());
Ted Kremenek14f779c2012-09-21 00:09:11 +0000517 return CE;
518}
519
Ted Kremenek089ffd02012-10-11 20:58:18 +0000520static Stmt *create_OSAtomicCompareAndSwap(ASTContext &C, const FunctionDecl *D)
521{
522 // There are exactly 3 arguments.
523 if (D->param_size() != 3)
Craig Topper25542942014-05-20 04:30:07 +0000524 return nullptr;
525
Anna Zaks064185a2013-02-05 19:52:26 +0000526 // Signature:
527 // _Bool OSAtomicCompareAndSwapPtr(void *__oldValue,
528 // void *__newValue,
529 // void * volatile *__theValue)
530 // Generate body:
Ted Kremenek089ffd02012-10-11 20:58:18 +0000531 // if (oldValue == *theValue) {
532 // *theValue = newValue;
533 // return YES;
534 // }
535 // else return NO;
Alp Toker314cc812014-01-25 16:55:45 +0000536
537 QualType ResultTy = D->getReturnType();
Ted Kremenek6fdefb52012-10-12 00:18:19 +0000538 bool isBoolean = ResultTy->isBooleanType();
539 if (!isBoolean && !ResultTy->isIntegralType(C))
Craig Topper25542942014-05-20 04:30:07 +0000540 return nullptr;
541
Ted Kremenek089ffd02012-10-11 20:58:18 +0000542 const ParmVarDecl *OldValue = D->getParamDecl(0);
543 QualType OldValueTy = OldValue->getType();
544
545 const ParmVarDecl *NewValue = D->getParamDecl(1);
546 QualType NewValueTy = NewValue->getType();
547
548 assert(OldValueTy == NewValueTy);
549
550 const ParmVarDecl *TheValue = D->getParamDecl(2);
551 QualType TheValueTy = TheValue->getType();
552 const PointerType *PT = TheValueTy->getAs<PointerType>();
553 if (!PT)
Craig Topper25542942014-05-20 04:30:07 +0000554 return nullptr;
Ted Kremenek089ffd02012-10-11 20:58:18 +0000555 QualType PointeeTy = PT->getPointeeType();
556
557 ASTMaker M(C);
558 // Construct the comparison.
559 Expr *Comparison =
560 M.makeComparison(
561 M.makeLvalueToRvalue(M.makeDeclRefExpr(OldValue), OldValueTy),
562 M.makeLvalueToRvalue(
563 M.makeDereference(
564 M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
565 PointeeTy),
566 PointeeTy),
567 BO_EQ);
568
569 // Construct the body of the IfStmt.
570 Stmt *Stmts[2];
571 Stmts[0] =
572 M.makeAssignment(
573 M.makeDereference(
574 M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
575 PointeeTy),
576 M.makeLvalueToRvalue(M.makeDeclRefExpr(NewValue), NewValueTy),
577 NewValueTy);
Ted Kremenek6fdefb52012-10-12 00:18:19 +0000578
579 Expr *BoolVal = M.makeObjCBool(true);
580 Expr *RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
581 : M.makeIntegralCast(BoolVal, ResultTy);
582 Stmts[1] = M.makeReturn(RetVal);
Craig Topper5fc8fc22014-08-27 06:28:36 +0000583 CompoundStmt *Body = M.makeCompound(Stmts);
Ted Kremenek089ffd02012-10-11 20:58:18 +0000584
585 // Construct the else clause.
Ted Kremenek6fdefb52012-10-12 00:18:19 +0000586 BoolVal = M.makeObjCBool(false);
587 RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
588 : M.makeIntegralCast(BoolVal, ResultTy);
589 Stmt *Else = M.makeReturn(RetVal);
Ted Kremenek089ffd02012-10-11 20:58:18 +0000590
591 /// Construct the If.
Richard Smitha547eb22016-07-14 00:11:03 +0000592 Stmt *If = new (C) IfStmt(C, SourceLocation(), false, nullptr, nullptr,
593 Comparison, Body, SourceLocation(), Else);
Craig Topper25542942014-05-20 04:30:07 +0000594
Ted Kremenek089ffd02012-10-11 20:58:18 +0000595 return If;
596}
597
Ted Kremenek14f779c2012-09-21 00:09:11 +0000598Stmt *BodyFarm::getBody(const FunctionDecl *D) {
599 D = D->getCanonicalDecl();
600
David Blaikie05785d12013-02-20 22:23:23 +0000601 Optional<Stmt *> &Val = Bodies[D];
Ted Kremenek14f779c2012-09-21 00:09:11 +0000602 if (Val.hasValue())
603 return Val.getValue();
Craig Topper25542942014-05-20 04:30:07 +0000604
605 Val = nullptr;
606
607 if (D->getIdentifier() == nullptr)
608 return nullptr;
Ted Kremenek14f779c2012-09-21 00:09:11 +0000609
610 StringRef Name = D->getName();
611 if (Name.empty())
Craig Topper25542942014-05-20 04:30:07 +0000612 return nullptr;
Ted Kremenek089ffd02012-10-11 20:58:18 +0000613
614 FunctionFarmer FF;
615
616 if (Name.startswith("OSAtomicCompareAndSwap") ||
617 Name.startswith("objc_atomicCompareAndSwap")) {
618 FF = create_OSAtomicCompareAndSwap;
George Karpenkov657a5892017-09-30 00:03:22 +0000619 } else if (Name == "call_once" && D->getDeclContext()->isStdNamespace()) {
620 FF = create_call_once;
621 } else {
Ted Kremenek089ffd02012-10-11 20:58:18 +0000622 FF = llvm::StringSwitch<FunctionFarmer>(Name)
623 .Case("dispatch_sync", create_dispatch_sync)
624 .Case("dispatch_once", create_dispatch_once)
Craig Topper25542942014-05-20 04:30:07 +0000625 .Default(nullptr);
Ted Kremenek14f779c2012-09-21 00:09:11 +0000626 }
627
Ted Kremenek089ffd02012-10-11 20:58:18 +0000628 if (FF) { Val = FF(C, D); }
Ted Kremenekeeccb302014-08-27 15:14:15 +0000629 else if (Injector) { Val = Injector->getBody(D); }
Ted Kremenek14f779c2012-09-21 00:09:11 +0000630 return Val.getValue();
631}
632
Devin Coughlinb7e810b2016-01-26 23:58:48 +0000633static const ObjCIvarDecl *findBackingIvar(const ObjCPropertyDecl *Prop) {
634 const ObjCIvarDecl *IVar = Prop->getPropertyIvarDecl();
635
636 if (IVar)
637 return IVar;
638
639 // When a readonly property is shadowed in a class extensions with a
640 // a readwrite property, the instance variable belongs to the shadowing
641 // property rather than the shadowed property. If there is no instance
642 // variable on a readonly property, check to see whether the property is
643 // shadowed and if so try to get the instance variable from shadowing
644 // property.
645 if (!Prop->isReadOnly())
646 return nullptr;
647
648 auto *Container = cast<ObjCContainerDecl>(Prop->getDeclContext());
649 const ObjCInterfaceDecl *PrimaryInterface = nullptr;
650 if (auto *InterfaceDecl = dyn_cast<ObjCInterfaceDecl>(Container)) {
651 PrimaryInterface = InterfaceDecl;
652 } else if (auto *CategoryDecl = dyn_cast<ObjCCategoryDecl>(Container)) {
653 PrimaryInterface = CategoryDecl->getClassInterface();
654 } else if (auto *ImplDecl = dyn_cast<ObjCImplDecl>(Container)) {
655 PrimaryInterface = ImplDecl->getClassInterface();
656 } else {
657 return nullptr;
658 }
659
660 // FindPropertyVisibleInPrimaryClass() looks first in class extensions, so it
661 // is guaranteed to find the shadowing property, if it exists, rather than
662 // the shadowed property.
663 auto *ShadowingProp = PrimaryInterface->FindPropertyVisibleInPrimaryClass(
Manman Ren5b786402016-01-28 18:49:28 +0000664 Prop->getIdentifier(), Prop->getQueryKind());
Devin Coughlinb7e810b2016-01-26 23:58:48 +0000665 if (ShadowingProp && ShadowingProp != Prop) {
666 IVar = ShadowingProp->getPropertyIvarDecl();
667 }
668
669 return IVar;
670}
671
Jordan Rose1a866cd2014-01-10 20:06:06 +0000672static Stmt *createObjCPropertyGetter(ASTContext &Ctx,
673 const ObjCPropertyDecl *Prop) {
Jordan Roseddf19662014-01-23 03:59:10 +0000674 // First, find the backing ivar.
Devin Coughlinb7e810b2016-01-26 23:58:48 +0000675 const ObjCIvarDecl *IVar = findBackingIvar(Prop);
Jordan Rose1a866cd2014-01-10 20:06:06 +0000676 if (!IVar)
Craig Topper25542942014-05-20 04:30:07 +0000677 return nullptr;
Jordan Roseddf19662014-01-23 03:59:10 +0000678
679 // Ignore weak variables, which have special behavior.
Jordan Rose1a866cd2014-01-10 20:06:06 +0000680 if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak)
Craig Topper25542942014-05-20 04:30:07 +0000681 return nullptr;
Jordan Rosea3f27812014-01-14 17:29:06 +0000682
Jordan Roseddf19662014-01-23 03:59:10 +0000683 // Look to see if Sema has synthesized a body for us. This happens in
684 // Objective-C++ because the return value may be a C++ class type with a
685 // non-trivial copy constructor. We can only do this if we can find the
686 // @synthesize for this property, though (or if we know it's been auto-
687 // synthesized).
Jordan Rosea3f27812014-01-14 17:29:06 +0000688 const ObjCImplementationDecl *ImplDecl =
689 IVar->getContainingInterface()->getImplementation();
690 if (ImplDecl) {
Aaron Ballmand85eff42014-03-14 15:02:45 +0000691 for (const auto *I : ImplDecl->property_impls()) {
Jordan Rosea3f27812014-01-14 17:29:06 +0000692 if (I->getPropertyDecl() != Prop)
693 continue;
694
695 if (I->getGetterCXXConstructor()) {
696 ASTMaker M(Ctx);
697 return M.makeReturn(I->getGetterCXXConstructor());
698 }
699 }
700 }
701
Jordan Roseddf19662014-01-23 03:59:10 +0000702 // Sanity check that the property is the same type as the ivar, or a
703 // reference to it, and that it is either an object pointer or trivially
704 // copyable.
705 if (!Ctx.hasSameUnqualifiedType(IVar->getType(),
706 Prop->getType().getNonReferenceType()))
Craig Topper25542942014-05-20 04:30:07 +0000707 return nullptr;
Jordan Roseddf19662014-01-23 03:59:10 +0000708 if (!IVar->getType()->isObjCLifetimeType() &&
709 !IVar->getType().isTriviallyCopyableType(Ctx))
Craig Topper25542942014-05-20 04:30:07 +0000710 return nullptr;
Jordan Rose1a866cd2014-01-10 20:06:06 +0000711
Jordan Roseddf19662014-01-23 03:59:10 +0000712 // Generate our body:
713 // return self->_ivar;
Jordan Rose1a866cd2014-01-10 20:06:06 +0000714 ASTMaker M(Ctx);
715
716 const VarDecl *selfVar = Prop->getGetterMethodDecl()->getSelfDecl();
Devin Coughlinaac894f2017-01-11 01:02:34 +0000717 if (!selfVar)
718 return nullptr;
Jordan Rose1a866cd2014-01-10 20:06:06 +0000719
720 Expr *loadedIVar =
721 M.makeObjCIvarRef(
722 M.makeLvalueToRvalue(
723 M.makeDeclRefExpr(selfVar),
724 selfVar->getType()),
725 IVar);
726
727 if (!Prop->getType()->isReferenceType())
728 loadedIVar = M.makeLvalueToRvalue(loadedIVar, IVar->getType());
729
730 return M.makeReturn(loadedIVar);
731}
732
Jordan Roseddf19662014-01-23 03:59:10 +0000733Stmt *BodyFarm::getBody(const ObjCMethodDecl *D) {
734 // We currently only know how to synthesize property accessors.
Jordan Rose1a866cd2014-01-10 20:06:06 +0000735 if (!D->isPropertyAccessor())
Craig Topper25542942014-05-20 04:30:07 +0000736 return nullptr;
Jordan Rose1a866cd2014-01-10 20:06:06 +0000737
738 D = D->getCanonicalDecl();
739
740 Optional<Stmt *> &Val = Bodies[D];
741 if (Val.hasValue())
742 return Val.getValue();
Craig Topper25542942014-05-20 04:30:07 +0000743 Val = nullptr;
Jordan Rose1a866cd2014-01-10 20:06:06 +0000744
Jordan Roseddf19662014-01-23 03:59:10 +0000745 const ObjCPropertyDecl *Prop = D->findPropertyDecl();
Jordan Rose1a866cd2014-01-10 20:06:06 +0000746 if (!Prop)
Craig Topper25542942014-05-20 04:30:07 +0000747 return nullptr;
Jordan Rose1a866cd2014-01-10 20:06:06 +0000748
Jordan Roseddf19662014-01-23 03:59:10 +0000749 // For now, we only synthesize getters.
Devin Coughlinef3697e2016-02-18 19:37:39 +0000750 // Synthesizing setters would cause false negatives in the
751 // RetainCountChecker because the method body would bind the parameter
752 // to an instance variable, causing it to escape. This would prevent
753 // warning in the following common scenario:
754 //
755 // id foo = [[NSObject alloc] init];
756 // self.foo = foo; // We should warn that foo leaks here.
757 //
Jordan Rose1a866cd2014-01-10 20:06:06 +0000758 if (D->param_size() != 0)
Craig Topper25542942014-05-20 04:30:07 +0000759 return nullptr;
Jordan Rose1a866cd2014-01-10 20:06:06 +0000760
761 Val = createObjCPropertyGetter(C, Prop);
762
763 return Val.getValue();
764}
765