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