/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Analysis/ObjCNoReturn.cpp
Line | Count | Source |
1 | | //= ObjCNoReturn.cpp - Handling of Cocoa APIs known not to return --*- C++ -*--- |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | // |
9 | | // This file implements special handling of recognizing ObjC API hooks that |
10 | | // do not return but aren't marked as such in API headers. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "clang/AST/ASTContext.h" |
15 | | #include "clang/AST/ExprObjC.h" |
16 | | #include "clang/Analysis/DomainSpecific/ObjCNoReturn.h" |
17 | | |
18 | | using namespace clang; |
19 | | |
20 | 3.09k | static bool isSubclass(const ObjCInterfaceDecl *Class, IdentifierInfo *II) { |
21 | 3.09k | if (!Class) |
22 | 1.01k | return false; |
23 | 2.08k | if (Class->getIdentifier() == II) |
24 | 10 | return true; |
25 | 2.07k | return isSubclass(Class->getSuperClass(), II); |
26 | 2.08k | } |
27 | | |
28 | | ObjCNoReturn::ObjCNoReturn(ASTContext &C) |
29 | | : RaiseSel(GetNullarySelector("raise", C)), |
30 | | NSExceptionII(&C.Idents.get("NSException")) |
31 | 26.6k | { |
32 | | // Generate selectors. |
33 | 26.6k | SmallVector<IdentifierInfo*, 3> II; |
34 | | |
35 | | // raise:format: |
36 | 26.6k | II.push_back(&C.Idents.get("raise")); |
37 | 26.6k | II.push_back(&C.Idents.get("format")); |
38 | 26.6k | NSExceptionInstanceRaiseSelectors[0] = |
39 | 26.6k | C.Selectors.getSelector(II.size(), &II[0]); |
40 | | |
41 | | // raise:format:arguments: |
42 | 26.6k | II.push_back(&C.Idents.get("arguments")); |
43 | 26.6k | NSExceptionInstanceRaiseSelectors[1] = |
44 | 26.6k | C.Selectors.getSelector(II.size(), &II[0]); |
45 | 26.6k | } |
46 | | |
47 | | |
48 | 4.09k | bool ObjCNoReturn::isImplicitNoReturn(const ObjCMessageExpr *ME) { |
49 | 4.09k | Selector S = ME->getSelector(); |
50 | | |
51 | 4.09k | if (ME->isInstanceMessage()) { |
52 | | // Check for the "raise" message. |
53 | 3.06k | return S == RaiseSel; |
54 | 3.06k | } |
55 | | |
56 | 1.02k | if (const ObjCInterfaceDecl *ID = ME->getReceiverInterface()) { |
57 | 1.02k | if (isSubclass(ID, NSExceptionII) && |
58 | 1.02k | llvm::is_contained(NSExceptionInstanceRaiseSelectors, S)10 ) |
59 | 7 | return true; |
60 | 1.02k | } |
61 | | |
62 | 1.01k | return false; |
63 | 1.02k | } |