blob: 217f607d56f50c88a87c7be329e409d8046ae86d [file] [log] [blame]
Ted Kremeneka43df952012-09-21 00:09:11 +00001//== 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