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