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