blob: dd348847b3caf8b93a0d78d6283727341c7c5342 [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
George Karpenkov3d64d6e2017-10-23 23:59:52 +000015#include "clang/Analysis/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,
George Karpenkovb2a60c62017-10-17 22:28:18 +000066 bool RefersToEnclosingVariableOrCapture = false);
Ted Kremenek72418132012-09-21 17:54:35 +000067
Ted Kremenekdff35532012-09-21 18:33:52 +000068 /// Create a new UnaryOperator representing a dereference.
69 UnaryOperator *makeDereference(const Expr *Arg, QualType Ty);
70
Ted Kremenek69bcb822012-09-21 18:13:23 +000071 /// Create an implicit cast for an integer conversion.
Ted Kremenek6fdefb52012-10-12 00:18:19 +000072 Expr *makeIntegralCast(const Expr *Arg, QualType Ty);
Ted Kremenek69bcb822012-09-21 18:13:23 +000073
Ted Kremenek089ffd02012-10-11 20:58:18 +000074 /// Create an implicit cast to a builtin boolean type.
75 ImplicitCastExpr *makeIntegralCastToBoolean(const Expr *Arg);
76
George Karpenkov657a5892017-09-30 00:03:22 +000077 /// Create an implicit cast for lvalue-to-rvaluate conversions.
Ted Kremenekca90ea52012-09-21 18:13:27 +000078 ImplicitCastExpr *makeLvalueToRvalue(const Expr *Arg, QualType Ty);
79
George Karpenkov657a5892017-09-30 00:03:22 +000080 /// Make RValue out of variable declaration, creating a temporary
81 /// DeclRefExpr in the process.
82 ImplicitCastExpr *
83 makeLvalueToRvalue(const VarDecl *Decl,
George Karpenkovb2a60c62017-10-17 22:28:18 +000084 bool RefersToEnclosingVariableOrCapture = false);
George Karpenkov657a5892017-09-30 00:03:22 +000085
86 /// Create an implicit cast of the given type.
87 ImplicitCastExpr *makeImplicitCast(const Expr *Arg, QualType Ty,
88 CastKind CK = CK_LValueToRValue);
89
Ted Kremenek089ffd02012-10-11 20:58:18 +000090 /// Create an Objective-C bool literal.
91 ObjCBoolLiteralExpr *makeObjCBool(bool Val);
Jordan Rose1a866cd2014-01-10 20:06:06 +000092
93 /// Create an Objective-C ivar reference.
94 ObjCIvarRefExpr *makeObjCIvarRef(const Expr *Base, const ObjCIvarDecl *IVar);
Ted Kremenek089ffd02012-10-11 20:58:18 +000095
96 /// Create a Return statement.
97 ReturnStmt *makeReturn(const Expr *RetVal);
98
George Karpenkov657a5892017-09-30 00:03:22 +000099 /// Create an integer literal.
100 IntegerLiteral *makeIntegerLiteral(uint64_t value);
101
102 /// Create a member expression.
103 MemberExpr *makeMemberExpression(Expr *base, ValueDecl *MemberDecl,
104 bool IsArrow = false,
105 ExprValueKind ValueKind = VK_LValue);
106
107 /// Returns a *first* member field of a record declaration with a given name.
108 /// \return an nullptr if no member with such a name exists.
George Karpenkovc928e1f2017-10-11 20:53:01 +0000109 ValueDecl *findMemberField(const RecordDecl *RD, StringRef Name);
George Karpenkov657a5892017-09-30 00:03:22 +0000110
Ted Kremenek72418132012-09-21 17:54:35 +0000111private:
112 ASTContext &C;
113};
Alexander Kornienkoab9db512015-06-22 23:07:51 +0000114}
Ted Kremenek72418132012-09-21 17:54:35 +0000115
Ted Kremenekf465dc12012-09-21 18:33:54 +0000116BinaryOperator *ASTMaker::makeAssignment(const Expr *LHS, const Expr *RHS,
117 QualType Ty) {
118 return new (C) BinaryOperator(const_cast<Expr*>(LHS), const_cast<Expr*>(RHS),
119 BO_Assign, Ty, VK_RValue,
Adam Nemet484aa452017-03-27 19:17:25 +0000120 OK_Ordinary, SourceLocation(), FPOptions());
Ted Kremenekf465dc12012-09-21 18:33:54 +0000121}
122
Ted Kremenek089ffd02012-10-11 20:58:18 +0000123BinaryOperator *ASTMaker::makeComparison(const Expr *LHS, const Expr *RHS,
124 BinaryOperator::Opcode Op) {
125 assert(BinaryOperator::isLogicalOp(Op) ||
126 BinaryOperator::isComparisonOp(Op));
127 return new (C) BinaryOperator(const_cast<Expr*>(LHS),
128 const_cast<Expr*>(RHS),
129 Op,
130 C.getLogicalOperationType(),
131 VK_RValue,
Adam Nemet484aa452017-03-27 19:17:25 +0000132 OK_Ordinary, SourceLocation(), FPOptions());
Ted Kremenek089ffd02012-10-11 20:58:18 +0000133}
134
135CompoundStmt *ASTMaker::makeCompound(ArrayRef<Stmt *> Stmts) {
Nico Webera2a0eb92012-12-29 20:03:39 +0000136 return new (C) CompoundStmt(C, Stmts, SourceLocation(), SourceLocation());
Ted Kremenek089ffd02012-10-11 20:58:18 +0000137}
138
George Karpenkovb2a60c62017-10-17 22:28:18 +0000139DeclRefExpr *ASTMaker::makeDeclRefExpr(
140 const VarDecl *D,
141 bool RefersToEnclosingVariableOrCapture) {
142 QualType Type = D->getType().getNonReferenceType();
George Karpenkov657a5892017-09-30 00:03:22 +0000143
144 DeclRefExpr *DR = DeclRefExpr::Create(
145 C, NestedNameSpecifierLoc(), SourceLocation(), const_cast<VarDecl *>(D),
146 RefersToEnclosingVariableOrCapture, SourceLocation(), Type, VK_LValue);
Ted Kremenek72418132012-09-21 17:54:35 +0000147 return DR;
148}
149
Ted Kremenekdff35532012-09-21 18:33:52 +0000150UnaryOperator *ASTMaker::makeDereference(const Expr *Arg, QualType Ty) {
151 return new (C) UnaryOperator(const_cast<Expr*>(Arg), UO_Deref, Ty,
152 VK_LValue, OK_Ordinary, SourceLocation());
153}
154
Ted Kremenekca90ea52012-09-21 18:13:27 +0000155ImplicitCastExpr *ASTMaker::makeLvalueToRvalue(const Expr *Arg, QualType Ty) {
George Karpenkov657a5892017-09-30 00:03:22 +0000156 return makeImplicitCast(Arg, Ty, CK_LValueToRValue);
157}
158
George Karpenkov657a5892017-09-30 00:03:22 +0000159ImplicitCastExpr *
160ASTMaker::makeLvalueToRvalue(const VarDecl *Arg,
George Karpenkovb2a60c62017-10-17 22:28:18 +0000161 bool RefersToEnclosingVariableOrCapture) {
162 QualType Type = Arg->getType().getNonReferenceType();
George Karpenkov657a5892017-09-30 00:03:22 +0000163 return makeLvalueToRvalue(makeDeclRefExpr(Arg,
George Karpenkovb2a60c62017-10-17 22:28:18 +0000164 RefersToEnclosingVariableOrCapture),
George Karpenkov657a5892017-09-30 00:03:22 +0000165 Type);
166}
167
168ImplicitCastExpr *ASTMaker::makeImplicitCast(const Expr *Arg, QualType Ty,
169 CastKind CK) {
170 return ImplicitCastExpr::Create(C, Ty,
171 /* CastKind= */ CK,
172 /* Expr= */ const_cast<Expr *>(Arg),
173 /* CXXCastPath= */ nullptr,
174 /* ExprValueKind= */ VK_RValue);
Ted Kremenekca90ea52012-09-21 18:13:27 +0000175}
176
Ted Kremenek6fdefb52012-10-12 00:18:19 +0000177Expr *ASTMaker::makeIntegralCast(const Expr *Arg, QualType Ty) {
178 if (Arg->getType() == Ty)
179 return const_cast<Expr*>(Arg);
Craig Topper25542942014-05-20 04:30:07 +0000180
Ted Kremenek69bcb822012-09-21 18:13:23 +0000181 return ImplicitCastExpr::Create(C, Ty, CK_IntegralCast,
Craig Topper25542942014-05-20 04:30:07 +0000182 const_cast<Expr*>(Arg), nullptr, VK_RValue);
Ted Kremenek69bcb822012-09-21 18:13:23 +0000183}
184
Ted Kremenek089ffd02012-10-11 20:58:18 +0000185ImplicitCastExpr *ASTMaker::makeIntegralCastToBoolean(const Expr *Arg) {
186 return ImplicitCastExpr::Create(C, C.BoolTy, CK_IntegralToBoolean,
Craig Topper25542942014-05-20 04:30:07 +0000187 const_cast<Expr*>(Arg), nullptr, VK_RValue);
Ted Kremenek089ffd02012-10-11 20:58:18 +0000188}
189
190ObjCBoolLiteralExpr *ASTMaker::makeObjCBool(bool Val) {
191 QualType Ty = C.getBOOLDecl() ? C.getBOOLType() : C.ObjCBuiltinBoolTy;
192 return new (C) ObjCBoolLiteralExpr(Val, Ty, SourceLocation());
193}
194
Jordan Rose1a866cd2014-01-10 20:06:06 +0000195ObjCIvarRefExpr *ASTMaker::makeObjCIvarRef(const Expr *Base,
196 const ObjCIvarDecl *IVar) {
197 return new (C) ObjCIvarRefExpr(const_cast<ObjCIvarDecl*>(IVar),
198 IVar->getType(), SourceLocation(),
199 SourceLocation(), const_cast<Expr*>(Base),
200 /*arrow=*/true, /*free=*/false);
201}
202
203
Ted Kremenek089ffd02012-10-11 20:58:18 +0000204ReturnStmt *ASTMaker::makeReturn(const Expr *RetVal) {
Craig Topper25542942014-05-20 04:30:07 +0000205 return new (C) ReturnStmt(SourceLocation(), const_cast<Expr*>(RetVal),
206 nullptr);
Ted Kremenek089ffd02012-10-11 20:58:18 +0000207}
208
George Karpenkov657a5892017-09-30 00:03:22 +0000209IntegerLiteral *ASTMaker::makeIntegerLiteral(uint64_t value) {
210 return IntegerLiteral::Create(C,
211 llvm::APInt(
212 /*numBits=*/C.getTypeSize(C.IntTy), value),
213 /*QualType=*/C.IntTy, SourceLocation());
214}
215
216MemberExpr *ASTMaker::makeMemberExpression(Expr *base, ValueDecl *MemberDecl,
217 bool IsArrow,
218 ExprValueKind ValueKind) {
219
220 DeclAccessPair FoundDecl = DeclAccessPair::make(MemberDecl, AS_public);
221 return MemberExpr::Create(
222 C, base, IsArrow, SourceLocation(), NestedNameSpecifierLoc(),
223 SourceLocation(), MemberDecl, FoundDecl,
224 DeclarationNameInfo(MemberDecl->getDeclName(), SourceLocation()),
225 /* TemplateArgumentListInfo= */ nullptr, MemberDecl->getType(), ValueKind,
226 OK_Ordinary);
227}
228
George Karpenkovc928e1f2017-10-11 20:53:01 +0000229ValueDecl *ASTMaker::findMemberField(const RecordDecl *RD, StringRef Name) {
George Karpenkov657a5892017-09-30 00:03:22 +0000230
231 CXXBasePaths Paths(
232 /* FindAmbiguities=*/false,
233 /* RecordPaths=*/false,
234 /* DetectVirtual= */ false);
235 const IdentifierInfo &II = C.Idents.get(Name);
236 DeclarationName DeclName = C.DeclarationNames.getIdentifier(&II);
237
238 DeclContextLookupResult Decls = RD->lookup(DeclName);
239 for (NamedDecl *FoundDecl : Decls)
240 if (!FoundDecl->getDeclContext()->isFunctionOrMethod())
George Karpenkovc928e1f2017-10-11 20:53:01 +0000241 return cast<ValueDecl>(FoundDecl);
George Karpenkov657a5892017-09-30 00:03:22 +0000242
243 return nullptr;
244}
245
Ted Kremenek2b5c83c2012-09-21 17:54:32 +0000246//===----------------------------------------------------------------------===//
247// Creation functions for faux ASTs.
248//===----------------------------------------------------------------------===//
249
250typedef Stmt *(*FunctionFarmer)(ASTContext &C, const FunctionDecl *D);
251
George Karpenkov6dda6712017-10-02 21:01:46 +0000252static CallExpr *create_call_once_funcptr_call(ASTContext &C, ASTMaker M,
253 const ParmVarDecl *Callback,
254 ArrayRef<Expr *> CallArgs) {
George Karpenkov657a5892017-09-30 00:03:22 +0000255
256 return new (C) CallExpr(
257 /*ASTContext=*/C,
258 /*StmtClass=*/M.makeLvalueToRvalue(/*Expr=*/Callback),
259 /*args=*/CallArgs,
260 /*QualType=*/C.VoidTy,
261 /*ExprValueType=*/VK_RValue,
262 /*SourceLocation=*/SourceLocation());
263}
264
George Karpenkov6dda6712017-10-02 21:01:46 +0000265static CallExpr *create_call_once_lambda_call(ASTContext &C, ASTMaker M,
266 const ParmVarDecl *Callback,
George Karpenkovbd4254c2017-10-20 23:29:59 +0000267 CXXRecordDecl *CallbackDecl,
George Karpenkov6dda6712017-10-02 21:01:46 +0000268 ArrayRef<Expr *> CallArgs) {
George Karpenkov657a5892017-09-30 00:03:22 +0000269 assert(CallbackDecl != nullptr);
270 assert(CallbackDecl->isLambda());
271 FunctionDecl *callOperatorDecl = CallbackDecl->getLambdaCallOperator();
272 assert(callOperatorDecl != nullptr);
273
274 DeclRefExpr *callOperatorDeclRef =
275 DeclRefExpr::Create(/* Ctx = */ C,
276 /* QualifierLoc = */ NestedNameSpecifierLoc(),
277 /* TemplateKWLoc = */ SourceLocation(),
278 const_cast<FunctionDecl *>(callOperatorDecl),
279 /* RefersToEnclosingVariableOrCapture= */ false,
280 /* NameLoc = */ SourceLocation(),
281 /* T = */ callOperatorDecl->getType(),
282 /* VK = */ VK_LValue);
283
George Karpenkov657a5892017-09-30 00:03:22 +0000284 return new (C)
285 CXXOperatorCallExpr(/*AstContext=*/C, OO_Call, callOperatorDeclRef,
286 /*args=*/CallArgs,
287 /*QualType=*/C.VoidTy,
288 /*ExprValueType=*/VK_RValue,
289 /*SourceLocation=*/SourceLocation(), FPOptions());
290}
291
292/// Create a fake body for std::call_once.
293/// Emulates the following function body:
294///
295/// \code
296/// typedef struct once_flag_s {
297/// unsigned long __state = 0;
298/// } once_flag;
299/// template<class Callable>
300/// void call_once(once_flag& o, Callable func) {
301/// if (!o.__state) {
302/// func();
303/// }
304/// o.__state = 1;
305/// }
306/// \endcode
307static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) {
308 DEBUG(llvm::dbgs() << "Generating body for call_once\n");
309
310 // We need at least two parameters.
311 if (D->param_size() < 2)
312 return nullptr;
313
314 ASTMaker M(C);
315
316 const ParmVarDecl *Flag = D->getParamDecl(0);
317 const ParmVarDecl *Callback = D->getParamDecl(1);
318 QualType CallbackType = Callback->getType().getNonReferenceType();
George Karpenkovbd4254c2017-10-20 23:29:59 +0000319
320 // Nullable pointer, non-null iff function is a CXXRecordDecl.
321 CXXRecordDecl *CallbackRecordDecl = CallbackType->getAsCXXRecordDecl();
George Karpenkov8b53f7c2017-10-09 23:20:46 +0000322 QualType FlagType = Flag->getType().getNonReferenceType();
George Karpenkovc928e1f2017-10-11 20:53:01 +0000323 auto *FlagRecordDecl = dyn_cast_or_null<RecordDecl>(FlagType->getAsTagDecl());
324
325 if (!FlagRecordDecl) {
326 DEBUG(llvm::dbgs() << "Flag field is not a record: "
327 << "unknown std::call_once implementation, "
328 << "ignoring the call.\n");
George Karpenkov8b53f7c2017-10-09 23:20:46 +0000329 return nullptr;
330 }
331
George Karpenkovc928e1f2017-10-11 20:53:01 +0000332 // We initially assume libc++ implementation of call_once,
333 // where the once_flag struct has a field `__state_`.
334 ValueDecl *FlagFieldDecl = M.findMemberField(FlagRecordDecl, "__state_");
335
336 // Otherwise, try libstdc++ implementation, with a field
337 // `_M_once`
338 if (!FlagFieldDecl) {
George Karpenkov8b53f7c2017-10-09 23:20:46 +0000339 DEBUG(llvm::dbgs() << "No field __state_ found on std::once_flag struct, "
George Karpenkovc928e1f2017-10-11 20:53:01 +0000340 << "assuming libstdc++ implementation\n");
341 FlagFieldDecl = M.findMemberField(FlagRecordDecl, "_M_once");
342 }
343
344 if (!FlagFieldDecl) {
345 DEBUG(llvm::dbgs() << "No field _M_once found on std::once flag struct: "
346 << "unknown std::call_once implementation, "
347 << "ignoring the call");
George Karpenkov8b53f7c2017-10-09 23:20:46 +0000348 return nullptr;
349 }
George Karpenkov657a5892017-09-30 00:03:22 +0000350
George Karpenkovbd4254c2017-10-20 23:29:59 +0000351 bool isLambdaCall = CallbackRecordDecl && CallbackRecordDecl->isLambda();
352 if (CallbackRecordDecl && !isLambdaCall) {
353 DEBUG(llvm::dbgs() << "Not supported: synthesizing body for functors when "
354 << "body farming std::call_once, ignoring the call.");
355 return nullptr;
356 }
George Karpenkov6dda6712017-10-02 21:01:46 +0000357
George Karpenkov657a5892017-09-30 00:03:22 +0000358 SmallVector<Expr *, 5> CallArgs;
George Karpenkovbd4254c2017-10-20 23:29:59 +0000359 const FunctionProtoType *CallbackFunctionType;
360 if (isLambdaCall) {
George Karpenkov657a5892017-09-30 00:03:22 +0000361
George Karpenkov6dda6712017-10-02 21:01:46 +0000362 // Lambda requires callback itself inserted as a first parameter.
363 CallArgs.push_back(
364 M.makeDeclRefExpr(Callback,
George Karpenkovb2a60c62017-10-17 22:28:18 +0000365 /* RefersToEnclosingVariableOrCapture= */ true));
George Karpenkovbd4254c2017-10-20 23:29:59 +0000366 CallbackFunctionType = CallbackRecordDecl->getLambdaCallOperator()
367 ->getType()
368 ->getAs<FunctionProtoType>();
369 } else {
370 CallbackFunctionType =
371 CallbackType->getPointeeType()->getAs<FunctionProtoType>();
372 }
George Karpenkov6dda6712017-10-02 21:01:46 +0000373
George Karpenkovbd4254c2017-10-20 23:29:59 +0000374 if (!CallbackFunctionType)
375 return nullptr;
376
377 // First two arguments are used for the flag and for the callback.
378 if (D->getNumParams() != CallbackFunctionType->getNumParams() + 2) {
379 DEBUG(llvm::dbgs() << "Number of params of the callback does not match "
380 << "the number of params passed to std::call_once, "
381 << "ignoring the call");
382 return nullptr;
383 }
384
385 // All arguments past first two ones are passed to the callback,
386 // and we turn lvalues into rvalues if the argument is not passed by
387 // reference.
388 for (unsigned int ParamIdx = 2; ParamIdx < D->getNumParams(); ParamIdx++) {
389 const ParmVarDecl *PDecl = D->getParamDecl(ParamIdx);
390 Expr *ParamExpr = M.makeDeclRefExpr(PDecl);
391 if (!CallbackFunctionType->getParamType(ParamIdx - 2)->isReferenceType()) {
392 QualType PTy = PDecl->getType().getNonReferenceType();
393 ParamExpr = M.makeLvalueToRvalue(ParamExpr, PTy);
394 }
395 CallArgs.push_back(ParamExpr);
396 }
George Karpenkov657a5892017-09-30 00:03:22 +0000397
398 CallExpr *CallbackCall;
George Karpenkov6dda6712017-10-02 21:01:46 +0000399 if (isLambdaCall) {
George Karpenkov657a5892017-09-30 00:03:22 +0000400
George Karpenkovbd4254c2017-10-20 23:29:59 +0000401 CallbackCall = create_call_once_lambda_call(C, M, Callback,
402 CallbackRecordDecl, CallArgs);
George Karpenkov657a5892017-09-30 00:03:22 +0000403 } else {
404
405 // Function pointer case.
406 CallbackCall = create_call_once_funcptr_call(C, M, Callback, CallArgs);
407 }
408
George Karpenkov657a5892017-09-30 00:03:22 +0000409 DeclRefExpr *FlagDecl =
410 M.makeDeclRefExpr(Flag,
George Karpenkovb2a60c62017-10-17 22:28:18 +0000411 /* RefersToEnclosingVariableOrCapture=*/true);
George Karpenkov657a5892017-09-30 00:03:22 +0000412
George Karpenkov657a5892017-09-30 00:03:22 +0000413
George Karpenkovc928e1f2017-10-11 20:53:01 +0000414 MemberExpr *Deref = M.makeMemberExpression(FlagDecl, FlagFieldDecl);
George Karpenkov657a5892017-09-30 00:03:22 +0000415 assert(Deref->isLValue());
416 QualType DerefType = Deref->getType();
417
418 // Negation predicate.
419 UnaryOperator *FlagCheck = new (C) UnaryOperator(
420 /* input= */
421 M.makeImplicitCast(M.makeLvalueToRvalue(Deref, DerefType), DerefType,
422 CK_IntegralToBoolean),
423 /* opc= */ UO_LNot,
424 /* QualType= */ C.IntTy,
425 /* ExprValueKind= */ VK_RValue,
426 /* ExprObjectKind= */ OK_Ordinary, SourceLocation());
427
428 // Create assignment.
429 BinaryOperator *FlagAssignment = M.makeAssignment(
430 Deref, M.makeIntegralCast(M.makeIntegerLiteral(1), DerefType), DerefType);
431
432 IfStmt *Out = new (C)
433 IfStmt(C, SourceLocation(),
434 /* IsConstexpr= */ false,
435 /* init= */ nullptr,
436 /* var= */ nullptr,
437 /* cond= */ FlagCheck,
438 /* then= */ M.makeCompound({CallbackCall, FlagAssignment}));
439
440 return Out;
441}
442
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000443/// Create a fake body for dispatch_once.
444static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
445 // Check if we have at least two parameters.
446 if (D->param_size() != 2)
Craig Topper25542942014-05-20 04:30:07 +0000447 return nullptr;
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000448
449 // Check if the first parameter is a pointer to integer type.
450 const ParmVarDecl *Predicate = D->getParamDecl(0);
451 QualType PredicateQPtrTy = Predicate->getType();
452 const PointerType *PredicatePtrTy = PredicateQPtrTy->getAs<PointerType>();
453 if (!PredicatePtrTy)
Craig Topper25542942014-05-20 04:30:07 +0000454 return nullptr;
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000455 QualType PredicateTy = PredicatePtrTy->getPointeeType();
456 if (!PredicateTy->isIntegerType())
Craig Topper25542942014-05-20 04:30:07 +0000457 return nullptr;
458
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000459 // Check if the second parameter is the proper block type.
460 const ParmVarDecl *Block = D->getParamDecl(1);
461 QualType Ty = Block->getType();
462 if (!isDispatchBlock(Ty))
Craig Topper25542942014-05-20 04:30:07 +0000463 return nullptr;
464
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000465 // Everything checks out. Create a fakse body that checks the predicate,
466 // sets it, and calls the block. Basically, an AST dump of:
467 //
468 // void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block) {
469 // if (!*predicate) {
470 // *predicate = 1;
471 // block();
472 // }
473 // }
474
Ted Kremenek72418132012-09-21 17:54:35 +0000475 ASTMaker M(C);
476
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000477 // (1) Create the call.
George Karpenkov657a5892017-09-30 00:03:22 +0000478 CallExpr *CE = new (C) CallExpr(
479 /*ASTContext=*/C,
480 /*StmtClass=*/M.makeLvalueToRvalue(/*Expr=*/Block),
481 /*args=*/None,
482 /*QualType=*/C.VoidTy,
483 /*ExprValueType=*/VK_RValue,
484 /*SourceLocation=*/SourceLocation());
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000485
486 // (2) Create the assignment to the predicate.
George Karpenkov657a5892017-09-30 00:03:22 +0000487 IntegerLiteral *IL = M.makeIntegerLiteral(1);
488
Ted Kremeneke7ad5352012-09-21 18:33:56 +0000489 BinaryOperator *B =
490 M.makeAssignment(
491 M.makeDereference(
492 M.makeLvalueToRvalue(
493 M.makeDeclRefExpr(Predicate), PredicateQPtrTy),
494 PredicateTy),
495 M.makeIntegralCast(IL, PredicateTy),
496 PredicateTy);
497
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000498 // (3) Create the compound statement.
Craig Topper5fc8fc22014-08-27 06:28:36 +0000499 Stmt *Stmts[] = { B, CE };
500 CompoundStmt *CS = M.makeCompound(Stmts);
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000501
502 // (4) Create the 'if' condition.
Ted Kremeneke7ad5352012-09-21 18:33:56 +0000503 ImplicitCastExpr *LValToRval =
504 M.makeLvalueToRvalue(
505 M.makeDereference(
506 M.makeLvalueToRvalue(
507 M.makeDeclRefExpr(Predicate),
508 PredicateQPtrTy),
509 PredicateTy),
510 PredicateTy);
511
George Karpenkov657a5892017-09-30 00:03:22 +0000512 UnaryOperator *UO = new (C) UnaryOperator(
513 /* input= */ LValToRval,
514 /* opc= */ UO_LNot,
515 /* QualType= */ C.IntTy,
516 /* ExprValueKind= */ VK_RValue,
517 /* ExprObjectKind= */ OK_Ordinary, SourceLocation());
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000518
519 // (5) Create the 'if' statement.
George Karpenkov657a5892017-09-30 00:03:22 +0000520 IfStmt *If = new (C) IfStmt(C, SourceLocation(),
521 /* IsConstexpr= */ false,
522 /* init= */ nullptr,
523 /* var= */ nullptr,
524 /* cond= */ UO,
525 /* then= */ CS);
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000526 return If;
527}
528
Ted Kremenek14f779c2012-09-21 00:09:11 +0000529/// Create a fake body for dispatch_sync.
530static Stmt *create_dispatch_sync(ASTContext &C, const FunctionDecl *D) {
531 // Check if we have at least two parameters.
532 if (D->param_size() != 2)
Craig Topper25542942014-05-20 04:30:07 +0000533 return nullptr;
534
Ted Kremenek14f779c2012-09-21 00:09:11 +0000535 // Check if the second parameter is a block.
536 const ParmVarDecl *PV = D->getParamDecl(1);
537 QualType Ty = PV->getType();
Ted Kremenekd81a4a12012-09-21 00:52:24 +0000538 if (!isDispatchBlock(Ty))
Craig Topper25542942014-05-20 04:30:07 +0000539 return nullptr;
540
Ted Kremenek14f779c2012-09-21 00:09:11 +0000541 // Everything checks out. Create a fake body that just calls the block.
542 // This is basically just an AST dump of:
543 //
544 // void dispatch_sync(dispatch_queue_t queue, void (^block)(void)) {
545 // block();
546 // }
Ted Kremenek72418132012-09-21 17:54:35 +0000547 //
548 ASTMaker M(C);
549 DeclRefExpr *DR = M.makeDeclRefExpr(PV);
Ted Kremenekdff35532012-09-21 18:33:52 +0000550 ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty);
Dmitri Gribenko44ebbd52013-05-05 00:41:58 +0000551 CallExpr *CE = new (C) CallExpr(C, ICE, None, C.VoidTy, VK_RValue,
552 SourceLocation());
Ted Kremenek14f779c2012-09-21 00:09:11 +0000553 return CE;
554}
555
Ted Kremenek089ffd02012-10-11 20:58:18 +0000556static Stmt *create_OSAtomicCompareAndSwap(ASTContext &C, const FunctionDecl *D)
557{
558 // There are exactly 3 arguments.
559 if (D->param_size() != 3)
Craig Topper25542942014-05-20 04:30:07 +0000560 return nullptr;
561
Anna Zaks064185a2013-02-05 19:52:26 +0000562 // Signature:
563 // _Bool OSAtomicCompareAndSwapPtr(void *__oldValue,
564 // void *__newValue,
565 // void * volatile *__theValue)
566 // Generate body:
Ted Kremenek089ffd02012-10-11 20:58:18 +0000567 // if (oldValue == *theValue) {
568 // *theValue = newValue;
569 // return YES;
570 // }
571 // else return NO;
Alp Toker314cc812014-01-25 16:55:45 +0000572
573 QualType ResultTy = D->getReturnType();
Ted Kremenek6fdefb52012-10-12 00:18:19 +0000574 bool isBoolean = ResultTy->isBooleanType();
575 if (!isBoolean && !ResultTy->isIntegralType(C))
Craig Topper25542942014-05-20 04:30:07 +0000576 return nullptr;
577
Ted Kremenek089ffd02012-10-11 20:58:18 +0000578 const ParmVarDecl *OldValue = D->getParamDecl(0);
579 QualType OldValueTy = OldValue->getType();
580
581 const ParmVarDecl *NewValue = D->getParamDecl(1);
582 QualType NewValueTy = NewValue->getType();
583
584 assert(OldValueTy == NewValueTy);
585
586 const ParmVarDecl *TheValue = D->getParamDecl(2);
587 QualType TheValueTy = TheValue->getType();
588 const PointerType *PT = TheValueTy->getAs<PointerType>();
589 if (!PT)
Craig Topper25542942014-05-20 04:30:07 +0000590 return nullptr;
Ted Kremenek089ffd02012-10-11 20:58:18 +0000591 QualType PointeeTy = PT->getPointeeType();
592
593 ASTMaker M(C);
594 // Construct the comparison.
595 Expr *Comparison =
596 M.makeComparison(
597 M.makeLvalueToRvalue(M.makeDeclRefExpr(OldValue), OldValueTy),
598 M.makeLvalueToRvalue(
599 M.makeDereference(
600 M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
601 PointeeTy),
602 PointeeTy),
603 BO_EQ);
604
605 // Construct the body of the IfStmt.
606 Stmt *Stmts[2];
607 Stmts[0] =
608 M.makeAssignment(
609 M.makeDereference(
610 M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
611 PointeeTy),
612 M.makeLvalueToRvalue(M.makeDeclRefExpr(NewValue), NewValueTy),
613 NewValueTy);
Ted Kremenek6fdefb52012-10-12 00:18:19 +0000614
615 Expr *BoolVal = M.makeObjCBool(true);
616 Expr *RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
617 : M.makeIntegralCast(BoolVal, ResultTy);
618 Stmts[1] = M.makeReturn(RetVal);
Craig Topper5fc8fc22014-08-27 06:28:36 +0000619 CompoundStmt *Body = M.makeCompound(Stmts);
Ted Kremenek089ffd02012-10-11 20:58:18 +0000620
621 // Construct the else clause.
Ted Kremenek6fdefb52012-10-12 00:18:19 +0000622 BoolVal = M.makeObjCBool(false);
623 RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
624 : M.makeIntegralCast(BoolVal, ResultTy);
625 Stmt *Else = M.makeReturn(RetVal);
Ted Kremenek089ffd02012-10-11 20:58:18 +0000626
627 /// Construct the If.
Richard Smitha547eb22016-07-14 00:11:03 +0000628 Stmt *If = new (C) IfStmt(C, SourceLocation(), false, nullptr, nullptr,
629 Comparison, Body, SourceLocation(), Else);
Craig Topper25542942014-05-20 04:30:07 +0000630
Ted Kremenek089ffd02012-10-11 20:58:18 +0000631 return If;
632}
633
Ted Kremenek14f779c2012-09-21 00:09:11 +0000634Stmt *BodyFarm::getBody(const FunctionDecl *D) {
635 D = D->getCanonicalDecl();
636
David Blaikie05785d12013-02-20 22:23:23 +0000637 Optional<Stmt *> &Val = Bodies[D];
Ted Kremenek14f779c2012-09-21 00:09:11 +0000638 if (Val.hasValue())
639 return Val.getValue();
Craig Topper25542942014-05-20 04:30:07 +0000640
641 Val = nullptr;
642
643 if (D->getIdentifier() == nullptr)
644 return nullptr;
Ted Kremenek14f779c2012-09-21 00:09:11 +0000645
646 StringRef Name = D->getName();
647 if (Name.empty())
Craig Topper25542942014-05-20 04:30:07 +0000648 return nullptr;
Ted Kremenek089ffd02012-10-11 20:58:18 +0000649
650 FunctionFarmer FF;
651
652 if (Name.startswith("OSAtomicCompareAndSwap") ||
653 Name.startswith("objc_atomicCompareAndSwap")) {
654 FF = create_OSAtomicCompareAndSwap;
George Karpenkov657a5892017-09-30 00:03:22 +0000655 } else if (Name == "call_once" && D->getDeclContext()->isStdNamespace()) {
656 FF = create_call_once;
657 } else {
Ted Kremenek089ffd02012-10-11 20:58:18 +0000658 FF = llvm::StringSwitch<FunctionFarmer>(Name)
659 .Case("dispatch_sync", create_dispatch_sync)
660 .Case("dispatch_once", create_dispatch_once)
Craig Topper25542942014-05-20 04:30:07 +0000661 .Default(nullptr);
Ted Kremenek14f779c2012-09-21 00:09:11 +0000662 }
663
Ted Kremenek089ffd02012-10-11 20:58:18 +0000664 if (FF) { Val = FF(C, D); }
Ted Kremenekeeccb302014-08-27 15:14:15 +0000665 else if (Injector) { Val = Injector->getBody(D); }
Ted Kremenek14f779c2012-09-21 00:09:11 +0000666 return Val.getValue();
667}
668
Devin Coughlinb7e810b2016-01-26 23:58:48 +0000669static const ObjCIvarDecl *findBackingIvar(const ObjCPropertyDecl *Prop) {
670 const ObjCIvarDecl *IVar = Prop->getPropertyIvarDecl();
671
672 if (IVar)
673 return IVar;
674
675 // When a readonly property is shadowed in a class extensions with a
676 // a readwrite property, the instance variable belongs to the shadowing
677 // property rather than the shadowed property. If there is no instance
678 // variable on a readonly property, check to see whether the property is
679 // shadowed and if so try to get the instance variable from shadowing
680 // property.
681 if (!Prop->isReadOnly())
682 return nullptr;
683
684 auto *Container = cast<ObjCContainerDecl>(Prop->getDeclContext());
685 const ObjCInterfaceDecl *PrimaryInterface = nullptr;
686 if (auto *InterfaceDecl = dyn_cast<ObjCInterfaceDecl>(Container)) {
687 PrimaryInterface = InterfaceDecl;
688 } else if (auto *CategoryDecl = dyn_cast<ObjCCategoryDecl>(Container)) {
689 PrimaryInterface = CategoryDecl->getClassInterface();
690 } else if (auto *ImplDecl = dyn_cast<ObjCImplDecl>(Container)) {
691 PrimaryInterface = ImplDecl->getClassInterface();
692 } else {
693 return nullptr;
694 }
695
696 // FindPropertyVisibleInPrimaryClass() looks first in class extensions, so it
697 // is guaranteed to find the shadowing property, if it exists, rather than
698 // the shadowed property.
699 auto *ShadowingProp = PrimaryInterface->FindPropertyVisibleInPrimaryClass(
Manman Ren5b786402016-01-28 18:49:28 +0000700 Prop->getIdentifier(), Prop->getQueryKind());
Devin Coughlinb7e810b2016-01-26 23:58:48 +0000701 if (ShadowingProp && ShadowingProp != Prop) {
702 IVar = ShadowingProp->getPropertyIvarDecl();
703 }
704
705 return IVar;
706}
707
Jordan Rose1a866cd2014-01-10 20:06:06 +0000708static Stmt *createObjCPropertyGetter(ASTContext &Ctx,
709 const ObjCPropertyDecl *Prop) {
Jordan Roseddf19662014-01-23 03:59:10 +0000710 // First, find the backing ivar.
Devin Coughlinb7e810b2016-01-26 23:58:48 +0000711 const ObjCIvarDecl *IVar = findBackingIvar(Prop);
Jordan Rose1a866cd2014-01-10 20:06:06 +0000712 if (!IVar)
Craig Topper25542942014-05-20 04:30:07 +0000713 return nullptr;
Jordan Roseddf19662014-01-23 03:59:10 +0000714
715 // Ignore weak variables, which have special behavior.
Jordan Rose1a866cd2014-01-10 20:06:06 +0000716 if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak)
Craig Topper25542942014-05-20 04:30:07 +0000717 return nullptr;
Jordan Rosea3f27812014-01-14 17:29:06 +0000718
Jordan Roseddf19662014-01-23 03:59:10 +0000719 // Look to see if Sema has synthesized a body for us. This happens in
720 // Objective-C++ because the return value may be a C++ class type with a
721 // non-trivial copy constructor. We can only do this if we can find the
722 // @synthesize for this property, though (or if we know it's been auto-
723 // synthesized).
Jordan Rosea3f27812014-01-14 17:29:06 +0000724 const ObjCImplementationDecl *ImplDecl =
725 IVar->getContainingInterface()->getImplementation();
726 if (ImplDecl) {
Aaron Ballmand85eff42014-03-14 15:02:45 +0000727 for (const auto *I : ImplDecl->property_impls()) {
Jordan Rosea3f27812014-01-14 17:29:06 +0000728 if (I->getPropertyDecl() != Prop)
729 continue;
730
731 if (I->getGetterCXXConstructor()) {
732 ASTMaker M(Ctx);
733 return M.makeReturn(I->getGetterCXXConstructor());
734 }
735 }
736 }
737
Jordan Roseddf19662014-01-23 03:59:10 +0000738 // Sanity check that the property is the same type as the ivar, or a
739 // reference to it, and that it is either an object pointer or trivially
740 // copyable.
741 if (!Ctx.hasSameUnqualifiedType(IVar->getType(),
742 Prop->getType().getNonReferenceType()))
Craig Topper25542942014-05-20 04:30:07 +0000743 return nullptr;
Jordan Roseddf19662014-01-23 03:59:10 +0000744 if (!IVar->getType()->isObjCLifetimeType() &&
745 !IVar->getType().isTriviallyCopyableType(Ctx))
Craig Topper25542942014-05-20 04:30:07 +0000746 return nullptr;
Jordan Rose1a866cd2014-01-10 20:06:06 +0000747
Jordan Roseddf19662014-01-23 03:59:10 +0000748 // Generate our body:
749 // return self->_ivar;
Jordan Rose1a866cd2014-01-10 20:06:06 +0000750 ASTMaker M(Ctx);
751
752 const VarDecl *selfVar = Prop->getGetterMethodDecl()->getSelfDecl();
Devin Coughlinaac894f2017-01-11 01:02:34 +0000753 if (!selfVar)
754 return nullptr;
Jordan Rose1a866cd2014-01-10 20:06:06 +0000755
756 Expr *loadedIVar =
757 M.makeObjCIvarRef(
758 M.makeLvalueToRvalue(
759 M.makeDeclRefExpr(selfVar),
760 selfVar->getType()),
761 IVar);
762
763 if (!Prop->getType()->isReferenceType())
764 loadedIVar = M.makeLvalueToRvalue(loadedIVar, IVar->getType());
765
766 return M.makeReturn(loadedIVar);
767}
768
Jordan Roseddf19662014-01-23 03:59:10 +0000769Stmt *BodyFarm::getBody(const ObjCMethodDecl *D) {
770 // We currently only know how to synthesize property accessors.
Jordan Rose1a866cd2014-01-10 20:06:06 +0000771 if (!D->isPropertyAccessor())
Craig Topper25542942014-05-20 04:30:07 +0000772 return nullptr;
Jordan Rose1a866cd2014-01-10 20:06:06 +0000773
774 D = D->getCanonicalDecl();
775
776 Optional<Stmt *> &Val = Bodies[D];
777 if (Val.hasValue())
778 return Val.getValue();
Craig Topper25542942014-05-20 04:30:07 +0000779 Val = nullptr;
Jordan Rose1a866cd2014-01-10 20:06:06 +0000780
Jordan Roseddf19662014-01-23 03:59:10 +0000781 const ObjCPropertyDecl *Prop = D->findPropertyDecl();
Jordan Rose1a866cd2014-01-10 20:06:06 +0000782 if (!Prop)
Craig Topper25542942014-05-20 04:30:07 +0000783 return nullptr;
Jordan Rose1a866cd2014-01-10 20:06:06 +0000784
Jordan Roseddf19662014-01-23 03:59:10 +0000785 // For now, we only synthesize getters.
Devin Coughlinef3697e2016-02-18 19:37:39 +0000786 // Synthesizing setters would cause false negatives in the
787 // RetainCountChecker because the method body would bind the parameter
788 // to an instance variable, causing it to escape. This would prevent
789 // warning in the following common scenario:
790 //
791 // id foo = [[NSObject alloc] init];
792 // self.foo = foo; // We should warn that foo leaks here.
793 //
Jordan Rose1a866cd2014-01-10 20:06:06 +0000794 if (D->param_size() != 0)
Craig Topper25542942014-05-20 04:30:07 +0000795 return nullptr;
Jordan Rose1a866cd2014-01-10 20:06:06 +0000796
797 Val = createObjCPropertyGetter(C, Prop);
798
799 return Val.getValue();
800}
801