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