1 //== BodyFarm.cpp - Factory for conjuring up fake bodies ----------*- C++ -*-//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // BodyFarm is a factory for creating faux implementations for functions/methods
10 // for analysis purposes.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "clang/Analysis/BodyFarm.h"
15 #include "clang/AST/ASTContext.h"
16 #include "clang/AST/CXXInheritance.h"
17 #include "clang/AST/Decl.h"
18 #include "clang/AST/Expr.h"
19 #include "clang/AST/ExprCXX.h"
20 #include "clang/AST/ExprObjC.h"
21 #include "clang/AST/NestedNameSpecifier.h"
22 #include "clang/Analysis/CodeInjector.h"
23 #include "clang/Basic/OperatorKinds.h"
24 #include "llvm/ADT/StringSwitch.h"
25 #include "llvm/Support/Debug.h"
26
27 #define DEBUG_TYPE "body-farm"
28
29 using namespace clang;
30
31 //===----------------------------------------------------------------------===//
32 // Helper creation functions for constructing faux ASTs.
33 //===----------------------------------------------------------------------===//
34
isDispatchBlock(QualType Ty)35 static bool isDispatchBlock(QualType Ty) {
36 // Is it a block pointer?
37 const BlockPointerType *BPT = Ty->getAs<BlockPointerType>();
38 if (!BPT)
39 return false;
40
41 // Check if the block pointer type takes no arguments and
42 // returns void.
43 const FunctionProtoType *FT =
44 BPT->getPointeeType()->getAs<FunctionProtoType>();
45 return FT && FT->getReturnType()->isVoidType() && FT->getNumParams() == 0;
46 }
47
48 namespace {
49 class ASTMaker {
50 public:
ASTMaker(ASTContext & C)51 ASTMaker(ASTContext &C) : C(C) {}
52
53 /// Create a new BinaryOperator representing a simple assignment.
54 BinaryOperator *makeAssignment(const Expr *LHS, const Expr *RHS, QualType Ty);
55
56 /// Create a new BinaryOperator representing a comparison.
57 BinaryOperator *makeComparison(const Expr *LHS, const Expr *RHS,
58 BinaryOperator::Opcode Op);
59
60 /// Create a new compound stmt using the provided statements.
61 CompoundStmt *makeCompound(ArrayRef<Stmt*>);
62
63 /// Create a new DeclRefExpr for the referenced variable.
64 DeclRefExpr *makeDeclRefExpr(const VarDecl *D,
65 bool RefersToEnclosingVariableOrCapture = false);
66
67 /// Create a new UnaryOperator representing a dereference.
68 UnaryOperator *makeDereference(const Expr *Arg, QualType Ty);
69
70 /// Create an implicit cast for an integer conversion.
71 Expr *makeIntegralCast(const Expr *Arg, QualType Ty);
72
73 /// Create an implicit cast to a builtin boolean type.
74 ImplicitCastExpr *makeIntegralCastToBoolean(const Expr *Arg);
75
76 /// Create an implicit cast for lvalue-to-rvaluate conversions.
77 ImplicitCastExpr *makeLvalueToRvalue(const Expr *Arg, QualType Ty);
78
79 /// Make RValue out of variable declaration, creating a temporary
80 /// DeclRefExpr in the process.
81 ImplicitCastExpr *
82 makeLvalueToRvalue(const VarDecl *Decl,
83 bool RefersToEnclosingVariableOrCapture = false);
84
85 /// Create an implicit cast of the given type.
86 ImplicitCastExpr *makeImplicitCast(const Expr *Arg, QualType Ty,
87 CastKind CK = CK_LValueToRValue);
88
89 /// Create an Objective-C bool literal.
90 ObjCBoolLiteralExpr *makeObjCBool(bool Val);
91
92 /// Create an Objective-C ivar reference.
93 ObjCIvarRefExpr *makeObjCIvarRef(const Expr *Base, const ObjCIvarDecl *IVar);
94
95 /// Create a Return statement.
96 ReturnStmt *makeReturn(const Expr *RetVal);
97
98 /// Create an integer literal expression of the given type.
99 IntegerLiteral *makeIntegerLiteral(uint64_t Value, QualType Ty);
100
101 /// Create a member expression.
102 MemberExpr *makeMemberExpression(Expr *base, ValueDecl *MemberDecl,
103 bool IsArrow = false,
104 ExprValueKind ValueKind = VK_LValue);
105
106 /// Returns a *first* member field of a record declaration with a given name.
107 /// \return an nullptr if no member with such a name exists.
108 ValueDecl *findMemberField(const RecordDecl *RD, StringRef Name);
109
110 private:
111 ASTContext &C;
112 };
113 }
114
makeAssignment(const Expr * LHS,const Expr * RHS,QualType Ty)115 BinaryOperator *ASTMaker::makeAssignment(const Expr *LHS, const Expr *RHS,
116 QualType Ty) {
117 return BinaryOperator::Create(
118 C, const_cast<Expr *>(LHS), const_cast<Expr *>(RHS), BO_Assign, Ty,
119 VK_RValue, OK_Ordinary, SourceLocation(), FPOptionsOverride());
120 }
121
makeComparison(const Expr * LHS,const Expr * RHS,BinaryOperator::Opcode Op)122 BinaryOperator *ASTMaker::makeComparison(const Expr *LHS, const Expr *RHS,
123 BinaryOperator::Opcode Op) {
124 assert(BinaryOperator::isLogicalOp(Op) ||
125 BinaryOperator::isComparisonOp(Op));
126 return BinaryOperator::Create(
127 C, const_cast<Expr *>(LHS), const_cast<Expr *>(RHS), Op,
128 C.getLogicalOperationType(), VK_RValue, OK_Ordinary, SourceLocation(),
129 FPOptionsOverride());
130 }
131
makeCompound(ArrayRef<Stmt * > Stmts)132 CompoundStmt *ASTMaker::makeCompound(ArrayRef<Stmt *> Stmts) {
133 return CompoundStmt::Create(C, Stmts, SourceLocation(), SourceLocation());
134 }
135
makeDeclRefExpr(const VarDecl * D,bool RefersToEnclosingVariableOrCapture)136 DeclRefExpr *ASTMaker::makeDeclRefExpr(
137 const VarDecl *D,
138 bool RefersToEnclosingVariableOrCapture) {
139 QualType Type = D->getType().getNonReferenceType();
140
141 DeclRefExpr *DR = DeclRefExpr::Create(
142 C, NestedNameSpecifierLoc(), SourceLocation(), const_cast<VarDecl *>(D),
143 RefersToEnclosingVariableOrCapture, SourceLocation(), Type, VK_LValue);
144 return DR;
145 }
146
makeDereference(const Expr * Arg,QualType Ty)147 UnaryOperator *ASTMaker::makeDereference(const Expr *Arg, QualType Ty) {
148 return UnaryOperator::Create(C, const_cast<Expr *>(Arg), UO_Deref, Ty,
149 VK_LValue, OK_Ordinary, SourceLocation(),
150 /*CanOverflow*/ false, FPOptionsOverride());
151 }
152
makeLvalueToRvalue(const Expr * Arg,QualType Ty)153 ImplicitCastExpr *ASTMaker::makeLvalueToRvalue(const Expr *Arg, QualType Ty) {
154 return makeImplicitCast(Arg, Ty, CK_LValueToRValue);
155 }
156
157 ImplicitCastExpr *
makeLvalueToRvalue(const VarDecl * Arg,bool RefersToEnclosingVariableOrCapture)158 ASTMaker::makeLvalueToRvalue(const VarDecl *Arg,
159 bool RefersToEnclosingVariableOrCapture) {
160 QualType Type = Arg->getType().getNonReferenceType();
161 return makeLvalueToRvalue(makeDeclRefExpr(Arg,
162 RefersToEnclosingVariableOrCapture),
163 Type);
164 }
165
makeImplicitCast(const Expr * Arg,QualType Ty,CastKind CK)166 ImplicitCastExpr *ASTMaker::makeImplicitCast(const Expr *Arg, QualType Ty,
167 CastKind CK) {
168 return ImplicitCastExpr::Create(C, Ty,
169 /* CastKind=*/CK,
170 /* Expr=*/const_cast<Expr *>(Arg),
171 /* CXXCastPath=*/nullptr,
172 /* ExprValueKind=*/VK_RValue,
173 /* FPFeatures */ FPOptionsOverride());
174 }
175
makeIntegralCast(const Expr * Arg,QualType Ty)176 Expr *ASTMaker::makeIntegralCast(const Expr *Arg, QualType Ty) {
177 if (Arg->getType() == Ty)
178 return const_cast<Expr*>(Arg);
179 return makeImplicitCast(Arg, Ty, CK_IntegralCast);
180 }
181
makeIntegralCastToBoolean(const Expr * Arg)182 ImplicitCastExpr *ASTMaker::makeIntegralCastToBoolean(const Expr *Arg) {
183 return makeImplicitCast(Arg, C.BoolTy, CK_IntegralToBoolean);
184 }
185
makeObjCBool(bool Val)186 ObjCBoolLiteralExpr *ASTMaker::makeObjCBool(bool Val) {
187 QualType Ty = C.getBOOLDecl() ? C.getBOOLType() : C.ObjCBuiltinBoolTy;
188 return new (C) ObjCBoolLiteralExpr(Val, Ty, SourceLocation());
189 }
190
makeObjCIvarRef(const Expr * Base,const ObjCIvarDecl * IVar)191 ObjCIvarRefExpr *ASTMaker::makeObjCIvarRef(const Expr *Base,
192 const ObjCIvarDecl *IVar) {
193 return new (C) ObjCIvarRefExpr(const_cast<ObjCIvarDecl*>(IVar),
194 IVar->getType(), SourceLocation(),
195 SourceLocation(), const_cast<Expr*>(Base),
196 /*arrow=*/true, /*free=*/false);
197 }
198
makeReturn(const Expr * RetVal)199 ReturnStmt *ASTMaker::makeReturn(const Expr *RetVal) {
200 return ReturnStmt::Create(C, SourceLocation(), const_cast<Expr *>(RetVal),
201 /* NRVOCandidate=*/nullptr);
202 }
203
makeIntegerLiteral(uint64_t Value,QualType Ty)204 IntegerLiteral *ASTMaker::makeIntegerLiteral(uint64_t Value, QualType Ty) {
205 llvm::APInt APValue = llvm::APInt(C.getTypeSize(Ty), Value);
206 return IntegerLiteral::Create(C, APValue, Ty, SourceLocation());
207 }
208
makeMemberExpression(Expr * base,ValueDecl * MemberDecl,bool IsArrow,ExprValueKind ValueKind)209 MemberExpr *ASTMaker::makeMemberExpression(Expr *base, ValueDecl *MemberDecl,
210 bool IsArrow,
211 ExprValueKind ValueKind) {
212
213 DeclAccessPair FoundDecl = DeclAccessPair::make(MemberDecl, AS_public);
214 return MemberExpr::Create(
215 C, base, IsArrow, SourceLocation(), NestedNameSpecifierLoc(),
216 SourceLocation(), MemberDecl, FoundDecl,
217 DeclarationNameInfo(MemberDecl->getDeclName(), SourceLocation()),
218 /* TemplateArgumentListInfo=*/ nullptr, MemberDecl->getType(), ValueKind,
219 OK_Ordinary, NOUR_None);
220 }
221
findMemberField(const RecordDecl * RD,StringRef Name)222 ValueDecl *ASTMaker::findMemberField(const RecordDecl *RD, StringRef Name) {
223
224 CXXBasePaths Paths(
225 /* FindAmbiguities=*/false,
226 /* RecordPaths=*/false,
227 /* DetectVirtual=*/ false);
228 const IdentifierInfo &II = C.Idents.get(Name);
229 DeclarationName DeclName = C.DeclarationNames.getIdentifier(&II);
230
231 DeclContextLookupResult Decls = RD->lookup(DeclName);
232 for (NamedDecl *FoundDecl : Decls)
233 if (!FoundDecl->getDeclContext()->isFunctionOrMethod())
234 return cast<ValueDecl>(FoundDecl);
235
236 return nullptr;
237 }
238
239 //===----------------------------------------------------------------------===//
240 // Creation functions for faux ASTs.
241 //===----------------------------------------------------------------------===//
242
243 typedef Stmt *(*FunctionFarmer)(ASTContext &C, const FunctionDecl *D);
244
create_call_once_funcptr_call(ASTContext & C,ASTMaker M,const ParmVarDecl * Callback,ArrayRef<Expr * > CallArgs)245 static CallExpr *create_call_once_funcptr_call(ASTContext &C, ASTMaker M,
246 const ParmVarDecl *Callback,
247 ArrayRef<Expr *> CallArgs) {
248
249 QualType Ty = Callback->getType();
250 DeclRefExpr *Call = M.makeDeclRefExpr(Callback);
251 Expr *SubExpr;
252 if (Ty->isRValueReferenceType()) {
253 SubExpr = M.makeImplicitCast(
254 Call, Ty.getNonReferenceType(), CK_LValueToRValue);
255 } else if (Ty->isLValueReferenceType() &&
256 Call->getType()->isFunctionType()) {
257 Ty = C.getPointerType(Ty.getNonReferenceType());
258 SubExpr = M.makeImplicitCast(Call, Ty, CK_FunctionToPointerDecay);
259 } else if (Ty->isLValueReferenceType()
260 && Call->getType()->isPointerType()
261 && Call->getType()->getPointeeType()->isFunctionType()){
262 SubExpr = Call;
263 } else {
264 llvm_unreachable("Unexpected state");
265 }
266
267 return CallExpr::Create(C, SubExpr, CallArgs, C.VoidTy, VK_RValue,
268 SourceLocation(), FPOptionsOverride());
269 }
270
create_call_once_lambda_call(ASTContext & C,ASTMaker M,const ParmVarDecl * Callback,CXXRecordDecl * CallbackDecl,ArrayRef<Expr * > CallArgs)271 static CallExpr *create_call_once_lambda_call(ASTContext &C, ASTMaker M,
272 const ParmVarDecl *Callback,
273 CXXRecordDecl *CallbackDecl,
274 ArrayRef<Expr *> CallArgs) {
275 assert(CallbackDecl != nullptr);
276 assert(CallbackDecl->isLambda());
277 FunctionDecl *callOperatorDecl = CallbackDecl->getLambdaCallOperator();
278 assert(callOperatorDecl != nullptr);
279
280 DeclRefExpr *callOperatorDeclRef =
281 DeclRefExpr::Create(/* Ctx =*/ C,
282 /* QualifierLoc =*/ NestedNameSpecifierLoc(),
283 /* TemplateKWLoc =*/ SourceLocation(),
284 const_cast<FunctionDecl *>(callOperatorDecl),
285 /* RefersToEnclosingVariableOrCapture=*/ false,
286 /* NameLoc =*/ SourceLocation(),
287 /* T =*/ callOperatorDecl->getType(),
288 /* VK =*/ VK_LValue);
289
290 return CXXOperatorCallExpr::Create(
291 /*AstContext=*/C, OO_Call, callOperatorDeclRef,
292 /*Args=*/CallArgs,
293 /*QualType=*/C.VoidTy,
294 /*ExprValueType=*/VK_RValue,
295 /*SourceLocation=*/SourceLocation(),
296 /*FPFeatures=*/FPOptionsOverride());
297 }
298
299 /// Create a fake body for std::call_once.
300 /// Emulates the following function body:
301 ///
302 /// \code
303 /// typedef struct once_flag_s {
304 /// unsigned long __state = 0;
305 /// } once_flag;
306 /// template<class Callable>
307 /// void call_once(once_flag& o, Callable func) {
308 /// if (!o.__state) {
309 /// func();
310 /// }
311 /// o.__state = 1;
312 /// }
313 /// \endcode
create_call_once(ASTContext & C,const FunctionDecl * D)314 static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) {
315 LLVM_DEBUG(llvm::dbgs() << "Generating body for call_once\n");
316
317 // We need at least two parameters.
318 if (D->param_size() < 2)
319 return nullptr;
320
321 ASTMaker M(C);
322
323 const ParmVarDecl *Flag = D->getParamDecl(0);
324 const ParmVarDecl *Callback = D->getParamDecl(1);
325
326 if (!Callback->getType()->isReferenceType()) {
327 llvm::dbgs() << "libcxx03 std::call_once implementation, skipping.\n";
328 return nullptr;
329 }
330 if (!Flag->getType()->isReferenceType()) {
331 llvm::dbgs() << "unknown std::call_once implementation, skipping.\n";
332 return nullptr;
333 }
334
335 QualType CallbackType = Callback->getType().getNonReferenceType();
336
337 // Nullable pointer, non-null iff function is a CXXRecordDecl.
338 CXXRecordDecl *CallbackRecordDecl = CallbackType->getAsCXXRecordDecl();
339 QualType FlagType = Flag->getType().getNonReferenceType();
340 auto *FlagRecordDecl = FlagType->getAsRecordDecl();
341
342 if (!FlagRecordDecl) {
343 LLVM_DEBUG(llvm::dbgs() << "Flag field is not a record: "
344 << "unknown std::call_once implementation, "
345 << "ignoring the call.\n");
346 return nullptr;
347 }
348
349 // We initially assume libc++ implementation of call_once,
350 // where the once_flag struct has a field `__state_`.
351 ValueDecl *FlagFieldDecl = M.findMemberField(FlagRecordDecl, "__state_");
352
353 // Otherwise, try libstdc++ implementation, with a field
354 // `_M_once`
355 if (!FlagFieldDecl) {
356 FlagFieldDecl = M.findMemberField(FlagRecordDecl, "_M_once");
357 }
358
359 if (!FlagFieldDecl) {
360 LLVM_DEBUG(llvm::dbgs() << "No field _M_once or __state_ found on "
361 << "std::once_flag struct: unknown std::call_once "
362 << "implementation, ignoring the call.");
363 return nullptr;
364 }
365
366 bool isLambdaCall = CallbackRecordDecl && CallbackRecordDecl->isLambda();
367 if (CallbackRecordDecl && !isLambdaCall) {
368 LLVM_DEBUG(llvm::dbgs()
369 << "Not supported: synthesizing body for functors when "
370 << "body farming std::call_once, ignoring the call.");
371 return nullptr;
372 }
373
374 SmallVector<Expr *, 5> CallArgs;
375 const FunctionProtoType *CallbackFunctionType;
376 if (isLambdaCall) {
377
378 // Lambda requires callback itself inserted as a first parameter.
379 CallArgs.push_back(
380 M.makeDeclRefExpr(Callback,
381 /* RefersToEnclosingVariableOrCapture=*/ true));
382 CallbackFunctionType = CallbackRecordDecl->getLambdaCallOperator()
383 ->getType()
384 ->getAs<FunctionProtoType>();
385 } else if (!CallbackType->getPointeeType().isNull()) {
386 CallbackFunctionType =
387 CallbackType->getPointeeType()->getAs<FunctionProtoType>();
388 } else {
389 CallbackFunctionType = CallbackType->getAs<FunctionProtoType>();
390 }
391
392 if (!CallbackFunctionType)
393 return nullptr;
394
395 // First two arguments are used for the flag and for the callback.
396 if (D->getNumParams() != CallbackFunctionType->getNumParams() + 2) {
397 LLVM_DEBUG(llvm::dbgs() << "Types of params of the callback do not match "
398 << "params passed to std::call_once, "
399 << "ignoring the call\n");
400 return nullptr;
401 }
402
403 // All arguments past first two ones are passed to the callback,
404 // and we turn lvalues into rvalues if the argument is not passed by
405 // reference.
406 for (unsigned int ParamIdx = 2; ParamIdx < D->getNumParams(); ParamIdx++) {
407 const ParmVarDecl *PDecl = D->getParamDecl(ParamIdx);
408 assert(PDecl);
409 if (CallbackFunctionType->getParamType(ParamIdx - 2)
410 .getNonReferenceType()
411 .getCanonicalType() !=
412 PDecl->getType().getNonReferenceType().getCanonicalType()) {
413 LLVM_DEBUG(llvm::dbgs() << "Types of params of the callback do not match "
414 << "params passed to std::call_once, "
415 << "ignoring the call\n");
416 return nullptr;
417 }
418 Expr *ParamExpr = M.makeDeclRefExpr(PDecl);
419 if (!CallbackFunctionType->getParamType(ParamIdx - 2)->isReferenceType()) {
420 QualType PTy = PDecl->getType().getNonReferenceType();
421 ParamExpr = M.makeLvalueToRvalue(ParamExpr, PTy);
422 }
423 CallArgs.push_back(ParamExpr);
424 }
425
426 CallExpr *CallbackCall;
427 if (isLambdaCall) {
428
429 CallbackCall = create_call_once_lambda_call(C, M, Callback,
430 CallbackRecordDecl, CallArgs);
431 } else {
432
433 // Function pointer case.
434 CallbackCall = create_call_once_funcptr_call(C, M, Callback, CallArgs);
435 }
436
437 DeclRefExpr *FlagDecl =
438 M.makeDeclRefExpr(Flag,
439 /* RefersToEnclosingVariableOrCapture=*/true);
440
441
442 MemberExpr *Deref = M.makeMemberExpression(FlagDecl, FlagFieldDecl);
443 assert(Deref->isLValue());
444 QualType DerefType = Deref->getType();
445
446 // Negation predicate.
447 UnaryOperator *FlagCheck = UnaryOperator::Create(
448 C,
449 /* input=*/
450 M.makeImplicitCast(M.makeLvalueToRvalue(Deref, DerefType), DerefType,
451 CK_IntegralToBoolean),
452 /* opc=*/UO_LNot,
453 /* QualType=*/C.IntTy,
454 /* ExprValueKind=*/VK_RValue,
455 /* ExprObjectKind=*/OK_Ordinary, SourceLocation(),
456 /* CanOverflow*/ false, FPOptionsOverride());
457
458 // Create assignment.
459 BinaryOperator *FlagAssignment = M.makeAssignment(
460 Deref, M.makeIntegralCast(M.makeIntegerLiteral(1, C.IntTy), DerefType),
461 DerefType);
462
463 auto *Out =
464 IfStmt::Create(C, SourceLocation(),
465 /* IsConstexpr=*/false,
466 /* Init=*/nullptr,
467 /* Var=*/nullptr,
468 /* Cond=*/FlagCheck,
469 /* LPL=*/SourceLocation(),
470 /* RPL=*/SourceLocation(),
471 /* Then=*/M.makeCompound({CallbackCall, FlagAssignment}));
472
473 return Out;
474 }
475
476 /// Create a fake body for dispatch_once.
create_dispatch_once(ASTContext & C,const FunctionDecl * D)477 static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
478 // Check if we have at least two parameters.
479 if (D->param_size() != 2)
480 return nullptr;
481
482 // Check if the first parameter is a pointer to integer type.
483 const ParmVarDecl *Predicate = D->getParamDecl(0);
484 QualType PredicateQPtrTy = Predicate->getType();
485 const PointerType *PredicatePtrTy = PredicateQPtrTy->getAs<PointerType>();
486 if (!PredicatePtrTy)
487 return nullptr;
488 QualType PredicateTy = PredicatePtrTy->getPointeeType();
489 if (!PredicateTy->isIntegerType())
490 return nullptr;
491
492 // Check if the second parameter is the proper block type.
493 const ParmVarDecl *Block = D->getParamDecl(1);
494 QualType Ty = Block->getType();
495 if (!isDispatchBlock(Ty))
496 return nullptr;
497
498 // Everything checks out. Create a fakse body that checks the predicate,
499 // sets it, and calls the block. Basically, an AST dump of:
500 //
501 // void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block) {
502 // if (*predicate != ~0l) {
503 // *predicate = ~0l;
504 // block();
505 // }
506 // }
507
508 ASTMaker M(C);
509
510 // (1) Create the call.
511 CallExpr *CE = CallExpr::Create(
512 /*ASTContext=*/C,
513 /*StmtClass=*/M.makeLvalueToRvalue(/*Expr=*/Block),
514 /*Args=*/None,
515 /*QualType=*/C.VoidTy,
516 /*ExprValueType=*/VK_RValue,
517 /*SourceLocation=*/SourceLocation(), FPOptionsOverride());
518
519 // (2) Create the assignment to the predicate.
520 Expr *DoneValue =
521 UnaryOperator::Create(C, M.makeIntegerLiteral(0, C.LongTy), UO_Not,
522 C.LongTy, VK_RValue, OK_Ordinary, SourceLocation(),
523 /*CanOverflow*/ false, FPOptionsOverride());
524
525 BinaryOperator *B =
526 M.makeAssignment(
527 M.makeDereference(
528 M.makeLvalueToRvalue(
529 M.makeDeclRefExpr(Predicate), PredicateQPtrTy),
530 PredicateTy),
531 M.makeIntegralCast(DoneValue, PredicateTy),
532 PredicateTy);
533
534 // (3) Create the compound statement.
535 Stmt *Stmts[] = { B, CE };
536 CompoundStmt *CS = M.makeCompound(Stmts);
537
538 // (4) Create the 'if' condition.
539 ImplicitCastExpr *LValToRval =
540 M.makeLvalueToRvalue(
541 M.makeDereference(
542 M.makeLvalueToRvalue(
543 M.makeDeclRefExpr(Predicate),
544 PredicateQPtrTy),
545 PredicateTy),
546 PredicateTy);
547
548 Expr *GuardCondition = M.makeComparison(LValToRval, DoneValue, BO_NE);
549 // (5) Create the 'if' statement.
550 auto *If = IfStmt::Create(C, SourceLocation(),
551 /* IsConstexpr=*/false,
552 /* Init=*/nullptr,
553 /* Var=*/nullptr,
554 /* Cond=*/GuardCondition,
555 /* LPL=*/SourceLocation(),
556 /* RPL=*/SourceLocation(),
557 /* Then=*/CS);
558 return If;
559 }
560
561 /// Create a fake body for dispatch_sync.
create_dispatch_sync(ASTContext & C,const FunctionDecl * D)562 static Stmt *create_dispatch_sync(ASTContext &C, const FunctionDecl *D) {
563 // Check if we have at least two parameters.
564 if (D->param_size() != 2)
565 return nullptr;
566
567 // Check if the second parameter is a block.
568 const ParmVarDecl *PV = D->getParamDecl(1);
569 QualType Ty = PV->getType();
570 if (!isDispatchBlock(Ty))
571 return nullptr;
572
573 // Everything checks out. Create a fake body that just calls the block.
574 // This is basically just an AST dump of:
575 //
576 // void dispatch_sync(dispatch_queue_t queue, void (^block)(void)) {
577 // block();
578 // }
579 //
580 ASTMaker M(C);
581 DeclRefExpr *DR = M.makeDeclRefExpr(PV);
582 ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty);
583 CallExpr *CE = CallExpr::Create(C, ICE, None, C.VoidTy, VK_RValue,
584 SourceLocation(), FPOptionsOverride());
585 return CE;
586 }
587
create_OSAtomicCompareAndSwap(ASTContext & C,const FunctionDecl * D)588 static Stmt *create_OSAtomicCompareAndSwap(ASTContext &C, const FunctionDecl *D)
589 {
590 // There are exactly 3 arguments.
591 if (D->param_size() != 3)
592 return nullptr;
593
594 // Signature:
595 // _Bool OSAtomicCompareAndSwapPtr(void *__oldValue,
596 // void *__newValue,
597 // void * volatile *__theValue)
598 // Generate body:
599 // if (oldValue == *theValue) {
600 // *theValue = newValue;
601 // return YES;
602 // }
603 // else return NO;
604
605 QualType ResultTy = D->getReturnType();
606 bool isBoolean = ResultTy->isBooleanType();
607 if (!isBoolean && !ResultTy->isIntegralType(C))
608 return nullptr;
609
610 const ParmVarDecl *OldValue = D->getParamDecl(0);
611 QualType OldValueTy = OldValue->getType();
612
613 const ParmVarDecl *NewValue = D->getParamDecl(1);
614 QualType NewValueTy = NewValue->getType();
615
616 assert(OldValueTy == NewValueTy);
617
618 const ParmVarDecl *TheValue = D->getParamDecl(2);
619 QualType TheValueTy = TheValue->getType();
620 const PointerType *PT = TheValueTy->getAs<PointerType>();
621 if (!PT)
622 return nullptr;
623 QualType PointeeTy = PT->getPointeeType();
624
625 ASTMaker M(C);
626 // Construct the comparison.
627 Expr *Comparison =
628 M.makeComparison(
629 M.makeLvalueToRvalue(M.makeDeclRefExpr(OldValue), OldValueTy),
630 M.makeLvalueToRvalue(
631 M.makeDereference(
632 M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
633 PointeeTy),
634 PointeeTy),
635 BO_EQ);
636
637 // Construct the body of the IfStmt.
638 Stmt *Stmts[2];
639 Stmts[0] =
640 M.makeAssignment(
641 M.makeDereference(
642 M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
643 PointeeTy),
644 M.makeLvalueToRvalue(M.makeDeclRefExpr(NewValue), NewValueTy),
645 NewValueTy);
646
647 Expr *BoolVal = M.makeObjCBool(true);
648 Expr *RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
649 : M.makeIntegralCast(BoolVal, ResultTy);
650 Stmts[1] = M.makeReturn(RetVal);
651 CompoundStmt *Body = M.makeCompound(Stmts);
652
653 // Construct the else clause.
654 BoolVal = M.makeObjCBool(false);
655 RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
656 : M.makeIntegralCast(BoolVal, ResultTy);
657 Stmt *Else = M.makeReturn(RetVal);
658
659 /// Construct the If.
660 auto *If =
661 IfStmt::Create(C, SourceLocation(),
662 /* IsConstexpr=*/false,
663 /* Init=*/nullptr,
664 /* Var=*/nullptr, Comparison,
665 /* LPL=*/SourceLocation(),
666 /* RPL=*/SourceLocation(), Body, SourceLocation(), Else);
667
668 return If;
669 }
670
getBody(const FunctionDecl * D)671 Stmt *BodyFarm::getBody(const FunctionDecl *D) {
672 Optional<Stmt *> &Val = Bodies[D];
673 if (Val.hasValue())
674 return Val.getValue();
675
676 Val = nullptr;
677
678 if (D->getIdentifier() == nullptr)
679 return nullptr;
680
681 StringRef Name = D->getName();
682 if (Name.empty())
683 return nullptr;
684
685 FunctionFarmer FF;
686
687 if (Name.startswith("OSAtomicCompareAndSwap") ||
688 Name.startswith("objc_atomicCompareAndSwap")) {
689 FF = create_OSAtomicCompareAndSwap;
690 } else if (Name == "call_once" && D->getDeclContext()->isStdNamespace()) {
691 FF = create_call_once;
692 } else {
693 FF = llvm::StringSwitch<FunctionFarmer>(Name)
694 .Case("dispatch_sync", create_dispatch_sync)
695 .Case("dispatch_once", create_dispatch_once)
696 .Default(nullptr);
697 }
698
699 if (FF) { Val = FF(C, D); }
700 else if (Injector) { Val = Injector->getBody(D); }
701 return Val.getValue();
702 }
703
findBackingIvar(const ObjCPropertyDecl * Prop)704 static const ObjCIvarDecl *findBackingIvar(const ObjCPropertyDecl *Prop) {
705 const ObjCIvarDecl *IVar = Prop->getPropertyIvarDecl();
706
707 if (IVar)
708 return IVar;
709
710 // When a readonly property is shadowed in a class extensions with a
711 // a readwrite property, the instance variable belongs to the shadowing
712 // property rather than the shadowed property. If there is no instance
713 // variable on a readonly property, check to see whether the property is
714 // shadowed and if so try to get the instance variable from shadowing
715 // property.
716 if (!Prop->isReadOnly())
717 return nullptr;
718
719 auto *Container = cast<ObjCContainerDecl>(Prop->getDeclContext());
720 const ObjCInterfaceDecl *PrimaryInterface = nullptr;
721 if (auto *InterfaceDecl = dyn_cast<ObjCInterfaceDecl>(Container)) {
722 PrimaryInterface = InterfaceDecl;
723 } else if (auto *CategoryDecl = dyn_cast<ObjCCategoryDecl>(Container)) {
724 PrimaryInterface = CategoryDecl->getClassInterface();
725 } else if (auto *ImplDecl = dyn_cast<ObjCImplDecl>(Container)) {
726 PrimaryInterface = ImplDecl->getClassInterface();
727 } else {
728 return nullptr;
729 }
730
731 // FindPropertyVisibleInPrimaryClass() looks first in class extensions, so it
732 // is guaranteed to find the shadowing property, if it exists, rather than
733 // the shadowed property.
734 auto *ShadowingProp = PrimaryInterface->FindPropertyVisibleInPrimaryClass(
735 Prop->getIdentifier(), Prop->getQueryKind());
736 if (ShadowingProp && ShadowingProp != Prop) {
737 IVar = ShadowingProp->getPropertyIvarDecl();
738 }
739
740 return IVar;
741 }
742
createObjCPropertyGetter(ASTContext & Ctx,const ObjCMethodDecl * MD)743 static Stmt *createObjCPropertyGetter(ASTContext &Ctx,
744 const ObjCMethodDecl *MD) {
745 // First, find the backing ivar.
746 const ObjCIvarDecl *IVar = nullptr;
747 const ObjCPropertyDecl *Prop = nullptr;
748
749 // Property accessor stubs sometimes do not correspond to any property decl
750 // in the current interface (but in a superclass). They still have a
751 // corresponding property impl decl in this case.
752 if (MD->isSynthesizedAccessorStub()) {
753 const ObjCInterfaceDecl *IntD = MD->getClassInterface();
754 const ObjCImplementationDecl *ImpD = IntD->getImplementation();
755 for (const auto *PI : ImpD->property_impls()) {
756 if (const ObjCPropertyDecl *Candidate = PI->getPropertyDecl()) {
757 if (Candidate->getGetterName() == MD->getSelector()) {
758 Prop = Candidate;
759 IVar = Prop->getPropertyIvarDecl();
760 }
761 }
762 }
763 }
764
765 if (!IVar) {
766 Prop = MD->findPropertyDecl();
767 IVar = findBackingIvar(Prop);
768 }
769
770 if (!IVar || !Prop)
771 return nullptr;
772
773 // Ignore weak variables, which have special behavior.
774 if (Prop->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak)
775 return nullptr;
776
777 // Look to see if Sema has synthesized a body for us. This happens in
778 // Objective-C++ because the return value may be a C++ class type with a
779 // non-trivial copy constructor. We can only do this if we can find the
780 // @synthesize for this property, though (or if we know it's been auto-
781 // synthesized).
782 const ObjCImplementationDecl *ImplDecl =
783 IVar->getContainingInterface()->getImplementation();
784 if (ImplDecl) {
785 for (const auto *I : ImplDecl->property_impls()) {
786 if (I->getPropertyDecl() != Prop)
787 continue;
788
789 if (I->getGetterCXXConstructor()) {
790 ASTMaker M(Ctx);
791 return M.makeReturn(I->getGetterCXXConstructor());
792 }
793 }
794 }
795
796 // Sanity check that the property is the same type as the ivar, or a
797 // reference to it, and that it is either an object pointer or trivially
798 // copyable.
799 if (!Ctx.hasSameUnqualifiedType(IVar->getType(),
800 Prop->getType().getNonReferenceType()))
801 return nullptr;
802 if (!IVar->getType()->isObjCLifetimeType() &&
803 !IVar->getType().isTriviallyCopyableType(Ctx))
804 return nullptr;
805
806 // Generate our body:
807 // return self->_ivar;
808 ASTMaker M(Ctx);
809
810 const VarDecl *selfVar = MD->getSelfDecl();
811 if (!selfVar)
812 return nullptr;
813
814 Expr *loadedIVar = M.makeObjCIvarRef(
815 M.makeLvalueToRvalue(M.makeDeclRefExpr(selfVar), selfVar->getType()),
816 IVar);
817
818 if (!MD->getReturnType()->isReferenceType())
819 loadedIVar = M.makeLvalueToRvalue(loadedIVar, IVar->getType());
820
821 return M.makeReturn(loadedIVar);
822 }
823
getBody(const ObjCMethodDecl * D)824 Stmt *BodyFarm::getBody(const ObjCMethodDecl *D) {
825 // We currently only know how to synthesize property accessors.
826 if (!D->isPropertyAccessor())
827 return nullptr;
828
829 D = D->getCanonicalDecl();
830
831 // We should not try to synthesize explicitly redefined accessors.
832 // We do not know for sure how they behave.
833 if (!D->isImplicit())
834 return nullptr;
835
836 Optional<Stmt *> &Val = Bodies[D];
837 if (Val.hasValue())
838 return Val.getValue();
839 Val = nullptr;
840
841 // For now, we only synthesize getters.
842 // Synthesizing setters would cause false negatives in the
843 // RetainCountChecker because the method body would bind the parameter
844 // to an instance variable, causing it to escape. This would prevent
845 // warning in the following common scenario:
846 //
847 // id foo = [[NSObject alloc] init];
848 // self.foo = foo; // We should warn that foo leaks here.
849 //
850 if (D->param_size() != 0)
851 return nullptr;
852
853 // If the property was defined in an extension, search the extensions for
854 // overrides.
855 const ObjCInterfaceDecl *OID = D->getClassInterface();
856 if (dyn_cast<ObjCInterfaceDecl>(D->getParent()) != OID)
857 for (auto *Ext : OID->known_extensions()) {
858 auto *OMD = Ext->getInstanceMethod(D->getSelector());
859 if (OMD && !OMD->isImplicit())
860 return nullptr;
861 }
862
863 Val = createObjCPropertyGetter(C, D);
864
865 return Val.getValue();
866 }
867