1243791Sdim//= ObjCNoReturn.cpp - Handling of Cocoa APIs known not to return --*- C++ -*--- 2243791Sdim// 3243791Sdim// The LLVM Compiler Infrastructure 4243791Sdim// 5243791Sdim// This file is distributed under the University of Illinois Open Source 6243791Sdim// License. See LICENSE.TXT for details. 7243791Sdim// 8243791Sdim//===----------------------------------------------------------------------===// 9243791Sdim// 10243791Sdim// This file implements special handling of recognizing ObjC API hooks that 11243791Sdim// do not return but aren't marked as such in API headers. 12243791Sdim// 13243791Sdim//===----------------------------------------------------------------------===// 14243791Sdim 15243791Sdim#include "clang/AST/ASTContext.h" 16243791Sdim#include "clang/AST/ExprObjC.h" 17243791Sdim#include "clang/Analysis/DomainSpecific/ObjCNoReturn.h" 18243791Sdim 19243791Sdimusing namespace clang; 20243791Sdim 21243791Sdimstatic bool isSubclass(const ObjCInterfaceDecl *Class, IdentifierInfo *II) { 22243791Sdim if (!Class) 23243791Sdim return false; 24243791Sdim if (Class->getIdentifier() == II) 25243791Sdim return true; 26243791Sdim return isSubclass(Class->getSuperClass(), II); 27243791Sdim} 28243791Sdim 29243791SdimObjCNoReturn::ObjCNoReturn(ASTContext &C) 30243791Sdim : RaiseSel(GetNullarySelector("raise", C)), 31243791Sdim NSExceptionII(&C.Idents.get("NSException")) 32243791Sdim{ 33243791Sdim // Generate selectors. 34243791Sdim SmallVector<IdentifierInfo*, 3> II; 35243791Sdim 36243791Sdim // raise:format: 37243791Sdim II.push_back(&C.Idents.get("raise")); 38243791Sdim II.push_back(&C.Idents.get("format")); 39243791Sdim NSExceptionInstanceRaiseSelectors[0] = 40243791Sdim C.Selectors.getSelector(II.size(), &II[0]); 41243791Sdim 42243791Sdim // raise:format:arguments: 43243791Sdim II.push_back(&C.Idents.get("arguments")); 44243791Sdim NSExceptionInstanceRaiseSelectors[1] = 45243791Sdim C.Selectors.getSelector(II.size(), &II[0]); 46243791Sdim} 47243791Sdim 48243791Sdim 49243791Sdimbool ObjCNoReturn::isImplicitNoReturn(const ObjCMessageExpr *ME) { 50243791Sdim Selector S = ME->getSelector(); 51243791Sdim 52243791Sdim if (ME->isInstanceMessage()) { 53243791Sdim // Check for the "raise" message. 54243791Sdim return S == RaiseSel; 55243791Sdim } 56243791Sdim 57243791Sdim if (const ObjCInterfaceDecl *ID = ME->getReceiverInterface()) { 58243791Sdim if (isSubclass(ID, NSExceptionII)) { 59243791Sdim for (unsigned i = 0; i < NUM_RAISE_SELECTORS; ++i) { 60243791Sdim if (S == NSExceptionInstanceRaiseSelectors[i]) 61243791Sdim return true; 62243791Sdim } 63243791Sdim } 64243791Sdim } 65243791Sdim 66243791Sdim return false; 67243791Sdim} 68