10b57cec5SDimitry Andric //== BodyFarm.cpp  - Factory for conjuring up fake bodies ----------*- C++ -*-//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // BodyFarm is a factory for creating faux implementations for functions/methods
100b57cec5SDimitry Andric // for analysis purposes.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "clang/Analysis/BodyFarm.h"
150b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
160b57cec5SDimitry Andric #include "clang/AST/CXXInheritance.h"
170b57cec5SDimitry Andric #include "clang/AST/Decl.h"
180b57cec5SDimitry Andric #include "clang/AST/Expr.h"
190b57cec5SDimitry Andric #include "clang/AST/ExprCXX.h"
200b57cec5SDimitry Andric #include "clang/AST/ExprObjC.h"
210b57cec5SDimitry Andric #include "clang/AST/NestedNameSpecifier.h"
220b57cec5SDimitry Andric #include "clang/Analysis/CodeInjector.h"
230b57cec5SDimitry Andric #include "clang/Basic/OperatorKinds.h"
240b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
250b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric #define DEBUG_TYPE "body-farm"
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric using namespace clang;
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
320b57cec5SDimitry Andric // Helper creation functions for constructing faux ASTs.
330b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric static bool isDispatchBlock(QualType Ty) {
360b57cec5SDimitry Andric   // Is it a block pointer?
370b57cec5SDimitry Andric   const BlockPointerType *BPT = Ty->getAs<BlockPointerType>();
380b57cec5SDimitry Andric   if (!BPT)
390b57cec5SDimitry Andric     return false;
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric   // Check if the block pointer type takes no arguments and
420b57cec5SDimitry Andric   // returns void.
430b57cec5SDimitry Andric   const FunctionProtoType *FT =
440b57cec5SDimitry Andric   BPT->getPointeeType()->getAs<FunctionProtoType>();
450b57cec5SDimitry Andric   return FT && FT->getReturnType()->isVoidType() && FT->getNumParams() == 0;
460b57cec5SDimitry Andric }
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric namespace {
490b57cec5SDimitry Andric class ASTMaker {
500b57cec5SDimitry Andric public:
510b57cec5SDimitry Andric   ASTMaker(ASTContext &C) : C(C) {}
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   /// Create a new BinaryOperator representing a simple assignment.
540b57cec5SDimitry Andric   BinaryOperator *makeAssignment(const Expr *LHS, const Expr *RHS, QualType Ty);
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric   /// Create a new BinaryOperator representing a comparison.
570b57cec5SDimitry Andric   BinaryOperator *makeComparison(const Expr *LHS, const Expr *RHS,
580b57cec5SDimitry Andric                                  BinaryOperator::Opcode Op);
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric   /// Create a new compound stmt using the provided statements.
610b57cec5SDimitry Andric   CompoundStmt *makeCompound(ArrayRef<Stmt*>);
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric   /// Create a new DeclRefExpr for the referenced variable.
640b57cec5SDimitry Andric   DeclRefExpr *makeDeclRefExpr(const VarDecl *D,
650b57cec5SDimitry Andric                                bool RefersToEnclosingVariableOrCapture = false);
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric   /// Create a new UnaryOperator representing a dereference.
680b57cec5SDimitry Andric   UnaryOperator *makeDereference(const Expr *Arg, QualType Ty);
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric   /// Create an implicit cast for an integer conversion.
710b57cec5SDimitry Andric   Expr *makeIntegralCast(const Expr *Arg, QualType Ty);
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   /// Create an implicit cast to a builtin boolean type.
740b57cec5SDimitry Andric   ImplicitCastExpr *makeIntegralCastToBoolean(const Expr *Arg);
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric   /// Create an implicit cast for lvalue-to-rvaluate conversions.
770b57cec5SDimitry Andric   ImplicitCastExpr *makeLvalueToRvalue(const Expr *Arg, QualType Ty);
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric   /// Make RValue out of variable declaration, creating a temporary
800b57cec5SDimitry Andric   /// DeclRefExpr in the process.
810b57cec5SDimitry Andric   ImplicitCastExpr *
820b57cec5SDimitry Andric   makeLvalueToRvalue(const VarDecl *Decl,
830b57cec5SDimitry Andric                      bool RefersToEnclosingVariableOrCapture = false);
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   /// Create an implicit cast of the given type.
860b57cec5SDimitry Andric   ImplicitCastExpr *makeImplicitCast(const Expr *Arg, QualType Ty,
870b57cec5SDimitry Andric                                      CastKind CK = CK_LValueToRValue);
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric   /// Create an Objective-C bool literal.
900b57cec5SDimitry Andric   ObjCBoolLiteralExpr *makeObjCBool(bool Val);
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric   /// Create an Objective-C ivar reference.
930b57cec5SDimitry Andric   ObjCIvarRefExpr *makeObjCIvarRef(const Expr *Base, const ObjCIvarDecl *IVar);
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric   /// Create a Return statement.
960b57cec5SDimitry Andric   ReturnStmt *makeReturn(const Expr *RetVal);
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric   /// Create an integer literal expression of the given type.
990b57cec5SDimitry Andric   IntegerLiteral *makeIntegerLiteral(uint64_t Value, QualType Ty);
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   /// Create a member expression.
1020b57cec5SDimitry Andric   MemberExpr *makeMemberExpression(Expr *base, ValueDecl *MemberDecl,
1030b57cec5SDimitry Andric                                    bool IsArrow = false,
1040b57cec5SDimitry Andric                                    ExprValueKind ValueKind = VK_LValue);
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric   /// Returns a *first* member field of a record declaration with a given name.
1070b57cec5SDimitry Andric   /// \return an nullptr if no member with such a name exists.
1080b57cec5SDimitry Andric   ValueDecl *findMemberField(const RecordDecl *RD, StringRef Name);
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric private:
1110b57cec5SDimitry Andric   ASTContext &C;
1120b57cec5SDimitry Andric };
1130b57cec5SDimitry Andric }
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric BinaryOperator *ASTMaker::makeAssignment(const Expr *LHS, const Expr *RHS,
1160b57cec5SDimitry Andric                                          QualType Ty) {
1175ffd83dbSDimitry Andric   return BinaryOperator::Create(
1185ffd83dbSDimitry Andric       C, const_cast<Expr *>(LHS), const_cast<Expr *>(RHS), BO_Assign, Ty,
119fe6060f1SDimitry Andric       VK_PRValue, OK_Ordinary, SourceLocation(), FPOptionsOverride());
1200b57cec5SDimitry Andric }
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric BinaryOperator *ASTMaker::makeComparison(const Expr *LHS, const Expr *RHS,
1230b57cec5SDimitry Andric                                          BinaryOperator::Opcode Op) {
1240b57cec5SDimitry Andric   assert(BinaryOperator::isLogicalOp(Op) ||
1250b57cec5SDimitry Andric          BinaryOperator::isComparisonOp(Op));
1265ffd83dbSDimitry Andric   return BinaryOperator::Create(
1275ffd83dbSDimitry Andric       C, const_cast<Expr *>(LHS), const_cast<Expr *>(RHS), Op,
128fe6060f1SDimitry Andric       C.getLogicalOperationType(), VK_PRValue, OK_Ordinary, SourceLocation(),
1295ffd83dbSDimitry Andric       FPOptionsOverride());
1300b57cec5SDimitry Andric }
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric CompoundStmt *ASTMaker::makeCompound(ArrayRef<Stmt *> Stmts) {
1330b57cec5SDimitry Andric   return CompoundStmt::Create(C, Stmts, SourceLocation(), SourceLocation());
1340b57cec5SDimitry Andric }
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric DeclRefExpr *ASTMaker::makeDeclRefExpr(
1370b57cec5SDimitry Andric     const VarDecl *D,
1380b57cec5SDimitry Andric     bool RefersToEnclosingVariableOrCapture) {
1390b57cec5SDimitry Andric   QualType Type = D->getType().getNonReferenceType();
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric   DeclRefExpr *DR = DeclRefExpr::Create(
1420b57cec5SDimitry Andric       C, NestedNameSpecifierLoc(), SourceLocation(), const_cast<VarDecl *>(D),
1430b57cec5SDimitry Andric       RefersToEnclosingVariableOrCapture, SourceLocation(), Type, VK_LValue);
1440b57cec5SDimitry Andric   return DR;
1450b57cec5SDimitry Andric }
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric UnaryOperator *ASTMaker::makeDereference(const Expr *Arg, QualType Ty) {
1485ffd83dbSDimitry Andric   return UnaryOperator::Create(C, const_cast<Expr *>(Arg), UO_Deref, Ty,
1490b57cec5SDimitry Andric                                VK_LValue, OK_Ordinary, SourceLocation(),
1505ffd83dbSDimitry Andric                                /*CanOverflow*/ false, FPOptionsOverride());
1510b57cec5SDimitry Andric }
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric ImplicitCastExpr *ASTMaker::makeLvalueToRvalue(const Expr *Arg, QualType Ty) {
1540b57cec5SDimitry Andric   return makeImplicitCast(Arg, Ty, CK_LValueToRValue);
1550b57cec5SDimitry Andric }
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric ImplicitCastExpr *
1580b57cec5SDimitry Andric ASTMaker::makeLvalueToRvalue(const VarDecl *Arg,
1590b57cec5SDimitry Andric                              bool RefersToEnclosingVariableOrCapture) {
1600b57cec5SDimitry Andric   QualType Type = Arg->getType().getNonReferenceType();
1610b57cec5SDimitry Andric   return makeLvalueToRvalue(makeDeclRefExpr(Arg,
1620b57cec5SDimitry Andric                                             RefersToEnclosingVariableOrCapture),
1630b57cec5SDimitry Andric                             Type);
1640b57cec5SDimitry Andric }
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric ImplicitCastExpr *ASTMaker::makeImplicitCast(const Expr *Arg, QualType Ty,
1670b57cec5SDimitry Andric                                              CastKind CK) {
1680b57cec5SDimitry Andric   return ImplicitCastExpr::Create(C, Ty,
1690b57cec5SDimitry Andric                                   /* CastKind=*/CK,
1700b57cec5SDimitry Andric                                   /* Expr=*/const_cast<Expr *>(Arg),
1710b57cec5SDimitry Andric                                   /* CXXCastPath=*/nullptr,
172fe6060f1SDimitry Andric                                   /* ExprValueKind=*/VK_PRValue,
173e8d8bef9SDimitry Andric                                   /* FPFeatures */ FPOptionsOverride());
1740b57cec5SDimitry Andric }
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric Expr *ASTMaker::makeIntegralCast(const Expr *Arg, QualType Ty) {
1770b57cec5SDimitry Andric   if (Arg->getType() == Ty)
1780b57cec5SDimitry Andric     return const_cast<Expr*>(Arg);
179e8d8bef9SDimitry Andric   return makeImplicitCast(Arg, Ty, CK_IntegralCast);
1800b57cec5SDimitry Andric }
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric ImplicitCastExpr *ASTMaker::makeIntegralCastToBoolean(const Expr *Arg) {
183e8d8bef9SDimitry Andric   return makeImplicitCast(Arg, C.BoolTy, CK_IntegralToBoolean);
1840b57cec5SDimitry Andric }
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric ObjCBoolLiteralExpr *ASTMaker::makeObjCBool(bool Val) {
1870b57cec5SDimitry Andric   QualType Ty = C.getBOOLDecl() ? C.getBOOLType() : C.ObjCBuiltinBoolTy;
1880b57cec5SDimitry Andric   return new (C) ObjCBoolLiteralExpr(Val, Ty, SourceLocation());
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric ObjCIvarRefExpr *ASTMaker::makeObjCIvarRef(const Expr *Base,
1920b57cec5SDimitry Andric                                            const ObjCIvarDecl *IVar) {
1930b57cec5SDimitry Andric   return new (C) ObjCIvarRefExpr(const_cast<ObjCIvarDecl*>(IVar),
1940b57cec5SDimitry Andric                                  IVar->getType(), SourceLocation(),
1950b57cec5SDimitry Andric                                  SourceLocation(), const_cast<Expr*>(Base),
1960b57cec5SDimitry Andric                                  /*arrow=*/true, /*free=*/false);
1970b57cec5SDimitry Andric }
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric ReturnStmt *ASTMaker::makeReturn(const Expr *RetVal) {
2000b57cec5SDimitry Andric   return ReturnStmt::Create(C, SourceLocation(), const_cast<Expr *>(RetVal),
2010b57cec5SDimitry Andric                             /* NRVOCandidate=*/nullptr);
2020b57cec5SDimitry Andric }
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric IntegerLiteral *ASTMaker::makeIntegerLiteral(uint64_t Value, QualType Ty) {
2050b57cec5SDimitry Andric   llvm::APInt APValue = llvm::APInt(C.getTypeSize(Ty), Value);
2060b57cec5SDimitry Andric   return IntegerLiteral::Create(C, APValue, Ty, SourceLocation());
2070b57cec5SDimitry Andric }
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric MemberExpr *ASTMaker::makeMemberExpression(Expr *base, ValueDecl *MemberDecl,
2100b57cec5SDimitry Andric                                            bool IsArrow,
2110b57cec5SDimitry Andric                                            ExprValueKind ValueKind) {
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric   DeclAccessPair FoundDecl = DeclAccessPair::make(MemberDecl, AS_public);
2140b57cec5SDimitry Andric   return MemberExpr::Create(
2150b57cec5SDimitry Andric       C, base, IsArrow, SourceLocation(), NestedNameSpecifierLoc(),
2160b57cec5SDimitry Andric       SourceLocation(), MemberDecl, FoundDecl,
2170b57cec5SDimitry Andric       DeclarationNameInfo(MemberDecl->getDeclName(), SourceLocation()),
2180b57cec5SDimitry Andric       /* TemplateArgumentListInfo=*/ nullptr, MemberDecl->getType(), ValueKind,
2190b57cec5SDimitry Andric       OK_Ordinary, NOUR_None);
2200b57cec5SDimitry Andric }
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric ValueDecl *ASTMaker::findMemberField(const RecordDecl *RD, StringRef Name) {
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric   CXXBasePaths Paths(
2250b57cec5SDimitry Andric       /* FindAmbiguities=*/false,
2260b57cec5SDimitry Andric       /* RecordPaths=*/false,
2270b57cec5SDimitry Andric       /* DetectVirtual=*/ false);
2280b57cec5SDimitry Andric   const IdentifierInfo &II = C.Idents.get(Name);
2290b57cec5SDimitry Andric   DeclarationName DeclName = C.DeclarationNames.getIdentifier(&II);
2300b57cec5SDimitry Andric 
2310b57cec5SDimitry Andric   DeclContextLookupResult Decls = RD->lookup(DeclName);
2320b57cec5SDimitry Andric   for (NamedDecl *FoundDecl : Decls)
2330b57cec5SDimitry Andric     if (!FoundDecl->getDeclContext()->isFunctionOrMethod())
2340b57cec5SDimitry Andric       return cast<ValueDecl>(FoundDecl);
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric   return nullptr;
2370b57cec5SDimitry Andric }
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
2400b57cec5SDimitry Andric // Creation functions for faux ASTs.
2410b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric typedef Stmt *(*FunctionFarmer)(ASTContext &C, const FunctionDecl *D);
2440b57cec5SDimitry Andric 
2450b57cec5SDimitry Andric static CallExpr *create_call_once_funcptr_call(ASTContext &C, ASTMaker M,
2460b57cec5SDimitry Andric                                                const ParmVarDecl *Callback,
2470b57cec5SDimitry Andric                                                ArrayRef<Expr *> CallArgs) {
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric   QualType Ty = Callback->getType();
2500b57cec5SDimitry Andric   DeclRefExpr *Call = M.makeDeclRefExpr(Callback);
2510b57cec5SDimitry Andric   Expr *SubExpr;
2520b57cec5SDimitry Andric   if (Ty->isRValueReferenceType()) {
2530b57cec5SDimitry Andric     SubExpr = M.makeImplicitCast(
2540b57cec5SDimitry Andric         Call, Ty.getNonReferenceType(), CK_LValueToRValue);
2550b57cec5SDimitry Andric   } else if (Ty->isLValueReferenceType() &&
2560b57cec5SDimitry Andric              Call->getType()->isFunctionType()) {
2570b57cec5SDimitry Andric     Ty = C.getPointerType(Ty.getNonReferenceType());
2580b57cec5SDimitry Andric     SubExpr = M.makeImplicitCast(Call, Ty, CK_FunctionToPointerDecay);
2590b57cec5SDimitry Andric   } else if (Ty->isLValueReferenceType()
2600b57cec5SDimitry Andric              && Call->getType()->isPointerType()
2610b57cec5SDimitry Andric              && Call->getType()->getPointeeType()->isFunctionType()){
2620b57cec5SDimitry Andric     SubExpr = Call;
2630b57cec5SDimitry Andric   } else {
2640b57cec5SDimitry Andric     llvm_unreachable("Unexpected state");
2650b57cec5SDimitry Andric   }
2660b57cec5SDimitry Andric 
267fe6060f1SDimitry Andric   return CallExpr::Create(C, SubExpr, CallArgs, C.VoidTy, VK_PRValue,
268e8d8bef9SDimitry Andric                           SourceLocation(), FPOptionsOverride());
2690b57cec5SDimitry Andric }
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric static CallExpr *create_call_once_lambda_call(ASTContext &C, ASTMaker M,
2720b57cec5SDimitry Andric                                               const ParmVarDecl *Callback,
2730b57cec5SDimitry Andric                                               CXXRecordDecl *CallbackDecl,
2740b57cec5SDimitry Andric                                               ArrayRef<Expr *> CallArgs) {
2750b57cec5SDimitry Andric   assert(CallbackDecl != nullptr);
2760b57cec5SDimitry Andric   assert(CallbackDecl->isLambda());
2770b57cec5SDimitry Andric   FunctionDecl *callOperatorDecl = CallbackDecl->getLambdaCallOperator();
2780b57cec5SDimitry Andric   assert(callOperatorDecl != nullptr);
2790b57cec5SDimitry Andric 
2800b57cec5SDimitry Andric   DeclRefExpr *callOperatorDeclRef =
2810b57cec5SDimitry Andric       DeclRefExpr::Create(/* Ctx =*/ C,
2820b57cec5SDimitry Andric                           /* QualifierLoc =*/ NestedNameSpecifierLoc(),
2830b57cec5SDimitry Andric                           /* TemplateKWLoc =*/ SourceLocation(),
2840b57cec5SDimitry Andric                           const_cast<FunctionDecl *>(callOperatorDecl),
2850b57cec5SDimitry Andric                           /* RefersToEnclosingVariableOrCapture=*/ false,
2860b57cec5SDimitry Andric                           /* NameLoc =*/ SourceLocation(),
2870b57cec5SDimitry Andric                           /* T =*/ callOperatorDecl->getType(),
2880b57cec5SDimitry Andric                           /* VK =*/ VK_LValue);
2890b57cec5SDimitry Andric 
2900b57cec5SDimitry Andric   return CXXOperatorCallExpr::Create(
2910b57cec5SDimitry Andric       /*AstContext=*/C, OO_Call, callOperatorDeclRef,
2920b57cec5SDimitry Andric       /*Args=*/CallArgs,
2930b57cec5SDimitry Andric       /*QualType=*/C.VoidTy,
294fe6060f1SDimitry Andric       /*ExprValueType=*/VK_PRValue,
2955ffd83dbSDimitry Andric       /*SourceLocation=*/SourceLocation(),
2965ffd83dbSDimitry Andric       /*FPFeatures=*/FPOptionsOverride());
2970b57cec5SDimitry Andric }
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric /// Create a fake body for std::call_once.
3000b57cec5SDimitry Andric /// Emulates the following function body:
3010b57cec5SDimitry Andric ///
3020b57cec5SDimitry Andric /// \code
3030b57cec5SDimitry Andric /// typedef struct once_flag_s {
3040b57cec5SDimitry Andric ///   unsigned long __state = 0;
3050b57cec5SDimitry Andric /// } once_flag;
3060b57cec5SDimitry Andric /// template<class Callable>
3070b57cec5SDimitry Andric /// void call_once(once_flag& o, Callable func) {
3080b57cec5SDimitry Andric ///   if (!o.__state) {
3090b57cec5SDimitry Andric ///     func();
3100b57cec5SDimitry Andric ///   }
3110b57cec5SDimitry Andric ///   o.__state = 1;
3120b57cec5SDimitry Andric /// }
3130b57cec5SDimitry Andric /// \endcode
3140b57cec5SDimitry Andric static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) {
3150b57cec5SDimitry Andric   LLVM_DEBUG(llvm::dbgs() << "Generating body for call_once\n");
3160b57cec5SDimitry Andric 
3170b57cec5SDimitry Andric   // We need at least two parameters.
3180b57cec5SDimitry Andric   if (D->param_size() < 2)
3190b57cec5SDimitry Andric     return nullptr;
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric   ASTMaker M(C);
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric   const ParmVarDecl *Flag = D->getParamDecl(0);
3240b57cec5SDimitry Andric   const ParmVarDecl *Callback = D->getParamDecl(1);
3250b57cec5SDimitry Andric 
3260b57cec5SDimitry Andric   if (!Callback->getType()->isReferenceType()) {
3270b57cec5SDimitry Andric     llvm::dbgs() << "libcxx03 std::call_once implementation, skipping.\n";
3280b57cec5SDimitry Andric     return nullptr;
3290b57cec5SDimitry Andric   }
3300b57cec5SDimitry Andric   if (!Flag->getType()->isReferenceType()) {
3310b57cec5SDimitry Andric     llvm::dbgs() << "unknown std::call_once implementation, skipping.\n";
3320b57cec5SDimitry Andric     return nullptr;
3330b57cec5SDimitry Andric   }
3340b57cec5SDimitry Andric 
3350b57cec5SDimitry Andric   QualType CallbackType = Callback->getType().getNonReferenceType();
3360b57cec5SDimitry Andric 
3370b57cec5SDimitry Andric   // Nullable pointer, non-null iff function is a CXXRecordDecl.
3380b57cec5SDimitry Andric   CXXRecordDecl *CallbackRecordDecl = CallbackType->getAsCXXRecordDecl();
3390b57cec5SDimitry Andric   QualType FlagType = Flag->getType().getNonReferenceType();
3400b57cec5SDimitry Andric   auto *FlagRecordDecl = FlagType->getAsRecordDecl();
3410b57cec5SDimitry Andric 
3420b57cec5SDimitry Andric   if (!FlagRecordDecl) {
3430b57cec5SDimitry Andric     LLVM_DEBUG(llvm::dbgs() << "Flag field is not a record: "
3440b57cec5SDimitry Andric                             << "unknown std::call_once implementation, "
3450b57cec5SDimitry Andric                             << "ignoring the call.\n");
3460b57cec5SDimitry Andric     return nullptr;
3470b57cec5SDimitry Andric   }
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric   // We initially assume libc++ implementation of call_once,
3500b57cec5SDimitry Andric   // where the once_flag struct has a field `__state_`.
3510b57cec5SDimitry Andric   ValueDecl *FlagFieldDecl = M.findMemberField(FlagRecordDecl, "__state_");
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric   // Otherwise, try libstdc++ implementation, with a field
3540b57cec5SDimitry Andric   // `_M_once`
3550b57cec5SDimitry Andric   if (!FlagFieldDecl) {
3560b57cec5SDimitry Andric     FlagFieldDecl = M.findMemberField(FlagRecordDecl, "_M_once");
3570b57cec5SDimitry Andric   }
3580b57cec5SDimitry Andric 
3590b57cec5SDimitry Andric   if (!FlagFieldDecl) {
3600b57cec5SDimitry Andric     LLVM_DEBUG(llvm::dbgs() << "No field _M_once or __state_ found on "
3610b57cec5SDimitry Andric                             << "std::once_flag struct: unknown std::call_once "
3620b57cec5SDimitry Andric                             << "implementation, ignoring the call.");
3630b57cec5SDimitry Andric     return nullptr;
3640b57cec5SDimitry Andric   }
3650b57cec5SDimitry Andric 
3660b57cec5SDimitry Andric   bool isLambdaCall = CallbackRecordDecl && CallbackRecordDecl->isLambda();
3670b57cec5SDimitry Andric   if (CallbackRecordDecl && !isLambdaCall) {
3680b57cec5SDimitry Andric     LLVM_DEBUG(llvm::dbgs()
3690b57cec5SDimitry Andric                << "Not supported: synthesizing body for functors when "
3700b57cec5SDimitry Andric                << "body farming std::call_once, ignoring the call.");
3710b57cec5SDimitry Andric     return nullptr;
3720b57cec5SDimitry Andric   }
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric   SmallVector<Expr *, 5> CallArgs;
3750b57cec5SDimitry Andric   const FunctionProtoType *CallbackFunctionType;
3760b57cec5SDimitry Andric   if (isLambdaCall) {
3770b57cec5SDimitry Andric 
3780b57cec5SDimitry Andric     // Lambda requires callback itself inserted as a first parameter.
3790b57cec5SDimitry Andric     CallArgs.push_back(
3800b57cec5SDimitry Andric         M.makeDeclRefExpr(Callback,
3810b57cec5SDimitry Andric                           /* RefersToEnclosingVariableOrCapture=*/ true));
3820b57cec5SDimitry Andric     CallbackFunctionType = CallbackRecordDecl->getLambdaCallOperator()
3830b57cec5SDimitry Andric                                ->getType()
3840b57cec5SDimitry Andric                                ->getAs<FunctionProtoType>();
3850b57cec5SDimitry Andric   } else if (!CallbackType->getPointeeType().isNull()) {
3860b57cec5SDimitry Andric     CallbackFunctionType =
3870b57cec5SDimitry Andric         CallbackType->getPointeeType()->getAs<FunctionProtoType>();
3880b57cec5SDimitry Andric   } else {
3890b57cec5SDimitry Andric     CallbackFunctionType = CallbackType->getAs<FunctionProtoType>();
3900b57cec5SDimitry Andric   }
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric   if (!CallbackFunctionType)
3930b57cec5SDimitry Andric     return nullptr;
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric   // First two arguments are used for the flag and for the callback.
3960b57cec5SDimitry Andric   if (D->getNumParams() != CallbackFunctionType->getNumParams() + 2) {
3970b57cec5SDimitry Andric     LLVM_DEBUG(llvm::dbgs() << "Types of params of the callback do not match "
3980b57cec5SDimitry Andric                             << "params passed to std::call_once, "
3990b57cec5SDimitry Andric                             << "ignoring the call\n");
4000b57cec5SDimitry Andric     return nullptr;
4010b57cec5SDimitry Andric   }
4020b57cec5SDimitry Andric 
4030b57cec5SDimitry Andric   // All arguments past first two ones are passed to the callback,
4040b57cec5SDimitry Andric   // and we turn lvalues into rvalues if the argument is not passed by
4050b57cec5SDimitry Andric   // reference.
4060b57cec5SDimitry Andric   for (unsigned int ParamIdx = 2; ParamIdx < D->getNumParams(); ParamIdx++) {
4070b57cec5SDimitry Andric     const ParmVarDecl *PDecl = D->getParamDecl(ParamIdx);
408a7dea167SDimitry Andric     assert(PDecl);
409a7dea167SDimitry Andric     if (CallbackFunctionType->getParamType(ParamIdx - 2)
4100b57cec5SDimitry Andric                 .getNonReferenceType()
4110b57cec5SDimitry Andric                 .getCanonicalType() !=
4120b57cec5SDimitry Andric             PDecl->getType().getNonReferenceType().getCanonicalType()) {
4130b57cec5SDimitry Andric       LLVM_DEBUG(llvm::dbgs() << "Types of params of the callback do not match "
4140b57cec5SDimitry Andric                               << "params passed to std::call_once, "
4150b57cec5SDimitry Andric                               << "ignoring the call\n");
4160b57cec5SDimitry Andric       return nullptr;
4170b57cec5SDimitry Andric     }
4180b57cec5SDimitry Andric     Expr *ParamExpr = M.makeDeclRefExpr(PDecl);
4190b57cec5SDimitry Andric     if (!CallbackFunctionType->getParamType(ParamIdx - 2)->isReferenceType()) {
4200b57cec5SDimitry Andric       QualType PTy = PDecl->getType().getNonReferenceType();
4210b57cec5SDimitry Andric       ParamExpr = M.makeLvalueToRvalue(ParamExpr, PTy);
4220b57cec5SDimitry Andric     }
4230b57cec5SDimitry Andric     CallArgs.push_back(ParamExpr);
4240b57cec5SDimitry Andric   }
4250b57cec5SDimitry Andric 
4260b57cec5SDimitry Andric   CallExpr *CallbackCall;
4270b57cec5SDimitry Andric   if (isLambdaCall) {
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric     CallbackCall = create_call_once_lambda_call(C, M, Callback,
4300b57cec5SDimitry Andric                                                 CallbackRecordDecl, CallArgs);
4310b57cec5SDimitry Andric   } else {
4320b57cec5SDimitry Andric 
4330b57cec5SDimitry Andric     // Function pointer case.
4340b57cec5SDimitry Andric     CallbackCall = create_call_once_funcptr_call(C, M, Callback, CallArgs);
4350b57cec5SDimitry Andric   }
4360b57cec5SDimitry Andric 
4370b57cec5SDimitry Andric   DeclRefExpr *FlagDecl =
4380b57cec5SDimitry Andric       M.makeDeclRefExpr(Flag,
4390b57cec5SDimitry Andric                         /* RefersToEnclosingVariableOrCapture=*/true);
4400b57cec5SDimitry Andric 
4410b57cec5SDimitry Andric 
4420b57cec5SDimitry Andric   MemberExpr *Deref = M.makeMemberExpression(FlagDecl, FlagFieldDecl);
4430b57cec5SDimitry Andric   assert(Deref->isLValue());
4440b57cec5SDimitry Andric   QualType DerefType = Deref->getType();
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric   // Negation predicate.
4475ffd83dbSDimitry Andric   UnaryOperator *FlagCheck = UnaryOperator::Create(
4485ffd83dbSDimitry Andric       C,
4490b57cec5SDimitry Andric       /* input=*/
4500b57cec5SDimitry Andric       M.makeImplicitCast(M.makeLvalueToRvalue(Deref, DerefType), DerefType,
4510b57cec5SDimitry Andric                          CK_IntegralToBoolean),
4520b57cec5SDimitry Andric       /* opc=*/UO_LNot,
4530b57cec5SDimitry Andric       /* QualType=*/C.IntTy,
454fe6060f1SDimitry Andric       /* ExprValueKind=*/VK_PRValue,
4550b57cec5SDimitry Andric       /* ExprObjectKind=*/OK_Ordinary, SourceLocation(),
4565ffd83dbSDimitry Andric       /* CanOverflow*/ false, FPOptionsOverride());
4570b57cec5SDimitry Andric 
4580b57cec5SDimitry Andric   // Create assignment.
4590b57cec5SDimitry Andric   BinaryOperator *FlagAssignment = M.makeAssignment(
4600b57cec5SDimitry Andric       Deref, M.makeIntegralCast(M.makeIntegerLiteral(1, C.IntTy), DerefType),
4610b57cec5SDimitry Andric       DerefType);
4620b57cec5SDimitry Andric 
4630b57cec5SDimitry Andric   auto *Out =
464349cc55cSDimitry Andric       IfStmt::Create(C, SourceLocation(), IfStatementKind::Ordinary,
4650b57cec5SDimitry Andric                      /* Init=*/nullptr,
4660b57cec5SDimitry Andric                      /* Var=*/nullptr,
4670b57cec5SDimitry Andric                      /* Cond=*/FlagCheck,
468e8d8bef9SDimitry Andric                      /* LPL=*/SourceLocation(),
469e8d8bef9SDimitry Andric                      /* RPL=*/SourceLocation(),
4700b57cec5SDimitry Andric                      /* Then=*/M.makeCompound({CallbackCall, FlagAssignment}));
4710b57cec5SDimitry Andric 
4720b57cec5SDimitry Andric   return Out;
4730b57cec5SDimitry Andric }
4740b57cec5SDimitry Andric 
4750b57cec5SDimitry Andric /// Create a fake body for dispatch_once.
4760b57cec5SDimitry Andric static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
4770b57cec5SDimitry Andric   // Check if we have at least two parameters.
4780b57cec5SDimitry Andric   if (D->param_size() != 2)
4790b57cec5SDimitry Andric     return nullptr;
4800b57cec5SDimitry Andric 
4810b57cec5SDimitry Andric   // Check if the first parameter is a pointer to integer type.
4820b57cec5SDimitry Andric   const ParmVarDecl *Predicate = D->getParamDecl(0);
4830b57cec5SDimitry Andric   QualType PredicateQPtrTy = Predicate->getType();
4840b57cec5SDimitry Andric   const PointerType *PredicatePtrTy = PredicateQPtrTy->getAs<PointerType>();
4850b57cec5SDimitry Andric   if (!PredicatePtrTy)
4860b57cec5SDimitry Andric     return nullptr;
4870b57cec5SDimitry Andric   QualType PredicateTy = PredicatePtrTy->getPointeeType();
4880b57cec5SDimitry Andric   if (!PredicateTy->isIntegerType())
4890b57cec5SDimitry Andric     return nullptr;
4900b57cec5SDimitry Andric 
4910b57cec5SDimitry Andric   // Check if the second parameter is the proper block type.
4920b57cec5SDimitry Andric   const ParmVarDecl *Block = D->getParamDecl(1);
4930b57cec5SDimitry Andric   QualType Ty = Block->getType();
4940b57cec5SDimitry Andric   if (!isDispatchBlock(Ty))
4950b57cec5SDimitry Andric     return nullptr;
4960b57cec5SDimitry Andric 
4970b57cec5SDimitry Andric   // Everything checks out.  Create a fakse body that checks the predicate,
4980b57cec5SDimitry Andric   // sets it, and calls the block.  Basically, an AST dump of:
4990b57cec5SDimitry Andric   //
5000b57cec5SDimitry Andric   // void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block) {
5010b57cec5SDimitry Andric   //  if (*predicate != ~0l) {
5020b57cec5SDimitry Andric   //    *predicate = ~0l;
5030b57cec5SDimitry Andric   //    block();
5040b57cec5SDimitry Andric   //  }
5050b57cec5SDimitry Andric   // }
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric   ASTMaker M(C);
5080b57cec5SDimitry Andric 
5090b57cec5SDimitry Andric   // (1) Create the call.
5100b57cec5SDimitry Andric   CallExpr *CE = CallExpr::Create(
5110b57cec5SDimitry Andric       /*ASTContext=*/C,
5120b57cec5SDimitry Andric       /*StmtClass=*/M.makeLvalueToRvalue(/*Expr=*/Block),
5130b57cec5SDimitry Andric       /*Args=*/None,
5140b57cec5SDimitry Andric       /*QualType=*/C.VoidTy,
515fe6060f1SDimitry Andric       /*ExprValueType=*/VK_PRValue,
516e8d8bef9SDimitry Andric       /*SourceLocation=*/SourceLocation(), FPOptionsOverride());
5170b57cec5SDimitry Andric 
5180b57cec5SDimitry Andric   // (2) Create the assignment to the predicate.
5190b57cec5SDimitry Andric   Expr *DoneValue =
5205ffd83dbSDimitry Andric       UnaryOperator::Create(C, M.makeIntegerLiteral(0, C.LongTy), UO_Not,
521fe6060f1SDimitry Andric                             C.LongTy, VK_PRValue, OK_Ordinary, SourceLocation(),
5225ffd83dbSDimitry Andric                             /*CanOverflow*/ false, FPOptionsOverride());
5230b57cec5SDimitry Andric 
5240b57cec5SDimitry Andric   BinaryOperator *B =
5250b57cec5SDimitry Andric     M.makeAssignment(
5260b57cec5SDimitry Andric        M.makeDereference(
5270b57cec5SDimitry Andric           M.makeLvalueToRvalue(
5280b57cec5SDimitry Andric             M.makeDeclRefExpr(Predicate), PredicateQPtrTy),
5290b57cec5SDimitry Andric             PredicateTy),
5300b57cec5SDimitry Andric        M.makeIntegralCast(DoneValue, PredicateTy),
5310b57cec5SDimitry Andric        PredicateTy);
5320b57cec5SDimitry Andric 
5330b57cec5SDimitry Andric   // (3) Create the compound statement.
5340b57cec5SDimitry Andric   Stmt *Stmts[] = { B, CE };
5350b57cec5SDimitry Andric   CompoundStmt *CS = M.makeCompound(Stmts);
5360b57cec5SDimitry Andric 
5370b57cec5SDimitry Andric   // (4) Create the 'if' condition.
5380b57cec5SDimitry Andric   ImplicitCastExpr *LValToRval =
5390b57cec5SDimitry Andric     M.makeLvalueToRvalue(
5400b57cec5SDimitry Andric       M.makeDereference(
5410b57cec5SDimitry Andric         M.makeLvalueToRvalue(
5420b57cec5SDimitry Andric           M.makeDeclRefExpr(Predicate),
5430b57cec5SDimitry Andric           PredicateQPtrTy),
5440b57cec5SDimitry Andric         PredicateTy),
5450b57cec5SDimitry Andric     PredicateTy);
5460b57cec5SDimitry Andric 
5470b57cec5SDimitry Andric   Expr *GuardCondition = M.makeComparison(LValToRval, DoneValue, BO_NE);
5480b57cec5SDimitry Andric   // (5) Create the 'if' statement.
549349cc55cSDimitry Andric   auto *If = IfStmt::Create(C, SourceLocation(), IfStatementKind::Ordinary,
5500b57cec5SDimitry Andric                             /* Init=*/nullptr,
5510b57cec5SDimitry Andric                             /* Var=*/nullptr,
5520b57cec5SDimitry Andric                             /* Cond=*/GuardCondition,
553e8d8bef9SDimitry Andric                             /* LPL=*/SourceLocation(),
554e8d8bef9SDimitry Andric                             /* RPL=*/SourceLocation(),
5550b57cec5SDimitry Andric                             /* Then=*/CS);
5560b57cec5SDimitry Andric   return If;
5570b57cec5SDimitry Andric }
5580b57cec5SDimitry Andric 
5590b57cec5SDimitry Andric /// Create a fake body for dispatch_sync.
5600b57cec5SDimitry Andric static Stmt *create_dispatch_sync(ASTContext &C, const FunctionDecl *D) {
5610b57cec5SDimitry Andric   // Check if we have at least two parameters.
5620b57cec5SDimitry Andric   if (D->param_size() != 2)
5630b57cec5SDimitry Andric     return nullptr;
5640b57cec5SDimitry Andric 
5650b57cec5SDimitry Andric   // Check if the second parameter is a block.
5660b57cec5SDimitry Andric   const ParmVarDecl *PV = D->getParamDecl(1);
5670b57cec5SDimitry Andric   QualType Ty = PV->getType();
5680b57cec5SDimitry Andric   if (!isDispatchBlock(Ty))
5690b57cec5SDimitry Andric     return nullptr;
5700b57cec5SDimitry Andric 
5710b57cec5SDimitry Andric   // Everything checks out.  Create a fake body that just calls the block.
5720b57cec5SDimitry Andric   // This is basically just an AST dump of:
5730b57cec5SDimitry Andric   //
5740b57cec5SDimitry Andric   // void dispatch_sync(dispatch_queue_t queue, void (^block)(void)) {
5750b57cec5SDimitry Andric   //   block();
5760b57cec5SDimitry Andric   // }
5770b57cec5SDimitry Andric   //
5780b57cec5SDimitry Andric   ASTMaker M(C);
5790b57cec5SDimitry Andric   DeclRefExpr *DR = M.makeDeclRefExpr(PV);
5800b57cec5SDimitry Andric   ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty);
581fe6060f1SDimitry Andric   CallExpr *CE = CallExpr::Create(C, ICE, None, C.VoidTy, VK_PRValue,
582e8d8bef9SDimitry Andric                                   SourceLocation(), FPOptionsOverride());
5830b57cec5SDimitry Andric   return CE;
5840b57cec5SDimitry Andric }
5850b57cec5SDimitry Andric 
5860b57cec5SDimitry Andric static Stmt *create_OSAtomicCompareAndSwap(ASTContext &C, const FunctionDecl *D)
5870b57cec5SDimitry Andric {
5880b57cec5SDimitry Andric   // There are exactly 3 arguments.
5890b57cec5SDimitry Andric   if (D->param_size() != 3)
5900b57cec5SDimitry Andric     return nullptr;
5910b57cec5SDimitry Andric 
5920b57cec5SDimitry Andric   // Signature:
5930b57cec5SDimitry Andric   // _Bool OSAtomicCompareAndSwapPtr(void *__oldValue,
5940b57cec5SDimitry Andric   //                                 void *__newValue,
5950b57cec5SDimitry Andric   //                                 void * volatile *__theValue)
5960b57cec5SDimitry Andric   // Generate body:
5970b57cec5SDimitry Andric   //   if (oldValue == *theValue) {
5980b57cec5SDimitry Andric   //    *theValue = newValue;
5990b57cec5SDimitry Andric   //    return YES;
6000b57cec5SDimitry Andric   //   }
6010b57cec5SDimitry Andric   //   else return NO;
6020b57cec5SDimitry Andric 
6030b57cec5SDimitry Andric   QualType ResultTy = D->getReturnType();
6040b57cec5SDimitry Andric   bool isBoolean = ResultTy->isBooleanType();
6050b57cec5SDimitry Andric   if (!isBoolean && !ResultTy->isIntegralType(C))
6060b57cec5SDimitry Andric     return nullptr;
6070b57cec5SDimitry Andric 
6080b57cec5SDimitry Andric   const ParmVarDecl *OldValue = D->getParamDecl(0);
6090b57cec5SDimitry Andric   QualType OldValueTy = OldValue->getType();
6100b57cec5SDimitry Andric 
6110b57cec5SDimitry Andric   const ParmVarDecl *NewValue = D->getParamDecl(1);
6120b57cec5SDimitry Andric   QualType NewValueTy = NewValue->getType();
6130b57cec5SDimitry Andric 
6140b57cec5SDimitry Andric   assert(OldValueTy == NewValueTy);
6150b57cec5SDimitry Andric 
6160b57cec5SDimitry Andric   const ParmVarDecl *TheValue = D->getParamDecl(2);
6170b57cec5SDimitry Andric   QualType TheValueTy = TheValue->getType();
6180b57cec5SDimitry Andric   const PointerType *PT = TheValueTy->getAs<PointerType>();
6190b57cec5SDimitry Andric   if (!PT)
6200b57cec5SDimitry Andric     return nullptr;
6210b57cec5SDimitry Andric   QualType PointeeTy = PT->getPointeeType();
6220b57cec5SDimitry Andric 
6230b57cec5SDimitry Andric   ASTMaker M(C);
6240b57cec5SDimitry Andric   // Construct the comparison.
6250b57cec5SDimitry Andric   Expr *Comparison =
6260b57cec5SDimitry Andric     M.makeComparison(
6270b57cec5SDimitry Andric       M.makeLvalueToRvalue(M.makeDeclRefExpr(OldValue), OldValueTy),
6280b57cec5SDimitry Andric       M.makeLvalueToRvalue(
6290b57cec5SDimitry Andric         M.makeDereference(
6300b57cec5SDimitry Andric           M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
6310b57cec5SDimitry Andric           PointeeTy),
6320b57cec5SDimitry Andric         PointeeTy),
6330b57cec5SDimitry Andric       BO_EQ);
6340b57cec5SDimitry Andric 
6350b57cec5SDimitry Andric   // Construct the body of the IfStmt.
6360b57cec5SDimitry Andric   Stmt *Stmts[2];
6370b57cec5SDimitry Andric   Stmts[0] =
6380b57cec5SDimitry Andric     M.makeAssignment(
6390b57cec5SDimitry Andric       M.makeDereference(
6400b57cec5SDimitry Andric         M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
6410b57cec5SDimitry Andric         PointeeTy),
6420b57cec5SDimitry Andric       M.makeLvalueToRvalue(M.makeDeclRefExpr(NewValue), NewValueTy),
6430b57cec5SDimitry Andric       NewValueTy);
6440b57cec5SDimitry Andric 
6450b57cec5SDimitry Andric   Expr *BoolVal = M.makeObjCBool(true);
6460b57cec5SDimitry Andric   Expr *RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
6470b57cec5SDimitry Andric                            : M.makeIntegralCast(BoolVal, ResultTy);
6480b57cec5SDimitry Andric   Stmts[1] = M.makeReturn(RetVal);
6490b57cec5SDimitry Andric   CompoundStmt *Body = M.makeCompound(Stmts);
6500b57cec5SDimitry Andric 
6510b57cec5SDimitry Andric   // Construct the else clause.
6520b57cec5SDimitry Andric   BoolVal = M.makeObjCBool(false);
6530b57cec5SDimitry Andric   RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
6540b57cec5SDimitry Andric                      : M.makeIntegralCast(BoolVal, ResultTy);
6550b57cec5SDimitry Andric   Stmt *Else = M.makeReturn(RetVal);
6560b57cec5SDimitry Andric 
6570b57cec5SDimitry Andric   /// Construct the If.
658e8d8bef9SDimitry Andric   auto *If =
659349cc55cSDimitry Andric       IfStmt::Create(C, SourceLocation(), IfStatementKind::Ordinary,
6600b57cec5SDimitry Andric                      /* Init=*/nullptr,
661e8d8bef9SDimitry Andric                      /* Var=*/nullptr, Comparison,
662e8d8bef9SDimitry Andric                      /* LPL=*/SourceLocation(),
663e8d8bef9SDimitry Andric                      /* RPL=*/SourceLocation(), Body, SourceLocation(), Else);
6640b57cec5SDimitry Andric 
6650b57cec5SDimitry Andric   return If;
6660b57cec5SDimitry Andric }
6670b57cec5SDimitry Andric 
6680b57cec5SDimitry Andric Stmt *BodyFarm::getBody(const FunctionDecl *D) {
6690b57cec5SDimitry Andric   Optional<Stmt *> &Val = Bodies[D];
6700b57cec5SDimitry Andric   if (Val.hasValue())
6710b57cec5SDimitry Andric     return Val.getValue();
6720b57cec5SDimitry Andric 
6730b57cec5SDimitry Andric   Val = nullptr;
6740b57cec5SDimitry Andric 
6750b57cec5SDimitry Andric   if (D->getIdentifier() == nullptr)
6760b57cec5SDimitry Andric     return nullptr;
6770b57cec5SDimitry Andric 
6780b57cec5SDimitry Andric   StringRef Name = D->getName();
6790b57cec5SDimitry Andric   if (Name.empty())
6800b57cec5SDimitry Andric     return nullptr;
6810b57cec5SDimitry Andric 
6820b57cec5SDimitry Andric   FunctionFarmer FF;
6830b57cec5SDimitry Andric 
6840b57cec5SDimitry Andric   if (Name.startswith("OSAtomicCompareAndSwap") ||
6850b57cec5SDimitry Andric       Name.startswith("objc_atomicCompareAndSwap")) {
6860b57cec5SDimitry Andric     FF = create_OSAtomicCompareAndSwap;
6870b57cec5SDimitry Andric   } else if (Name == "call_once" && D->getDeclContext()->isStdNamespace()) {
6880b57cec5SDimitry Andric     FF = create_call_once;
6890b57cec5SDimitry Andric   } else {
6900b57cec5SDimitry Andric     FF = llvm::StringSwitch<FunctionFarmer>(Name)
6910b57cec5SDimitry Andric           .Case("dispatch_sync", create_dispatch_sync)
6920b57cec5SDimitry Andric           .Case("dispatch_once", create_dispatch_once)
6930b57cec5SDimitry Andric           .Default(nullptr);
6940b57cec5SDimitry Andric   }
6950b57cec5SDimitry Andric 
6960b57cec5SDimitry Andric   if (FF) { Val = FF(C, D); }
6970b57cec5SDimitry Andric   else if (Injector) { Val = Injector->getBody(D); }
6980b57cec5SDimitry Andric   return Val.getValue();
6990b57cec5SDimitry Andric }
7000b57cec5SDimitry Andric 
7010b57cec5SDimitry Andric static const ObjCIvarDecl *findBackingIvar(const ObjCPropertyDecl *Prop) {
7020b57cec5SDimitry Andric   const ObjCIvarDecl *IVar = Prop->getPropertyIvarDecl();
7030b57cec5SDimitry Andric 
7040b57cec5SDimitry Andric   if (IVar)
7050b57cec5SDimitry Andric     return IVar;
7060b57cec5SDimitry Andric 
7070b57cec5SDimitry Andric   // When a readonly property is shadowed in a class extensions with a
7080b57cec5SDimitry Andric   // a readwrite property, the instance variable belongs to the shadowing
7090b57cec5SDimitry Andric   // property rather than the shadowed property. If there is no instance
7100b57cec5SDimitry Andric   // variable on a readonly property, check to see whether the property is
7110b57cec5SDimitry Andric   // shadowed and if so try to get the instance variable from shadowing
7120b57cec5SDimitry Andric   // property.
7130b57cec5SDimitry Andric   if (!Prop->isReadOnly())
7140b57cec5SDimitry Andric     return nullptr;
7150b57cec5SDimitry Andric 
7160b57cec5SDimitry Andric   auto *Container = cast<ObjCContainerDecl>(Prop->getDeclContext());
7170b57cec5SDimitry Andric   const ObjCInterfaceDecl *PrimaryInterface = nullptr;
7180b57cec5SDimitry Andric   if (auto *InterfaceDecl = dyn_cast<ObjCInterfaceDecl>(Container)) {
7190b57cec5SDimitry Andric     PrimaryInterface = InterfaceDecl;
7200b57cec5SDimitry Andric   } else if (auto *CategoryDecl = dyn_cast<ObjCCategoryDecl>(Container)) {
7210b57cec5SDimitry Andric     PrimaryInterface = CategoryDecl->getClassInterface();
7220b57cec5SDimitry Andric   } else if (auto *ImplDecl = dyn_cast<ObjCImplDecl>(Container)) {
7230b57cec5SDimitry Andric     PrimaryInterface = ImplDecl->getClassInterface();
7240b57cec5SDimitry Andric   } else {
7250b57cec5SDimitry Andric     return nullptr;
7260b57cec5SDimitry Andric   }
7270b57cec5SDimitry Andric 
7280b57cec5SDimitry Andric   // FindPropertyVisibleInPrimaryClass() looks first in class extensions, so it
7290b57cec5SDimitry Andric   // is guaranteed to find the shadowing property, if it exists, rather than
7300b57cec5SDimitry Andric   // the shadowed property.
7310b57cec5SDimitry Andric   auto *ShadowingProp = PrimaryInterface->FindPropertyVisibleInPrimaryClass(
7320b57cec5SDimitry Andric       Prop->getIdentifier(), Prop->getQueryKind());
7330b57cec5SDimitry Andric   if (ShadowingProp && ShadowingProp != Prop) {
7340b57cec5SDimitry Andric     IVar = ShadowingProp->getPropertyIvarDecl();
7350b57cec5SDimitry Andric   }
7360b57cec5SDimitry Andric 
7370b57cec5SDimitry Andric   return IVar;
7380b57cec5SDimitry Andric }
7390b57cec5SDimitry Andric 
7400b57cec5SDimitry Andric static Stmt *createObjCPropertyGetter(ASTContext &Ctx,
741480093f4SDimitry Andric                                       const ObjCMethodDecl *MD) {
7420b57cec5SDimitry Andric   // First, find the backing ivar.
743480093f4SDimitry Andric   const ObjCIvarDecl *IVar = nullptr;
744fe6060f1SDimitry Andric   const ObjCPropertyDecl *Prop = nullptr;
745480093f4SDimitry Andric 
746480093f4SDimitry Andric   // Property accessor stubs sometimes do not correspond to any property decl
747480093f4SDimitry Andric   // in the current interface (but in a superclass). They still have a
748480093f4SDimitry Andric   // corresponding property impl decl in this case.
749480093f4SDimitry Andric   if (MD->isSynthesizedAccessorStub()) {
750480093f4SDimitry Andric     const ObjCInterfaceDecl *IntD = MD->getClassInterface();
751480093f4SDimitry Andric     const ObjCImplementationDecl *ImpD = IntD->getImplementation();
752480093f4SDimitry Andric     for (const auto *PI : ImpD->property_impls()) {
753fe6060f1SDimitry Andric       if (const ObjCPropertyDecl *Candidate = PI->getPropertyDecl()) {
754fe6060f1SDimitry Andric         if (Candidate->getGetterName() == MD->getSelector()) {
755fe6060f1SDimitry Andric           Prop = Candidate;
756fe6060f1SDimitry Andric           IVar = Prop->getPropertyIvarDecl();
757fe6060f1SDimitry Andric         }
758480093f4SDimitry Andric       }
759480093f4SDimitry Andric     }
760480093f4SDimitry Andric   }
761480093f4SDimitry Andric 
762480093f4SDimitry Andric   if (!IVar) {
763fe6060f1SDimitry Andric     Prop = MD->findPropertyDecl();
764480093f4SDimitry Andric     IVar = findBackingIvar(Prop);
765fe6060f1SDimitry Andric   }
766fe6060f1SDimitry Andric 
767fe6060f1SDimitry Andric   if (!IVar || !Prop)
7680b57cec5SDimitry Andric     return nullptr;
7690b57cec5SDimitry Andric 
7700b57cec5SDimitry Andric   // Ignore weak variables, which have special behavior.
7715ffd83dbSDimitry Andric   if (Prop->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak)
7720b57cec5SDimitry Andric     return nullptr;
7730b57cec5SDimitry Andric 
7740b57cec5SDimitry Andric   // Look to see if Sema has synthesized a body for us. This happens in
7750b57cec5SDimitry Andric   // Objective-C++ because the return value may be a C++ class type with a
7760b57cec5SDimitry Andric   // non-trivial copy constructor. We can only do this if we can find the
7770b57cec5SDimitry Andric   // @synthesize for this property, though (or if we know it's been auto-
7780b57cec5SDimitry Andric   // synthesized).
7790b57cec5SDimitry Andric   const ObjCImplementationDecl *ImplDecl =
7800b57cec5SDimitry Andric       IVar->getContainingInterface()->getImplementation();
7810b57cec5SDimitry Andric   if (ImplDecl) {
7820b57cec5SDimitry Andric     for (const auto *I : ImplDecl->property_impls()) {
7830b57cec5SDimitry Andric       if (I->getPropertyDecl() != Prop)
7840b57cec5SDimitry Andric         continue;
7850b57cec5SDimitry Andric 
7860b57cec5SDimitry Andric       if (I->getGetterCXXConstructor()) {
7870b57cec5SDimitry Andric         ASTMaker M(Ctx);
7880b57cec5SDimitry Andric         return M.makeReturn(I->getGetterCXXConstructor());
7890b57cec5SDimitry Andric       }
7900b57cec5SDimitry Andric     }
7910b57cec5SDimitry Andric   }
7920b57cec5SDimitry Andric 
7935e801ac6SDimitry Andric   // We expect that the property is the same type as the ivar, or a reference to
7945e801ac6SDimitry Andric   // it, and that it is either an object pointer or trivially copyable.
7950b57cec5SDimitry Andric   if (!Ctx.hasSameUnqualifiedType(IVar->getType(),
7960b57cec5SDimitry Andric                                   Prop->getType().getNonReferenceType()))
7970b57cec5SDimitry Andric     return nullptr;
7980b57cec5SDimitry Andric   if (!IVar->getType()->isObjCLifetimeType() &&
7990b57cec5SDimitry Andric       !IVar->getType().isTriviallyCopyableType(Ctx))
8000b57cec5SDimitry Andric     return nullptr;
8010b57cec5SDimitry Andric 
8020b57cec5SDimitry Andric   // Generate our body:
8030b57cec5SDimitry Andric   //   return self->_ivar;
8040b57cec5SDimitry Andric   ASTMaker M(Ctx);
8050b57cec5SDimitry Andric 
806480093f4SDimitry Andric   const VarDecl *selfVar = MD->getSelfDecl();
8070b57cec5SDimitry Andric   if (!selfVar)
8080b57cec5SDimitry Andric     return nullptr;
8090b57cec5SDimitry Andric 
810fe6060f1SDimitry Andric   Expr *loadedIVar = M.makeObjCIvarRef(
811fe6060f1SDimitry Andric       M.makeLvalueToRvalue(M.makeDeclRefExpr(selfVar), selfVar->getType()),
8120b57cec5SDimitry Andric       IVar);
8130b57cec5SDimitry Andric 
814480093f4SDimitry Andric   if (!MD->getReturnType()->isReferenceType())
8150b57cec5SDimitry Andric     loadedIVar = M.makeLvalueToRvalue(loadedIVar, IVar->getType());
8160b57cec5SDimitry Andric 
8170b57cec5SDimitry Andric   return M.makeReturn(loadedIVar);
8180b57cec5SDimitry Andric }
8190b57cec5SDimitry Andric 
8200b57cec5SDimitry Andric Stmt *BodyFarm::getBody(const ObjCMethodDecl *D) {
8210b57cec5SDimitry Andric   // We currently only know how to synthesize property accessors.
8220b57cec5SDimitry Andric   if (!D->isPropertyAccessor())
8230b57cec5SDimitry Andric     return nullptr;
8240b57cec5SDimitry Andric 
8250b57cec5SDimitry Andric   D = D->getCanonicalDecl();
8260b57cec5SDimitry Andric 
8270b57cec5SDimitry Andric   // We should not try to synthesize explicitly redefined accessors.
8280b57cec5SDimitry Andric   // We do not know for sure how they behave.
8290b57cec5SDimitry Andric   if (!D->isImplicit())
8300b57cec5SDimitry Andric     return nullptr;
8310b57cec5SDimitry Andric 
8320b57cec5SDimitry Andric   Optional<Stmt *> &Val = Bodies[D];
8330b57cec5SDimitry Andric   if (Val.hasValue())
8340b57cec5SDimitry Andric     return Val.getValue();
8350b57cec5SDimitry Andric   Val = nullptr;
8360b57cec5SDimitry Andric 
8370b57cec5SDimitry Andric   // For now, we only synthesize getters.
8380b57cec5SDimitry Andric   // Synthesizing setters would cause false negatives in the
8390b57cec5SDimitry Andric   // RetainCountChecker because the method body would bind the parameter
8400b57cec5SDimitry Andric   // to an instance variable, causing it to escape. This would prevent
8410b57cec5SDimitry Andric   // warning in the following common scenario:
8420b57cec5SDimitry Andric   //
8430b57cec5SDimitry Andric   //  id foo = [[NSObject alloc] init];
8440b57cec5SDimitry Andric   //  self.foo = foo; // We should warn that foo leaks here.
8450b57cec5SDimitry Andric   //
8460b57cec5SDimitry Andric   if (D->param_size() != 0)
8470b57cec5SDimitry Andric     return nullptr;
8480b57cec5SDimitry Andric 
849480093f4SDimitry Andric   // If the property was defined in an extension, search the extensions for
850480093f4SDimitry Andric   // overrides.
851480093f4SDimitry Andric   const ObjCInterfaceDecl *OID = D->getClassInterface();
852480093f4SDimitry Andric   if (dyn_cast<ObjCInterfaceDecl>(D->getParent()) != OID)
853480093f4SDimitry Andric     for (auto *Ext : OID->known_extensions()) {
854480093f4SDimitry Andric       auto *OMD = Ext->getInstanceMethod(D->getSelector());
855480093f4SDimitry Andric       if (OMD && !OMD->isImplicit())
856480093f4SDimitry Andric         return nullptr;
857480093f4SDimitry Andric     }
858480093f4SDimitry Andric 
859480093f4SDimitry Andric   Val = createObjCPropertyGetter(C, D);
8600b57cec5SDimitry Andric 
8610b57cec5SDimitry Andric   return Val.getValue();
8620b57cec5SDimitry Andric }
863