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"
2381ad6265SDimitry Andric #include "clang/Basic/Builtins.h"
240b57cec5SDimitry Andric #include "clang/Basic/OperatorKinds.h"
250b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
260b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
27bdd1243dSDimitry Andric #include <optional>
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric #define DEBUG_TYPE "body-farm"
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric using namespace clang;
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
340b57cec5SDimitry Andric // Helper creation functions for constructing faux ASTs.
350b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
360b57cec5SDimitry Andric 
isDispatchBlock(QualType Ty)370b57cec5SDimitry Andric static bool isDispatchBlock(QualType Ty) {
380b57cec5SDimitry Andric   // Is it a block pointer?
390b57cec5SDimitry Andric   const BlockPointerType *BPT = Ty->getAs<BlockPointerType>();
400b57cec5SDimitry Andric   if (!BPT)
410b57cec5SDimitry Andric     return false;
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric   // Check if the block pointer type takes no arguments and
440b57cec5SDimitry Andric   // returns void.
450b57cec5SDimitry Andric   const FunctionProtoType *FT =
460b57cec5SDimitry Andric   BPT->getPointeeType()->getAs<FunctionProtoType>();
470b57cec5SDimitry Andric   return FT && FT->getReturnType()->isVoidType() && FT->getNumParams() == 0;
480b57cec5SDimitry Andric }
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric namespace {
510b57cec5SDimitry Andric class ASTMaker {
520b57cec5SDimitry Andric public:
ASTMaker(ASTContext & C)530b57cec5SDimitry Andric   ASTMaker(ASTContext &C) : C(C) {}
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric   /// Create a new BinaryOperator representing a simple assignment.
560b57cec5SDimitry Andric   BinaryOperator *makeAssignment(const Expr *LHS, const Expr *RHS, QualType Ty);
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric   /// Create a new BinaryOperator representing a comparison.
590b57cec5SDimitry Andric   BinaryOperator *makeComparison(const Expr *LHS, const Expr *RHS,
600b57cec5SDimitry Andric                                  BinaryOperator::Opcode Op);
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric   /// Create a new compound stmt using the provided statements.
630b57cec5SDimitry Andric   CompoundStmt *makeCompound(ArrayRef<Stmt*>);
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric   /// Create a new DeclRefExpr for the referenced variable.
660b57cec5SDimitry Andric   DeclRefExpr *makeDeclRefExpr(const VarDecl *D,
670b57cec5SDimitry Andric                                bool RefersToEnclosingVariableOrCapture = false);
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric   /// Create a new UnaryOperator representing a dereference.
700b57cec5SDimitry Andric   UnaryOperator *makeDereference(const Expr *Arg, QualType Ty);
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric   /// Create an implicit cast for an integer conversion.
730b57cec5SDimitry Andric   Expr *makeIntegralCast(const Expr *Arg, QualType Ty);
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric   /// Create an implicit cast to a builtin boolean type.
760b57cec5SDimitry Andric   ImplicitCastExpr *makeIntegralCastToBoolean(const Expr *Arg);
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric   /// Create an implicit cast for lvalue-to-rvaluate conversions.
790b57cec5SDimitry Andric   ImplicitCastExpr *makeLvalueToRvalue(const Expr *Arg, QualType Ty);
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric   /// Make RValue out of variable declaration, creating a temporary
820b57cec5SDimitry Andric   /// DeclRefExpr in the process.
830b57cec5SDimitry Andric   ImplicitCastExpr *
840b57cec5SDimitry Andric   makeLvalueToRvalue(const VarDecl *Decl,
850b57cec5SDimitry Andric                      bool RefersToEnclosingVariableOrCapture = false);
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   /// Create an implicit cast of the given type.
880b57cec5SDimitry Andric   ImplicitCastExpr *makeImplicitCast(const Expr *Arg, QualType Ty,
890b57cec5SDimitry Andric                                      CastKind CK = CK_LValueToRValue);
900b57cec5SDimitry Andric 
9181ad6265SDimitry Andric   /// Create a cast to reference type.
9281ad6265SDimitry Andric   CastExpr *makeReferenceCast(const Expr *Arg, QualType Ty);
9381ad6265SDimitry Andric 
940b57cec5SDimitry Andric   /// Create an Objective-C bool literal.
950b57cec5SDimitry Andric   ObjCBoolLiteralExpr *makeObjCBool(bool Val);
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric   /// Create an Objective-C ivar reference.
980b57cec5SDimitry Andric   ObjCIvarRefExpr *makeObjCIvarRef(const Expr *Base, const ObjCIvarDecl *IVar);
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric   /// Create a Return statement.
1010b57cec5SDimitry Andric   ReturnStmt *makeReturn(const Expr *RetVal);
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric   /// Create an integer literal expression of the given type.
1040b57cec5SDimitry Andric   IntegerLiteral *makeIntegerLiteral(uint64_t Value, QualType Ty);
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric   /// Create a member expression.
1070b57cec5SDimitry Andric   MemberExpr *makeMemberExpression(Expr *base, ValueDecl *MemberDecl,
1080b57cec5SDimitry Andric                                    bool IsArrow = false,
1090b57cec5SDimitry Andric                                    ExprValueKind ValueKind = VK_LValue);
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric   /// Returns a *first* member field of a record declaration with a given name.
1120b57cec5SDimitry Andric   /// \return an nullptr if no member with such a name exists.
1130b57cec5SDimitry Andric   ValueDecl *findMemberField(const RecordDecl *RD, StringRef Name);
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric private:
1160b57cec5SDimitry Andric   ASTContext &C;
1170b57cec5SDimitry Andric };
1180b57cec5SDimitry Andric }
1190b57cec5SDimitry Andric 
makeAssignment(const Expr * LHS,const Expr * RHS,QualType Ty)1200b57cec5SDimitry Andric BinaryOperator *ASTMaker::makeAssignment(const Expr *LHS, const Expr *RHS,
1210b57cec5SDimitry Andric                                          QualType Ty) {
1225ffd83dbSDimitry Andric   return BinaryOperator::Create(
1235ffd83dbSDimitry Andric       C, const_cast<Expr *>(LHS), const_cast<Expr *>(RHS), BO_Assign, Ty,
124fe6060f1SDimitry Andric       VK_PRValue, OK_Ordinary, SourceLocation(), FPOptionsOverride());
1250b57cec5SDimitry Andric }
1260b57cec5SDimitry Andric 
makeComparison(const Expr * LHS,const Expr * RHS,BinaryOperator::Opcode Op)1270b57cec5SDimitry Andric BinaryOperator *ASTMaker::makeComparison(const Expr *LHS, const Expr *RHS,
1280b57cec5SDimitry Andric                                          BinaryOperator::Opcode Op) {
1290b57cec5SDimitry Andric   assert(BinaryOperator::isLogicalOp(Op) ||
1300b57cec5SDimitry Andric          BinaryOperator::isComparisonOp(Op));
1315ffd83dbSDimitry Andric   return BinaryOperator::Create(
1325ffd83dbSDimitry Andric       C, const_cast<Expr *>(LHS), const_cast<Expr *>(RHS), Op,
133fe6060f1SDimitry Andric       C.getLogicalOperationType(), VK_PRValue, OK_Ordinary, SourceLocation(),
1345ffd83dbSDimitry Andric       FPOptionsOverride());
1350b57cec5SDimitry Andric }
1360b57cec5SDimitry Andric 
makeCompound(ArrayRef<Stmt * > Stmts)1370b57cec5SDimitry Andric CompoundStmt *ASTMaker::makeCompound(ArrayRef<Stmt *> Stmts) {
13881ad6265SDimitry Andric   return CompoundStmt::Create(C, Stmts, FPOptionsOverride(), SourceLocation(),
13981ad6265SDimitry Andric                               SourceLocation());
1400b57cec5SDimitry Andric }
1410b57cec5SDimitry Andric 
makeDeclRefExpr(const VarDecl * D,bool RefersToEnclosingVariableOrCapture)1420b57cec5SDimitry Andric DeclRefExpr *ASTMaker::makeDeclRefExpr(
1430b57cec5SDimitry Andric     const VarDecl *D,
1440b57cec5SDimitry Andric     bool RefersToEnclosingVariableOrCapture) {
1450b57cec5SDimitry Andric   QualType Type = D->getType().getNonReferenceType();
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric   DeclRefExpr *DR = DeclRefExpr::Create(
1480b57cec5SDimitry Andric       C, NestedNameSpecifierLoc(), SourceLocation(), const_cast<VarDecl *>(D),
1490b57cec5SDimitry Andric       RefersToEnclosingVariableOrCapture, SourceLocation(), Type, VK_LValue);
1500b57cec5SDimitry Andric   return DR;
1510b57cec5SDimitry Andric }
1520b57cec5SDimitry Andric 
makeDereference(const Expr * Arg,QualType Ty)1530b57cec5SDimitry Andric UnaryOperator *ASTMaker::makeDereference(const Expr *Arg, QualType Ty) {
1545ffd83dbSDimitry Andric   return UnaryOperator::Create(C, const_cast<Expr *>(Arg), UO_Deref, Ty,
1550b57cec5SDimitry Andric                                VK_LValue, OK_Ordinary, SourceLocation(),
1565ffd83dbSDimitry Andric                                /*CanOverflow*/ false, FPOptionsOverride());
1570b57cec5SDimitry Andric }
1580b57cec5SDimitry Andric 
makeLvalueToRvalue(const Expr * Arg,QualType Ty)1590b57cec5SDimitry Andric ImplicitCastExpr *ASTMaker::makeLvalueToRvalue(const Expr *Arg, QualType Ty) {
1600b57cec5SDimitry Andric   return makeImplicitCast(Arg, Ty, CK_LValueToRValue);
1610b57cec5SDimitry Andric }
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric ImplicitCastExpr *
makeLvalueToRvalue(const VarDecl * Arg,bool RefersToEnclosingVariableOrCapture)1640b57cec5SDimitry Andric ASTMaker::makeLvalueToRvalue(const VarDecl *Arg,
1650b57cec5SDimitry Andric                              bool RefersToEnclosingVariableOrCapture) {
1660b57cec5SDimitry Andric   QualType Type = Arg->getType().getNonReferenceType();
1670b57cec5SDimitry Andric   return makeLvalueToRvalue(makeDeclRefExpr(Arg,
1680b57cec5SDimitry Andric                                             RefersToEnclosingVariableOrCapture),
1690b57cec5SDimitry Andric                             Type);
1700b57cec5SDimitry Andric }
1710b57cec5SDimitry Andric 
makeImplicitCast(const Expr * Arg,QualType Ty,CastKind CK)1720b57cec5SDimitry Andric ImplicitCastExpr *ASTMaker::makeImplicitCast(const Expr *Arg, QualType Ty,
1730b57cec5SDimitry Andric                                              CastKind CK) {
1740b57cec5SDimitry Andric   return ImplicitCastExpr::Create(C, Ty,
1750b57cec5SDimitry Andric                                   /* CastKind=*/CK,
1760b57cec5SDimitry Andric                                   /* Expr=*/const_cast<Expr *>(Arg),
1770b57cec5SDimitry Andric                                   /* CXXCastPath=*/nullptr,
178fe6060f1SDimitry Andric                                   /* ExprValueKind=*/VK_PRValue,
179e8d8bef9SDimitry Andric                                   /* FPFeatures */ FPOptionsOverride());
1800b57cec5SDimitry Andric }
1810b57cec5SDimitry Andric 
makeReferenceCast(const Expr * Arg,QualType Ty)18281ad6265SDimitry Andric CastExpr *ASTMaker::makeReferenceCast(const Expr *Arg, QualType Ty) {
18381ad6265SDimitry Andric   assert(Ty->isReferenceType());
18481ad6265SDimitry Andric   return CXXStaticCastExpr::Create(
18581ad6265SDimitry Andric       C, Ty.getNonReferenceType(),
18681ad6265SDimitry Andric       Ty->isLValueReferenceType() ? VK_LValue : VK_XValue, CK_NoOp,
18781ad6265SDimitry Andric       const_cast<Expr *>(Arg), /*CXXCastPath=*/nullptr,
18881ad6265SDimitry Andric       /*Written=*/C.getTrivialTypeSourceInfo(Ty), FPOptionsOverride(),
18981ad6265SDimitry Andric       SourceLocation(), SourceLocation(), SourceRange());
19081ad6265SDimitry Andric }
19181ad6265SDimitry Andric 
makeIntegralCast(const Expr * Arg,QualType Ty)1920b57cec5SDimitry Andric Expr *ASTMaker::makeIntegralCast(const Expr *Arg, QualType Ty) {
1930b57cec5SDimitry Andric   if (Arg->getType() == Ty)
1940b57cec5SDimitry Andric     return const_cast<Expr*>(Arg);
195e8d8bef9SDimitry Andric   return makeImplicitCast(Arg, Ty, CK_IntegralCast);
1960b57cec5SDimitry Andric }
1970b57cec5SDimitry Andric 
makeIntegralCastToBoolean(const Expr * Arg)1980b57cec5SDimitry Andric ImplicitCastExpr *ASTMaker::makeIntegralCastToBoolean(const Expr *Arg) {
199e8d8bef9SDimitry Andric   return makeImplicitCast(Arg, C.BoolTy, CK_IntegralToBoolean);
2000b57cec5SDimitry Andric }
2010b57cec5SDimitry Andric 
makeObjCBool(bool Val)2020b57cec5SDimitry Andric ObjCBoolLiteralExpr *ASTMaker::makeObjCBool(bool Val) {
2030b57cec5SDimitry Andric   QualType Ty = C.getBOOLDecl() ? C.getBOOLType() : C.ObjCBuiltinBoolTy;
2040b57cec5SDimitry Andric   return new (C) ObjCBoolLiteralExpr(Val, Ty, SourceLocation());
2050b57cec5SDimitry Andric }
2060b57cec5SDimitry Andric 
makeObjCIvarRef(const Expr * Base,const ObjCIvarDecl * IVar)2070b57cec5SDimitry Andric ObjCIvarRefExpr *ASTMaker::makeObjCIvarRef(const Expr *Base,
2080b57cec5SDimitry Andric                                            const ObjCIvarDecl *IVar) {
2090b57cec5SDimitry Andric   return new (C) ObjCIvarRefExpr(const_cast<ObjCIvarDecl*>(IVar),
2100b57cec5SDimitry Andric                                  IVar->getType(), SourceLocation(),
2110b57cec5SDimitry Andric                                  SourceLocation(), const_cast<Expr*>(Base),
2120b57cec5SDimitry Andric                                  /*arrow=*/true, /*free=*/false);
2130b57cec5SDimitry Andric }
2140b57cec5SDimitry Andric 
makeReturn(const Expr * RetVal)2150b57cec5SDimitry Andric ReturnStmt *ASTMaker::makeReturn(const Expr *RetVal) {
2160b57cec5SDimitry Andric   return ReturnStmt::Create(C, SourceLocation(), const_cast<Expr *>(RetVal),
2170b57cec5SDimitry Andric                             /* NRVOCandidate=*/nullptr);
2180b57cec5SDimitry Andric }
2190b57cec5SDimitry Andric 
makeIntegerLiteral(uint64_t Value,QualType Ty)2200b57cec5SDimitry Andric IntegerLiteral *ASTMaker::makeIntegerLiteral(uint64_t Value, QualType Ty) {
2210b57cec5SDimitry Andric   llvm::APInt APValue = llvm::APInt(C.getTypeSize(Ty), Value);
2220b57cec5SDimitry Andric   return IntegerLiteral::Create(C, APValue, Ty, SourceLocation());
2230b57cec5SDimitry Andric }
2240b57cec5SDimitry Andric 
makeMemberExpression(Expr * base,ValueDecl * MemberDecl,bool IsArrow,ExprValueKind ValueKind)2250b57cec5SDimitry Andric MemberExpr *ASTMaker::makeMemberExpression(Expr *base, ValueDecl *MemberDecl,
2260b57cec5SDimitry Andric                                            bool IsArrow,
2270b57cec5SDimitry Andric                                            ExprValueKind ValueKind) {
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric   DeclAccessPair FoundDecl = DeclAccessPair::make(MemberDecl, AS_public);
2300b57cec5SDimitry Andric   return MemberExpr::Create(
2310b57cec5SDimitry Andric       C, base, IsArrow, SourceLocation(), NestedNameSpecifierLoc(),
2320b57cec5SDimitry Andric       SourceLocation(), MemberDecl, FoundDecl,
2330b57cec5SDimitry Andric       DeclarationNameInfo(MemberDecl->getDeclName(), SourceLocation()),
2340b57cec5SDimitry Andric       /* TemplateArgumentListInfo=*/ nullptr, MemberDecl->getType(), ValueKind,
2350b57cec5SDimitry Andric       OK_Ordinary, NOUR_None);
2360b57cec5SDimitry Andric }
2370b57cec5SDimitry Andric 
findMemberField(const RecordDecl * RD,StringRef Name)2380b57cec5SDimitry Andric ValueDecl *ASTMaker::findMemberField(const RecordDecl *RD, StringRef Name) {
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric   CXXBasePaths Paths(
2410b57cec5SDimitry Andric       /* FindAmbiguities=*/false,
2420b57cec5SDimitry Andric       /* RecordPaths=*/false,
2430b57cec5SDimitry Andric       /* DetectVirtual=*/ false);
2440b57cec5SDimitry Andric   const IdentifierInfo &II = C.Idents.get(Name);
2450b57cec5SDimitry Andric   DeclarationName DeclName = C.DeclarationNames.getIdentifier(&II);
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric   DeclContextLookupResult Decls = RD->lookup(DeclName);
2480b57cec5SDimitry Andric   for (NamedDecl *FoundDecl : Decls)
2490b57cec5SDimitry Andric     if (!FoundDecl->getDeclContext()->isFunctionOrMethod())
2500b57cec5SDimitry Andric       return cast<ValueDecl>(FoundDecl);
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric   return nullptr;
2530b57cec5SDimitry Andric }
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
2560b57cec5SDimitry Andric // Creation functions for faux ASTs.
2570b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric typedef Stmt *(*FunctionFarmer)(ASTContext &C, const FunctionDecl *D);
2600b57cec5SDimitry Andric 
create_call_once_funcptr_call(ASTContext & C,ASTMaker M,const ParmVarDecl * Callback,ArrayRef<Expr * > CallArgs)2610b57cec5SDimitry Andric static CallExpr *create_call_once_funcptr_call(ASTContext &C, ASTMaker M,
2620b57cec5SDimitry Andric                                                const ParmVarDecl *Callback,
2630b57cec5SDimitry Andric                                                ArrayRef<Expr *> CallArgs) {
2640b57cec5SDimitry Andric 
2650b57cec5SDimitry Andric   QualType Ty = Callback->getType();
2660b57cec5SDimitry Andric   DeclRefExpr *Call = M.makeDeclRefExpr(Callback);
2670b57cec5SDimitry Andric   Expr *SubExpr;
2680b57cec5SDimitry Andric   if (Ty->isRValueReferenceType()) {
2690b57cec5SDimitry Andric     SubExpr = M.makeImplicitCast(
2700b57cec5SDimitry Andric         Call, Ty.getNonReferenceType(), CK_LValueToRValue);
2710b57cec5SDimitry Andric   } else if (Ty->isLValueReferenceType() &&
2720b57cec5SDimitry Andric              Call->getType()->isFunctionType()) {
2730b57cec5SDimitry Andric     Ty = C.getPointerType(Ty.getNonReferenceType());
2740b57cec5SDimitry Andric     SubExpr = M.makeImplicitCast(Call, Ty, CK_FunctionToPointerDecay);
2750b57cec5SDimitry Andric   } else if (Ty->isLValueReferenceType()
2760b57cec5SDimitry Andric              && Call->getType()->isPointerType()
2770b57cec5SDimitry Andric              && Call->getType()->getPointeeType()->isFunctionType()){
2780b57cec5SDimitry Andric     SubExpr = Call;
2790b57cec5SDimitry Andric   } else {
2800b57cec5SDimitry Andric     llvm_unreachable("Unexpected state");
2810b57cec5SDimitry Andric   }
2820b57cec5SDimitry Andric 
283fe6060f1SDimitry Andric   return CallExpr::Create(C, SubExpr, CallArgs, C.VoidTy, VK_PRValue,
284e8d8bef9SDimitry Andric                           SourceLocation(), FPOptionsOverride());
2850b57cec5SDimitry Andric }
2860b57cec5SDimitry Andric 
create_call_once_lambda_call(ASTContext & C,ASTMaker M,const ParmVarDecl * Callback,CXXRecordDecl * CallbackDecl,ArrayRef<Expr * > CallArgs)2870b57cec5SDimitry Andric static CallExpr *create_call_once_lambda_call(ASTContext &C, ASTMaker M,
2880b57cec5SDimitry Andric                                               const ParmVarDecl *Callback,
2890b57cec5SDimitry Andric                                               CXXRecordDecl *CallbackDecl,
2900b57cec5SDimitry Andric                                               ArrayRef<Expr *> CallArgs) {
2910b57cec5SDimitry Andric   assert(CallbackDecl != nullptr);
2920b57cec5SDimitry Andric   assert(CallbackDecl->isLambda());
2930b57cec5SDimitry Andric   FunctionDecl *callOperatorDecl = CallbackDecl->getLambdaCallOperator();
2940b57cec5SDimitry Andric   assert(callOperatorDecl != nullptr);
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric   DeclRefExpr *callOperatorDeclRef =
2970b57cec5SDimitry Andric       DeclRefExpr::Create(/* Ctx =*/ C,
2980b57cec5SDimitry Andric                           /* QualifierLoc =*/ NestedNameSpecifierLoc(),
2990b57cec5SDimitry Andric                           /* TemplateKWLoc =*/ SourceLocation(),
3000b57cec5SDimitry Andric                           const_cast<FunctionDecl *>(callOperatorDecl),
3010b57cec5SDimitry Andric                           /* RefersToEnclosingVariableOrCapture=*/ false,
3020b57cec5SDimitry Andric                           /* NameLoc =*/ SourceLocation(),
3030b57cec5SDimitry Andric                           /* T =*/ callOperatorDecl->getType(),
3040b57cec5SDimitry Andric                           /* VK =*/ VK_LValue);
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric   return CXXOperatorCallExpr::Create(
3070b57cec5SDimitry Andric       /*AstContext=*/C, OO_Call, callOperatorDeclRef,
3080b57cec5SDimitry Andric       /*Args=*/CallArgs,
3090b57cec5SDimitry Andric       /*QualType=*/C.VoidTy,
310fe6060f1SDimitry Andric       /*ExprValueType=*/VK_PRValue,
3115ffd83dbSDimitry Andric       /*SourceLocation=*/SourceLocation(),
3125ffd83dbSDimitry Andric       /*FPFeatures=*/FPOptionsOverride());
3130b57cec5SDimitry Andric }
3140b57cec5SDimitry Andric 
31581ad6265SDimitry Andric /// Create a fake body for 'std::move' or 'std::forward'. This is just:
31681ad6265SDimitry Andric ///
31781ad6265SDimitry Andric /// \code
31881ad6265SDimitry Andric /// return static_cast<return_type>(param);
31981ad6265SDimitry Andric /// \endcode
create_std_move_forward(ASTContext & C,const FunctionDecl * D)32081ad6265SDimitry Andric static Stmt *create_std_move_forward(ASTContext &C, const FunctionDecl *D) {
32181ad6265SDimitry Andric   LLVM_DEBUG(llvm::dbgs() << "Generating body for std::move / std::forward\n");
32281ad6265SDimitry Andric 
32381ad6265SDimitry Andric   ASTMaker M(C);
32481ad6265SDimitry Andric 
32581ad6265SDimitry Andric   QualType ReturnType = D->getType()->castAs<FunctionType>()->getReturnType();
32681ad6265SDimitry Andric   Expr *Param = M.makeDeclRefExpr(D->getParamDecl(0));
32781ad6265SDimitry Andric   Expr *Cast = M.makeReferenceCast(Param, ReturnType);
32881ad6265SDimitry Andric   return M.makeReturn(Cast);
32981ad6265SDimitry Andric }
33081ad6265SDimitry Andric 
3310b57cec5SDimitry Andric /// Create a fake body for std::call_once.
3320b57cec5SDimitry Andric /// Emulates the following function body:
3330b57cec5SDimitry Andric ///
3340b57cec5SDimitry Andric /// \code
3350b57cec5SDimitry Andric /// typedef struct once_flag_s {
3360b57cec5SDimitry Andric ///   unsigned long __state = 0;
3370b57cec5SDimitry Andric /// } once_flag;
3380b57cec5SDimitry Andric /// template<class Callable>
3390b57cec5SDimitry Andric /// void call_once(once_flag& o, Callable func) {
3400b57cec5SDimitry Andric ///   if (!o.__state) {
3410b57cec5SDimitry Andric ///     func();
3420b57cec5SDimitry Andric ///   }
3430b57cec5SDimitry Andric ///   o.__state = 1;
3440b57cec5SDimitry Andric /// }
3450b57cec5SDimitry Andric /// \endcode
create_call_once(ASTContext & C,const FunctionDecl * D)3460b57cec5SDimitry Andric static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) {
3470b57cec5SDimitry Andric   LLVM_DEBUG(llvm::dbgs() << "Generating body for call_once\n");
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric   // We need at least two parameters.
3500b57cec5SDimitry Andric   if (D->param_size() < 2)
3510b57cec5SDimitry Andric     return nullptr;
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric   ASTMaker M(C);
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric   const ParmVarDecl *Flag = D->getParamDecl(0);
3560b57cec5SDimitry Andric   const ParmVarDecl *Callback = D->getParamDecl(1);
3570b57cec5SDimitry Andric 
3580b57cec5SDimitry Andric   if (!Callback->getType()->isReferenceType()) {
3590b57cec5SDimitry Andric     llvm::dbgs() << "libcxx03 std::call_once implementation, skipping.\n";
3600b57cec5SDimitry Andric     return nullptr;
3610b57cec5SDimitry Andric   }
3620b57cec5SDimitry Andric   if (!Flag->getType()->isReferenceType()) {
3630b57cec5SDimitry Andric     llvm::dbgs() << "unknown std::call_once implementation, skipping.\n";
3640b57cec5SDimitry Andric     return nullptr;
3650b57cec5SDimitry Andric   }
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric   QualType CallbackType = Callback->getType().getNonReferenceType();
3680b57cec5SDimitry Andric 
3690b57cec5SDimitry Andric   // Nullable pointer, non-null iff function is a CXXRecordDecl.
3700b57cec5SDimitry Andric   CXXRecordDecl *CallbackRecordDecl = CallbackType->getAsCXXRecordDecl();
3710b57cec5SDimitry Andric   QualType FlagType = Flag->getType().getNonReferenceType();
3720b57cec5SDimitry Andric   auto *FlagRecordDecl = FlagType->getAsRecordDecl();
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric   if (!FlagRecordDecl) {
3750b57cec5SDimitry Andric     LLVM_DEBUG(llvm::dbgs() << "Flag field is not a record: "
3760b57cec5SDimitry Andric                             << "unknown std::call_once implementation, "
3770b57cec5SDimitry Andric                             << "ignoring the call.\n");
3780b57cec5SDimitry Andric     return nullptr;
3790b57cec5SDimitry Andric   }
3800b57cec5SDimitry Andric 
3810b57cec5SDimitry Andric   // We initially assume libc++ implementation of call_once,
3820b57cec5SDimitry Andric   // where the once_flag struct has a field `__state_`.
3830b57cec5SDimitry Andric   ValueDecl *FlagFieldDecl = M.findMemberField(FlagRecordDecl, "__state_");
3840b57cec5SDimitry Andric 
3850b57cec5SDimitry Andric   // Otherwise, try libstdc++ implementation, with a field
3860b57cec5SDimitry Andric   // `_M_once`
3870b57cec5SDimitry Andric   if (!FlagFieldDecl) {
3880b57cec5SDimitry Andric     FlagFieldDecl = M.findMemberField(FlagRecordDecl, "_M_once");
3890b57cec5SDimitry Andric   }
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric   if (!FlagFieldDecl) {
3920b57cec5SDimitry Andric     LLVM_DEBUG(llvm::dbgs() << "No field _M_once or __state_ found on "
3930b57cec5SDimitry Andric                             << "std::once_flag struct: unknown std::call_once "
3940b57cec5SDimitry Andric                             << "implementation, ignoring the call.");
3950b57cec5SDimitry Andric     return nullptr;
3960b57cec5SDimitry Andric   }
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric   bool isLambdaCall = CallbackRecordDecl && CallbackRecordDecl->isLambda();
3990b57cec5SDimitry Andric   if (CallbackRecordDecl && !isLambdaCall) {
4000b57cec5SDimitry Andric     LLVM_DEBUG(llvm::dbgs()
4010b57cec5SDimitry Andric                << "Not supported: synthesizing body for functors when "
4020b57cec5SDimitry Andric                << "body farming std::call_once, ignoring the call.");
4030b57cec5SDimitry Andric     return nullptr;
4040b57cec5SDimitry Andric   }
4050b57cec5SDimitry Andric 
4060b57cec5SDimitry Andric   SmallVector<Expr *, 5> CallArgs;
4070b57cec5SDimitry Andric   const FunctionProtoType *CallbackFunctionType;
4080b57cec5SDimitry Andric   if (isLambdaCall) {
4090b57cec5SDimitry Andric 
4100b57cec5SDimitry Andric     // Lambda requires callback itself inserted as a first parameter.
4110b57cec5SDimitry Andric     CallArgs.push_back(
4120b57cec5SDimitry Andric         M.makeDeclRefExpr(Callback,
4130b57cec5SDimitry Andric                           /* RefersToEnclosingVariableOrCapture=*/ true));
4140b57cec5SDimitry Andric     CallbackFunctionType = CallbackRecordDecl->getLambdaCallOperator()
4150b57cec5SDimitry Andric                                ->getType()
4160b57cec5SDimitry Andric                                ->getAs<FunctionProtoType>();
4170b57cec5SDimitry Andric   } else if (!CallbackType->getPointeeType().isNull()) {
4180b57cec5SDimitry Andric     CallbackFunctionType =
4190b57cec5SDimitry Andric         CallbackType->getPointeeType()->getAs<FunctionProtoType>();
4200b57cec5SDimitry Andric   } else {
4210b57cec5SDimitry Andric     CallbackFunctionType = CallbackType->getAs<FunctionProtoType>();
4220b57cec5SDimitry Andric   }
4230b57cec5SDimitry Andric 
4240b57cec5SDimitry Andric   if (!CallbackFunctionType)
4250b57cec5SDimitry Andric     return nullptr;
4260b57cec5SDimitry Andric 
4270b57cec5SDimitry Andric   // First two arguments are used for the flag and for the callback.
4280b57cec5SDimitry Andric   if (D->getNumParams() != CallbackFunctionType->getNumParams() + 2) {
4290b57cec5SDimitry Andric     LLVM_DEBUG(llvm::dbgs() << "Types of params of the callback do not match "
4300b57cec5SDimitry Andric                             << "params passed to std::call_once, "
4310b57cec5SDimitry Andric                             << "ignoring the call\n");
4320b57cec5SDimitry Andric     return nullptr;
4330b57cec5SDimitry Andric   }
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric   // All arguments past first two ones are passed to the callback,
4360b57cec5SDimitry Andric   // and we turn lvalues into rvalues if the argument is not passed by
4370b57cec5SDimitry Andric   // reference.
4380b57cec5SDimitry Andric   for (unsigned int ParamIdx = 2; ParamIdx < D->getNumParams(); ParamIdx++) {
4390b57cec5SDimitry Andric     const ParmVarDecl *PDecl = D->getParamDecl(ParamIdx);
440a7dea167SDimitry Andric     assert(PDecl);
441a7dea167SDimitry Andric     if (CallbackFunctionType->getParamType(ParamIdx - 2)
4420b57cec5SDimitry Andric                 .getNonReferenceType()
4430b57cec5SDimitry Andric                 .getCanonicalType() !=
4440b57cec5SDimitry Andric             PDecl->getType().getNonReferenceType().getCanonicalType()) {
4450b57cec5SDimitry Andric       LLVM_DEBUG(llvm::dbgs() << "Types of params of the callback do not match "
4460b57cec5SDimitry Andric                               << "params passed to std::call_once, "
4470b57cec5SDimitry Andric                               << "ignoring the call\n");
4480b57cec5SDimitry Andric       return nullptr;
4490b57cec5SDimitry Andric     }
4500b57cec5SDimitry Andric     Expr *ParamExpr = M.makeDeclRefExpr(PDecl);
4510b57cec5SDimitry Andric     if (!CallbackFunctionType->getParamType(ParamIdx - 2)->isReferenceType()) {
4520b57cec5SDimitry Andric       QualType PTy = PDecl->getType().getNonReferenceType();
4530b57cec5SDimitry Andric       ParamExpr = M.makeLvalueToRvalue(ParamExpr, PTy);
4540b57cec5SDimitry Andric     }
4550b57cec5SDimitry Andric     CallArgs.push_back(ParamExpr);
4560b57cec5SDimitry Andric   }
4570b57cec5SDimitry Andric 
4580b57cec5SDimitry Andric   CallExpr *CallbackCall;
4590b57cec5SDimitry Andric   if (isLambdaCall) {
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric     CallbackCall = create_call_once_lambda_call(C, M, Callback,
4620b57cec5SDimitry Andric                                                 CallbackRecordDecl, CallArgs);
4630b57cec5SDimitry Andric   } else {
4640b57cec5SDimitry Andric 
4650b57cec5SDimitry Andric     // Function pointer case.
4660b57cec5SDimitry Andric     CallbackCall = create_call_once_funcptr_call(C, M, Callback, CallArgs);
4670b57cec5SDimitry Andric   }
4680b57cec5SDimitry Andric 
4690b57cec5SDimitry Andric   DeclRefExpr *FlagDecl =
4700b57cec5SDimitry Andric       M.makeDeclRefExpr(Flag,
4710b57cec5SDimitry Andric                         /* RefersToEnclosingVariableOrCapture=*/true);
4720b57cec5SDimitry Andric 
4730b57cec5SDimitry Andric 
4740b57cec5SDimitry Andric   MemberExpr *Deref = M.makeMemberExpression(FlagDecl, FlagFieldDecl);
4750b57cec5SDimitry Andric   assert(Deref->isLValue());
4760b57cec5SDimitry Andric   QualType DerefType = Deref->getType();
4770b57cec5SDimitry Andric 
4780b57cec5SDimitry Andric   // Negation predicate.
4795ffd83dbSDimitry Andric   UnaryOperator *FlagCheck = UnaryOperator::Create(
4805ffd83dbSDimitry Andric       C,
4810b57cec5SDimitry Andric       /* input=*/
4820b57cec5SDimitry Andric       M.makeImplicitCast(M.makeLvalueToRvalue(Deref, DerefType), DerefType,
4830b57cec5SDimitry Andric                          CK_IntegralToBoolean),
4840b57cec5SDimitry Andric       /* opc=*/UO_LNot,
4850b57cec5SDimitry Andric       /* QualType=*/C.IntTy,
486fe6060f1SDimitry Andric       /* ExprValueKind=*/VK_PRValue,
4870b57cec5SDimitry Andric       /* ExprObjectKind=*/OK_Ordinary, SourceLocation(),
4885ffd83dbSDimitry Andric       /* CanOverflow*/ false, FPOptionsOverride());
4890b57cec5SDimitry Andric 
4900b57cec5SDimitry Andric   // Create assignment.
4910b57cec5SDimitry Andric   BinaryOperator *FlagAssignment = M.makeAssignment(
4920b57cec5SDimitry Andric       Deref, M.makeIntegralCast(M.makeIntegerLiteral(1, C.IntTy), DerefType),
4930b57cec5SDimitry Andric       DerefType);
4940b57cec5SDimitry Andric 
4950b57cec5SDimitry Andric   auto *Out =
496349cc55cSDimitry Andric       IfStmt::Create(C, SourceLocation(), IfStatementKind::Ordinary,
4970b57cec5SDimitry Andric                      /* Init=*/nullptr,
4980b57cec5SDimitry Andric                      /* Var=*/nullptr,
4990b57cec5SDimitry Andric                      /* Cond=*/FlagCheck,
500e8d8bef9SDimitry Andric                      /* LPL=*/SourceLocation(),
501e8d8bef9SDimitry Andric                      /* RPL=*/SourceLocation(),
5020b57cec5SDimitry Andric                      /* Then=*/M.makeCompound({CallbackCall, FlagAssignment}));
5030b57cec5SDimitry Andric 
5040b57cec5SDimitry Andric   return Out;
5050b57cec5SDimitry Andric }
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric /// Create a fake body for dispatch_once.
create_dispatch_once(ASTContext & C,const FunctionDecl * D)5080b57cec5SDimitry Andric static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
5090b57cec5SDimitry Andric   // Check if we have at least two parameters.
5100b57cec5SDimitry Andric   if (D->param_size() != 2)
5110b57cec5SDimitry Andric     return nullptr;
5120b57cec5SDimitry Andric 
5130b57cec5SDimitry Andric   // Check if the first parameter is a pointer to integer type.
5140b57cec5SDimitry Andric   const ParmVarDecl *Predicate = D->getParamDecl(0);
5150b57cec5SDimitry Andric   QualType PredicateQPtrTy = Predicate->getType();
5160b57cec5SDimitry Andric   const PointerType *PredicatePtrTy = PredicateQPtrTy->getAs<PointerType>();
5170b57cec5SDimitry Andric   if (!PredicatePtrTy)
5180b57cec5SDimitry Andric     return nullptr;
5190b57cec5SDimitry Andric   QualType PredicateTy = PredicatePtrTy->getPointeeType();
5200b57cec5SDimitry Andric   if (!PredicateTy->isIntegerType())
5210b57cec5SDimitry Andric     return nullptr;
5220b57cec5SDimitry Andric 
5230b57cec5SDimitry Andric   // Check if the second parameter is the proper block type.
5240b57cec5SDimitry Andric   const ParmVarDecl *Block = D->getParamDecl(1);
5250b57cec5SDimitry Andric   QualType Ty = Block->getType();
5260b57cec5SDimitry Andric   if (!isDispatchBlock(Ty))
5270b57cec5SDimitry Andric     return nullptr;
5280b57cec5SDimitry Andric 
5290b57cec5SDimitry Andric   // Everything checks out.  Create a fakse body that checks the predicate,
5300b57cec5SDimitry Andric   // sets it, and calls the block.  Basically, an AST dump of:
5310b57cec5SDimitry Andric   //
5320b57cec5SDimitry Andric   // void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block) {
5330b57cec5SDimitry Andric   //  if (*predicate != ~0l) {
5340b57cec5SDimitry Andric   //    *predicate = ~0l;
5350b57cec5SDimitry Andric   //    block();
5360b57cec5SDimitry Andric   //  }
5370b57cec5SDimitry Andric   // }
5380b57cec5SDimitry Andric 
5390b57cec5SDimitry Andric   ASTMaker M(C);
5400b57cec5SDimitry Andric 
5410b57cec5SDimitry Andric   // (1) Create the call.
5420b57cec5SDimitry Andric   CallExpr *CE = CallExpr::Create(
5430b57cec5SDimitry Andric       /*ASTContext=*/C,
5440b57cec5SDimitry Andric       /*StmtClass=*/M.makeLvalueToRvalue(/*Expr=*/Block),
545bdd1243dSDimitry Andric       /*Args=*/std::nullopt,
5460b57cec5SDimitry Andric       /*QualType=*/C.VoidTy,
547fe6060f1SDimitry Andric       /*ExprValueType=*/VK_PRValue,
548e8d8bef9SDimitry Andric       /*SourceLocation=*/SourceLocation(), FPOptionsOverride());
5490b57cec5SDimitry Andric 
5500b57cec5SDimitry Andric   // (2) Create the assignment to the predicate.
5510b57cec5SDimitry Andric   Expr *DoneValue =
5525ffd83dbSDimitry Andric       UnaryOperator::Create(C, M.makeIntegerLiteral(0, C.LongTy), UO_Not,
553fe6060f1SDimitry Andric                             C.LongTy, VK_PRValue, OK_Ordinary, SourceLocation(),
5545ffd83dbSDimitry Andric                             /*CanOverflow*/ false, FPOptionsOverride());
5550b57cec5SDimitry Andric 
5560b57cec5SDimitry Andric   BinaryOperator *B =
5570b57cec5SDimitry Andric     M.makeAssignment(
5580b57cec5SDimitry Andric        M.makeDereference(
5590b57cec5SDimitry Andric           M.makeLvalueToRvalue(
5600b57cec5SDimitry Andric             M.makeDeclRefExpr(Predicate), PredicateQPtrTy),
5610b57cec5SDimitry Andric             PredicateTy),
5620b57cec5SDimitry Andric        M.makeIntegralCast(DoneValue, PredicateTy),
5630b57cec5SDimitry Andric        PredicateTy);
5640b57cec5SDimitry Andric 
5650b57cec5SDimitry Andric   // (3) Create the compound statement.
5660b57cec5SDimitry Andric   Stmt *Stmts[] = { B, CE };
5670b57cec5SDimitry Andric   CompoundStmt *CS = M.makeCompound(Stmts);
5680b57cec5SDimitry Andric 
5690b57cec5SDimitry Andric   // (4) Create the 'if' condition.
5700b57cec5SDimitry Andric   ImplicitCastExpr *LValToRval =
5710b57cec5SDimitry Andric     M.makeLvalueToRvalue(
5720b57cec5SDimitry Andric       M.makeDereference(
5730b57cec5SDimitry Andric         M.makeLvalueToRvalue(
5740b57cec5SDimitry Andric           M.makeDeclRefExpr(Predicate),
5750b57cec5SDimitry Andric           PredicateQPtrTy),
5760b57cec5SDimitry Andric         PredicateTy),
5770b57cec5SDimitry Andric     PredicateTy);
5780b57cec5SDimitry Andric 
5790b57cec5SDimitry Andric   Expr *GuardCondition = M.makeComparison(LValToRval, DoneValue, BO_NE);
5800b57cec5SDimitry Andric   // (5) Create the 'if' statement.
581349cc55cSDimitry Andric   auto *If = IfStmt::Create(C, SourceLocation(), IfStatementKind::Ordinary,
5820b57cec5SDimitry Andric                             /* Init=*/nullptr,
5830b57cec5SDimitry Andric                             /* Var=*/nullptr,
5840b57cec5SDimitry Andric                             /* Cond=*/GuardCondition,
585e8d8bef9SDimitry Andric                             /* LPL=*/SourceLocation(),
586e8d8bef9SDimitry Andric                             /* RPL=*/SourceLocation(),
5870b57cec5SDimitry Andric                             /* Then=*/CS);
5880b57cec5SDimitry Andric   return If;
5890b57cec5SDimitry Andric }
5900b57cec5SDimitry Andric 
5910b57cec5SDimitry Andric /// Create a fake body for dispatch_sync.
create_dispatch_sync(ASTContext & C,const FunctionDecl * D)5920b57cec5SDimitry Andric static Stmt *create_dispatch_sync(ASTContext &C, const FunctionDecl *D) {
5930b57cec5SDimitry Andric   // Check if we have at least two parameters.
5940b57cec5SDimitry Andric   if (D->param_size() != 2)
5950b57cec5SDimitry Andric     return nullptr;
5960b57cec5SDimitry Andric 
5970b57cec5SDimitry Andric   // Check if the second parameter is a block.
5980b57cec5SDimitry Andric   const ParmVarDecl *PV = D->getParamDecl(1);
5990b57cec5SDimitry Andric   QualType Ty = PV->getType();
6000b57cec5SDimitry Andric   if (!isDispatchBlock(Ty))
6010b57cec5SDimitry Andric     return nullptr;
6020b57cec5SDimitry Andric 
6030b57cec5SDimitry Andric   // Everything checks out.  Create a fake body that just calls the block.
6040b57cec5SDimitry Andric   // This is basically just an AST dump of:
6050b57cec5SDimitry Andric   //
6060b57cec5SDimitry Andric   // void dispatch_sync(dispatch_queue_t queue, void (^block)(void)) {
6070b57cec5SDimitry Andric   //   block();
6080b57cec5SDimitry Andric   // }
6090b57cec5SDimitry Andric   //
6100b57cec5SDimitry Andric   ASTMaker M(C);
6110b57cec5SDimitry Andric   DeclRefExpr *DR = M.makeDeclRefExpr(PV);
6120b57cec5SDimitry Andric   ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty);
613bdd1243dSDimitry Andric   CallExpr *CE = CallExpr::Create(C, ICE, std::nullopt, C.VoidTy, VK_PRValue,
614e8d8bef9SDimitry Andric                                   SourceLocation(), FPOptionsOverride());
6150b57cec5SDimitry Andric   return CE;
6160b57cec5SDimitry Andric }
6170b57cec5SDimitry Andric 
create_OSAtomicCompareAndSwap(ASTContext & C,const FunctionDecl * D)6180b57cec5SDimitry Andric static Stmt *create_OSAtomicCompareAndSwap(ASTContext &C, const FunctionDecl *D)
6190b57cec5SDimitry Andric {
6200b57cec5SDimitry Andric   // There are exactly 3 arguments.
6210b57cec5SDimitry Andric   if (D->param_size() != 3)
6220b57cec5SDimitry Andric     return nullptr;
6230b57cec5SDimitry Andric 
6240b57cec5SDimitry Andric   // Signature:
6250b57cec5SDimitry Andric   // _Bool OSAtomicCompareAndSwapPtr(void *__oldValue,
6260b57cec5SDimitry Andric   //                                 void *__newValue,
6270b57cec5SDimitry Andric   //                                 void * volatile *__theValue)
6280b57cec5SDimitry Andric   // Generate body:
6290b57cec5SDimitry Andric   //   if (oldValue == *theValue) {
6300b57cec5SDimitry Andric   //    *theValue = newValue;
6310b57cec5SDimitry Andric   //    return YES;
6320b57cec5SDimitry Andric   //   }
6330b57cec5SDimitry Andric   //   else return NO;
6340b57cec5SDimitry Andric 
6350b57cec5SDimitry Andric   QualType ResultTy = D->getReturnType();
6360b57cec5SDimitry Andric   bool isBoolean = ResultTy->isBooleanType();
6370b57cec5SDimitry Andric   if (!isBoolean && !ResultTy->isIntegralType(C))
6380b57cec5SDimitry Andric     return nullptr;
6390b57cec5SDimitry Andric 
6400b57cec5SDimitry Andric   const ParmVarDecl *OldValue = D->getParamDecl(0);
6410b57cec5SDimitry Andric   QualType OldValueTy = OldValue->getType();
6420b57cec5SDimitry Andric 
6430b57cec5SDimitry Andric   const ParmVarDecl *NewValue = D->getParamDecl(1);
6440b57cec5SDimitry Andric   QualType NewValueTy = NewValue->getType();
6450b57cec5SDimitry Andric 
6460b57cec5SDimitry Andric   assert(OldValueTy == NewValueTy);
6470b57cec5SDimitry Andric 
6480b57cec5SDimitry Andric   const ParmVarDecl *TheValue = D->getParamDecl(2);
6490b57cec5SDimitry Andric   QualType TheValueTy = TheValue->getType();
6500b57cec5SDimitry Andric   const PointerType *PT = TheValueTy->getAs<PointerType>();
6510b57cec5SDimitry Andric   if (!PT)
6520b57cec5SDimitry Andric     return nullptr;
6530b57cec5SDimitry Andric   QualType PointeeTy = PT->getPointeeType();
6540b57cec5SDimitry Andric 
6550b57cec5SDimitry Andric   ASTMaker M(C);
6560b57cec5SDimitry Andric   // Construct the comparison.
6570b57cec5SDimitry Andric   Expr *Comparison =
6580b57cec5SDimitry Andric     M.makeComparison(
6590b57cec5SDimitry Andric       M.makeLvalueToRvalue(M.makeDeclRefExpr(OldValue), OldValueTy),
6600b57cec5SDimitry Andric       M.makeLvalueToRvalue(
6610b57cec5SDimitry Andric         M.makeDereference(
6620b57cec5SDimitry Andric           M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
6630b57cec5SDimitry Andric           PointeeTy),
6640b57cec5SDimitry Andric         PointeeTy),
6650b57cec5SDimitry Andric       BO_EQ);
6660b57cec5SDimitry Andric 
6670b57cec5SDimitry Andric   // Construct the body of the IfStmt.
6680b57cec5SDimitry Andric   Stmt *Stmts[2];
6690b57cec5SDimitry Andric   Stmts[0] =
6700b57cec5SDimitry Andric     M.makeAssignment(
6710b57cec5SDimitry Andric       M.makeDereference(
6720b57cec5SDimitry Andric         M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
6730b57cec5SDimitry Andric         PointeeTy),
6740b57cec5SDimitry Andric       M.makeLvalueToRvalue(M.makeDeclRefExpr(NewValue), NewValueTy),
6750b57cec5SDimitry Andric       NewValueTy);
6760b57cec5SDimitry Andric 
6770b57cec5SDimitry Andric   Expr *BoolVal = M.makeObjCBool(true);
6780b57cec5SDimitry Andric   Expr *RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
6790b57cec5SDimitry Andric                            : M.makeIntegralCast(BoolVal, ResultTy);
6800b57cec5SDimitry Andric   Stmts[1] = M.makeReturn(RetVal);
6810b57cec5SDimitry Andric   CompoundStmt *Body = M.makeCompound(Stmts);
6820b57cec5SDimitry Andric 
6830b57cec5SDimitry Andric   // Construct the else clause.
6840b57cec5SDimitry Andric   BoolVal = M.makeObjCBool(false);
6850b57cec5SDimitry Andric   RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
6860b57cec5SDimitry Andric                      : M.makeIntegralCast(BoolVal, ResultTy);
6870b57cec5SDimitry Andric   Stmt *Else = M.makeReturn(RetVal);
6880b57cec5SDimitry Andric 
6890b57cec5SDimitry Andric   /// Construct the If.
690e8d8bef9SDimitry Andric   auto *If =
691349cc55cSDimitry Andric       IfStmt::Create(C, SourceLocation(), IfStatementKind::Ordinary,
6920b57cec5SDimitry Andric                      /* Init=*/nullptr,
693e8d8bef9SDimitry Andric                      /* Var=*/nullptr, Comparison,
694e8d8bef9SDimitry Andric                      /* LPL=*/SourceLocation(),
695e8d8bef9SDimitry Andric                      /* RPL=*/SourceLocation(), Body, SourceLocation(), Else);
6960b57cec5SDimitry Andric 
6970b57cec5SDimitry Andric   return If;
6980b57cec5SDimitry Andric }
6990b57cec5SDimitry Andric 
getBody(const FunctionDecl * D)7000b57cec5SDimitry Andric Stmt *BodyFarm::getBody(const FunctionDecl *D) {
701bdd1243dSDimitry Andric   std::optional<Stmt *> &Val = Bodies[D];
70281ad6265SDimitry Andric   if (Val)
703bdd1243dSDimitry Andric     return *Val;
7040b57cec5SDimitry Andric 
7050b57cec5SDimitry Andric   Val = nullptr;
7060b57cec5SDimitry Andric 
7070b57cec5SDimitry Andric   if (D->getIdentifier() == nullptr)
7080b57cec5SDimitry Andric     return nullptr;
7090b57cec5SDimitry Andric 
7100b57cec5SDimitry Andric   StringRef Name = D->getName();
7110b57cec5SDimitry Andric   if (Name.empty())
7120b57cec5SDimitry Andric     return nullptr;
7130b57cec5SDimitry Andric 
7140b57cec5SDimitry Andric   FunctionFarmer FF;
7150b57cec5SDimitry Andric 
71681ad6265SDimitry Andric   if (unsigned BuiltinID = D->getBuiltinID()) {
71781ad6265SDimitry Andric     switch (BuiltinID) {
71881ad6265SDimitry Andric     case Builtin::BIas_const:
71981ad6265SDimitry Andric     case Builtin::BIforward:
72006c3fb27SDimitry Andric     case Builtin::BIforward_like:
72181ad6265SDimitry Andric     case Builtin::BImove:
72281ad6265SDimitry Andric     case Builtin::BImove_if_noexcept:
72381ad6265SDimitry Andric       FF = create_std_move_forward;
72481ad6265SDimitry Andric       break;
72581ad6265SDimitry Andric     default:
72681ad6265SDimitry Andric       FF = nullptr;
72781ad6265SDimitry Andric       break;
72881ad6265SDimitry Andric     }
7295f757f3fSDimitry Andric   } else if (Name.starts_with("OSAtomicCompareAndSwap") ||
7305f757f3fSDimitry Andric              Name.starts_with("objc_atomicCompareAndSwap")) {
7310b57cec5SDimitry Andric     FF = create_OSAtomicCompareAndSwap;
7320b57cec5SDimitry Andric   } else if (Name == "call_once" && D->getDeclContext()->isStdNamespace()) {
7330b57cec5SDimitry Andric     FF = create_call_once;
7340b57cec5SDimitry Andric   } else {
7350b57cec5SDimitry Andric     FF = llvm::StringSwitch<FunctionFarmer>(Name)
7360b57cec5SDimitry Andric           .Case("dispatch_sync", create_dispatch_sync)
7370b57cec5SDimitry Andric           .Case("dispatch_once", create_dispatch_once)
7380b57cec5SDimitry Andric           .Default(nullptr);
7390b57cec5SDimitry Andric   }
7400b57cec5SDimitry Andric 
7410b57cec5SDimitry Andric   if (FF) { Val = FF(C, D); }
7420b57cec5SDimitry Andric   else if (Injector) { Val = Injector->getBody(D); }
74381ad6265SDimitry Andric   return *Val;
7440b57cec5SDimitry Andric }
7450b57cec5SDimitry Andric 
findBackingIvar(const ObjCPropertyDecl * Prop)7460b57cec5SDimitry Andric static const ObjCIvarDecl *findBackingIvar(const ObjCPropertyDecl *Prop) {
7470b57cec5SDimitry Andric   const ObjCIvarDecl *IVar = Prop->getPropertyIvarDecl();
7480b57cec5SDimitry Andric 
7490b57cec5SDimitry Andric   if (IVar)
7500b57cec5SDimitry Andric     return IVar;
7510b57cec5SDimitry Andric 
7520b57cec5SDimitry Andric   // When a readonly property is shadowed in a class extensions with a
7530b57cec5SDimitry Andric   // a readwrite property, the instance variable belongs to the shadowing
7540b57cec5SDimitry Andric   // property rather than the shadowed property. If there is no instance
7550b57cec5SDimitry Andric   // variable on a readonly property, check to see whether the property is
7560b57cec5SDimitry Andric   // shadowed and if so try to get the instance variable from shadowing
7570b57cec5SDimitry Andric   // property.
7580b57cec5SDimitry Andric   if (!Prop->isReadOnly())
7590b57cec5SDimitry Andric     return nullptr;
7600b57cec5SDimitry Andric 
7610b57cec5SDimitry Andric   auto *Container = cast<ObjCContainerDecl>(Prop->getDeclContext());
7620b57cec5SDimitry Andric   const ObjCInterfaceDecl *PrimaryInterface = nullptr;
7630b57cec5SDimitry Andric   if (auto *InterfaceDecl = dyn_cast<ObjCInterfaceDecl>(Container)) {
7640b57cec5SDimitry Andric     PrimaryInterface = InterfaceDecl;
7650b57cec5SDimitry Andric   } else if (auto *CategoryDecl = dyn_cast<ObjCCategoryDecl>(Container)) {
7660b57cec5SDimitry Andric     PrimaryInterface = CategoryDecl->getClassInterface();
7670b57cec5SDimitry Andric   } else if (auto *ImplDecl = dyn_cast<ObjCImplDecl>(Container)) {
7680b57cec5SDimitry Andric     PrimaryInterface = ImplDecl->getClassInterface();
7690b57cec5SDimitry Andric   } else {
7700b57cec5SDimitry Andric     return nullptr;
7710b57cec5SDimitry Andric   }
7720b57cec5SDimitry Andric 
7730b57cec5SDimitry Andric   // FindPropertyVisibleInPrimaryClass() looks first in class extensions, so it
7740b57cec5SDimitry Andric   // is guaranteed to find the shadowing property, if it exists, rather than
7750b57cec5SDimitry Andric   // the shadowed property.
7760b57cec5SDimitry Andric   auto *ShadowingProp = PrimaryInterface->FindPropertyVisibleInPrimaryClass(
7770b57cec5SDimitry Andric       Prop->getIdentifier(), Prop->getQueryKind());
7780b57cec5SDimitry Andric   if (ShadowingProp && ShadowingProp != Prop) {
7790b57cec5SDimitry Andric     IVar = ShadowingProp->getPropertyIvarDecl();
7800b57cec5SDimitry Andric   }
7810b57cec5SDimitry Andric 
7820b57cec5SDimitry Andric   return IVar;
7830b57cec5SDimitry Andric }
7840b57cec5SDimitry Andric 
createObjCPropertyGetter(ASTContext & Ctx,const ObjCMethodDecl * MD)7850b57cec5SDimitry Andric static Stmt *createObjCPropertyGetter(ASTContext &Ctx,
786480093f4SDimitry Andric                                       const ObjCMethodDecl *MD) {
7870b57cec5SDimitry Andric   // First, find the backing ivar.
788480093f4SDimitry Andric   const ObjCIvarDecl *IVar = nullptr;
789fe6060f1SDimitry Andric   const ObjCPropertyDecl *Prop = nullptr;
790480093f4SDimitry Andric 
791480093f4SDimitry Andric   // Property accessor stubs sometimes do not correspond to any property decl
792480093f4SDimitry Andric   // in the current interface (but in a superclass). They still have a
793480093f4SDimitry Andric   // corresponding property impl decl in this case.
794480093f4SDimitry Andric   if (MD->isSynthesizedAccessorStub()) {
795480093f4SDimitry Andric     const ObjCInterfaceDecl *IntD = MD->getClassInterface();
796480093f4SDimitry Andric     const ObjCImplementationDecl *ImpD = IntD->getImplementation();
797480093f4SDimitry Andric     for (const auto *PI : ImpD->property_impls()) {
798fe6060f1SDimitry Andric       if (const ObjCPropertyDecl *Candidate = PI->getPropertyDecl()) {
799fe6060f1SDimitry Andric         if (Candidate->getGetterName() == MD->getSelector()) {
800fe6060f1SDimitry Andric           Prop = Candidate;
801fe6060f1SDimitry Andric           IVar = Prop->getPropertyIvarDecl();
802fe6060f1SDimitry Andric         }
803480093f4SDimitry Andric       }
804480093f4SDimitry Andric     }
805480093f4SDimitry Andric   }
806480093f4SDimitry Andric 
807480093f4SDimitry Andric   if (!IVar) {
808fe6060f1SDimitry Andric     Prop = MD->findPropertyDecl();
8095f757f3fSDimitry Andric     IVar = Prop ? findBackingIvar(Prop) : nullptr;
810fe6060f1SDimitry Andric   }
811fe6060f1SDimitry Andric 
812fe6060f1SDimitry Andric   if (!IVar || !Prop)
8130b57cec5SDimitry Andric     return nullptr;
8140b57cec5SDimitry Andric 
8150b57cec5SDimitry Andric   // Ignore weak variables, which have special behavior.
8165ffd83dbSDimitry Andric   if (Prop->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak)
8170b57cec5SDimitry Andric     return nullptr;
8180b57cec5SDimitry Andric 
8190b57cec5SDimitry Andric   // Look to see if Sema has synthesized a body for us. This happens in
8200b57cec5SDimitry Andric   // Objective-C++ because the return value may be a C++ class type with a
8210b57cec5SDimitry Andric   // non-trivial copy constructor. We can only do this if we can find the
8220b57cec5SDimitry Andric   // @synthesize for this property, though (or if we know it's been auto-
8230b57cec5SDimitry Andric   // synthesized).
8240b57cec5SDimitry Andric   const ObjCImplementationDecl *ImplDecl =
8250b57cec5SDimitry Andric       IVar->getContainingInterface()->getImplementation();
8260b57cec5SDimitry Andric   if (ImplDecl) {
8270b57cec5SDimitry Andric     for (const auto *I : ImplDecl->property_impls()) {
8280b57cec5SDimitry Andric       if (I->getPropertyDecl() != Prop)
8290b57cec5SDimitry Andric         continue;
8300b57cec5SDimitry Andric 
8310b57cec5SDimitry Andric       if (I->getGetterCXXConstructor()) {
8320b57cec5SDimitry Andric         ASTMaker M(Ctx);
8330b57cec5SDimitry Andric         return M.makeReturn(I->getGetterCXXConstructor());
8340b57cec5SDimitry Andric       }
8350b57cec5SDimitry Andric     }
8360b57cec5SDimitry Andric   }
8370b57cec5SDimitry Andric 
8385e801ac6SDimitry Andric   // We expect that the property is the same type as the ivar, or a reference to
8395e801ac6SDimitry Andric   // it, and that it is either an object pointer or trivially copyable.
8400b57cec5SDimitry Andric   if (!Ctx.hasSameUnqualifiedType(IVar->getType(),
8410b57cec5SDimitry Andric                                   Prop->getType().getNonReferenceType()))
8420b57cec5SDimitry Andric     return nullptr;
8430b57cec5SDimitry Andric   if (!IVar->getType()->isObjCLifetimeType() &&
8440b57cec5SDimitry Andric       !IVar->getType().isTriviallyCopyableType(Ctx))
8450b57cec5SDimitry Andric     return nullptr;
8460b57cec5SDimitry Andric 
8470b57cec5SDimitry Andric   // Generate our body:
8480b57cec5SDimitry Andric   //   return self->_ivar;
8490b57cec5SDimitry Andric   ASTMaker M(Ctx);
8500b57cec5SDimitry Andric 
851480093f4SDimitry Andric   const VarDecl *selfVar = MD->getSelfDecl();
8520b57cec5SDimitry Andric   if (!selfVar)
8530b57cec5SDimitry Andric     return nullptr;
8540b57cec5SDimitry Andric 
855fe6060f1SDimitry Andric   Expr *loadedIVar = M.makeObjCIvarRef(
856fe6060f1SDimitry Andric       M.makeLvalueToRvalue(M.makeDeclRefExpr(selfVar), selfVar->getType()),
8570b57cec5SDimitry Andric       IVar);
8580b57cec5SDimitry Andric 
859480093f4SDimitry Andric   if (!MD->getReturnType()->isReferenceType())
8600b57cec5SDimitry Andric     loadedIVar = M.makeLvalueToRvalue(loadedIVar, IVar->getType());
8610b57cec5SDimitry Andric 
8620b57cec5SDimitry Andric   return M.makeReturn(loadedIVar);
8630b57cec5SDimitry Andric }
8640b57cec5SDimitry Andric 
getBody(const ObjCMethodDecl * D)8650b57cec5SDimitry Andric Stmt *BodyFarm::getBody(const ObjCMethodDecl *D) {
8660b57cec5SDimitry Andric   // We currently only know how to synthesize property accessors.
8670b57cec5SDimitry Andric   if (!D->isPropertyAccessor())
8680b57cec5SDimitry Andric     return nullptr;
8690b57cec5SDimitry Andric 
8700b57cec5SDimitry Andric   D = D->getCanonicalDecl();
8710b57cec5SDimitry Andric 
8720b57cec5SDimitry Andric   // We should not try to synthesize explicitly redefined accessors.
8730b57cec5SDimitry Andric   // We do not know for sure how they behave.
8740b57cec5SDimitry Andric   if (!D->isImplicit())
8750b57cec5SDimitry Andric     return nullptr;
8760b57cec5SDimitry Andric 
877bdd1243dSDimitry Andric   std::optional<Stmt *> &Val = Bodies[D];
87881ad6265SDimitry Andric   if (Val)
879bdd1243dSDimitry Andric     return *Val;
8800b57cec5SDimitry Andric   Val = nullptr;
8810b57cec5SDimitry Andric 
8820b57cec5SDimitry Andric   // For now, we only synthesize getters.
8830b57cec5SDimitry Andric   // Synthesizing setters would cause false negatives in the
8840b57cec5SDimitry Andric   // RetainCountChecker because the method body would bind the parameter
8850b57cec5SDimitry Andric   // to an instance variable, causing it to escape. This would prevent
8860b57cec5SDimitry Andric   // warning in the following common scenario:
8870b57cec5SDimitry Andric   //
8880b57cec5SDimitry Andric   //  id foo = [[NSObject alloc] init];
8890b57cec5SDimitry Andric   //  self.foo = foo; // We should warn that foo leaks here.
8900b57cec5SDimitry Andric   //
8910b57cec5SDimitry Andric   if (D->param_size() != 0)
8920b57cec5SDimitry Andric     return nullptr;
8930b57cec5SDimitry Andric 
894480093f4SDimitry Andric   // If the property was defined in an extension, search the extensions for
895480093f4SDimitry Andric   // overrides.
896480093f4SDimitry Andric   const ObjCInterfaceDecl *OID = D->getClassInterface();
897480093f4SDimitry Andric   if (dyn_cast<ObjCInterfaceDecl>(D->getParent()) != OID)
898480093f4SDimitry Andric     for (auto *Ext : OID->known_extensions()) {
899480093f4SDimitry Andric       auto *OMD = Ext->getInstanceMethod(D->getSelector());
900480093f4SDimitry Andric       if (OMD && !OMD->isImplicit())
901480093f4SDimitry Andric         return nullptr;
902480093f4SDimitry Andric     }
903480093f4SDimitry Andric 
904480093f4SDimitry Andric   Val = createObjCPropertyGetter(C, D);
9050b57cec5SDimitry Andric 
90681ad6265SDimitry Andric   return *Val;
9070b57cec5SDimitry Andric }
908