Home | History | Annotate | Download | only in Analysis
      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 
     21 static 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 
     29 ObjCNoReturn::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 
     49 bool 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