1243791Sdim//== BodyFarm.cpp  - Factory for conjuring up fake bodies ----------*- C++ -*-//
2243791Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6243791Sdim//
7243791Sdim//===----------------------------------------------------------------------===//
8243791Sdim//
9243791Sdim// BodyFarm is a factory for creating faux implementations for functions/methods
10243791Sdim// for analysis purposes.
11243791Sdim//
12243791Sdim//===----------------------------------------------------------------------===//
13243791Sdim
14327952Sdim#include "clang/Analysis/BodyFarm.h"
15243791Sdim#include "clang/AST/ASTContext.h"
16327952Sdim#include "clang/AST/CXXInheritance.h"
17249423Sdim#include "clang/AST/Decl.h"
18243791Sdim#include "clang/AST/Expr.h"
19327952Sdim#include "clang/AST/ExprCXX.h"
20243791Sdim#include "clang/AST/ExprObjC.h"
21327952Sdim#include "clang/AST/NestedNameSpecifier.h"
22280031Sdim#include "clang/Analysis/CodeInjector.h"
23327952Sdim#include "clang/Basic/OperatorKinds.h"
24249423Sdim#include "llvm/ADT/StringSwitch.h"
25327952Sdim#include "llvm/Support/Debug.h"
26243791Sdim
27327952Sdim#define DEBUG_TYPE "body-farm"
28327952Sdim
29243791Sdimusing namespace clang;
30243791Sdim
31243791Sdim//===----------------------------------------------------------------------===//
32243791Sdim// Helper creation functions for constructing faux ASTs.
33243791Sdim//===----------------------------------------------------------------------===//
34243791Sdim
35243791Sdimstatic bool isDispatchBlock(QualType Ty) {
36243791Sdim  // Is it a block pointer?
37243791Sdim  const BlockPointerType *BPT = Ty->getAs<BlockPointerType>();
38243791Sdim  if (!BPT)
39243791Sdim    return false;
40243791Sdim
41243791Sdim  // Check if the block pointer type takes no arguments and
42243791Sdim  // returns void.
43243791Sdim  const FunctionProtoType *FT =
44243791Sdim  BPT->getPointeeType()->getAs<FunctionProtoType>();
45296417Sdim  return FT && FT->getReturnType()->isVoidType() && FT->getNumParams() == 0;
46243791Sdim}
47243791Sdim
48243791Sdimnamespace {
49243791Sdimclass ASTMaker {
50243791Sdimpublic:
51243791Sdim  ASTMaker(ASTContext &C) : C(C) {}
52341825Sdim
53243791Sdim  /// Create a new BinaryOperator representing a simple assignment.
54243791Sdim  BinaryOperator *makeAssignment(const Expr *LHS, const Expr *RHS, QualType Ty);
55341825Sdim
56243791Sdim  /// Create a new BinaryOperator representing a comparison.
57243791Sdim  BinaryOperator *makeComparison(const Expr *LHS, const Expr *RHS,
58243791Sdim                                 BinaryOperator::Opcode Op);
59341825Sdim
60243791Sdim  /// Create a new compound stmt using the provided statements.
61243791Sdim  CompoundStmt *makeCompound(ArrayRef<Stmt*>);
62341825Sdim
63243791Sdim  /// Create a new DeclRefExpr for the referenced variable.
64327952Sdim  DeclRefExpr *makeDeclRefExpr(const VarDecl *D,
65327952Sdim                               bool RefersToEnclosingVariableOrCapture = false);
66341825Sdim
67243791Sdim  /// Create a new UnaryOperator representing a dereference.
68243791Sdim  UnaryOperator *makeDereference(const Expr *Arg, QualType Ty);
69341825Sdim
70243791Sdim  /// Create an implicit cast for an integer conversion.
71243791Sdim  Expr *makeIntegralCast(const Expr *Arg, QualType Ty);
72341825Sdim
73243791Sdim  /// Create an implicit cast to a builtin boolean type.
74243791Sdim  ImplicitCastExpr *makeIntegralCastToBoolean(const Expr *Arg);
75341825Sdim
76327952Sdim  /// Create an implicit cast for lvalue-to-rvaluate conversions.
77243791Sdim  ImplicitCastExpr *makeLvalueToRvalue(const Expr *Arg, QualType Ty);
78341825Sdim
79327952Sdim  /// Make RValue out of variable declaration, creating a temporary
80327952Sdim  /// DeclRefExpr in the process.
81327952Sdim  ImplicitCastExpr *
82327952Sdim  makeLvalueToRvalue(const VarDecl *Decl,
83327952Sdim                     bool RefersToEnclosingVariableOrCapture = false);
84327952Sdim
85327952Sdim  /// Create an implicit cast of the given type.
86327952Sdim  ImplicitCastExpr *makeImplicitCast(const Expr *Arg, QualType Ty,
87327952Sdim                                     CastKind CK = CK_LValueToRValue);
88327952Sdim
89243791Sdim  /// Create an Objective-C bool literal.
90243791Sdim  ObjCBoolLiteralExpr *makeObjCBool(bool Val);
91276479Sdim
92276479Sdim  /// Create an Objective-C ivar reference.
93276479Sdim  ObjCIvarRefExpr *makeObjCIvarRef(const Expr *Base, const ObjCIvarDecl *IVar);
94341825Sdim
95243791Sdim  /// Create a Return statement.
96243791Sdim  ReturnStmt *makeReturn(const Expr *RetVal);
97341825Sdim
98327952Sdim  /// Create an integer literal expression of the given type.
99327952Sdim  IntegerLiteral *makeIntegerLiteral(uint64_t Value, QualType Ty);
100327952Sdim
101327952Sdim  /// Create a member expression.
102327952Sdim  MemberExpr *makeMemberExpression(Expr *base, ValueDecl *MemberDecl,
103327952Sdim                                   bool IsArrow = false,
104327952Sdim                                   ExprValueKind ValueKind = VK_LValue);
105327952Sdim
106327952Sdim  /// Returns a *first* member field of a record declaration with a given name.
107327952Sdim  /// \return an nullptr if no member with such a name exists.
108327952Sdim  ValueDecl *findMemberField(const RecordDecl *RD, StringRef Name);
109327952Sdim
110243791Sdimprivate:
111243791Sdim  ASTContext &C;
112243791Sdim};
113243791Sdim}
114243791Sdim
115243791SdimBinaryOperator *ASTMaker::makeAssignment(const Expr *LHS, const Expr *RHS,
116243791Sdim                                         QualType Ty) {
117243791Sdim return new (C) BinaryOperator(const_cast<Expr*>(LHS), const_cast<Expr*>(RHS),
118243791Sdim                               BO_Assign, Ty, VK_RValue,
119321369Sdim                               OK_Ordinary, SourceLocation(), FPOptions());
120243791Sdim}
121243791Sdim
122243791SdimBinaryOperator *ASTMaker::makeComparison(const Expr *LHS, const Expr *RHS,
123243791Sdim                                         BinaryOperator::Opcode Op) {
124243791Sdim  assert(BinaryOperator::isLogicalOp(Op) ||
125243791Sdim         BinaryOperator::isComparisonOp(Op));
126243791Sdim  return new (C) BinaryOperator(const_cast<Expr*>(LHS),
127243791Sdim                                const_cast<Expr*>(RHS),
128243791Sdim                                Op,
129243791Sdim                                C.getLogicalOperationType(),
130243791Sdim                                VK_RValue,
131321369Sdim                                OK_Ordinary, SourceLocation(), FPOptions());
132243791Sdim}
133243791Sdim
134243791SdimCompoundStmt *ASTMaker::makeCompound(ArrayRef<Stmt *> Stmts) {
135327952Sdim  return CompoundStmt::Create(C, Stmts, SourceLocation(), SourceLocation());
136243791Sdim}
137243791Sdim
138327952SdimDeclRefExpr *ASTMaker::makeDeclRefExpr(
139327952Sdim    const VarDecl *D,
140327952Sdim    bool RefersToEnclosingVariableOrCapture) {
141327952Sdim  QualType Type = D->getType().getNonReferenceType();
142327952Sdim
143327952Sdim  DeclRefExpr *DR = DeclRefExpr::Create(
144327952Sdim      C, NestedNameSpecifierLoc(), SourceLocation(), const_cast<VarDecl *>(D),
145327952Sdim      RefersToEnclosingVariableOrCapture, SourceLocation(), Type, VK_LValue);
146243791Sdim  return DR;
147243791Sdim}
148243791Sdim
149243791SdimUnaryOperator *ASTMaker::makeDereference(const Expr *Arg, QualType Ty) {
150243791Sdim  return new (C) UnaryOperator(const_cast<Expr*>(Arg), UO_Deref, Ty,
151341825Sdim                               VK_LValue, OK_Ordinary, SourceLocation(),
152341825Sdim                              /*CanOverflow*/ false);
153243791Sdim}
154243791Sdim
155243791SdimImplicitCastExpr *ASTMaker::makeLvalueToRvalue(const Expr *Arg, QualType Ty) {
156327952Sdim  return makeImplicitCast(Arg, Ty, CK_LValueToRValue);
157243791Sdim}
158243791Sdim
159327952SdimImplicitCastExpr *
160327952SdimASTMaker::makeLvalueToRvalue(const VarDecl *Arg,
161327952Sdim                             bool RefersToEnclosingVariableOrCapture) {
162327952Sdim  QualType Type = Arg->getType().getNonReferenceType();
163327952Sdim  return makeLvalueToRvalue(makeDeclRefExpr(Arg,
164327952Sdim                                            RefersToEnclosingVariableOrCapture),
165327952Sdim                            Type);
166327952Sdim}
167327952Sdim
168327952SdimImplicitCastExpr *ASTMaker::makeImplicitCast(const Expr *Arg, QualType Ty,
169327952Sdim                                             CastKind CK) {
170327952Sdim  return ImplicitCastExpr::Create(C, Ty,
171327952Sdim                                  /* CastKind=*/ CK,
172327952Sdim                                  /* Expr=*/ const_cast<Expr *>(Arg),
173327952Sdim                                  /* CXXCastPath=*/ nullptr,
174327952Sdim                                  /* ExprValueKind=*/ VK_RValue);
175327952Sdim}
176327952Sdim
177243791SdimExpr *ASTMaker::makeIntegralCast(const Expr *Arg, QualType Ty) {
178243791Sdim  if (Arg->getType() == Ty)
179243791Sdim    return const_cast<Expr*>(Arg);
180276479Sdim
181243791Sdim  return ImplicitCastExpr::Create(C, Ty, CK_IntegralCast,
182276479Sdim                                  const_cast<Expr*>(Arg), nullptr, VK_RValue);
183243791Sdim}
184243791Sdim
185243791SdimImplicitCastExpr *ASTMaker::makeIntegralCastToBoolean(const Expr *Arg) {
186243791Sdim  return ImplicitCastExpr::Create(C, C.BoolTy, CK_IntegralToBoolean,
187276479Sdim                                  const_cast<Expr*>(Arg), nullptr, VK_RValue);
188243791Sdim}
189243791Sdim
190243791SdimObjCBoolLiteralExpr *ASTMaker::makeObjCBool(bool Val) {
191243791Sdim  QualType Ty = C.getBOOLDecl() ? C.getBOOLType() : C.ObjCBuiltinBoolTy;
192243791Sdim  return new (C) ObjCBoolLiteralExpr(Val, Ty, SourceLocation());
193243791Sdim}
194243791Sdim
195276479SdimObjCIvarRefExpr *ASTMaker::makeObjCIvarRef(const Expr *Base,
196276479Sdim                                           const ObjCIvarDecl *IVar) {
197276479Sdim  return new (C) ObjCIvarRefExpr(const_cast<ObjCIvarDecl*>(IVar),
198276479Sdim                                 IVar->getType(), SourceLocation(),
199276479Sdim                                 SourceLocation(), const_cast<Expr*>(Base),
200276479Sdim                                 /*arrow=*/true, /*free=*/false);
201276479Sdim}
202276479Sdim
203243791SdimReturnStmt *ASTMaker::makeReturn(const Expr *RetVal) {
204344779Sdim  return ReturnStmt::Create(C, SourceLocation(), const_cast<Expr *>(RetVal),
205344779Sdim                            /* NRVOCandidate=*/nullptr);
206243791Sdim}
207243791Sdim
208327952SdimIntegerLiteral *ASTMaker::makeIntegerLiteral(uint64_t Value, QualType Ty) {
209327952Sdim  llvm::APInt APValue = llvm::APInt(C.getTypeSize(Ty), Value);
210327952Sdim  return IntegerLiteral::Create(C, APValue, Ty, SourceLocation());
211327952Sdim}
212327952Sdim
213327952SdimMemberExpr *ASTMaker::makeMemberExpression(Expr *base, ValueDecl *MemberDecl,
214327952Sdim                                           bool IsArrow,
215327952Sdim                                           ExprValueKind ValueKind) {
216327952Sdim
217327952Sdim  DeclAccessPair FoundDecl = DeclAccessPair::make(MemberDecl, AS_public);
218327952Sdim  return MemberExpr::Create(
219327952Sdim      C, base, IsArrow, SourceLocation(), NestedNameSpecifierLoc(),
220327952Sdim      SourceLocation(), MemberDecl, FoundDecl,
221327952Sdim      DeclarationNameInfo(MemberDecl->getDeclName(), SourceLocation()),
222327952Sdim      /* TemplateArgumentListInfo=*/ nullptr, MemberDecl->getType(), ValueKind,
223353358Sdim      OK_Ordinary, NOUR_None);
224327952Sdim}
225327952Sdim
226327952SdimValueDecl *ASTMaker::findMemberField(const RecordDecl *RD, StringRef Name) {
227327952Sdim
228327952Sdim  CXXBasePaths Paths(
229327952Sdim      /* FindAmbiguities=*/false,
230327952Sdim      /* RecordPaths=*/false,
231327952Sdim      /* DetectVirtual=*/ false);
232327952Sdim  const IdentifierInfo &II = C.Idents.get(Name);
233327952Sdim  DeclarationName DeclName = C.DeclarationNames.getIdentifier(&II);
234327952Sdim
235327952Sdim  DeclContextLookupResult Decls = RD->lookup(DeclName);
236327952Sdim  for (NamedDecl *FoundDecl : Decls)
237327952Sdim    if (!FoundDecl->getDeclContext()->isFunctionOrMethod())
238327952Sdim      return cast<ValueDecl>(FoundDecl);
239327952Sdim
240327952Sdim  return nullptr;
241327952Sdim}
242327952Sdim
243243791Sdim//===----------------------------------------------------------------------===//
244243791Sdim// Creation functions for faux ASTs.
245243791Sdim//===----------------------------------------------------------------------===//
246243791Sdim
247243791Sdimtypedef Stmt *(*FunctionFarmer)(ASTContext &C, const FunctionDecl *D);
248243791Sdim
249327952Sdimstatic CallExpr *create_call_once_funcptr_call(ASTContext &C, ASTMaker M,
250327952Sdim                                               const ParmVarDecl *Callback,
251327952Sdim                                               ArrayRef<Expr *> CallArgs) {
252327952Sdim
253327952Sdim  QualType Ty = Callback->getType();
254327952Sdim  DeclRefExpr *Call = M.makeDeclRefExpr(Callback);
255341825Sdim  Expr *SubExpr;
256327952Sdim  if (Ty->isRValueReferenceType()) {
257341825Sdim    SubExpr = M.makeImplicitCast(
258341825Sdim        Call, Ty.getNonReferenceType(), CK_LValueToRValue);
259341825Sdim  } else if (Ty->isLValueReferenceType() &&
260341825Sdim             Call->getType()->isFunctionType()) {
261341825Sdim    Ty = C.getPointerType(Ty.getNonReferenceType());
262341825Sdim    SubExpr = M.makeImplicitCast(Call, Ty, CK_FunctionToPointerDecay);
263341825Sdim  } else if (Ty->isLValueReferenceType()
264341825Sdim             && Call->getType()->isPointerType()
265341825Sdim             && Call->getType()->getPointeeType()->isFunctionType()){
266341825Sdim    SubExpr = Call;
267327952Sdim  } else {
268341825Sdim    llvm_unreachable("Unexpected state");
269327952Sdim  }
270327952Sdim
271344779Sdim  return CallExpr::Create(C, SubExpr, CallArgs, C.VoidTy, VK_RValue,
272344779Sdim                          SourceLocation());
273327952Sdim}
274327952Sdim
275327952Sdimstatic CallExpr *create_call_once_lambda_call(ASTContext &C, ASTMaker M,
276327952Sdim                                              const ParmVarDecl *Callback,
277327952Sdim                                              CXXRecordDecl *CallbackDecl,
278327952Sdim                                              ArrayRef<Expr *> CallArgs) {
279327952Sdim  assert(CallbackDecl != nullptr);
280327952Sdim  assert(CallbackDecl->isLambda());
281327952Sdim  FunctionDecl *callOperatorDecl = CallbackDecl->getLambdaCallOperator();
282327952Sdim  assert(callOperatorDecl != nullptr);
283327952Sdim
284327952Sdim  DeclRefExpr *callOperatorDeclRef =
285327952Sdim      DeclRefExpr::Create(/* Ctx =*/ C,
286327952Sdim                          /* QualifierLoc =*/ NestedNameSpecifierLoc(),
287327952Sdim                          /* TemplateKWLoc =*/ SourceLocation(),
288327952Sdim                          const_cast<FunctionDecl *>(callOperatorDecl),
289327952Sdim                          /* RefersToEnclosingVariableOrCapture=*/ false,
290327952Sdim                          /* NameLoc =*/ SourceLocation(),
291327952Sdim                          /* T =*/ callOperatorDecl->getType(),
292327952Sdim                          /* VK =*/ VK_LValue);
293327952Sdim
294344779Sdim  return CXXOperatorCallExpr::Create(
295344779Sdim      /*AstContext=*/C, OO_Call, callOperatorDeclRef,
296353358Sdim      /*Args=*/CallArgs,
297344779Sdim      /*QualType=*/C.VoidTy,
298344779Sdim      /*ExprValueType=*/VK_RValue,
299344779Sdim      /*SourceLocation=*/SourceLocation(), FPOptions());
300327952Sdim}
301327952Sdim
302327952Sdim/// Create a fake body for std::call_once.
303327952Sdim/// Emulates the following function body:
304327952Sdim///
305327952Sdim/// \code
306327952Sdim/// typedef struct once_flag_s {
307327952Sdim///   unsigned long __state = 0;
308327952Sdim/// } once_flag;
309327952Sdim/// template<class Callable>
310327952Sdim/// void call_once(once_flag& o, Callable func) {
311327952Sdim///   if (!o.__state) {
312327952Sdim///     func();
313327952Sdim///   }
314327952Sdim///   o.__state = 1;
315327952Sdim/// }
316327952Sdim/// \endcode
317327952Sdimstatic Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) {
318341825Sdim  LLVM_DEBUG(llvm::dbgs() << "Generating body for call_once\n");
319327952Sdim
320327952Sdim  // We need at least two parameters.
321327952Sdim  if (D->param_size() < 2)
322327952Sdim    return nullptr;
323327952Sdim
324327952Sdim  ASTMaker M(C);
325327952Sdim
326327952Sdim  const ParmVarDecl *Flag = D->getParamDecl(0);
327327952Sdim  const ParmVarDecl *Callback = D->getParamDecl(1);
328327952Sdim
329327952Sdim  if (!Callback->getType()->isReferenceType()) {
330327952Sdim    llvm::dbgs() << "libcxx03 std::call_once implementation, skipping.\n";
331327952Sdim    return nullptr;
332327952Sdim  }
333327952Sdim  if (!Flag->getType()->isReferenceType()) {
334327952Sdim    llvm::dbgs() << "unknown std::call_once implementation, skipping.\n";
335327952Sdim    return nullptr;
336327952Sdim  }
337327952Sdim
338327952Sdim  QualType CallbackType = Callback->getType().getNonReferenceType();
339327952Sdim
340327952Sdim  // Nullable pointer, non-null iff function is a CXXRecordDecl.
341327952Sdim  CXXRecordDecl *CallbackRecordDecl = CallbackType->getAsCXXRecordDecl();
342327952Sdim  QualType FlagType = Flag->getType().getNonReferenceType();
343341825Sdim  auto *FlagRecordDecl = FlagType->getAsRecordDecl();
344327952Sdim
345327952Sdim  if (!FlagRecordDecl) {
346341825Sdim    LLVM_DEBUG(llvm::dbgs() << "Flag field is not a record: "
347341825Sdim                            << "unknown std::call_once implementation, "
348341825Sdim                            << "ignoring the call.\n");
349327952Sdim    return nullptr;
350327952Sdim  }
351327952Sdim
352327952Sdim  // We initially assume libc++ implementation of call_once,
353327952Sdim  // where the once_flag struct has a field `__state_`.
354327952Sdim  ValueDecl *FlagFieldDecl = M.findMemberField(FlagRecordDecl, "__state_");
355327952Sdim
356327952Sdim  // Otherwise, try libstdc++ implementation, with a field
357327952Sdim  // `_M_once`
358327952Sdim  if (!FlagFieldDecl) {
359327952Sdim    FlagFieldDecl = M.findMemberField(FlagRecordDecl, "_M_once");
360327952Sdim  }
361327952Sdim
362327952Sdim  if (!FlagFieldDecl) {
363341825Sdim    LLVM_DEBUG(llvm::dbgs() << "No field _M_once or __state_ found on "
364341825Sdim                            << "std::once_flag struct: unknown std::call_once "
365341825Sdim                            << "implementation, ignoring the call.");
366327952Sdim    return nullptr;
367327952Sdim  }
368327952Sdim
369327952Sdim  bool isLambdaCall = CallbackRecordDecl && CallbackRecordDecl->isLambda();
370327952Sdim  if (CallbackRecordDecl && !isLambdaCall) {
371341825Sdim    LLVM_DEBUG(llvm::dbgs()
372341825Sdim               << "Not supported: synthesizing body for functors when "
373341825Sdim               << "body farming std::call_once, ignoring the call.");
374327952Sdim    return nullptr;
375327952Sdim  }
376327952Sdim
377327952Sdim  SmallVector<Expr *, 5> CallArgs;
378327952Sdim  const FunctionProtoType *CallbackFunctionType;
379327952Sdim  if (isLambdaCall) {
380327952Sdim
381327952Sdim    // Lambda requires callback itself inserted as a first parameter.
382327952Sdim    CallArgs.push_back(
383327952Sdim        M.makeDeclRefExpr(Callback,
384327952Sdim                          /* RefersToEnclosingVariableOrCapture=*/ true));
385327952Sdim    CallbackFunctionType = CallbackRecordDecl->getLambdaCallOperator()
386327952Sdim                               ->getType()
387327952Sdim                               ->getAs<FunctionProtoType>();
388327952Sdim  } else if (!CallbackType->getPointeeType().isNull()) {
389327952Sdim    CallbackFunctionType =
390327952Sdim        CallbackType->getPointeeType()->getAs<FunctionProtoType>();
391327952Sdim  } else {
392327952Sdim    CallbackFunctionType = CallbackType->getAs<FunctionProtoType>();
393327952Sdim  }
394327952Sdim
395327952Sdim  if (!CallbackFunctionType)
396327952Sdim    return nullptr;
397327952Sdim
398327952Sdim  // First two arguments are used for the flag and for the callback.
399327952Sdim  if (D->getNumParams() != CallbackFunctionType->getNumParams() + 2) {
400341825Sdim    LLVM_DEBUG(llvm::dbgs() << "Types of params of the callback do not match "
401341825Sdim                            << "params passed to std::call_once, "
402341825Sdim                            << "ignoring the call\n");
403327952Sdim    return nullptr;
404327952Sdim  }
405327952Sdim
406327952Sdim  // All arguments past first two ones are passed to the callback,
407327952Sdim  // and we turn lvalues into rvalues if the argument is not passed by
408327952Sdim  // reference.
409327952Sdim  for (unsigned int ParamIdx = 2; ParamIdx < D->getNumParams(); ParamIdx++) {
410327952Sdim    const ParmVarDecl *PDecl = D->getParamDecl(ParamIdx);
411360784Sdim    assert(PDecl);
412360784Sdim    if (CallbackFunctionType->getParamType(ParamIdx - 2)
413341825Sdim                .getNonReferenceType()
414341825Sdim                .getCanonicalType() !=
415341825Sdim            PDecl->getType().getNonReferenceType().getCanonicalType()) {
416341825Sdim      LLVM_DEBUG(llvm::dbgs() << "Types of params of the callback do not match "
417341825Sdim                              << "params passed to std::call_once, "
418341825Sdim                              << "ignoring the call\n");
419341825Sdim      return nullptr;
420341825Sdim    }
421327952Sdim    Expr *ParamExpr = M.makeDeclRefExpr(PDecl);
422327952Sdim    if (!CallbackFunctionType->getParamType(ParamIdx - 2)->isReferenceType()) {
423327952Sdim      QualType PTy = PDecl->getType().getNonReferenceType();
424327952Sdim      ParamExpr = M.makeLvalueToRvalue(ParamExpr, PTy);
425327952Sdim    }
426327952Sdim    CallArgs.push_back(ParamExpr);
427327952Sdim  }
428327952Sdim
429327952Sdim  CallExpr *CallbackCall;
430327952Sdim  if (isLambdaCall) {
431327952Sdim
432327952Sdim    CallbackCall = create_call_once_lambda_call(C, M, Callback,
433327952Sdim                                                CallbackRecordDecl, CallArgs);
434327952Sdim  } else {
435327952Sdim
436327952Sdim    // Function pointer case.
437327952Sdim    CallbackCall = create_call_once_funcptr_call(C, M, Callback, CallArgs);
438327952Sdim  }
439327952Sdim
440327952Sdim  DeclRefExpr *FlagDecl =
441327952Sdim      M.makeDeclRefExpr(Flag,
442327952Sdim                        /* RefersToEnclosingVariableOrCapture=*/true);
443327952Sdim
444327952Sdim
445327952Sdim  MemberExpr *Deref = M.makeMemberExpression(FlagDecl, FlagFieldDecl);
446327952Sdim  assert(Deref->isLValue());
447327952Sdim  QualType DerefType = Deref->getType();
448327952Sdim
449327952Sdim  // Negation predicate.
450327952Sdim  UnaryOperator *FlagCheck = new (C) UnaryOperator(
451327952Sdim      /* input=*/
452327952Sdim      M.makeImplicitCast(M.makeLvalueToRvalue(Deref, DerefType), DerefType,
453327952Sdim                         CK_IntegralToBoolean),
454327952Sdim      /* opc=*/ UO_LNot,
455327952Sdim      /* QualType=*/ C.IntTy,
456327952Sdim      /* ExprValueKind=*/ VK_RValue,
457341825Sdim      /* ExprObjectKind=*/ OK_Ordinary, SourceLocation(),
458341825Sdim      /* CanOverflow*/ false);
459327952Sdim
460327952Sdim  // Create assignment.
461327952Sdim  BinaryOperator *FlagAssignment = M.makeAssignment(
462327952Sdim      Deref, M.makeIntegralCast(M.makeIntegerLiteral(1, C.IntTy), DerefType),
463327952Sdim      DerefType);
464327952Sdim
465344779Sdim  auto *Out =
466344779Sdim      IfStmt::Create(C, SourceLocation(),
467344779Sdim                     /* IsConstexpr=*/false,
468353358Sdim                     /* Init=*/nullptr,
469353358Sdim                     /* Var=*/nullptr,
470353358Sdim                     /* Cond=*/FlagCheck,
471353358Sdim                     /* Then=*/M.makeCompound({CallbackCall, FlagAssignment}));
472327952Sdim
473327952Sdim  return Out;
474327952Sdim}
475327952Sdim
476243791Sdim/// Create a fake body for dispatch_once.
477243791Sdimstatic Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
478243791Sdim  // Check if we have at least two parameters.
479243791Sdim  if (D->param_size() != 2)
480276479Sdim    return nullptr;
481243791Sdim
482243791Sdim  // Check if the first parameter is a pointer to integer type.
483243791Sdim  const ParmVarDecl *Predicate = D->getParamDecl(0);
484243791Sdim  QualType PredicateQPtrTy = Predicate->getType();
485243791Sdim  const PointerType *PredicatePtrTy = PredicateQPtrTy->getAs<PointerType>();
486243791Sdim  if (!PredicatePtrTy)
487276479Sdim    return nullptr;
488243791Sdim  QualType PredicateTy = PredicatePtrTy->getPointeeType();
489243791Sdim  if (!PredicateTy->isIntegerType())
490276479Sdim    return nullptr;
491276479Sdim
492243791Sdim  // Check if the second parameter is the proper block type.
493243791Sdim  const ParmVarDecl *Block = D->getParamDecl(1);
494243791Sdim  QualType Ty = Block->getType();
495243791Sdim  if (!isDispatchBlock(Ty))
496276479Sdim    return nullptr;
497276479Sdim
498243791Sdim  // Everything checks out.  Create a fakse body that checks the predicate,
499243791Sdim  // sets it, and calls the block.  Basically, an AST dump of:
500243791Sdim  //
501243791Sdim  // void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block) {
502327952Sdim  //  if (*predicate != ~0l) {
503327952Sdim  //    *predicate = ~0l;
504243791Sdim  //    block();
505243791Sdim  //  }
506243791Sdim  // }
507341825Sdim
508243791Sdim  ASTMaker M(C);
509341825Sdim
510243791Sdim  // (1) Create the call.
511344779Sdim  CallExpr *CE = CallExpr::Create(
512327952Sdim      /*ASTContext=*/C,
513327952Sdim      /*StmtClass=*/M.makeLvalueToRvalue(/*Expr=*/Block),
514353358Sdim      /*Args=*/None,
515327952Sdim      /*QualType=*/C.VoidTy,
516327952Sdim      /*ExprValueType=*/VK_RValue,
517327952Sdim      /*SourceLocation=*/SourceLocation());
518243791Sdim
519243791Sdim  // (2) Create the assignment to the predicate.
520327952Sdim  Expr *DoneValue =
521327952Sdim      new (C) UnaryOperator(M.makeIntegerLiteral(0, C.LongTy), UO_Not, C.LongTy,
522341825Sdim                            VK_RValue, OK_Ordinary, SourceLocation(),
523341825Sdim                            /*CanOverflow*/false);
524327952Sdim
525243791Sdim  BinaryOperator *B =
526243791Sdim    M.makeAssignment(
527243791Sdim       M.makeDereference(
528243791Sdim          M.makeLvalueToRvalue(
529243791Sdim            M.makeDeclRefExpr(Predicate), PredicateQPtrTy),
530243791Sdim            PredicateTy),
531327952Sdim       M.makeIntegralCast(DoneValue, PredicateTy),
532243791Sdim       PredicateTy);
533341825Sdim
534243791Sdim  // (3) Create the compound statement.
535280031Sdim  Stmt *Stmts[] = { B, CE };
536280031Sdim  CompoundStmt *CS = M.makeCompound(Stmts);
537341825Sdim
538243791Sdim  // (4) Create the 'if' condition.
539243791Sdim  ImplicitCastExpr *LValToRval =
540243791Sdim    M.makeLvalueToRvalue(
541243791Sdim      M.makeDereference(
542243791Sdim        M.makeLvalueToRvalue(
543243791Sdim          M.makeDeclRefExpr(Predicate),
544243791Sdim          PredicateQPtrTy),
545243791Sdim        PredicateTy),
546243791Sdim    PredicateTy);
547327952Sdim
548327952Sdim  Expr *GuardCondition = M.makeComparison(LValToRval, DoneValue, BO_NE);
549243791Sdim  // (5) Create the 'if' statement.
550344779Sdim  auto *If = IfStmt::Create(C, SourceLocation(),
551344779Sdim                            /* IsConstexpr=*/false,
552353358Sdim                            /* Init=*/nullptr,
553353358Sdim                            /* Var=*/nullptr,
554353358Sdim                            /* Cond=*/GuardCondition,
555353358Sdim                            /* Then=*/CS);
556243791Sdim  return If;
557243791Sdim}
558243791Sdim
559243791Sdim/// Create a fake body for dispatch_sync.
560243791Sdimstatic Stmt *create_dispatch_sync(ASTContext &C, const FunctionDecl *D) {
561243791Sdim  // Check if we have at least two parameters.
562243791Sdim  if (D->param_size() != 2)
563276479Sdim    return nullptr;
564276479Sdim
565243791Sdim  // Check if the second parameter is a block.
566243791Sdim  const ParmVarDecl *PV = D->getParamDecl(1);
567243791Sdim  QualType Ty = PV->getType();
568243791Sdim  if (!isDispatchBlock(Ty))
569276479Sdim    return nullptr;
570276479Sdim
571243791Sdim  // Everything checks out.  Create a fake body that just calls the block.
572243791Sdim  // This is basically just an AST dump of:
573243791Sdim  //
574243791Sdim  // void dispatch_sync(dispatch_queue_t queue, void (^block)(void)) {
575243791Sdim  //   block();
576243791Sdim  // }
577341825Sdim  //
578243791Sdim  ASTMaker M(C);
579243791Sdim  DeclRefExpr *DR = M.makeDeclRefExpr(PV);
580243791Sdim  ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty);
581344779Sdim  CallExpr *CE =
582344779Sdim      CallExpr::Create(C, ICE, None, C.VoidTy, VK_RValue, SourceLocation());
583243791Sdim  return CE;
584243791Sdim}
585243791Sdim
586243791Sdimstatic Stmt *create_OSAtomicCompareAndSwap(ASTContext &C, const FunctionDecl *D)
587243791Sdim{
588243791Sdim  // There are exactly 3 arguments.
589243791Sdim  if (D->param_size() != 3)
590276479Sdim    return nullptr;
591276479Sdim
592249423Sdim  // Signature:
593249423Sdim  // _Bool OSAtomicCompareAndSwapPtr(void *__oldValue,
594249423Sdim  //                                 void *__newValue,
595249423Sdim  //                                 void * volatile *__theValue)
596249423Sdim  // Generate body:
597243791Sdim  //   if (oldValue == *theValue) {
598243791Sdim  //    *theValue = newValue;
599243791Sdim  //    return YES;
600243791Sdim  //   }
601243791Sdim  //   else return NO;
602276479Sdim
603276479Sdim  QualType ResultTy = D->getReturnType();
604243791Sdim  bool isBoolean = ResultTy->isBooleanType();
605243791Sdim  if (!isBoolean && !ResultTy->isIntegralType(C))
606276479Sdim    return nullptr;
607276479Sdim
608243791Sdim  const ParmVarDecl *OldValue = D->getParamDecl(0);
609243791Sdim  QualType OldValueTy = OldValue->getType();
610243791Sdim
611243791Sdim  const ParmVarDecl *NewValue = D->getParamDecl(1);
612243791Sdim  QualType NewValueTy = NewValue->getType();
613341825Sdim
614243791Sdim  assert(OldValueTy == NewValueTy);
615341825Sdim
616243791Sdim  const ParmVarDecl *TheValue = D->getParamDecl(2);
617243791Sdim  QualType TheValueTy = TheValue->getType();
618243791Sdim  const PointerType *PT = TheValueTy->getAs<PointerType>();
619243791Sdim  if (!PT)
620276479Sdim    return nullptr;
621243791Sdim  QualType PointeeTy = PT->getPointeeType();
622341825Sdim
623243791Sdim  ASTMaker M(C);
624243791Sdim  // Construct the comparison.
625243791Sdim  Expr *Comparison =
626243791Sdim    M.makeComparison(
627243791Sdim      M.makeLvalueToRvalue(M.makeDeclRefExpr(OldValue), OldValueTy),
628243791Sdim      M.makeLvalueToRvalue(
629243791Sdim        M.makeDereference(
630243791Sdim          M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
631243791Sdim          PointeeTy),
632243791Sdim        PointeeTy),
633243791Sdim      BO_EQ);
634243791Sdim
635243791Sdim  // Construct the body of the IfStmt.
636243791Sdim  Stmt *Stmts[2];
637243791Sdim  Stmts[0] =
638243791Sdim    M.makeAssignment(
639243791Sdim      M.makeDereference(
640243791Sdim        M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
641243791Sdim        PointeeTy),
642243791Sdim      M.makeLvalueToRvalue(M.makeDeclRefExpr(NewValue), NewValueTy),
643243791Sdim      NewValueTy);
644341825Sdim
645243791Sdim  Expr *BoolVal = M.makeObjCBool(true);
646243791Sdim  Expr *RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
647243791Sdim                           : M.makeIntegralCast(BoolVal, ResultTy);
648243791Sdim  Stmts[1] = M.makeReturn(RetVal);
649280031Sdim  CompoundStmt *Body = M.makeCompound(Stmts);
650341825Sdim
651243791Sdim  // Construct the else clause.
652243791Sdim  BoolVal = M.makeObjCBool(false);
653243791Sdim  RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
654243791Sdim                     : M.makeIntegralCast(BoolVal, ResultTy);
655243791Sdim  Stmt *Else = M.makeReturn(RetVal);
656341825Sdim
657243791Sdim  /// Construct the If.
658344779Sdim  auto *If = IfStmt::Create(C, SourceLocation(),
659344779Sdim                            /* IsConstexpr=*/false,
660353358Sdim                            /* Init=*/nullptr,
661353358Sdim                            /* Var=*/nullptr, Comparison, Body,
662344779Sdim                            SourceLocation(), Else);
663276479Sdim
664341825Sdim  return If;
665243791Sdim}
666243791Sdim
667243791SdimStmt *BodyFarm::getBody(const FunctionDecl *D) {
668249423Sdim  Optional<Stmt *> &Val = Bodies[D];
669243791Sdim  if (Val.hasValue())
670243791Sdim    return Val.getValue();
671243791Sdim
672276479Sdim  Val = nullptr;
673276479Sdim
674276479Sdim  if (D->getIdentifier() == nullptr)
675276479Sdim    return nullptr;
676276479Sdim
677243791Sdim  StringRef Name = D->getName();
678243791Sdim  if (Name.empty())
679276479Sdim    return nullptr;
680243791Sdim
681243791Sdim  FunctionFarmer FF;
682243791Sdim
683243791Sdim  if (Name.startswith("OSAtomicCompareAndSwap") ||
684243791Sdim      Name.startswith("objc_atomicCompareAndSwap")) {
685243791Sdim    FF = create_OSAtomicCompareAndSwap;
686327952Sdim  } else if (Name == "call_once" && D->getDeclContext()->isStdNamespace()) {
687327952Sdim    FF = create_call_once;
688327952Sdim  } else {
689243791Sdim    FF = llvm::StringSwitch<FunctionFarmer>(Name)
690243791Sdim          .Case("dispatch_sync", create_dispatch_sync)
691243791Sdim          .Case("dispatch_once", create_dispatch_once)
692276479Sdim          .Default(nullptr);
693243791Sdim  }
694341825Sdim
695243791Sdim  if (FF) { Val = FF(C, D); }
696280031Sdim  else if (Injector) { Val = Injector->getBody(D); }
697243791Sdim  return Val.getValue();
698243791Sdim}
699243791Sdim
700309124Sdimstatic const ObjCIvarDecl *findBackingIvar(const ObjCPropertyDecl *Prop) {
701309124Sdim  const ObjCIvarDecl *IVar = Prop->getPropertyIvarDecl();
702309124Sdim
703309124Sdim  if (IVar)
704309124Sdim    return IVar;
705309124Sdim
706309124Sdim  // When a readonly property is shadowed in a class extensions with a
707309124Sdim  // a readwrite property, the instance variable belongs to the shadowing
708309124Sdim  // property rather than the shadowed property. If there is no instance
709309124Sdim  // variable on a readonly property, check to see whether the property is
710309124Sdim  // shadowed and if so try to get the instance variable from shadowing
711309124Sdim  // property.
712309124Sdim  if (!Prop->isReadOnly())
713309124Sdim    return nullptr;
714309124Sdim
715309124Sdim  auto *Container = cast<ObjCContainerDecl>(Prop->getDeclContext());
716309124Sdim  const ObjCInterfaceDecl *PrimaryInterface = nullptr;
717309124Sdim  if (auto *InterfaceDecl = dyn_cast<ObjCInterfaceDecl>(Container)) {
718309124Sdim    PrimaryInterface = InterfaceDecl;
719309124Sdim  } else if (auto *CategoryDecl = dyn_cast<ObjCCategoryDecl>(Container)) {
720309124Sdim    PrimaryInterface = CategoryDecl->getClassInterface();
721309124Sdim  } else if (auto *ImplDecl = dyn_cast<ObjCImplDecl>(Container)) {
722309124Sdim    PrimaryInterface = ImplDecl->getClassInterface();
723309124Sdim  } else {
724309124Sdim    return nullptr;
725309124Sdim  }
726309124Sdim
727309124Sdim  // FindPropertyVisibleInPrimaryClass() looks first in class extensions, so it
728309124Sdim  // is guaranteed to find the shadowing property, if it exists, rather than
729309124Sdim  // the shadowed property.
730309124Sdim  auto *ShadowingProp = PrimaryInterface->FindPropertyVisibleInPrimaryClass(
731309124Sdim      Prop->getIdentifier(), Prop->getQueryKind());
732309124Sdim  if (ShadowingProp && ShadowingProp != Prop) {
733309124Sdim    IVar = ShadowingProp->getPropertyIvarDecl();
734309124Sdim  }
735309124Sdim
736309124Sdim  return IVar;
737309124Sdim}
738309124Sdim
739276479Sdimstatic Stmt *createObjCPropertyGetter(ASTContext &Ctx,
740360784Sdim                                      const ObjCMethodDecl *MD) {
741360784Sdim    // First, find the backing ivar.
742360784Sdim  const ObjCIvarDecl *IVar = nullptr;
743276479Sdim
744360784Sdim  // Property accessor stubs sometimes do not correspond to any property decl
745360784Sdim  // in the current interface (but in a superclass). They still have a
746360784Sdim  // corresponding property impl decl in this case.
747360784Sdim  if (MD->isSynthesizedAccessorStub()) {
748360784Sdim    const ObjCInterfaceDecl *IntD = MD->getClassInterface();
749360784Sdim    const ObjCImplementationDecl *ImpD = IntD->getImplementation();
750360784Sdim    for (const auto *PI: ImpD->property_impls()) {
751360784Sdim      if (const ObjCPropertyDecl *P = PI->getPropertyDecl()) {
752360784Sdim        if (P->getGetterName() == MD->getSelector())
753360784Sdim          IVar = P->getPropertyIvarDecl();
754360784Sdim      }
755360784Sdim    }
756360784Sdim  }
757276479Sdim
758360784Sdim  if (!IVar) {
759360784Sdim    const ObjCPropertyDecl *Prop = MD->findPropertyDecl();
760360784Sdim    IVar = findBackingIvar(Prop);
761360784Sdim    if (!IVar)
762360784Sdim      return nullptr;
763276479Sdim
764360784Sdim    // Ignore weak variables, which have special behavior.
765360784Sdim    if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak)
766360784Sdim      return nullptr;
767360784Sdim
768360784Sdim    // Look to see if Sema has synthesized a body for us. This happens in
769360784Sdim    // Objective-C++ because the return value may be a C++ class type with a
770360784Sdim    // non-trivial copy constructor. We can only do this if we can find the
771360784Sdim    // @synthesize for this property, though (or if we know it's been auto-
772360784Sdim    // synthesized).
773360784Sdim    const ObjCImplementationDecl *ImplDecl =
774360784Sdim      IVar->getContainingInterface()->getImplementation();
775360784Sdim    if (ImplDecl) {
776360784Sdim      for (const auto *I : ImplDecl->property_impls()) {
777360784Sdim        if (I->getPropertyDecl() != Prop)
778360784Sdim          continue;
779360784Sdim
780360784Sdim        if (I->getGetterCXXConstructor()) {
781360784Sdim          ASTMaker M(Ctx);
782360784Sdim          return M.makeReturn(I->getGetterCXXConstructor());
783360784Sdim        }
784276479Sdim      }
785276479Sdim    }
786360784Sdim
787360784Sdim    // Sanity check that the property is the same type as the ivar, or a
788360784Sdim    // reference to it, and that it is either an object pointer or trivially
789360784Sdim    // copyable.
790360784Sdim    if (!Ctx.hasSameUnqualifiedType(IVar->getType(),
791360784Sdim                                    Prop->getType().getNonReferenceType()))
792360784Sdim      return nullptr;
793360784Sdim    if (!IVar->getType()->isObjCLifetimeType() &&
794360784Sdim        !IVar->getType().isTriviallyCopyableType(Ctx))
795360784Sdim      return nullptr;
796276479Sdim  }
797276479Sdim
798276479Sdim  // Generate our body:
799276479Sdim  //   return self->_ivar;
800276479Sdim  ASTMaker M(Ctx);
801276479Sdim
802360784Sdim  const VarDecl *selfVar = MD->getSelfDecl();
803314564Sdim  if (!selfVar)
804314564Sdim    return nullptr;
805276479Sdim
806276479Sdim  Expr *loadedIVar =
807276479Sdim    M.makeObjCIvarRef(
808276479Sdim      M.makeLvalueToRvalue(
809276479Sdim        M.makeDeclRefExpr(selfVar),
810276479Sdim        selfVar->getType()),
811276479Sdim      IVar);
812276479Sdim
813360784Sdim  if (!MD->getReturnType()->isReferenceType())
814276479Sdim    loadedIVar = M.makeLvalueToRvalue(loadedIVar, IVar->getType());
815276479Sdim
816276479Sdim  return M.makeReturn(loadedIVar);
817276479Sdim}
818276479Sdim
819276479SdimStmt *BodyFarm::getBody(const ObjCMethodDecl *D) {
820276479Sdim  // We currently only know how to synthesize property accessors.
821276479Sdim  if (!D->isPropertyAccessor())
822276479Sdim    return nullptr;
823276479Sdim
824276479Sdim  D = D->getCanonicalDecl();
825276479Sdim
826353358Sdim  // We should not try to synthesize explicitly redefined accessors.
827353358Sdim  // We do not know for sure how they behave.
828353358Sdim  if (!D->isImplicit())
829353358Sdim    return nullptr;
830353358Sdim
831276479Sdim  Optional<Stmt *> &Val = Bodies[D];
832276479Sdim  if (Val.hasValue())
833276479Sdim    return Val.getValue();
834276479Sdim  Val = nullptr;
835276479Sdim
836276479Sdim  // For now, we only synthesize getters.
837309124Sdim  // Synthesizing setters would cause false negatives in the
838309124Sdim  // RetainCountChecker because the method body would bind the parameter
839309124Sdim  // to an instance variable, causing it to escape. This would prevent
840309124Sdim  // warning in the following common scenario:
841309124Sdim  //
842309124Sdim  //  id foo = [[NSObject alloc] init];
843309124Sdim  //  self.foo = foo; // We should warn that foo leaks here.
844309124Sdim  //
845276479Sdim  if (D->param_size() != 0)
846276479Sdim    return nullptr;
847276479Sdim
848360784Sdim  // If the property was defined in an extension, search the extensions for
849360784Sdim  // overrides.
850360784Sdim  const ObjCInterfaceDecl *OID = D->getClassInterface();
851360784Sdim  if (dyn_cast<ObjCInterfaceDecl>(D->getParent()) != OID)
852360784Sdim    for (auto *Ext : OID->known_extensions()) {
853360784Sdim      auto *OMD = Ext->getInstanceMethod(D->getSelector());
854360784Sdim      if (OMD && !OMD->isImplicit())
855360784Sdim        return nullptr;
856360784Sdim    }
857276479Sdim
858360784Sdim  Val = createObjCPropertyGetter(C, D);
859360784Sdim
860276479Sdim  return Val.getValue();
861276479Sdim}
862