1 //== BodyFarm.cpp - Factory for conjuring up fake bodies ----------*- C++ -*-//
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
7 //===----------------------------------------------------------------------===//
9 // BodyFarm is a factory for creating faux implementations for functions/methods
10 // for analysis purposes.
12 //===----------------------------------------------------------------------===//
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/Builtins.h"
24 #include "clang/Basic/OperatorKinds.h"
25 #include "llvm/ADT/StringSwitch.h"
26 #include "llvm/Support/Debug.h"
29 #define DEBUG_TYPE "body-farm"
31 using namespace clang
;
33 //===----------------------------------------------------------------------===//
34 // Helper creation functions for constructing faux ASTs.
35 //===----------------------------------------------------------------------===//
37 static bool isDispatchBlock(QualType Ty
) {
38 // Is it a block pointer?
39 const BlockPointerType
*BPT
= Ty
->getAs
<BlockPointerType
>();
43 // Check if the block pointer type takes no arguments and
45 const FunctionProtoType
*FT
=
46 BPT
->getPointeeType()->getAs
<FunctionProtoType
>();
47 return FT
&& FT
->getReturnType()->isVoidType() && FT
->getNumParams() == 0;
53 ASTMaker(ASTContext
&C
) : C(C
) {}
55 /// Create a new BinaryOperator representing a simple assignment.
56 BinaryOperator
*makeAssignment(const Expr
*LHS
, const Expr
*RHS
, QualType Ty
);
58 /// Create a new BinaryOperator representing a comparison.
59 BinaryOperator
*makeComparison(const Expr
*LHS
, const Expr
*RHS
,
60 BinaryOperator::Opcode Op
);
62 /// Create a new compound stmt using the provided statements.
63 CompoundStmt
*makeCompound(ArrayRef
<Stmt
*>);
65 /// Create a new DeclRefExpr for the referenced variable.
66 DeclRefExpr
*makeDeclRefExpr(const VarDecl
*D
,
67 bool RefersToEnclosingVariableOrCapture
= false);
69 /// Create a new UnaryOperator representing a dereference.
70 UnaryOperator
*makeDereference(const Expr
*Arg
, QualType Ty
);
72 /// Create an implicit cast for an integer conversion.
73 Expr
*makeIntegralCast(const Expr
*Arg
, QualType Ty
);
75 /// Create an implicit cast to a builtin boolean type.
76 ImplicitCastExpr
*makeIntegralCastToBoolean(const Expr
*Arg
);
78 /// Create an implicit cast for lvalue-to-rvaluate conversions.
79 ImplicitCastExpr
*makeLvalueToRvalue(const Expr
*Arg
, QualType Ty
);
81 /// Make RValue out of variable declaration, creating a temporary
82 /// DeclRefExpr in the process.
84 makeLvalueToRvalue(const VarDecl
*Decl
,
85 bool RefersToEnclosingVariableOrCapture
= false);
87 /// Create an implicit cast of the given type.
88 ImplicitCastExpr
*makeImplicitCast(const Expr
*Arg
, QualType Ty
,
89 CastKind CK
= CK_LValueToRValue
);
91 /// Create a cast to reference type.
92 CastExpr
*makeReferenceCast(const Expr
*Arg
, QualType Ty
);
94 /// Create an Objective-C bool literal.
95 ObjCBoolLiteralExpr
*makeObjCBool(bool Val
);
97 /// Create an Objective-C ivar reference.
98 ObjCIvarRefExpr
*makeObjCIvarRef(const Expr
*Base
, const ObjCIvarDecl
*IVar
);
100 /// Create a Return statement.
101 ReturnStmt
*makeReturn(const Expr
*RetVal
);
103 /// Create an integer literal expression of the given type.
104 IntegerLiteral
*makeIntegerLiteral(uint64_t Value
, QualType Ty
);
106 /// Create a member expression.
107 MemberExpr
*makeMemberExpression(Expr
*base
, ValueDecl
*MemberDecl
,
108 bool IsArrow
= false,
109 ExprValueKind ValueKind
= VK_LValue
);
111 /// Returns a *first* member field of a record declaration with a given name.
112 /// \return an nullptr if no member with such a name exists.
113 ValueDecl
*findMemberField(const RecordDecl
*RD
, StringRef Name
);
120 BinaryOperator
*ASTMaker::makeAssignment(const Expr
*LHS
, const Expr
*RHS
,
122 return BinaryOperator::Create(
123 C
, const_cast<Expr
*>(LHS
), const_cast<Expr
*>(RHS
), BO_Assign
, Ty
,
124 VK_PRValue
, OK_Ordinary
, SourceLocation(), FPOptionsOverride());
127 BinaryOperator
*ASTMaker::makeComparison(const Expr
*LHS
, const Expr
*RHS
,
128 BinaryOperator::Opcode Op
) {
129 assert(BinaryOperator::isLogicalOp(Op
) ||
130 BinaryOperator::isComparisonOp(Op
));
131 return BinaryOperator::Create(
132 C
, const_cast<Expr
*>(LHS
), const_cast<Expr
*>(RHS
), Op
,
133 C
.getLogicalOperationType(), VK_PRValue
, OK_Ordinary
, SourceLocation(),
134 FPOptionsOverride());
137 CompoundStmt
*ASTMaker::makeCompound(ArrayRef
<Stmt
*> Stmts
) {
138 return CompoundStmt::Create(C
, Stmts
, FPOptionsOverride(), SourceLocation(),
142 DeclRefExpr
*ASTMaker::makeDeclRefExpr(
144 bool RefersToEnclosingVariableOrCapture
) {
145 QualType Type
= D
->getType().getNonReferenceType();
147 DeclRefExpr
*DR
= DeclRefExpr::Create(
148 C
, NestedNameSpecifierLoc(), SourceLocation(), const_cast<VarDecl
*>(D
),
149 RefersToEnclosingVariableOrCapture
, SourceLocation(), Type
, VK_LValue
);
153 UnaryOperator
*ASTMaker::makeDereference(const Expr
*Arg
, QualType Ty
) {
154 return UnaryOperator::Create(C
, const_cast<Expr
*>(Arg
), UO_Deref
, Ty
,
155 VK_LValue
, OK_Ordinary
, SourceLocation(),
156 /*CanOverflow*/ false, FPOptionsOverride());
159 ImplicitCastExpr
*ASTMaker::makeLvalueToRvalue(const Expr
*Arg
, QualType Ty
) {
160 return makeImplicitCast(Arg
, Ty
, CK_LValueToRValue
);
164 ASTMaker::makeLvalueToRvalue(const VarDecl
*Arg
,
165 bool RefersToEnclosingVariableOrCapture
) {
166 QualType Type
= Arg
->getType().getNonReferenceType();
167 return makeLvalueToRvalue(makeDeclRefExpr(Arg
,
168 RefersToEnclosingVariableOrCapture
),
172 ImplicitCastExpr
*ASTMaker::makeImplicitCast(const Expr
*Arg
, QualType Ty
,
174 return ImplicitCastExpr::Create(C
, Ty
,
176 /* Expr=*/const_cast<Expr
*>(Arg
),
177 /* CXXCastPath=*/nullptr,
178 /* ExprValueKind=*/VK_PRValue
,
179 /* FPFeatures */ FPOptionsOverride());
182 CastExpr
*ASTMaker::makeReferenceCast(const Expr
*Arg
, QualType Ty
) {
183 assert(Ty
->isReferenceType());
184 return CXXStaticCastExpr::Create(
185 C
, Ty
.getNonReferenceType(),
186 Ty
->isLValueReferenceType() ? VK_LValue
: VK_XValue
, CK_NoOp
,
187 const_cast<Expr
*>(Arg
), /*CXXCastPath=*/nullptr,
188 /*Written=*/C
.getTrivialTypeSourceInfo(Ty
), FPOptionsOverride(),
189 SourceLocation(), SourceLocation(), SourceRange());
192 Expr
*ASTMaker::makeIntegralCast(const Expr
*Arg
, QualType Ty
) {
193 if (Arg
->getType() == Ty
)
194 return const_cast<Expr
*>(Arg
);
195 return makeImplicitCast(Arg
, Ty
, CK_IntegralCast
);
198 ImplicitCastExpr
*ASTMaker::makeIntegralCastToBoolean(const Expr
*Arg
) {
199 return makeImplicitCast(Arg
, C
.BoolTy
, CK_IntegralToBoolean
);
202 ObjCBoolLiteralExpr
*ASTMaker::makeObjCBool(bool Val
) {
203 QualType Ty
= C
.getBOOLDecl() ? C
.getBOOLType() : C
.ObjCBuiltinBoolTy
;
204 return new (C
) ObjCBoolLiteralExpr(Val
, Ty
, SourceLocation());
207 ObjCIvarRefExpr
*ASTMaker::makeObjCIvarRef(const Expr
*Base
,
208 const ObjCIvarDecl
*IVar
) {
209 return new (C
) ObjCIvarRefExpr(const_cast<ObjCIvarDecl
*>(IVar
),
210 IVar
->getType(), SourceLocation(),
211 SourceLocation(), const_cast<Expr
*>(Base
),
212 /*arrow=*/true, /*free=*/false);
215 ReturnStmt
*ASTMaker::makeReturn(const Expr
*RetVal
) {
216 return ReturnStmt::Create(C
, SourceLocation(), const_cast<Expr
*>(RetVal
),
217 /* NRVOCandidate=*/nullptr);
220 IntegerLiteral
*ASTMaker::makeIntegerLiteral(uint64_t Value
, QualType Ty
) {
221 llvm::APInt APValue
= llvm::APInt(C
.getTypeSize(Ty
), Value
);
222 return IntegerLiteral::Create(C
, APValue
, Ty
, SourceLocation());
225 MemberExpr
*ASTMaker::makeMemberExpression(Expr
*base
, ValueDecl
*MemberDecl
,
227 ExprValueKind ValueKind
) {
229 DeclAccessPair FoundDecl
= DeclAccessPair::make(MemberDecl
, AS_public
);
230 return MemberExpr::Create(
231 C
, base
, IsArrow
, SourceLocation(), NestedNameSpecifierLoc(),
232 SourceLocation(), MemberDecl
, FoundDecl
,
233 DeclarationNameInfo(MemberDecl
->getDeclName(), SourceLocation()),
234 /* TemplateArgumentListInfo=*/ nullptr, MemberDecl
->getType(), ValueKind
,
235 OK_Ordinary
, NOUR_None
);
238 ValueDecl
*ASTMaker::findMemberField(const RecordDecl
*RD
, StringRef Name
) {
241 /* FindAmbiguities=*/false,
242 /* RecordPaths=*/false,
243 /* DetectVirtual=*/ false);
244 const IdentifierInfo
&II
= C
.Idents
.get(Name
);
245 DeclarationName DeclName
= C
.DeclarationNames
.getIdentifier(&II
);
247 DeclContextLookupResult Decls
= RD
->lookup(DeclName
);
248 for (NamedDecl
*FoundDecl
: Decls
)
249 if (!FoundDecl
->getDeclContext()->isFunctionOrMethod())
250 return cast
<ValueDecl
>(FoundDecl
);
255 //===----------------------------------------------------------------------===//
256 // Creation functions for faux ASTs.
257 //===----------------------------------------------------------------------===//
259 typedef Stmt
*(*FunctionFarmer
)(ASTContext
&C
, const FunctionDecl
*D
);
261 static CallExpr
*create_call_once_funcptr_call(ASTContext
&C
, ASTMaker M
,
262 const ParmVarDecl
*Callback
,
263 ArrayRef
<Expr
*> CallArgs
) {
265 QualType Ty
= Callback
->getType();
266 DeclRefExpr
*Call
= M
.makeDeclRefExpr(Callback
);
268 if (Ty
->isRValueReferenceType()) {
269 SubExpr
= M
.makeImplicitCast(
270 Call
, Ty
.getNonReferenceType(), CK_LValueToRValue
);
271 } else if (Ty
->isLValueReferenceType() &&
272 Call
->getType()->isFunctionType()) {
273 Ty
= C
.getPointerType(Ty
.getNonReferenceType());
274 SubExpr
= M
.makeImplicitCast(Call
, Ty
, CK_FunctionToPointerDecay
);
275 } else if (Ty
->isLValueReferenceType()
276 && Call
->getType()->isPointerType()
277 && Call
->getType()->getPointeeType()->isFunctionType()){
280 llvm_unreachable("Unexpected state");
283 return CallExpr::Create(C
, SubExpr
, CallArgs
, C
.VoidTy
, VK_PRValue
,
284 SourceLocation(), FPOptionsOverride());
287 static CallExpr
*create_call_once_lambda_call(ASTContext
&C
, ASTMaker M
,
288 const ParmVarDecl
*Callback
,
289 CXXRecordDecl
*CallbackDecl
,
290 ArrayRef
<Expr
*> CallArgs
) {
291 assert(CallbackDecl
!= nullptr);
292 assert(CallbackDecl
->isLambda());
293 FunctionDecl
*callOperatorDecl
= CallbackDecl
->getLambdaCallOperator();
294 assert(callOperatorDecl
!= nullptr);
296 DeclRefExpr
*callOperatorDeclRef
=
297 DeclRefExpr::Create(/* Ctx =*/ C
,
298 /* QualifierLoc =*/ NestedNameSpecifierLoc(),
299 /* TemplateKWLoc =*/ SourceLocation(),
300 const_cast<FunctionDecl
*>(callOperatorDecl
),
301 /* RefersToEnclosingVariableOrCapture=*/ false,
302 /* NameLoc =*/ SourceLocation(),
303 /* T =*/ callOperatorDecl
->getType(),
304 /* VK =*/ VK_LValue
);
306 return CXXOperatorCallExpr::Create(
307 /*AstContext=*/C
, OO_Call
, callOperatorDeclRef
,
309 /*QualType=*/C
.VoidTy
,
310 /*ExprValueType=*/VK_PRValue
,
311 /*SourceLocation=*/SourceLocation(),
312 /*FPFeatures=*/FPOptionsOverride());
315 /// Create a fake body for 'std::move' or 'std::forward'. This is just:
318 /// return static_cast<return_type>(param);
320 static Stmt
*create_std_move_forward(ASTContext
&C
, const FunctionDecl
*D
) {
321 LLVM_DEBUG(llvm::dbgs() << "Generating body for std::move / std::forward\n");
325 QualType ReturnType
= D
->getType()->castAs
<FunctionType
>()->getReturnType();
326 Expr
*Param
= M
.makeDeclRefExpr(D
->getParamDecl(0));
327 Expr
*Cast
= M
.makeReferenceCast(Param
, ReturnType
);
328 return M
.makeReturn(Cast
);
331 /// Create a fake body for std::call_once.
332 /// Emulates the following function body:
335 /// typedef struct once_flag_s {
336 /// unsigned long __state = 0;
338 /// template<class Callable>
339 /// void call_once(once_flag& o, Callable func) {
340 /// if (!o.__state) {
346 static Stmt
*create_call_once(ASTContext
&C
, const FunctionDecl
*D
) {
347 LLVM_DEBUG(llvm::dbgs() << "Generating body for call_once\n");
349 // We need at least two parameters.
350 if (D
->param_size() < 2)
355 const ParmVarDecl
*Flag
= D
->getParamDecl(0);
356 const ParmVarDecl
*Callback
= D
->getParamDecl(1);
358 if (!Callback
->getType()->isReferenceType()) {
359 llvm::dbgs() << "libcxx03 std::call_once implementation, skipping.\n";
362 if (!Flag
->getType()->isReferenceType()) {
363 llvm::dbgs() << "unknown std::call_once implementation, skipping.\n";
367 QualType CallbackType
= Callback
->getType().getNonReferenceType();
369 // Nullable pointer, non-null iff function is a CXXRecordDecl.
370 CXXRecordDecl
*CallbackRecordDecl
= CallbackType
->getAsCXXRecordDecl();
371 QualType FlagType
= Flag
->getType().getNonReferenceType();
372 auto *FlagRecordDecl
= FlagType
->getAsRecordDecl();
374 if (!FlagRecordDecl
) {
375 LLVM_DEBUG(llvm::dbgs() << "Flag field is not a record: "
376 << "unknown std::call_once implementation, "
377 << "ignoring the call.\n");
381 // We initially assume libc++ implementation of call_once,
382 // where the once_flag struct has a field `__state_`.
383 ValueDecl
*FlagFieldDecl
= M
.findMemberField(FlagRecordDecl
, "__state_");
385 // Otherwise, try libstdc++ implementation, with a field
387 if (!FlagFieldDecl
) {
388 FlagFieldDecl
= M
.findMemberField(FlagRecordDecl
, "_M_once");
391 if (!FlagFieldDecl
) {
392 LLVM_DEBUG(llvm::dbgs() << "No field _M_once or __state_ found on "
393 << "std::once_flag struct: unknown std::call_once "
394 << "implementation, ignoring the call.");
398 bool isLambdaCall
= CallbackRecordDecl
&& CallbackRecordDecl
->isLambda();
399 if (CallbackRecordDecl
&& !isLambdaCall
) {
400 LLVM_DEBUG(llvm::dbgs()
401 << "Not supported: synthesizing body for functors when "
402 << "body farming std::call_once, ignoring the call.");
406 SmallVector
<Expr
*, 5> CallArgs
;
407 const FunctionProtoType
*CallbackFunctionType
;
410 // Lambda requires callback itself inserted as a first parameter.
412 M
.makeDeclRefExpr(Callback
,
413 /* RefersToEnclosingVariableOrCapture=*/ true));
414 CallbackFunctionType
= CallbackRecordDecl
->getLambdaCallOperator()
416 ->getAs
<FunctionProtoType
>();
417 } else if (!CallbackType
->getPointeeType().isNull()) {
418 CallbackFunctionType
=
419 CallbackType
->getPointeeType()->getAs
<FunctionProtoType
>();
421 CallbackFunctionType
= CallbackType
->getAs
<FunctionProtoType
>();
424 if (!CallbackFunctionType
)
427 // First two arguments are used for the flag and for the callback.
428 if (D
->getNumParams() != CallbackFunctionType
->getNumParams() + 2) {
429 LLVM_DEBUG(llvm::dbgs() << "Types of params of the callback do not match "
430 << "params passed to std::call_once, "
431 << "ignoring the call\n");
435 // All arguments past first two ones are passed to the callback,
436 // and we turn lvalues into rvalues if the argument is not passed by
438 for (unsigned int ParamIdx
= 2; ParamIdx
< D
->getNumParams(); ParamIdx
++) {
439 const ParmVarDecl
*PDecl
= D
->getParamDecl(ParamIdx
);
441 if (CallbackFunctionType
->getParamType(ParamIdx
- 2)
442 .getNonReferenceType()
443 .getCanonicalType() !=
444 PDecl
->getType().getNonReferenceType().getCanonicalType()) {
445 LLVM_DEBUG(llvm::dbgs() << "Types of params of the callback do not match "
446 << "params passed to std::call_once, "
447 << "ignoring the call\n");
450 Expr
*ParamExpr
= M
.makeDeclRefExpr(PDecl
);
451 if (!CallbackFunctionType
->getParamType(ParamIdx
- 2)->isReferenceType()) {
452 QualType PTy
= PDecl
->getType().getNonReferenceType();
453 ParamExpr
= M
.makeLvalueToRvalue(ParamExpr
, PTy
);
455 CallArgs
.push_back(ParamExpr
);
458 CallExpr
*CallbackCall
;
461 CallbackCall
= create_call_once_lambda_call(C
, M
, Callback
,
462 CallbackRecordDecl
, CallArgs
);
465 // Function pointer case.
466 CallbackCall
= create_call_once_funcptr_call(C
, M
, Callback
, CallArgs
);
469 DeclRefExpr
*FlagDecl
=
470 M
.makeDeclRefExpr(Flag
,
471 /* RefersToEnclosingVariableOrCapture=*/true);
474 MemberExpr
*Deref
= M
.makeMemberExpression(FlagDecl
, FlagFieldDecl
);
475 assert(Deref
->isLValue());
476 QualType DerefType
= Deref
->getType();
478 // Negation predicate.
479 UnaryOperator
*FlagCheck
= UnaryOperator::Create(
482 M
.makeImplicitCast(M
.makeLvalueToRvalue(Deref
, DerefType
), DerefType
,
483 CK_IntegralToBoolean
),
485 /* QualType=*/C
.IntTy
,
486 /* ExprValueKind=*/VK_PRValue
,
487 /* ExprObjectKind=*/OK_Ordinary
, SourceLocation(),
488 /* CanOverflow*/ false, FPOptionsOverride());
490 // Create assignment.
491 BinaryOperator
*FlagAssignment
= M
.makeAssignment(
492 Deref
, M
.makeIntegralCast(M
.makeIntegerLiteral(1, C
.IntTy
), DerefType
),
496 IfStmt::Create(C
, SourceLocation(), IfStatementKind::Ordinary
,
500 /* LPL=*/SourceLocation(),
501 /* RPL=*/SourceLocation(),
502 /* Then=*/M
.makeCompound({CallbackCall
, FlagAssignment
}));
507 /// Create a fake body for dispatch_once.
508 static Stmt
*create_dispatch_once(ASTContext
&C
, const FunctionDecl
*D
) {
509 // Check if we have at least two parameters.
510 if (D
->param_size() != 2)
513 // Check if the first parameter is a pointer to integer type.
514 const ParmVarDecl
*Predicate
= D
->getParamDecl(0);
515 QualType PredicateQPtrTy
= Predicate
->getType();
516 const PointerType
*PredicatePtrTy
= PredicateQPtrTy
->getAs
<PointerType
>();
519 QualType PredicateTy
= PredicatePtrTy
->getPointeeType();
520 if (!PredicateTy
->isIntegerType())
523 // Check if the second parameter is the proper block type.
524 const ParmVarDecl
*Block
= D
->getParamDecl(1);
525 QualType Ty
= Block
->getType();
526 if (!isDispatchBlock(Ty
))
529 // Everything checks out. Create a fakse body that checks the predicate,
530 // sets it, and calls the block. Basically, an AST dump of:
532 // void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block) {
533 // if (*predicate != ~0l) {
541 // (1) Create the call.
542 CallExpr
*CE
= CallExpr::Create(
544 /*StmtClass=*/M
.makeLvalueToRvalue(/*Expr=*/Block
),
545 /*Args=*/std::nullopt
,
546 /*QualType=*/C
.VoidTy
,
547 /*ExprValueType=*/VK_PRValue
,
548 /*SourceLocation=*/SourceLocation(), FPOptionsOverride());
550 // (2) Create the assignment to the predicate.
552 UnaryOperator::Create(C
, M
.makeIntegerLiteral(0, C
.LongTy
), UO_Not
,
553 C
.LongTy
, VK_PRValue
, OK_Ordinary
, SourceLocation(),
554 /*CanOverflow*/ false, FPOptionsOverride());
559 M
.makeLvalueToRvalue(
560 M
.makeDeclRefExpr(Predicate
), PredicateQPtrTy
),
562 M
.makeIntegralCast(DoneValue
, PredicateTy
),
565 // (3) Create the compound statement.
566 Stmt
*Stmts
[] = { B
, CE
};
567 CompoundStmt
*CS
= M
.makeCompound(Stmts
);
569 // (4) Create the 'if' condition.
570 ImplicitCastExpr
*LValToRval
=
571 M
.makeLvalueToRvalue(
573 M
.makeLvalueToRvalue(
574 M
.makeDeclRefExpr(Predicate
),
579 Expr
*GuardCondition
= M
.makeComparison(LValToRval
, DoneValue
, BO_NE
);
580 // (5) Create the 'if' statement.
581 auto *If
= IfStmt::Create(C
, SourceLocation(), IfStatementKind::Ordinary
,
584 /* Cond=*/GuardCondition
,
585 /* LPL=*/SourceLocation(),
586 /* RPL=*/SourceLocation(),
591 /// Create a fake body for dispatch_sync.
592 static Stmt
*create_dispatch_sync(ASTContext
&C
, const FunctionDecl
*D
) {
593 // Check if we have at least two parameters.
594 if (D
->param_size() != 2)
597 // Check if the second parameter is a block.
598 const ParmVarDecl
*PV
= D
->getParamDecl(1);
599 QualType Ty
= PV
->getType();
600 if (!isDispatchBlock(Ty
))
603 // Everything checks out. Create a fake body that just calls the block.
604 // This is basically just an AST dump of:
606 // void dispatch_sync(dispatch_queue_t queue, void (^block)(void)) {
611 DeclRefExpr
*DR
= M
.makeDeclRefExpr(PV
);
612 ImplicitCastExpr
*ICE
= M
.makeLvalueToRvalue(DR
, Ty
);
613 CallExpr
*CE
= CallExpr::Create(C
, ICE
, std::nullopt
, C
.VoidTy
, VK_PRValue
,
614 SourceLocation(), FPOptionsOverride());
618 static Stmt
*create_OSAtomicCompareAndSwap(ASTContext
&C
, const FunctionDecl
*D
)
620 // There are exactly 3 arguments.
621 if (D
->param_size() != 3)
625 // _Bool OSAtomicCompareAndSwapPtr(void *__oldValue,
627 // void * volatile *__theValue)
629 // if (oldValue == *theValue) {
630 // *theValue = newValue;
635 QualType ResultTy
= D
->getReturnType();
636 bool isBoolean
= ResultTy
->isBooleanType();
637 if (!isBoolean
&& !ResultTy
->isIntegralType(C
))
640 const ParmVarDecl
*OldValue
= D
->getParamDecl(0);
641 QualType OldValueTy
= OldValue
->getType();
643 const ParmVarDecl
*NewValue
= D
->getParamDecl(1);
644 QualType NewValueTy
= NewValue
->getType();
646 assert(OldValueTy
== NewValueTy
);
648 const ParmVarDecl
*TheValue
= D
->getParamDecl(2);
649 QualType TheValueTy
= TheValue
->getType();
650 const PointerType
*PT
= TheValueTy
->getAs
<PointerType
>();
653 QualType PointeeTy
= PT
->getPointeeType();
656 // Construct the comparison.
659 M
.makeLvalueToRvalue(M
.makeDeclRefExpr(OldValue
), OldValueTy
),
660 M
.makeLvalueToRvalue(
662 M
.makeLvalueToRvalue(M
.makeDeclRefExpr(TheValue
), TheValueTy
),
667 // Construct the body of the IfStmt.
672 M
.makeLvalueToRvalue(M
.makeDeclRefExpr(TheValue
), TheValueTy
),
674 M
.makeLvalueToRvalue(M
.makeDeclRefExpr(NewValue
), NewValueTy
),
677 Expr
*BoolVal
= M
.makeObjCBool(true);
678 Expr
*RetVal
= isBoolean
? M
.makeIntegralCastToBoolean(BoolVal
)
679 : M
.makeIntegralCast(BoolVal
, ResultTy
);
680 Stmts
[1] = M
.makeReturn(RetVal
);
681 CompoundStmt
*Body
= M
.makeCompound(Stmts
);
683 // Construct the else clause.
684 BoolVal
= M
.makeObjCBool(false);
685 RetVal
= isBoolean
? M
.makeIntegralCastToBoolean(BoolVal
)
686 : M
.makeIntegralCast(BoolVal
, ResultTy
);
687 Stmt
*Else
= M
.makeReturn(RetVal
);
689 /// Construct the If.
691 IfStmt::Create(C
, SourceLocation(), IfStatementKind::Ordinary
,
693 /* Var=*/nullptr, Comparison
,
694 /* LPL=*/SourceLocation(),
695 /* RPL=*/SourceLocation(), Body
, SourceLocation(), Else
);
700 Stmt
*BodyFarm::getBody(const FunctionDecl
*D
) {
701 std::optional
<Stmt
*> &Val
= Bodies
[D
];
707 if (D
->getIdentifier() == nullptr)
710 StringRef Name
= D
->getName();
716 if (unsigned BuiltinID
= D
->getBuiltinID()) {
718 case Builtin::BIas_const
:
719 case Builtin::BIforward
:
720 case Builtin::BIforward_like
:
721 case Builtin::BImove
:
722 case Builtin::BImove_if_noexcept
:
723 FF
= create_std_move_forward
;
729 } else if (Name
.startswith("OSAtomicCompareAndSwap") ||
730 Name
.startswith("objc_atomicCompareAndSwap")) {
731 FF
= create_OSAtomicCompareAndSwap
;
732 } else if (Name
== "call_once" && D
->getDeclContext()->isStdNamespace()) {
733 FF
= create_call_once
;
735 FF
= llvm::StringSwitch
<FunctionFarmer
>(Name
)
736 .Case("dispatch_sync", create_dispatch_sync
)
737 .Case("dispatch_once", create_dispatch_once
)
741 if (FF
) { Val
= FF(C
, D
); }
742 else if (Injector
) { Val
= Injector
->getBody(D
); }
746 static const ObjCIvarDecl
*findBackingIvar(const ObjCPropertyDecl
*Prop
) {
747 const ObjCIvarDecl
*IVar
= Prop
->getPropertyIvarDecl();
752 // When a readonly property is shadowed in a class extensions with a
753 // a readwrite property, the instance variable belongs to the shadowing
754 // property rather than the shadowed property. If there is no instance
755 // variable on a readonly property, check to see whether the property is
756 // shadowed and if so try to get the instance variable from shadowing
758 if (!Prop
->isReadOnly())
761 auto *Container
= cast
<ObjCContainerDecl
>(Prop
->getDeclContext());
762 const ObjCInterfaceDecl
*PrimaryInterface
= nullptr;
763 if (auto *InterfaceDecl
= dyn_cast
<ObjCInterfaceDecl
>(Container
)) {
764 PrimaryInterface
= InterfaceDecl
;
765 } else if (auto *CategoryDecl
= dyn_cast
<ObjCCategoryDecl
>(Container
)) {
766 PrimaryInterface
= CategoryDecl
->getClassInterface();
767 } else if (auto *ImplDecl
= dyn_cast
<ObjCImplDecl
>(Container
)) {
768 PrimaryInterface
= ImplDecl
->getClassInterface();
773 // FindPropertyVisibleInPrimaryClass() looks first in class extensions, so it
774 // is guaranteed to find the shadowing property, if it exists, rather than
775 // the shadowed property.
776 auto *ShadowingProp
= PrimaryInterface
->FindPropertyVisibleInPrimaryClass(
777 Prop
->getIdentifier(), Prop
->getQueryKind());
778 if (ShadowingProp
&& ShadowingProp
!= Prop
) {
779 IVar
= ShadowingProp
->getPropertyIvarDecl();
785 static Stmt
*createObjCPropertyGetter(ASTContext
&Ctx
,
786 const ObjCMethodDecl
*MD
) {
787 // First, find the backing ivar.
788 const ObjCIvarDecl
*IVar
= nullptr;
789 const ObjCPropertyDecl
*Prop
= nullptr;
791 // Property accessor stubs sometimes do not correspond to any property decl
792 // in the current interface (but in a superclass). They still have a
793 // corresponding property impl decl in this case.
794 if (MD
->isSynthesizedAccessorStub()) {
795 const ObjCInterfaceDecl
*IntD
= MD
->getClassInterface();
796 const ObjCImplementationDecl
*ImpD
= IntD
->getImplementation();
797 for (const auto *PI
: ImpD
->property_impls()) {
798 if (const ObjCPropertyDecl
*Candidate
= PI
->getPropertyDecl()) {
799 if (Candidate
->getGetterName() == MD
->getSelector()) {
801 IVar
= Prop
->getPropertyIvarDecl();
808 Prop
= MD
->findPropertyDecl();
809 IVar
= Prop
? findBackingIvar(Prop
) : nullptr;
815 // Ignore weak variables, which have special behavior.
816 if (Prop
->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak
)
819 // Look to see if Sema has synthesized a body for us. This happens in
820 // Objective-C++ because the return value may be a C++ class type with a
821 // non-trivial copy constructor. We can only do this if we can find the
822 // @synthesize for this property, though (or if we know it's been auto-
824 const ObjCImplementationDecl
*ImplDecl
=
825 IVar
->getContainingInterface()->getImplementation();
827 for (const auto *I
: ImplDecl
->property_impls()) {
828 if (I
->getPropertyDecl() != Prop
)
831 if (I
->getGetterCXXConstructor()) {
833 return M
.makeReturn(I
->getGetterCXXConstructor());
838 // We expect that the property is the same type as the ivar, or a reference to
839 // it, and that it is either an object pointer or trivially copyable.
840 if (!Ctx
.hasSameUnqualifiedType(IVar
->getType(),
841 Prop
->getType().getNonReferenceType()))
843 if (!IVar
->getType()->isObjCLifetimeType() &&
844 !IVar
->getType().isTriviallyCopyableType(Ctx
))
847 // Generate our body:
848 // return self->_ivar;
851 const VarDecl
*selfVar
= MD
->getSelfDecl();
855 Expr
*loadedIVar
= M
.makeObjCIvarRef(
856 M
.makeLvalueToRvalue(M
.makeDeclRefExpr(selfVar
), selfVar
->getType()),
859 if (!MD
->getReturnType()->isReferenceType())
860 loadedIVar
= M
.makeLvalueToRvalue(loadedIVar
, IVar
->getType());
862 return M
.makeReturn(loadedIVar
);
865 Stmt
*BodyFarm::getBody(const ObjCMethodDecl
*D
) {
866 // We currently only know how to synthesize property accessors.
867 if (!D
->isPropertyAccessor())
870 D
= D
->getCanonicalDecl();
872 // We should not try to synthesize explicitly redefined accessors.
873 // We do not know for sure how they behave.
874 if (!D
->isImplicit())
877 std::optional
<Stmt
*> &Val
= Bodies
[D
];
882 // For now, we only synthesize getters.
883 // Synthesizing setters would cause false negatives in the
884 // RetainCountChecker because the method body would bind the parameter
885 // to an instance variable, causing it to escape. This would prevent
886 // warning in the following common scenario:
888 // id foo = [[NSObject alloc] init];
889 // self.foo = foo; // We should warn that foo leaks here.
891 if (D
->param_size() != 0)
894 // If the property was defined in an extension, search the extensions for
896 const ObjCInterfaceDecl
*OID
= D
->getClassInterface();
897 if (dyn_cast
<ObjCInterfaceDecl
>(D
->getParent()) != OID
)
898 for (auto *Ext
: OID
->known_extensions()) {
899 auto *OMD
= Ext
->getInstanceMethod(D
->getSelector());
900 if (OMD
&& !OMD
->isImplicit())
904 Val
= createObjCPropertyGetter(C
, D
);