blob: 6ca758e82f912d9def169f3a826c75707baf076d [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 /// Create an implicit cast for lvalue-to-rvaluate conversions.
82 ImplicitCastExpr *makeLvalueToRvalue(const Expr *Arg,
83 bool GetNonReferenceType = false);
84
85 /// Make RValue out of variable declaration, creating a temporary
86 /// DeclRefExpr in the process.
87 ImplicitCastExpr *
88 makeLvalueToRvalue(const VarDecl *Decl,
89 bool RefersToEnclosingVariableOrCapture = false,
90 bool GetNonReferenceType = false);
91
92 /// Create an implicit cast of the given type.
93 ImplicitCastExpr *makeImplicitCast(const Expr *Arg, QualType Ty,
94 CastKind CK = CK_LValueToRValue);
95
Ted Kremenek089ffd02012-10-11 20:58:18 +000096 /// Create an Objective-C bool literal.
97 ObjCBoolLiteralExpr *makeObjCBool(bool Val);
Jordan Rose1a866cd2014-01-10 20:06:06 +000098
99 /// Create an Objective-C ivar reference.
100 ObjCIvarRefExpr *makeObjCIvarRef(const Expr *Base, const ObjCIvarDecl *IVar);
Ted Kremenek089ffd02012-10-11 20:58:18 +0000101
102 /// Create a Return statement.
103 ReturnStmt *makeReturn(const Expr *RetVal);
104
George Karpenkov657a5892017-09-30 00:03:22 +0000105 /// Create an integer literal.
106 IntegerLiteral *makeIntegerLiteral(uint64_t value);
107
108 /// Create a member expression.
109 MemberExpr *makeMemberExpression(Expr *base, ValueDecl *MemberDecl,
110 bool IsArrow = false,
111 ExprValueKind ValueKind = VK_LValue);
112
113 /// Returns a *first* member field of a record declaration with a given name.
114 /// \return an nullptr if no member with such a name exists.
115 NamedDecl *findMemberField(const CXXRecordDecl *RD, StringRef Name);
116
Ted Kremenek72418132012-09-21 17:54:35 +0000117private:
118 ASTContext &C;
119};
Alexander Kornienkoab9db512015-06-22 23:07:51 +0000120}
Ted Kremenek72418132012-09-21 17:54:35 +0000121
Ted Kremenekf465dc12012-09-21 18:33:54 +0000122BinaryOperator *ASTMaker::makeAssignment(const Expr *LHS, const Expr *RHS,
123 QualType Ty) {
124 return new (C) BinaryOperator(const_cast<Expr*>(LHS), const_cast<Expr*>(RHS),
125 BO_Assign, Ty, VK_RValue,
Adam Nemet484aa452017-03-27 19:17:25 +0000126 OK_Ordinary, SourceLocation(), FPOptions());
Ted Kremenekf465dc12012-09-21 18:33:54 +0000127}
128
Ted Kremenek089ffd02012-10-11 20:58:18 +0000129BinaryOperator *ASTMaker::makeComparison(const Expr *LHS, const Expr *RHS,
130 BinaryOperator::Opcode Op) {
131 assert(BinaryOperator::isLogicalOp(Op) ||
132 BinaryOperator::isComparisonOp(Op));
133 return new (C) BinaryOperator(const_cast<Expr*>(LHS),
134 const_cast<Expr*>(RHS),
135 Op,
136 C.getLogicalOperationType(),
137 VK_RValue,
Adam Nemet484aa452017-03-27 19:17:25 +0000138 OK_Ordinary, SourceLocation(), FPOptions());
Ted Kremenek089ffd02012-10-11 20:58:18 +0000139}
140
141CompoundStmt *ASTMaker::makeCompound(ArrayRef<Stmt *> Stmts) {
Nico Webera2a0eb92012-12-29 20:03:39 +0000142 return new (C) CompoundStmt(C, Stmts, SourceLocation(), SourceLocation());
Ted Kremenek089ffd02012-10-11 20:58:18 +0000143}
144
George Karpenkov657a5892017-09-30 00:03:22 +0000145DeclRefExpr *ASTMaker::makeDeclRefExpr(const VarDecl *D,
146 bool RefersToEnclosingVariableOrCapture,
147 bool GetNonReferenceType) {
148 auto Type = D->getType();
149 if (GetNonReferenceType)
150 Type = Type.getNonReferenceType();
151
152 DeclRefExpr *DR = DeclRefExpr::Create(
153 C, NestedNameSpecifierLoc(), SourceLocation(), const_cast<VarDecl *>(D),
154 RefersToEnclosingVariableOrCapture, SourceLocation(), Type, VK_LValue);
Ted Kremenek72418132012-09-21 17:54:35 +0000155 return DR;
156}
157
Ted Kremenekdff35532012-09-21 18:33:52 +0000158UnaryOperator *ASTMaker::makeDereference(const Expr *Arg, QualType Ty) {
159 return new (C) UnaryOperator(const_cast<Expr*>(Arg), UO_Deref, Ty,
160 VK_LValue, OK_Ordinary, SourceLocation());
161}
162
Ted Kremenekca90ea52012-09-21 18:13:27 +0000163ImplicitCastExpr *ASTMaker::makeLvalueToRvalue(const Expr *Arg, QualType Ty) {
George Karpenkov657a5892017-09-30 00:03:22 +0000164 return makeImplicitCast(Arg, Ty, CK_LValueToRValue);
165}
166
167ImplicitCastExpr *ASTMaker::makeLvalueToRvalue(const Expr *Arg,
168 bool GetNonReferenceType) {
169
170 QualType Type = Arg->getType();
171 if (GetNonReferenceType)
172 Type = Type.getNonReferenceType();
173 return makeImplicitCast(Arg, Type, CK_LValueToRValue);
174}
175
176ImplicitCastExpr *
177ASTMaker::makeLvalueToRvalue(const VarDecl *Arg,
178 bool RefersToEnclosingVariableOrCapture,
179 bool GetNonReferenceType) {
180 auto Type = Arg->getType();
181 if (GetNonReferenceType)
182 Type = Type.getNonReferenceType();
183 return makeLvalueToRvalue(makeDeclRefExpr(Arg,
184 RefersToEnclosingVariableOrCapture,
185 GetNonReferenceType),
186 Type);
187}
188
189ImplicitCastExpr *ASTMaker::makeImplicitCast(const Expr *Arg, QualType Ty,
190 CastKind CK) {
191 return ImplicitCastExpr::Create(C, Ty,
192 /* CastKind= */ CK,
193 /* Expr= */ const_cast<Expr *>(Arg),
194 /* CXXCastPath= */ nullptr,
195 /* ExprValueKind= */ VK_RValue);
Ted Kremenekca90ea52012-09-21 18:13:27 +0000196}
197
Ted Kremenek6fdefb52012-10-12 00:18:19 +0000198Expr *ASTMaker::makeIntegralCast(const Expr *Arg, QualType Ty) {
199 if (Arg->getType() == Ty)
200 return const_cast<Expr*>(Arg);
Craig Topper25542942014-05-20 04:30:07 +0000201
Ted Kremenek69bcb822012-09-21 18:13:23 +0000202 return ImplicitCastExpr::Create(C, Ty, CK_IntegralCast,
Craig Topper25542942014-05-20 04:30:07 +0000203 const_cast<Expr*>(Arg), nullptr, VK_RValue);
Ted Kremenek69bcb822012-09-21 18:13:23 +0000204}
205
Ted Kremenek089ffd02012-10-11 20:58:18 +0000206ImplicitCastExpr *ASTMaker::makeIntegralCastToBoolean(const Expr *Arg) {
207 return ImplicitCastExpr::Create(C, C.BoolTy, CK_IntegralToBoolean,
Craig Topper25542942014-05-20 04:30:07 +0000208 const_cast<Expr*>(Arg), nullptr, VK_RValue);
Ted Kremenek089ffd02012-10-11 20:58:18 +0000209}
210
211ObjCBoolLiteralExpr *ASTMaker::makeObjCBool(bool Val) {
212 QualType Ty = C.getBOOLDecl() ? C.getBOOLType() : C.ObjCBuiltinBoolTy;
213 return new (C) ObjCBoolLiteralExpr(Val, Ty, SourceLocation());
214}
215
Jordan Rose1a866cd2014-01-10 20:06:06 +0000216ObjCIvarRefExpr *ASTMaker::makeObjCIvarRef(const Expr *Base,
217 const ObjCIvarDecl *IVar) {
218 return new (C) ObjCIvarRefExpr(const_cast<ObjCIvarDecl*>(IVar),
219 IVar->getType(), SourceLocation(),
220 SourceLocation(), const_cast<Expr*>(Base),
221 /*arrow=*/true, /*free=*/false);
222}
223
224
Ted Kremenek089ffd02012-10-11 20:58:18 +0000225ReturnStmt *ASTMaker::makeReturn(const Expr *RetVal) {
Craig Topper25542942014-05-20 04:30:07 +0000226 return new (C) ReturnStmt(SourceLocation(), const_cast<Expr*>(RetVal),
227 nullptr);
Ted Kremenek089ffd02012-10-11 20:58:18 +0000228}
229
George Karpenkov657a5892017-09-30 00:03:22 +0000230IntegerLiteral *ASTMaker::makeIntegerLiteral(uint64_t value) {
231 return IntegerLiteral::Create(C,
232 llvm::APInt(
233 /*numBits=*/C.getTypeSize(C.IntTy), value),
234 /*QualType=*/C.IntTy, SourceLocation());
235}
236
237MemberExpr *ASTMaker::makeMemberExpression(Expr *base, ValueDecl *MemberDecl,
238 bool IsArrow,
239 ExprValueKind ValueKind) {
240
241 DeclAccessPair FoundDecl = DeclAccessPair::make(MemberDecl, AS_public);
242 return MemberExpr::Create(
243 C, base, IsArrow, SourceLocation(), NestedNameSpecifierLoc(),
244 SourceLocation(), MemberDecl, FoundDecl,
245 DeclarationNameInfo(MemberDecl->getDeclName(), SourceLocation()),
246 /* TemplateArgumentListInfo= */ nullptr, MemberDecl->getType(), ValueKind,
247 OK_Ordinary);
248}
249
250NamedDecl *ASTMaker::findMemberField(const CXXRecordDecl *RD, StringRef Name) {
251
252 CXXBasePaths Paths(
253 /* FindAmbiguities=*/false,
254 /* RecordPaths=*/false,
255 /* DetectVirtual= */ false);
256 const IdentifierInfo &II = C.Idents.get(Name);
257 DeclarationName DeclName = C.DeclarationNames.getIdentifier(&II);
258
259 DeclContextLookupResult Decls = RD->lookup(DeclName);
260 for (NamedDecl *FoundDecl : Decls)
261 if (!FoundDecl->getDeclContext()->isFunctionOrMethod())
262 return FoundDecl;
263
264 return nullptr;
265}
266
Ted Kremenek2b5c83c2012-09-21 17:54:32 +0000267//===----------------------------------------------------------------------===//
268// Creation functions for faux ASTs.
269//===----------------------------------------------------------------------===//
270
271typedef Stmt *(*FunctionFarmer)(ASTContext &C, const FunctionDecl *D);
272
George Karpenkov657a5892017-09-30 00:03:22 +0000273static CallExpr *
274create_call_once_funcptr_call(ASTContext &C, ASTMaker M,
275 const ParmVarDecl *Callback,
276 SmallVectorImpl<Expr *> &CallArgs) {
277
278 return new (C) CallExpr(
279 /*ASTContext=*/C,
280 /*StmtClass=*/M.makeLvalueToRvalue(/*Expr=*/Callback),
281 /*args=*/CallArgs,
282 /*QualType=*/C.VoidTy,
283 /*ExprValueType=*/VK_RValue,
284 /*SourceLocation=*/SourceLocation());
285}
286
287static CallExpr *
288create_call_once_lambda_call(ASTContext &C, ASTMaker M,
289 const ParmVarDecl *Callback, QualType CallbackType,
290 SmallVectorImpl<Expr *> &CallArgs) {
291
292 CXXRecordDecl *CallbackDecl = CallbackType->getAsCXXRecordDecl();
293
294 assert(CallbackDecl != nullptr);
295 assert(CallbackDecl->isLambda());
296 FunctionDecl *callOperatorDecl = CallbackDecl->getLambdaCallOperator();
297 assert(callOperatorDecl != nullptr);
298
299 DeclRefExpr *callOperatorDeclRef =
300 DeclRefExpr::Create(/* Ctx = */ C,
301 /* QualifierLoc = */ NestedNameSpecifierLoc(),
302 /* TemplateKWLoc = */ SourceLocation(),
303 const_cast<FunctionDecl *>(callOperatorDecl),
304 /* RefersToEnclosingVariableOrCapture= */ false,
305 /* NameLoc = */ SourceLocation(),
306 /* T = */ callOperatorDecl->getType(),
307 /* VK = */ VK_LValue);
308
309 CallArgs.insert(
310 CallArgs.begin(),
311 M.makeDeclRefExpr(Callback,
312 /* RefersToEnclosingVariableOrCapture= */ true,
313 /* GetNonReferenceType= */ true));
314
315 return new (C)
316 CXXOperatorCallExpr(/*AstContext=*/C, OO_Call, callOperatorDeclRef,
317 /*args=*/CallArgs,
318 /*QualType=*/C.VoidTy,
319 /*ExprValueType=*/VK_RValue,
320 /*SourceLocation=*/SourceLocation(), FPOptions());
321}
322
323/// Create a fake body for std::call_once.
324/// Emulates the following function body:
325///
326/// \code
327/// typedef struct once_flag_s {
328/// unsigned long __state = 0;
329/// } once_flag;
330/// template<class Callable>
331/// void call_once(once_flag& o, Callable func) {
332/// if (!o.__state) {
333/// func();
334/// }
335/// o.__state = 1;
336/// }
337/// \endcode
338static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) {
339 DEBUG(llvm::dbgs() << "Generating body for call_once\n");
340
341 // We need at least two parameters.
342 if (D->param_size() < 2)
343 return nullptr;
344
345 ASTMaker M(C);
346
347 const ParmVarDecl *Flag = D->getParamDecl(0);
348 const ParmVarDecl *Callback = D->getParamDecl(1);
349 QualType CallbackType = Callback->getType().getNonReferenceType();
350
351 SmallVector<Expr *, 5> CallArgs;
352
353 // All arguments past first two ones are passed to the callback.
354 for (unsigned int i = 2; i < D->getNumParams(); i++)
355 CallArgs.push_back(M.makeLvalueToRvalue(D->getParamDecl(i)));
356
357 CallExpr *CallbackCall;
358 if (CallbackType->getAsCXXRecordDecl() &&
359 CallbackType->getAsCXXRecordDecl()->isLambda()) {
360
361 CallbackCall =
362 create_call_once_lambda_call(C, M, Callback, CallbackType, CallArgs);
363 } else {
364
365 // Function pointer case.
366 CallbackCall = create_call_once_funcptr_call(C, M, Callback, CallArgs);
367 }
368
369 QualType FlagType = Flag->getType().getNonReferenceType();
370 DeclRefExpr *FlagDecl =
371 M.makeDeclRefExpr(Flag,
372 /* RefersToEnclosingVariableOrCapture=*/true,
373 /* GetNonReferenceType=*/true);
374
375 CXXRecordDecl *FlagCXXDecl = FlagType->getAsCXXRecordDecl();
376
377 // Note: here we are assuming libc++ implementation of call_once,
378 // which has a struct with a field `__state_`.
379 // Body farming might not work for other `call_once` implementations.
380 NamedDecl *FoundDecl = M.findMemberField(FlagCXXDecl, "__state_");
381 ValueDecl *FieldDecl;
382 if (FoundDecl) {
383 FieldDecl = dyn_cast<ValueDecl>(FoundDecl);
384 } else {
385 DEBUG(llvm::dbgs() << "No field __state_ found on std::once_flag struct, "
386 << "unable to synthesize call_once body, ignoring "
387 << "the call.\n");
388 return nullptr;
389 }
390
391 MemberExpr *Deref = M.makeMemberExpression(FlagDecl, FieldDecl);
392 assert(Deref->isLValue());
393 QualType DerefType = Deref->getType();
394
395 // Negation predicate.
396 UnaryOperator *FlagCheck = new (C) UnaryOperator(
397 /* input= */
398 M.makeImplicitCast(M.makeLvalueToRvalue(Deref, DerefType), DerefType,
399 CK_IntegralToBoolean),
400 /* opc= */ UO_LNot,
401 /* QualType= */ C.IntTy,
402 /* ExprValueKind= */ VK_RValue,
403 /* ExprObjectKind= */ OK_Ordinary, SourceLocation());
404
405 // Create assignment.
406 BinaryOperator *FlagAssignment = M.makeAssignment(
407 Deref, M.makeIntegralCast(M.makeIntegerLiteral(1), DerefType), DerefType);
408
409 IfStmt *Out = new (C)
410 IfStmt(C, SourceLocation(),
411 /* IsConstexpr= */ false,
412 /* init= */ nullptr,
413 /* var= */ nullptr,
414 /* cond= */ FlagCheck,
415 /* then= */ M.makeCompound({CallbackCall, FlagAssignment}));
416
417 return Out;
418}
419
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000420/// Create a fake body for dispatch_once.
421static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
422 // Check if we have at least two parameters.
423 if (D->param_size() != 2)
Craig Topper25542942014-05-20 04:30:07 +0000424 return nullptr;
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000425
426 // Check if the first parameter is a pointer to integer type.
427 const ParmVarDecl *Predicate = D->getParamDecl(0);
428 QualType PredicateQPtrTy = Predicate->getType();
429 const PointerType *PredicatePtrTy = PredicateQPtrTy->getAs<PointerType>();
430 if (!PredicatePtrTy)
Craig Topper25542942014-05-20 04:30:07 +0000431 return nullptr;
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000432 QualType PredicateTy = PredicatePtrTy->getPointeeType();
433 if (!PredicateTy->isIntegerType())
Craig Topper25542942014-05-20 04:30:07 +0000434 return nullptr;
435
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000436 // Check if the second parameter is the proper block type.
437 const ParmVarDecl *Block = D->getParamDecl(1);
438 QualType Ty = Block->getType();
439 if (!isDispatchBlock(Ty))
Craig Topper25542942014-05-20 04:30:07 +0000440 return nullptr;
441
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000442 // Everything checks out. Create a fakse body that checks the predicate,
443 // sets it, and calls the block. Basically, an AST dump of:
444 //
445 // void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block) {
446 // if (!*predicate) {
447 // *predicate = 1;
448 // block();
449 // }
450 // }
451
Ted Kremenek72418132012-09-21 17:54:35 +0000452 ASTMaker M(C);
453
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000454 // (1) Create the call.
George Karpenkov657a5892017-09-30 00:03:22 +0000455 CallExpr *CE = new (C) CallExpr(
456 /*ASTContext=*/C,
457 /*StmtClass=*/M.makeLvalueToRvalue(/*Expr=*/Block),
458 /*args=*/None,
459 /*QualType=*/C.VoidTy,
460 /*ExprValueType=*/VK_RValue,
461 /*SourceLocation=*/SourceLocation());
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000462
463 // (2) Create the assignment to the predicate.
George Karpenkov657a5892017-09-30 00:03:22 +0000464 IntegerLiteral *IL = M.makeIntegerLiteral(1);
465
Ted Kremeneke7ad5352012-09-21 18:33:56 +0000466 BinaryOperator *B =
467 M.makeAssignment(
468 M.makeDereference(
469 M.makeLvalueToRvalue(
470 M.makeDeclRefExpr(Predicate), PredicateQPtrTy),
471 PredicateTy),
472 M.makeIntegralCast(IL, PredicateTy),
473 PredicateTy);
474
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000475 // (3) Create the compound statement.
Craig Topper5fc8fc22014-08-27 06:28:36 +0000476 Stmt *Stmts[] = { B, CE };
477 CompoundStmt *CS = M.makeCompound(Stmts);
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000478
479 // (4) Create the 'if' condition.
Ted Kremeneke7ad5352012-09-21 18:33:56 +0000480 ImplicitCastExpr *LValToRval =
481 M.makeLvalueToRvalue(
482 M.makeDereference(
483 M.makeLvalueToRvalue(
484 M.makeDeclRefExpr(Predicate),
485 PredicateQPtrTy),
486 PredicateTy),
487 PredicateTy);
488
George Karpenkov657a5892017-09-30 00:03:22 +0000489 UnaryOperator *UO = new (C) UnaryOperator(
490 /* input= */ LValToRval,
491 /* opc= */ UO_LNot,
492 /* QualType= */ C.IntTy,
493 /* ExprValueKind= */ VK_RValue,
494 /* ExprObjectKind= */ OK_Ordinary, SourceLocation());
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000495
496 // (5) Create the 'if' statement.
George Karpenkov657a5892017-09-30 00:03:22 +0000497 IfStmt *If = new (C) IfStmt(C, SourceLocation(),
498 /* IsConstexpr= */ false,
499 /* init= */ nullptr,
500 /* var= */ nullptr,
501 /* cond= */ UO,
502 /* then= */ CS);
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000503 return If;
504}
505
Ted Kremenek14f779c2012-09-21 00:09:11 +0000506/// Create a fake body for dispatch_sync.
507static Stmt *create_dispatch_sync(ASTContext &C, const FunctionDecl *D) {
508 // Check if we have at least two parameters.
509 if (D->param_size() != 2)
Craig Topper25542942014-05-20 04:30:07 +0000510 return nullptr;
511
Ted Kremenek14f779c2012-09-21 00:09:11 +0000512 // Check if the second parameter is a block.
513 const ParmVarDecl *PV = D->getParamDecl(1);
514 QualType Ty = PV->getType();
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000515 if (!isDispatchBlock(Ty))
Craig Topper25542942014-05-20 04:30:07 +0000516 return nullptr;
517
Ted Kremenek14f779c2012-09-21 00:09:11 +0000518 // Everything checks out. Create a fake body that just calls the block.
519 // This is basically just an AST dump of:
520 //
521 // void dispatch_sync(dispatch_queue_t queue, void (^block)(void)) {
522 // block();
523 // }
Ted Kremenek72418132012-09-21 17:54:35 +0000524 //
525 ASTMaker M(C);
526 DeclRefExpr *DR = M.makeDeclRefExpr(PV);
Ted Kremenekdff35532012-09-21 18:33:52 +0000527 ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty);
Dmitri Gribenko44ebbd52013-05-05 00:41:58 +0000528 CallExpr *CE = new (C) CallExpr(C, ICE, None, C.VoidTy, VK_RValue,
529 SourceLocation());
Ted Kremenek14f779c2012-09-21 00:09:11 +0000530 return CE;
531}
532
Ted Kremenek089ffd02012-10-11 20:58:18 +0000533static Stmt *create_OSAtomicCompareAndSwap(ASTContext &C, const FunctionDecl *D)
534{
535 // There are exactly 3 arguments.
536 if (D->param_size() != 3)
Craig Topper25542942014-05-20 04:30:07 +0000537 return nullptr;
538
Anna Zaks064185a2013-02-05 19:52:26 +0000539 // Signature:
540 // _Bool OSAtomicCompareAndSwapPtr(void *__oldValue,
541 // void *__newValue,
542 // void * volatile *__theValue)
543 // Generate body:
Ted Kremenek089ffd02012-10-11 20:58:18 +0000544 // if (oldValue == *theValue) {
545 // *theValue = newValue;
546 // return YES;
547 // }
548 // else return NO;
Alp Toker314cc812014-01-25 16:55:45 +0000549
550 QualType ResultTy = D->getReturnType();
Ted Kremenek6fdefb52012-10-12 00:18:19 +0000551 bool isBoolean = ResultTy->isBooleanType();
552 if (!isBoolean && !ResultTy->isIntegralType(C))
Craig Topper25542942014-05-20 04:30:07 +0000553 return nullptr;
554
Ted Kremenek089ffd02012-10-11 20:58:18 +0000555 const ParmVarDecl *OldValue = D->getParamDecl(0);
556 QualType OldValueTy = OldValue->getType();
557
558 const ParmVarDecl *NewValue = D->getParamDecl(1);
559 QualType NewValueTy = NewValue->getType();
560
561 assert(OldValueTy == NewValueTy);
562
563 const ParmVarDecl *TheValue = D->getParamDecl(2);
564 QualType TheValueTy = TheValue->getType();
565 const PointerType *PT = TheValueTy->getAs<PointerType>();
566 if (!PT)
Craig Topper25542942014-05-20 04:30:07 +0000567 return nullptr;
Ted Kremenek089ffd02012-10-11 20:58:18 +0000568 QualType PointeeTy = PT->getPointeeType();
569
570 ASTMaker M(C);
571 // Construct the comparison.
572 Expr *Comparison =
573 M.makeComparison(
574 M.makeLvalueToRvalue(M.makeDeclRefExpr(OldValue), OldValueTy),
575 M.makeLvalueToRvalue(
576 M.makeDereference(
577 M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
578 PointeeTy),
579 PointeeTy),
580 BO_EQ);
581
582 // Construct the body of the IfStmt.
583 Stmt *Stmts[2];
584 Stmts[0] =
585 M.makeAssignment(
586 M.makeDereference(
587 M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
588 PointeeTy),
589 M.makeLvalueToRvalue(M.makeDeclRefExpr(NewValue), NewValueTy),
590 NewValueTy);
Ted Kremenek6fdefb52012-10-12 00:18:19 +0000591
592 Expr *BoolVal = M.makeObjCBool(true);
593 Expr *RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
594 : M.makeIntegralCast(BoolVal, ResultTy);
595 Stmts[1] = M.makeReturn(RetVal);
Craig Topper5fc8fc22014-08-27 06:28:36 +0000596 CompoundStmt *Body = M.makeCompound(Stmts);
Ted Kremenek089ffd02012-10-11 20:58:18 +0000597
598 // Construct the else clause.
Ted Kremenek6fdefb52012-10-12 00:18:19 +0000599 BoolVal = M.makeObjCBool(false);
600 RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
601 : M.makeIntegralCast(BoolVal, ResultTy);
602 Stmt *Else = M.makeReturn(RetVal);
Ted Kremenek089ffd02012-10-11 20:58:18 +0000603
604 /// Construct the If.
Richard Smitha547eb22016-07-14 00:11:03 +0000605 Stmt *If = new (C) IfStmt(C, SourceLocation(), false, nullptr, nullptr,
606 Comparison, Body, SourceLocation(), Else);
Craig Topper25542942014-05-20 04:30:07 +0000607
Ted Kremenek089ffd02012-10-11 20:58:18 +0000608 return If;
609}
610
Ted Kremenek14f779c2012-09-21 00:09:11 +0000611Stmt *BodyFarm::getBody(const FunctionDecl *D) {
612 D = D->getCanonicalDecl();
613
David Blaikie05785d12013-02-20 22:23:23 +0000614 Optional<Stmt *> &Val = Bodies[D];
Ted Kremenek14f779c2012-09-21 00:09:11 +0000615 if (Val.hasValue())
616 return Val.getValue();
Craig Topper25542942014-05-20 04:30:07 +0000617
618 Val = nullptr;
619
620 if (D->getIdentifier() == nullptr)
621 return nullptr;
Ted Kremenek14f779c2012-09-21 00:09:11 +0000622
623 StringRef Name = D->getName();
624 if (Name.empty())
Craig Topper25542942014-05-20 04:30:07 +0000625 return nullptr;
Ted Kremenek089ffd02012-10-11 20:58:18 +0000626
627 FunctionFarmer FF;
628
629 if (Name.startswith("OSAtomicCompareAndSwap") ||
630 Name.startswith("objc_atomicCompareAndSwap")) {
631 FF = create_OSAtomicCompareAndSwap;
George Karpenkov657a5892017-09-30 00:03:22 +0000632 } else if (Name == "call_once" && D->getDeclContext()->isStdNamespace()) {
633 FF = create_call_once;
634 } else {
Ted Kremenek089ffd02012-10-11 20:58:18 +0000635 FF = llvm::StringSwitch<FunctionFarmer>(Name)
636 .Case("dispatch_sync", create_dispatch_sync)
637 .Case("dispatch_once", create_dispatch_once)
Craig Topper25542942014-05-20 04:30:07 +0000638 .Default(nullptr);
Ted Kremenek14f779c2012-09-21 00:09:11 +0000639 }
640
Ted Kremenek089ffd02012-10-11 20:58:18 +0000641 if (FF) { Val = FF(C, D); }
Ted Kremenekeeccb302014-08-27 15:14:15 +0000642 else if (Injector) { Val = Injector->getBody(D); }
Ted Kremenek14f779c2012-09-21 00:09:11 +0000643 return Val.getValue();
644}
645
Devin Coughlinb7e810b2016-01-26 23:58:48 +0000646static const ObjCIvarDecl *findBackingIvar(const ObjCPropertyDecl *Prop) {
647 const ObjCIvarDecl *IVar = Prop->getPropertyIvarDecl();
648
649 if (IVar)
650 return IVar;
651
652 // When a readonly property is shadowed in a class extensions with a
653 // a readwrite property, the instance variable belongs to the shadowing
654 // property rather than the shadowed property. If there is no instance
655 // variable on a readonly property, check to see whether the property is
656 // shadowed and if so try to get the instance variable from shadowing
657 // property.
658 if (!Prop->isReadOnly())
659 return nullptr;
660
661 auto *Container = cast<ObjCContainerDecl>(Prop->getDeclContext());
662 const ObjCInterfaceDecl *PrimaryInterface = nullptr;
663 if (auto *InterfaceDecl = dyn_cast<ObjCInterfaceDecl>(Container)) {
664 PrimaryInterface = InterfaceDecl;
665 } else if (auto *CategoryDecl = dyn_cast<ObjCCategoryDecl>(Container)) {
666 PrimaryInterface = CategoryDecl->getClassInterface();
667 } else if (auto *ImplDecl = dyn_cast<ObjCImplDecl>(Container)) {
668 PrimaryInterface = ImplDecl->getClassInterface();
669 } else {
670 return nullptr;
671 }
672
673 // FindPropertyVisibleInPrimaryClass() looks first in class extensions, so it
674 // is guaranteed to find the shadowing property, if it exists, rather than
675 // the shadowed property.
676 auto *ShadowingProp = PrimaryInterface->FindPropertyVisibleInPrimaryClass(
Manman Ren5b786402016-01-28 18:49:28 +0000677 Prop->getIdentifier(), Prop->getQueryKind());
Devin Coughlinb7e810b2016-01-26 23:58:48 +0000678 if (ShadowingProp && ShadowingProp != Prop) {
679 IVar = ShadowingProp->getPropertyIvarDecl();
680 }
681
682 return IVar;
683}
684
Jordan Rose1a866cd2014-01-10 20:06:06 +0000685static Stmt *createObjCPropertyGetter(ASTContext &Ctx,
686 const ObjCPropertyDecl *Prop) {
Jordan Roseddf19662014-01-23 03:59:10 +0000687 // First, find the backing ivar.
Devin Coughlinb7e810b2016-01-26 23:58:48 +0000688 const ObjCIvarDecl *IVar = findBackingIvar(Prop);
Jordan Rose1a866cd2014-01-10 20:06:06 +0000689 if (!IVar)
Craig Topper25542942014-05-20 04:30:07 +0000690 return nullptr;
Jordan Roseddf19662014-01-23 03:59:10 +0000691
692 // Ignore weak variables, which have special behavior.
Jordan Rose1a866cd2014-01-10 20:06:06 +0000693 if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak)
Craig Topper25542942014-05-20 04:30:07 +0000694 return nullptr;
Jordan Rosea3f27812014-01-14 17:29:06 +0000695
Jordan Roseddf19662014-01-23 03:59:10 +0000696 // Look to see if Sema has synthesized a body for us. This happens in
697 // Objective-C++ because the return value may be a C++ class type with a
698 // non-trivial copy constructor. We can only do this if we can find the
699 // @synthesize for this property, though (or if we know it's been auto-
700 // synthesized).
Jordan Rosea3f27812014-01-14 17:29:06 +0000701 const ObjCImplementationDecl *ImplDecl =
702 IVar->getContainingInterface()->getImplementation();
703 if (ImplDecl) {
Aaron Ballmand85eff42014-03-14 15:02:45 +0000704 for (const auto *I : ImplDecl->property_impls()) {
Jordan Rosea3f27812014-01-14 17:29:06 +0000705 if (I->getPropertyDecl() != Prop)
706 continue;
707
708 if (I->getGetterCXXConstructor()) {
709 ASTMaker M(Ctx);
710 return M.makeReturn(I->getGetterCXXConstructor());
711 }
712 }
713 }
714
Jordan Roseddf19662014-01-23 03:59:10 +0000715 // Sanity check that the property is the same type as the ivar, or a
716 // reference to it, and that it is either an object pointer or trivially
717 // copyable.
718 if (!Ctx.hasSameUnqualifiedType(IVar->getType(),
719 Prop->getType().getNonReferenceType()))
Craig Topper25542942014-05-20 04:30:07 +0000720 return nullptr;
Jordan Roseddf19662014-01-23 03:59:10 +0000721 if (!IVar->getType()->isObjCLifetimeType() &&
722 !IVar->getType().isTriviallyCopyableType(Ctx))
Craig Topper25542942014-05-20 04:30:07 +0000723 return nullptr;
Jordan Rose1a866cd2014-01-10 20:06:06 +0000724
Jordan Roseddf19662014-01-23 03:59:10 +0000725 // Generate our body:
726 // return self->_ivar;
Jordan Rose1a866cd2014-01-10 20:06:06 +0000727 ASTMaker M(Ctx);
728
729 const VarDecl *selfVar = Prop->getGetterMethodDecl()->getSelfDecl();
Devin Coughlinaac894f2017-01-11 01:02:34 +0000730 if (!selfVar)
731 return nullptr;
Jordan Rose1a866cd2014-01-10 20:06:06 +0000732
733 Expr *loadedIVar =
734 M.makeObjCIvarRef(
735 M.makeLvalueToRvalue(
736 M.makeDeclRefExpr(selfVar),
737 selfVar->getType()),
738 IVar);
739
740 if (!Prop->getType()->isReferenceType())
741 loadedIVar = M.makeLvalueToRvalue(loadedIVar, IVar->getType());
742
743 return M.makeReturn(loadedIVar);
744}
745
Jordan Roseddf19662014-01-23 03:59:10 +0000746Stmt *BodyFarm::getBody(const ObjCMethodDecl *D) {
747 // We currently only know how to synthesize property accessors.
Jordan Rose1a866cd2014-01-10 20:06:06 +0000748 if (!D->isPropertyAccessor())
Craig Topper25542942014-05-20 04:30:07 +0000749 return nullptr;
Jordan Rose1a866cd2014-01-10 20:06:06 +0000750
751 D = D->getCanonicalDecl();
752
753 Optional<Stmt *> &Val = Bodies[D];
754 if (Val.hasValue())
755 return Val.getValue();
Craig Topper25542942014-05-20 04:30:07 +0000756 Val = nullptr;
Jordan Rose1a866cd2014-01-10 20:06:06 +0000757
Jordan Roseddf19662014-01-23 03:59:10 +0000758 const ObjCPropertyDecl *Prop = D->findPropertyDecl();
Jordan Rose1a866cd2014-01-10 20:06:06 +0000759 if (!Prop)
Craig Topper25542942014-05-20 04:30:07 +0000760 return nullptr;
Jordan Rose1a866cd2014-01-10 20:06:06 +0000761
Jordan Roseddf19662014-01-23 03:59:10 +0000762 // For now, we only synthesize getters.
Devin Coughlinef3697e2016-02-18 19:37:39 +0000763 // Synthesizing setters would cause false negatives in the
764 // RetainCountChecker because the method body would bind the parameter
765 // to an instance variable, causing it to escape. This would prevent
766 // warning in the following common scenario:
767 //
768 // id foo = [[NSObject alloc] init];
769 // self.foo = foo; // We should warn that foo leaks here.
770 //
Jordan Rose1a866cd2014-01-10 20:06:06 +0000771 if (D->param_size() != 0)
Craig Topper25542942014-05-20 04:30:07 +0000772 return nullptr;
Jordan Rose1a866cd2014-01-10 20:06:06 +0000773
774 Val = createObjCPropertyGetter(C, Prop);
775
776 return Val.getValue();
777}
778