BodyFarm.cpp revision a43df9539644bf1c258e12710cd69d79b0b078cd
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 "llvm/ADT/StringSwitch.h" 16#include "clang/AST/ASTContext.h" 17#include "clang/AST/Expr.h" 18#include "clang/AST/Decl.h" 19#include "BodyFarm.h" 20 21using namespace clang; 22 23typedef Stmt *(*FunctionFarmer)(ASTContext &C, const FunctionDecl *D); 24 25 26/// Create a fake body for dispatch_sync. 27static Stmt *create_dispatch_sync(ASTContext &C, const FunctionDecl *D) { 28 // Check if we have at least two parameters. 29 if (D->param_size() != 2) 30 return 0; 31 32 // Check if the second parameter is a block. 33 const ParmVarDecl *PV = D->getParamDecl(1); 34 QualType Ty = PV->getType(); 35 const BlockPointerType *BPT = Ty->getAs<BlockPointerType>(); 36 if (!BPT) 37 return 0; 38 39 // Check if the block pointer type takes no arguments and 40 // returns void. 41 const FunctionProtoType *FT = 42 BPT->getPointeeType()->getAs<FunctionProtoType>(); 43 if (!FT || !FT->getResultType()->isVoidType() || 44 FT->getNumArgs() != 0) 45 return 0; 46 47 // Everything checks out. Create a fake body that just calls the block. 48 // This is basically just an AST dump of: 49 // 50 // void dispatch_sync(dispatch_queue_t queue, void (^block)(void)) { 51 // block(); 52 // } 53 // 54 DeclRefExpr *DR = DeclRefExpr::CreateEmpty(C, false, false, false, false); 55 DR->setDecl(const_cast<ParmVarDecl*>(PV)); 56 DR->setValueKind(VK_LValue); 57 ImplicitCastExpr *ICE = ImplicitCastExpr::Create(C, Ty, CK_LValueToRValue, 58 DR, 0, VK_RValue); 59 CallExpr *CE = new (C) CallExpr(C, ICE, ArrayRef<Expr*>(), C.VoidTy, 60 VK_RValue, SourceLocation()); 61 return CE; 62} 63 64Stmt *BodyFarm::getBody(const FunctionDecl *D) { 65 D = D->getCanonicalDecl(); 66 67 llvm::Optional<Stmt *> &Val = Bodies[D]; 68 if (Val.hasValue()) 69 return Val.getValue(); 70 71 Val = 0; 72 73 if (D->getIdentifier() == 0) 74 return 0; 75 76 StringRef Name = D->getName(); 77 if (Name.empty()) 78 return 0; 79 80 FunctionFarmer FF = 81 llvm::StringSwitch<FunctionFarmer>(Name) 82 .Case("dispatch_sync", create_dispatch_sync) 83 .Default(NULL); 84 85 if (FF) { 86 Val = FF(C, D); 87 } 88 89 return Val.getValue(); 90} 91 92