Home | History | Annotate | Download | only in Analysis
      1 //== BodyFarm.cpp  - Factory for conjuring up fake bodies ----------*- C++ -*-//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // BodyFarm is a factory for creating faux implementations for functions/methods
     11 // for analysis purposes.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "BodyFarm.h"
     16 #include "clang/AST/ASTContext.h"
     17 #include "clang/AST/Decl.h"
     18 #include "clang/AST/Expr.h"
     19 #include "clang/AST/ExprObjC.h"
     20 #include "clang/Analysis/CodeInjector.h"
     21 #include "llvm/ADT/StringSwitch.h"
     22 
     23 using namespace clang;
     24 
     25 //===----------------------------------------------------------------------===//
     26 // Helper creation functions for constructing faux ASTs.
     27 //===----------------------------------------------------------------------===//
     28 
     29 static bool isDispatchBlock(QualType Ty) {
     30   // Is it a block pointer?
     31   const BlockPointerType *BPT = Ty->getAs<BlockPointerType>();
     32   if (!BPT)
     33     return false;
     34 
     35   // Check if the block pointer type takes no arguments and
     36   // returns void.
     37   const FunctionProtoType *FT =
     38   BPT->getPointeeType()->getAs<FunctionProtoType>();
     39   return FT && FT->getReturnType()->isVoidType() && FT->getNumParams() == 0;
     40 }
     41 
     42 namespace {
     43 class ASTMaker {
     44 public:
     45   ASTMaker(ASTContext &C) : C(C) {}
     46 
     47   /// Create a new BinaryOperator representing a simple assignment.
     48   BinaryOperator *makeAssignment(const Expr *LHS, const Expr *RHS, QualType Ty);
     49 
     50   /// Create a new BinaryOperator representing a comparison.
     51   BinaryOperator *makeComparison(const Expr *LHS, const Expr *RHS,
     52                                  BinaryOperator::Opcode Op);
     53 
     54   /// Create a new compound stmt using the provided statements.
     55   CompoundStmt *makeCompound(ArrayRef<Stmt*>);
     56 
     57   /// Create a new DeclRefExpr for the referenced variable.
     58   DeclRefExpr *makeDeclRefExpr(const VarDecl *D);
     59 
     60   /// Create a new UnaryOperator representing a dereference.
     61   UnaryOperator *makeDereference(const Expr *Arg, QualType Ty);
     62 
     63   /// Create an implicit cast for an integer conversion.
     64   Expr *makeIntegralCast(const Expr *Arg, QualType Ty);
     65 
     66   /// Create an implicit cast to a builtin boolean type.
     67   ImplicitCastExpr *makeIntegralCastToBoolean(const Expr *Arg);
     68 
     69   // Create an implicit cast for lvalue-to-rvaluate conversions.
     70   ImplicitCastExpr *makeLvalueToRvalue(const Expr *Arg, QualType Ty);
     71 
     72   /// Create an Objective-C bool literal.
     73   ObjCBoolLiteralExpr *makeObjCBool(bool Val);
     74 
     75   /// Create an Objective-C ivar reference.
     76   ObjCIvarRefExpr *makeObjCIvarRef(const Expr *Base, const ObjCIvarDecl *IVar);
     77 
     78   /// Create a Return statement.
     79   ReturnStmt *makeReturn(const Expr *RetVal);
     80 
     81 private:
     82   ASTContext &C;
     83 };
     84 }
     85 
     86 BinaryOperator *ASTMaker::makeAssignment(const Expr *LHS, const Expr *RHS,
     87                                          QualType Ty) {
     88  return new (C) BinaryOperator(const_cast<Expr*>(LHS), const_cast<Expr*>(RHS),
     89                                BO_Assign, Ty, VK_RValue,
     90                                OK_Ordinary, SourceLocation(), false);
     91 }
     92 
     93 BinaryOperator *ASTMaker::makeComparison(const Expr *LHS, const Expr *RHS,
     94                                          BinaryOperator::Opcode Op) {
     95   assert(BinaryOperator::isLogicalOp(Op) ||
     96          BinaryOperator::isComparisonOp(Op));
     97   return new (C) BinaryOperator(const_cast<Expr*>(LHS),
     98                                 const_cast<Expr*>(RHS),
     99                                 Op,
    100                                 C.getLogicalOperationType(),
    101                                 VK_RValue,
    102                                 OK_Ordinary, SourceLocation(), false);
    103 }
    104 
    105 CompoundStmt *ASTMaker::makeCompound(ArrayRef<Stmt *> Stmts) {
    106   return new (C) CompoundStmt(C, Stmts, SourceLocation(), SourceLocation());
    107 }
    108 
    109 DeclRefExpr *ASTMaker::makeDeclRefExpr(const VarDecl *D) {
    110   DeclRefExpr *DR =
    111     DeclRefExpr::Create(/* Ctx = */ C,
    112                         /* QualifierLoc = */ NestedNameSpecifierLoc(),
    113                         /* TemplateKWLoc = */ SourceLocation(),
    114                         /* D = */ const_cast<VarDecl*>(D),
    115                         /* RefersToEnclosingVariableOrCapture = */ false,
    116                         /* NameLoc = */ SourceLocation(),
    117                         /* T = */ D->getType(),
    118                         /* VK = */ VK_LValue);
    119   return DR;
    120 }
    121 
    122 UnaryOperator *ASTMaker::makeDereference(const Expr *Arg, QualType Ty) {
    123   return new (C) UnaryOperator(const_cast<Expr*>(Arg), UO_Deref, Ty,
    124                                VK_LValue, OK_Ordinary, SourceLocation());
    125 }
    126 
    127 ImplicitCastExpr *ASTMaker::makeLvalueToRvalue(const Expr *Arg, QualType Ty) {
    128   return ImplicitCastExpr::Create(C, Ty, CK_LValueToRValue,
    129                                   const_cast<Expr*>(Arg), nullptr, VK_RValue);
    130 }
    131 
    132 Expr *ASTMaker::makeIntegralCast(const Expr *Arg, QualType Ty) {
    133   if (Arg->getType() == Ty)
    134     return const_cast<Expr*>(Arg);
    135 
    136   return ImplicitCastExpr::Create(C, Ty, CK_IntegralCast,
    137                                   const_cast<Expr*>(Arg), nullptr, VK_RValue);
    138 }
    139 
    140 ImplicitCastExpr *ASTMaker::makeIntegralCastToBoolean(const Expr *Arg) {
    141   return ImplicitCastExpr::Create(C, C.BoolTy, CK_IntegralToBoolean,
    142                                   const_cast<Expr*>(Arg), nullptr, VK_RValue);
    143 }
    144 
    145 ObjCBoolLiteralExpr *ASTMaker::makeObjCBool(bool Val) {
    146   QualType Ty = C.getBOOLDecl() ? C.getBOOLType() : C.ObjCBuiltinBoolTy;
    147   return new (C) ObjCBoolLiteralExpr(Val, Ty, SourceLocation());
    148 }
    149 
    150 ObjCIvarRefExpr *ASTMaker::makeObjCIvarRef(const Expr *Base,
    151                                            const ObjCIvarDecl *IVar) {
    152   return new (C) ObjCIvarRefExpr(const_cast<ObjCIvarDecl*>(IVar),
    153                                  IVar->getType(), SourceLocation(),
    154                                  SourceLocation(), const_cast<Expr*>(Base),
    155                                  /*arrow=*/true, /*free=*/false);
    156 }
    157 
    158 
    159 ReturnStmt *ASTMaker::makeReturn(const Expr *RetVal) {
    160   return new (C) ReturnStmt(SourceLocation(), const_cast<Expr*>(RetVal),
    161                             nullptr);
    162 }
    163 
    164 //===----------------------------------------------------------------------===//
    165 // Creation functions for faux ASTs.
    166 //===----------------------------------------------------------------------===//
    167 
    168 typedef Stmt *(*FunctionFarmer)(ASTContext &C, const FunctionDecl *D);
    169 
    170 /// Create a fake body for dispatch_once.
    171 static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
    172   // Check if we have at least two parameters.
    173   if (D->param_size() != 2)
    174     return nullptr;
    175 
    176   // Check if the first parameter is a pointer to integer type.
    177   const ParmVarDecl *Predicate = D->getParamDecl(0);
    178   QualType PredicateQPtrTy = Predicate->getType();
    179   const PointerType *PredicatePtrTy = PredicateQPtrTy->getAs<PointerType>();
    180   if (!PredicatePtrTy)
    181     return nullptr;
    182   QualType PredicateTy = PredicatePtrTy->getPointeeType();
    183   if (!PredicateTy->isIntegerType())
    184     return nullptr;
    185 
    186   // Check if the second parameter is the proper block type.
    187   const ParmVarDecl *Block = D->getParamDecl(1);
    188   QualType Ty = Block->getType();
    189   if (!isDispatchBlock(Ty))
    190     return nullptr;
    191 
    192   // Everything checks out.  Create a fakse body that checks the predicate,
    193   // sets it, and calls the block.  Basically, an AST dump of:
    194   //
    195   // void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block) {
    196   //  if (!*predicate) {
    197   //    *predicate = 1;
    198   //    block();
    199   //  }
    200   // }
    201 
    202   ASTMaker M(C);
    203 
    204   // (1) Create the call.
    205   DeclRefExpr *DR = M.makeDeclRefExpr(Block);
    206   ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty);
    207   CallExpr *CE = new (C) CallExpr(C, ICE, None, C.VoidTy, VK_RValue,
    208                                   SourceLocation());
    209 
    210   // (2) Create the assignment to the predicate.
    211   IntegerLiteral *IL =
    212     IntegerLiteral::Create(C, llvm::APInt(C.getTypeSize(C.IntTy), (uint64_t) 1),
    213                            C.IntTy, SourceLocation());
    214   BinaryOperator *B =
    215     M.makeAssignment(
    216        M.makeDereference(
    217           M.makeLvalueToRvalue(
    218             M.makeDeclRefExpr(Predicate), PredicateQPtrTy),
    219             PredicateTy),
    220        M.makeIntegralCast(IL, PredicateTy),
    221        PredicateTy);
    222 
    223   // (3) Create the compound statement.
    224   Stmt *Stmts[] = { B, CE };
    225   CompoundStmt *CS = M.makeCompound(Stmts);
    226 
    227   // (4) Create the 'if' condition.
    228   ImplicitCastExpr *LValToRval =
    229     M.makeLvalueToRvalue(
    230       M.makeDereference(
    231         M.makeLvalueToRvalue(
    232           M.makeDeclRefExpr(Predicate),
    233           PredicateQPtrTy),
    234         PredicateTy),
    235     PredicateTy);
    236 
    237   UnaryOperator *UO = new (C) UnaryOperator(LValToRval, UO_LNot, C.IntTy,
    238                                            VK_RValue, OK_Ordinary,
    239                                            SourceLocation());
    240 
    241   // (5) Create the 'if' statement.
    242   IfStmt *If = new (C) IfStmt(C, SourceLocation(), false, nullptr, nullptr,
    243                               UO, CS);
    244   return If;
    245 }
    246 
    247 /// Create a fake body for dispatch_sync.
    248 static Stmt *create_dispatch_sync(ASTContext &C, const FunctionDecl *D) {
    249   // Check if we have at least two parameters.
    250   if (D->param_size() != 2)
    251     return nullptr;
    252 
    253   // Check if the second parameter is a block.
    254   const ParmVarDecl *PV = D->getParamDecl(1);
    255   QualType Ty = PV->getType();
    256   if (!isDispatchBlock(Ty))
    257     return nullptr;
    258 
    259   // Everything checks out.  Create a fake body that just calls the block.
    260   // This is basically just an AST dump of:
    261   //
    262   // void dispatch_sync(dispatch_queue_t queue, void (^block)(void)) {
    263   //   block();
    264   // }
    265   //
    266   ASTMaker M(C);
    267   DeclRefExpr *DR = M.makeDeclRefExpr(PV);
    268   ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty);
    269   CallExpr *CE = new (C) CallExpr(C, ICE, None, C.VoidTy, VK_RValue,
    270                                   SourceLocation());
    271   return CE;
    272 }
    273 
    274 static Stmt *create_OSAtomicCompareAndSwap(ASTContext &C, const FunctionDecl *D)
    275 {
    276   // There are exactly 3 arguments.
    277   if (D->param_size() != 3)
    278     return nullptr;
    279 
    280   // Signature:
    281   // _Bool OSAtomicCompareAndSwapPtr(void *__oldValue,
    282   //                                 void *__newValue,
    283   //                                 void * volatile *__theValue)
    284   // Generate body:
    285   //   if (oldValue == *theValue) {
    286   //    *theValue = newValue;
    287   //    return YES;
    288   //   }
    289   //   else return NO;
    290 
    291   QualType ResultTy = D->getReturnType();
    292   bool isBoolean = ResultTy->isBooleanType();
    293   if (!isBoolean && !ResultTy->isIntegralType(C))
    294     return nullptr;
    295 
    296   const ParmVarDecl *OldValue = D->getParamDecl(0);
    297   QualType OldValueTy = OldValue->getType();
    298 
    299   const ParmVarDecl *NewValue = D->getParamDecl(1);
    300   QualType NewValueTy = NewValue->getType();
    301 
    302   assert(OldValueTy == NewValueTy);
    303 
    304   const ParmVarDecl *TheValue = D->getParamDecl(2);
    305   QualType TheValueTy = TheValue->getType();
    306   const PointerType *PT = TheValueTy->getAs<PointerType>();
    307   if (!PT)
    308     return nullptr;
    309   QualType PointeeTy = PT->getPointeeType();
    310 
    311   ASTMaker M(C);
    312   // Construct the comparison.
    313   Expr *Comparison =
    314     M.makeComparison(
    315       M.makeLvalueToRvalue(M.makeDeclRefExpr(OldValue), OldValueTy),
    316       M.makeLvalueToRvalue(
    317         M.makeDereference(
    318           M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
    319           PointeeTy),
    320         PointeeTy),
    321       BO_EQ);
    322 
    323   // Construct the body of the IfStmt.
    324   Stmt *Stmts[2];
    325   Stmts[0] =
    326     M.makeAssignment(
    327       M.makeDereference(
    328         M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
    329         PointeeTy),
    330       M.makeLvalueToRvalue(M.makeDeclRefExpr(NewValue), NewValueTy),
    331       NewValueTy);
    332 
    333   Expr *BoolVal = M.makeObjCBool(true);
    334   Expr *RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
    335                            : M.makeIntegralCast(BoolVal, ResultTy);
    336   Stmts[1] = M.makeReturn(RetVal);
    337   CompoundStmt *Body = M.makeCompound(Stmts);
    338 
    339   // Construct the else clause.
    340   BoolVal = M.makeObjCBool(false);
    341   RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
    342                      : M.makeIntegralCast(BoolVal, ResultTy);
    343   Stmt *Else = M.makeReturn(RetVal);
    344 
    345   /// Construct the If.
    346   Stmt *If = new (C) IfStmt(C, SourceLocation(), false, nullptr, nullptr,
    347                             Comparison, Body, SourceLocation(), Else);
    348 
    349   return If;
    350 }
    351 
    352 Stmt *BodyFarm::getBody(const FunctionDecl *D) {
    353   D = D->getCanonicalDecl();
    354 
    355   Optional<Stmt *> &Val = Bodies[D];
    356   if (Val.hasValue())
    357     return Val.getValue();
    358 
    359   Val = nullptr;
    360 
    361   if (D->getIdentifier() == nullptr)
    362     return nullptr;
    363 
    364   StringRef Name = D->getName();
    365   if (Name.empty())
    366     return nullptr;
    367 
    368   FunctionFarmer FF;
    369 
    370   if (Name.startswith("OSAtomicCompareAndSwap") ||
    371       Name.startswith("objc_atomicCompareAndSwap")) {
    372     FF = create_OSAtomicCompareAndSwap;
    373   }
    374   else {
    375     FF = llvm::StringSwitch<FunctionFarmer>(Name)
    376           .Case("dispatch_sync", create_dispatch_sync)
    377           .Case("dispatch_once", create_dispatch_once)
    378           .Default(nullptr);
    379   }
    380 
    381   if (FF) { Val = FF(C, D); }
    382   else if (Injector) { Val = Injector->getBody(D); }
    383   return Val.getValue();
    384 }
    385 
    386 static const ObjCIvarDecl *findBackingIvar(const ObjCPropertyDecl *Prop) {
    387   const ObjCIvarDecl *IVar = Prop->getPropertyIvarDecl();
    388 
    389   if (IVar)
    390     return IVar;
    391 
    392   // When a readonly property is shadowed in a class extensions with a
    393   // a readwrite property, the instance variable belongs to the shadowing
    394   // property rather than the shadowed property. If there is no instance
    395   // variable on a readonly property, check to see whether the property is
    396   // shadowed and if so try to get the instance variable from shadowing
    397   // property.
    398   if (!Prop->isReadOnly())
    399     return nullptr;
    400 
    401   auto *Container = cast<ObjCContainerDecl>(Prop->getDeclContext());
    402   const ObjCInterfaceDecl *PrimaryInterface = nullptr;
    403   if (auto *InterfaceDecl = dyn_cast<ObjCInterfaceDecl>(Container)) {
    404     PrimaryInterface = InterfaceDecl;
    405   } else if (auto *CategoryDecl = dyn_cast<ObjCCategoryDecl>(Container)) {
    406     PrimaryInterface = CategoryDecl->getClassInterface();
    407   } else if (auto *ImplDecl = dyn_cast<ObjCImplDecl>(Container)) {
    408     PrimaryInterface = ImplDecl->getClassInterface();
    409   } else {
    410     return nullptr;
    411   }
    412 
    413   // FindPropertyVisibleInPrimaryClass() looks first in class extensions, so it
    414   // is guaranteed to find the shadowing property, if it exists, rather than
    415   // the shadowed property.
    416   auto *ShadowingProp = PrimaryInterface->FindPropertyVisibleInPrimaryClass(
    417       Prop->getIdentifier(), Prop->getQueryKind());
    418   if (ShadowingProp && ShadowingProp != Prop) {
    419     IVar = ShadowingProp->getPropertyIvarDecl();
    420   }
    421 
    422   return IVar;
    423 }
    424 
    425 static Stmt *createObjCPropertyGetter(ASTContext &Ctx,
    426                                       const ObjCPropertyDecl *Prop) {
    427   // First, find the backing ivar.
    428   const ObjCIvarDecl *IVar = findBackingIvar(Prop);
    429   if (!IVar)
    430     return nullptr;
    431 
    432   // Ignore weak variables, which have special behavior.
    433   if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak)
    434     return nullptr;
    435 
    436   // Look to see if Sema has synthesized a body for us. This happens in
    437   // Objective-C++ because the return value may be a C++ class type with a
    438   // non-trivial copy constructor. We can only do this if we can find the
    439   // @synthesize for this property, though (or if we know it's been auto-
    440   // synthesized).
    441   const ObjCImplementationDecl *ImplDecl =
    442     IVar->getContainingInterface()->getImplementation();
    443   if (ImplDecl) {
    444     for (const auto *I : ImplDecl->property_impls()) {
    445       if (I->getPropertyDecl() != Prop)
    446         continue;
    447 
    448       if (I->getGetterCXXConstructor()) {
    449         ASTMaker M(Ctx);
    450         return M.makeReturn(I->getGetterCXXConstructor());
    451       }
    452     }
    453   }
    454 
    455   // Sanity check that the property is the same type as the ivar, or a
    456   // reference to it, and that it is either an object pointer or trivially
    457   // copyable.
    458   if (!Ctx.hasSameUnqualifiedType(IVar->getType(),
    459                                   Prop->getType().getNonReferenceType()))
    460     return nullptr;
    461   if (!IVar->getType()->isObjCLifetimeType() &&
    462       !IVar->getType().isTriviallyCopyableType(Ctx))
    463     return nullptr;
    464 
    465   // Generate our body:
    466   //   return self->_ivar;
    467   ASTMaker M(Ctx);
    468 
    469   const VarDecl *selfVar = Prop->getGetterMethodDecl()->getSelfDecl();
    470 
    471   Expr *loadedIVar =
    472     M.makeObjCIvarRef(
    473       M.makeLvalueToRvalue(
    474         M.makeDeclRefExpr(selfVar),
    475         selfVar->getType()),
    476       IVar);
    477 
    478   if (!Prop->getType()->isReferenceType())
    479     loadedIVar = M.makeLvalueToRvalue(loadedIVar, IVar->getType());
    480 
    481   return M.makeReturn(loadedIVar);
    482 }
    483 
    484 Stmt *BodyFarm::getBody(const ObjCMethodDecl *D) {
    485   // We currently only know how to synthesize property accessors.
    486   if (!D->isPropertyAccessor())
    487     return nullptr;
    488 
    489   D = D->getCanonicalDecl();
    490 
    491   Optional<Stmt *> &Val = Bodies[D];
    492   if (Val.hasValue())
    493     return Val.getValue();
    494   Val = nullptr;
    495 
    496   const ObjCPropertyDecl *Prop = D->findPropertyDecl();
    497   if (!Prop)
    498     return nullptr;
    499 
    500   // For now, we only synthesize getters.
    501   // Synthesizing setters would cause false negatives in the
    502   // RetainCountChecker because the method body would bind the parameter
    503   // to an instance variable, causing it to escape. This would prevent
    504   // warning in the following common scenario:
    505   //
    506   //  id foo = [[NSObject alloc] init];
    507   //  self.foo = foo; // We should warn that foo leaks here.
    508   //
    509   if (D->param_size() != 0)
    510     return nullptr;
    511 
    512   Val = createObjCPropertyGetter(C, Prop);
    513 
    514   return Val.getValue();
    515 }
    516 
    517