clang API Documentation
00001 //== BodyFarm.cpp - Factory for conjuring up fake bodies ----------*- C++ -*-// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // BodyFarm is a factory for creating faux implementations for functions/methods 00011 // for analysis purposes. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #include "BodyFarm.h" 00016 #include "clang/Analysis/CodeInjector.h" 00017 #include "clang/AST/ASTContext.h" 00018 #include "clang/AST/Decl.h" 00019 #include "clang/AST/Expr.h" 00020 #include "clang/AST/ExprObjC.h" 00021 #include "llvm/ADT/StringSwitch.h" 00022 00023 using namespace clang; 00024 00025 //===----------------------------------------------------------------------===// 00026 // Helper creation functions for constructing faux ASTs. 00027 //===----------------------------------------------------------------------===// 00028 00029 static bool isDispatchBlock(QualType Ty) { 00030 // Is it a block pointer? 00031 const BlockPointerType *BPT = Ty->getAs<BlockPointerType>(); 00032 if (!BPT) 00033 return false; 00034 00035 // Check if the block pointer type takes no arguments and 00036 // returns void. 00037 const FunctionProtoType *FT = 00038 BPT->getPointeeType()->getAs<FunctionProtoType>(); 00039 if (!FT || !FT->getReturnType()->isVoidType() || FT->getNumParams() != 0) 00040 return false; 00041 00042 return true; 00043 } 00044 00045 namespace { 00046 class ASTMaker { 00047 public: 00048 ASTMaker(ASTContext &C) : C(C) {} 00049 00050 /// Create a new BinaryOperator representing a simple assignment. 00051 BinaryOperator *makeAssignment(const Expr *LHS, const Expr *RHS, QualType Ty); 00052 00053 /// Create a new BinaryOperator representing a comparison. 00054 BinaryOperator *makeComparison(const Expr *LHS, const Expr *RHS, 00055 BinaryOperator::Opcode Op); 00056 00057 /// Create a new compound stmt using the provided statements. 00058 CompoundStmt *makeCompound(ArrayRef<Stmt*>); 00059 00060 /// Create a new DeclRefExpr for the referenced variable. 00061 DeclRefExpr *makeDeclRefExpr(const VarDecl *D); 00062 00063 /// Create a new UnaryOperator representing a dereference. 00064 UnaryOperator *makeDereference(const Expr *Arg, QualType Ty); 00065 00066 /// Create an implicit cast for an integer conversion. 00067 Expr *makeIntegralCast(const Expr *Arg, QualType Ty); 00068 00069 /// Create an implicit cast to a builtin boolean type. 00070 ImplicitCastExpr *makeIntegralCastToBoolean(const Expr *Arg); 00071 00072 // Create an implicit cast for lvalue-to-rvaluate conversions. 00073 ImplicitCastExpr *makeLvalueToRvalue(const Expr *Arg, QualType Ty); 00074 00075 /// Create an Objective-C bool literal. 00076 ObjCBoolLiteralExpr *makeObjCBool(bool Val); 00077 00078 /// Create an Objective-C ivar reference. 00079 ObjCIvarRefExpr *makeObjCIvarRef(const Expr *Base, const ObjCIvarDecl *IVar); 00080 00081 /// Create a Return statement. 00082 ReturnStmt *makeReturn(const Expr *RetVal); 00083 00084 private: 00085 ASTContext &C; 00086 }; 00087 } 00088 00089 BinaryOperator *ASTMaker::makeAssignment(const Expr *LHS, const Expr *RHS, 00090 QualType Ty) { 00091 return new (C) BinaryOperator(const_cast<Expr*>(LHS), const_cast<Expr*>(RHS), 00092 BO_Assign, Ty, VK_RValue, 00093 OK_Ordinary, SourceLocation(), false); 00094 } 00095 00096 BinaryOperator *ASTMaker::makeComparison(const Expr *LHS, const Expr *RHS, 00097 BinaryOperator::Opcode Op) { 00098 assert(BinaryOperator::isLogicalOp(Op) || 00099 BinaryOperator::isComparisonOp(Op)); 00100 return new (C) BinaryOperator(const_cast<Expr*>(LHS), 00101 const_cast<Expr*>(RHS), 00102 Op, 00103 C.getLogicalOperationType(), 00104 VK_RValue, 00105 OK_Ordinary, SourceLocation(), false); 00106 } 00107 00108 CompoundStmt *ASTMaker::makeCompound(ArrayRef<Stmt *> Stmts) { 00109 return new (C) CompoundStmt(C, Stmts, SourceLocation(), SourceLocation()); 00110 } 00111 00112 DeclRefExpr *ASTMaker::makeDeclRefExpr(const VarDecl *D) { 00113 DeclRefExpr *DR = 00114 DeclRefExpr::Create(/* Ctx = */ C, 00115 /* QualifierLoc = */ NestedNameSpecifierLoc(), 00116 /* TemplateKWLoc = */ SourceLocation(), 00117 /* D = */ const_cast<VarDecl*>(D), 00118 /* isEnclosingLocal = */ false, 00119 /* NameLoc = */ SourceLocation(), 00120 /* T = */ D->getType(), 00121 /* VK = */ VK_LValue); 00122 return DR; 00123 } 00124 00125 UnaryOperator *ASTMaker::makeDereference(const Expr *Arg, QualType Ty) { 00126 return new (C) UnaryOperator(const_cast<Expr*>(Arg), UO_Deref, Ty, 00127 VK_LValue, OK_Ordinary, SourceLocation()); 00128 } 00129 00130 ImplicitCastExpr *ASTMaker::makeLvalueToRvalue(const Expr *Arg, QualType Ty) { 00131 return ImplicitCastExpr::Create(C, Ty, CK_LValueToRValue, 00132 const_cast<Expr*>(Arg), nullptr, VK_RValue); 00133 } 00134 00135 Expr *ASTMaker::makeIntegralCast(const Expr *Arg, QualType Ty) { 00136 if (Arg->getType() == Ty) 00137 return const_cast<Expr*>(Arg); 00138 00139 return ImplicitCastExpr::Create(C, Ty, CK_IntegralCast, 00140 const_cast<Expr*>(Arg), nullptr, VK_RValue); 00141 } 00142 00143 ImplicitCastExpr *ASTMaker::makeIntegralCastToBoolean(const Expr *Arg) { 00144 return ImplicitCastExpr::Create(C, C.BoolTy, CK_IntegralToBoolean, 00145 const_cast<Expr*>(Arg), nullptr, VK_RValue); 00146 } 00147 00148 ObjCBoolLiteralExpr *ASTMaker::makeObjCBool(bool Val) { 00149 QualType Ty = C.getBOOLDecl() ? C.getBOOLType() : C.ObjCBuiltinBoolTy; 00150 return new (C) ObjCBoolLiteralExpr(Val, Ty, SourceLocation()); 00151 } 00152 00153 ObjCIvarRefExpr *ASTMaker::makeObjCIvarRef(const Expr *Base, 00154 const ObjCIvarDecl *IVar) { 00155 return new (C) ObjCIvarRefExpr(const_cast<ObjCIvarDecl*>(IVar), 00156 IVar->getType(), SourceLocation(), 00157 SourceLocation(), const_cast<Expr*>(Base), 00158 /*arrow=*/true, /*free=*/false); 00159 } 00160 00161 00162 ReturnStmt *ASTMaker::makeReturn(const Expr *RetVal) { 00163 return new (C) ReturnStmt(SourceLocation(), const_cast<Expr*>(RetVal), 00164 nullptr); 00165 } 00166 00167 //===----------------------------------------------------------------------===// 00168 // Creation functions for faux ASTs. 00169 //===----------------------------------------------------------------------===// 00170 00171 typedef Stmt *(*FunctionFarmer)(ASTContext &C, const FunctionDecl *D); 00172 00173 /// Create a fake body for dispatch_once. 00174 static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) { 00175 // Check if we have at least two parameters. 00176 if (D->param_size() != 2) 00177 return nullptr; 00178 00179 // Check if the first parameter is a pointer to integer type. 00180 const ParmVarDecl *Predicate = D->getParamDecl(0); 00181 QualType PredicateQPtrTy = Predicate->getType(); 00182 const PointerType *PredicatePtrTy = PredicateQPtrTy->getAs<PointerType>(); 00183 if (!PredicatePtrTy) 00184 return nullptr; 00185 QualType PredicateTy = PredicatePtrTy->getPointeeType(); 00186 if (!PredicateTy->isIntegerType()) 00187 return nullptr; 00188 00189 // Check if the second parameter is the proper block type. 00190 const ParmVarDecl *Block = D->getParamDecl(1); 00191 QualType Ty = Block->getType(); 00192 if (!isDispatchBlock(Ty)) 00193 return nullptr; 00194 00195 // Everything checks out. Create a fakse body that checks the predicate, 00196 // sets it, and calls the block. Basically, an AST dump of: 00197 // 00198 // void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block) { 00199 // if (!*predicate) { 00200 // *predicate = 1; 00201 // block(); 00202 // } 00203 // } 00204 00205 ASTMaker M(C); 00206 00207 // (1) Create the call. 00208 DeclRefExpr *DR = M.makeDeclRefExpr(Block); 00209 ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty); 00210 CallExpr *CE = new (C) CallExpr(C, ICE, None, C.VoidTy, VK_RValue, 00211 SourceLocation()); 00212 00213 // (2) Create the assignment to the predicate. 00214 IntegerLiteral *IL = 00215 IntegerLiteral::Create(C, llvm::APInt(C.getTypeSize(C.IntTy), (uint64_t) 1), 00216 C.IntTy, SourceLocation()); 00217 BinaryOperator *B = 00218 M.makeAssignment( 00219 M.makeDereference( 00220 M.makeLvalueToRvalue( 00221 M.makeDeclRefExpr(Predicate), PredicateQPtrTy), 00222 PredicateTy), 00223 M.makeIntegralCast(IL, PredicateTy), 00224 PredicateTy); 00225 00226 // (3) Create the compound statement. 00227 Stmt *Stmts[] = { B, CE }; 00228 CompoundStmt *CS = M.makeCompound(Stmts); 00229 00230 // (4) Create the 'if' condition. 00231 ImplicitCastExpr *LValToRval = 00232 M.makeLvalueToRvalue( 00233 M.makeDereference( 00234 M.makeLvalueToRvalue( 00235 M.makeDeclRefExpr(Predicate), 00236 PredicateQPtrTy), 00237 PredicateTy), 00238 PredicateTy); 00239 00240 UnaryOperator *UO = new (C) UnaryOperator(LValToRval, UO_LNot, C.IntTy, 00241 VK_RValue, OK_Ordinary, 00242 SourceLocation()); 00243 00244 // (5) Create the 'if' statement. 00245 IfStmt *If = new (C) IfStmt(C, SourceLocation(), nullptr, UO, CS); 00246 return If; 00247 } 00248 00249 /// Create a fake body for dispatch_sync. 00250 static Stmt *create_dispatch_sync(ASTContext &C, const FunctionDecl *D) { 00251 // Check if we have at least two parameters. 00252 if (D->param_size() != 2) 00253 return nullptr; 00254 00255 // Check if the second parameter is a block. 00256 const ParmVarDecl *PV = D->getParamDecl(1); 00257 QualType Ty = PV->getType(); 00258 if (!isDispatchBlock(Ty)) 00259 return nullptr; 00260 00261 // Everything checks out. Create a fake body that just calls the block. 00262 // This is basically just an AST dump of: 00263 // 00264 // void dispatch_sync(dispatch_queue_t queue, void (^block)(void)) { 00265 // block(); 00266 // } 00267 // 00268 ASTMaker M(C); 00269 DeclRefExpr *DR = M.makeDeclRefExpr(PV); 00270 ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty); 00271 CallExpr *CE = new (C) CallExpr(C, ICE, None, C.VoidTy, VK_RValue, 00272 SourceLocation()); 00273 return CE; 00274 } 00275 00276 static Stmt *create_OSAtomicCompareAndSwap(ASTContext &C, const FunctionDecl *D) 00277 { 00278 // There are exactly 3 arguments. 00279 if (D->param_size() != 3) 00280 return nullptr; 00281 00282 // Signature: 00283 // _Bool OSAtomicCompareAndSwapPtr(void *__oldValue, 00284 // void *__newValue, 00285 // void * volatile *__theValue) 00286 // Generate body: 00287 // if (oldValue == *theValue) { 00288 // *theValue = newValue; 00289 // return YES; 00290 // } 00291 // else return NO; 00292 00293 QualType ResultTy = D->getReturnType(); 00294 bool isBoolean = ResultTy->isBooleanType(); 00295 if (!isBoolean && !ResultTy->isIntegralType(C)) 00296 return nullptr; 00297 00298 const ParmVarDecl *OldValue = D->getParamDecl(0); 00299 QualType OldValueTy = OldValue->getType(); 00300 00301 const ParmVarDecl *NewValue = D->getParamDecl(1); 00302 QualType NewValueTy = NewValue->getType(); 00303 00304 assert(OldValueTy == NewValueTy); 00305 00306 const ParmVarDecl *TheValue = D->getParamDecl(2); 00307 QualType TheValueTy = TheValue->getType(); 00308 const PointerType *PT = TheValueTy->getAs<PointerType>(); 00309 if (!PT) 00310 return nullptr; 00311 QualType PointeeTy = PT->getPointeeType(); 00312 00313 ASTMaker M(C); 00314 // Construct the comparison. 00315 Expr *Comparison = 00316 M.makeComparison( 00317 M.makeLvalueToRvalue(M.makeDeclRefExpr(OldValue), OldValueTy), 00318 M.makeLvalueToRvalue( 00319 M.makeDereference( 00320 M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy), 00321 PointeeTy), 00322 PointeeTy), 00323 BO_EQ); 00324 00325 // Construct the body of the IfStmt. 00326 Stmt *Stmts[2]; 00327 Stmts[0] = 00328 M.makeAssignment( 00329 M.makeDereference( 00330 M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy), 00331 PointeeTy), 00332 M.makeLvalueToRvalue(M.makeDeclRefExpr(NewValue), NewValueTy), 00333 NewValueTy); 00334 00335 Expr *BoolVal = M.makeObjCBool(true); 00336 Expr *RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal) 00337 : M.makeIntegralCast(BoolVal, ResultTy); 00338 Stmts[1] = M.makeReturn(RetVal); 00339 CompoundStmt *Body = M.makeCompound(Stmts); 00340 00341 // Construct the else clause. 00342 BoolVal = M.makeObjCBool(false); 00343 RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal) 00344 : M.makeIntegralCast(BoolVal, ResultTy); 00345 Stmt *Else = M.makeReturn(RetVal); 00346 00347 /// Construct the If. 00348 Stmt *If = 00349 new (C) IfStmt(C, SourceLocation(), nullptr, Comparison, Body, 00350 SourceLocation(), Else); 00351 00352 return If; 00353 } 00354 00355 Stmt *BodyFarm::getBody(const FunctionDecl *D) { 00356 D = D->getCanonicalDecl(); 00357 00358 Optional<Stmt *> &Val = Bodies[D]; 00359 if (Val.hasValue()) 00360 return Val.getValue(); 00361 00362 Val = nullptr; 00363 00364 if (D->getIdentifier() == nullptr) 00365 return nullptr; 00366 00367 StringRef Name = D->getName(); 00368 if (Name.empty()) 00369 return nullptr; 00370 00371 FunctionFarmer FF; 00372 00373 if (Name.startswith("OSAtomicCompareAndSwap") || 00374 Name.startswith("objc_atomicCompareAndSwap")) { 00375 FF = create_OSAtomicCompareAndSwap; 00376 } 00377 else { 00378 FF = llvm::StringSwitch<FunctionFarmer>(Name) 00379 .Case("dispatch_sync", create_dispatch_sync) 00380 .Case("dispatch_once", create_dispatch_once) 00381 .Default(nullptr); 00382 } 00383 00384 if (FF) { Val = FF(C, D); } 00385 else if (Injector) { Val = Injector->getBody(D); } 00386 return Val.getValue(); 00387 } 00388 00389 static Stmt *createObjCPropertyGetter(ASTContext &Ctx, 00390 const ObjCPropertyDecl *Prop) { 00391 // First, find the backing ivar. 00392 const ObjCIvarDecl *IVar = Prop->getPropertyIvarDecl(); 00393 if (!IVar) 00394 return nullptr; 00395 00396 // Ignore weak variables, which have special behavior. 00397 if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak) 00398 return nullptr; 00399 00400 // Look to see if Sema has synthesized a body for us. This happens in 00401 // Objective-C++ because the return value may be a C++ class type with a 00402 // non-trivial copy constructor. We can only do this if we can find the 00403 // @synthesize for this property, though (or if we know it's been auto- 00404 // synthesized). 00405 const ObjCImplementationDecl *ImplDecl = 00406 IVar->getContainingInterface()->getImplementation(); 00407 if (ImplDecl) { 00408 for (const auto *I : ImplDecl->property_impls()) { 00409 if (I->getPropertyDecl() != Prop) 00410 continue; 00411 00412 if (I->getGetterCXXConstructor()) { 00413 ASTMaker M(Ctx); 00414 return M.makeReturn(I->getGetterCXXConstructor()); 00415 } 00416 } 00417 } 00418 00419 // Sanity check that the property is the same type as the ivar, or a 00420 // reference to it, and that it is either an object pointer or trivially 00421 // copyable. 00422 if (!Ctx.hasSameUnqualifiedType(IVar->getType(), 00423 Prop->getType().getNonReferenceType())) 00424 return nullptr; 00425 if (!IVar->getType()->isObjCLifetimeType() && 00426 !IVar->getType().isTriviallyCopyableType(Ctx)) 00427 return nullptr; 00428 00429 // Generate our body: 00430 // return self->_ivar; 00431 ASTMaker M(Ctx); 00432 00433 const VarDecl *selfVar = Prop->getGetterMethodDecl()->getSelfDecl(); 00434 00435 Expr *loadedIVar = 00436 M.makeObjCIvarRef( 00437 M.makeLvalueToRvalue( 00438 M.makeDeclRefExpr(selfVar), 00439 selfVar->getType()), 00440 IVar); 00441 00442 if (!Prop->getType()->isReferenceType()) 00443 loadedIVar = M.makeLvalueToRvalue(loadedIVar, IVar->getType()); 00444 00445 return M.makeReturn(loadedIVar); 00446 } 00447 00448 Stmt *BodyFarm::getBody(const ObjCMethodDecl *D) { 00449 // We currently only know how to synthesize property accessors. 00450 if (!D->isPropertyAccessor()) 00451 return nullptr; 00452 00453 D = D->getCanonicalDecl(); 00454 00455 Optional<Stmt *> &Val = Bodies[D]; 00456 if (Val.hasValue()) 00457 return Val.getValue(); 00458 Val = nullptr; 00459 00460 const ObjCPropertyDecl *Prop = D->findPropertyDecl(); 00461 if (!Prop) 00462 return nullptr; 00463 00464 // For now, we only synthesize getters. 00465 if (D->param_size() != 0) 00466 return nullptr; 00467 00468 Val = createObjCPropertyGetter(C, Prop); 00469 00470 return Val.getValue(); 00471 } 00472