1 //= ObjCNoReturn.cpp - Handling of Cocoa APIs known not to return --*- 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 // This file implements special handling of recognizing ObjC API hooks that 11 // do not return but aren't marked as such in API headers. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "clang/AST/ASTContext.h" 16 #include "clang/AST/ExprObjC.h" 17 #include "clang/Analysis/DomainSpecific/ObjCNoReturn.h" 18 19 using namespace clang; 20 isSubclass(const ObjCInterfaceDecl * Class,IdentifierInfo * II)21static bool isSubclass(const ObjCInterfaceDecl *Class, IdentifierInfo *II) { 22 if (!Class) 23 return false; 24 if (Class->getIdentifier() == II) 25 return true; 26 return isSubclass(Class->getSuperClass(), II); 27 } 28 ObjCNoReturn(ASTContext & C)29ObjCNoReturn::ObjCNoReturn(ASTContext &C) 30 : RaiseSel(GetNullarySelector("raise", C)), 31 NSExceptionII(&C.Idents.get("NSException")) 32 { 33 // Generate selectors. 34 SmallVector<IdentifierInfo*, 3> II; 35 36 // raise:format: 37 II.push_back(&C.Idents.get("raise")); 38 II.push_back(&C.Idents.get("format")); 39 NSExceptionInstanceRaiseSelectors[0] = 40 C.Selectors.getSelector(II.size(), &II[0]); 41 42 // raise:format:arguments: 43 II.push_back(&C.Idents.get("arguments")); 44 NSExceptionInstanceRaiseSelectors[1] = 45 C.Selectors.getSelector(II.size(), &II[0]); 46 } 47 48 isImplicitNoReturn(const ObjCMessageExpr * ME)49bool ObjCNoReturn::isImplicitNoReturn(const ObjCMessageExpr *ME) { 50 Selector S = ME->getSelector(); 51 52 if (ME->isInstanceMessage()) { 53 // Check for the "raise" message. 54 return S == RaiseSel; 55 } 56 57 if (const ObjCInterfaceDecl *ID = ME->getReceiverInterface()) { 58 if (isSubclass(ID, NSExceptionII)) { 59 for (unsigned i = 0; i < NUM_RAISE_SELECTORS; ++i) { 60 if (S == NSExceptionInstanceRaiseSelectors[i]) 61 return true; 62 } 63 } 64 } 65 66 return false; 67 } 68