blob: 4c7f2cf25d1a7d3f65645938bb0b2a116bd0ae67 [file] [log] [blame]
Ted Kremenekf45d18c2008-09-18 06:33:41 +00001//=- CheckNSError.cpp - Coding conventions for uses of NSError ---*- 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 defines a CheckNSError, a flow-insenstive check
11// that determines if an Objective-C class interface correctly returns
12// a non-void return type.
13//
14// File under feature request PR 2600.
15//
16//===----------------------------------------------------------------------===//
17
18#include "clang/Analysis/LocalCheckers.h"
19#include "clang/Analysis/PathSensitive/BugReporter.h"
Ted Kremenekcfdf9b42008-09-18 21:25:13 +000020#include "clang/Analysis/PathSensitive/GRExprEngine.h"
21#include "BasicObjCFoundationChecks.h"
22#include "llvm/Support/Compiler.h"
Ted Kremenekf45d18c2008-09-18 06:33:41 +000023#include "clang/AST/DeclObjC.h"
Ted Kremenekcfdf9b42008-09-18 21:25:13 +000024#include "clang/AST/Decl.h"
25#include "llvm/ADT/SmallVector.h"
Ted Kremenekf45d18c2008-09-18 06:33:41 +000026
27using namespace clang;
28
Ted Kremenekcfdf9b42008-09-18 21:25:13 +000029namespace {
30class VISIBILITY_HIDDEN NSErrorCheck : public BugTypeCacheLocation {
31
32 void EmitGRWarnings(GRBugReporter& BR);
Ted Kremenekf45d18c2008-09-18 06:33:41 +000033
Ted Kremenekcfdf9b42008-09-18 21:25:13 +000034 void CheckSignature(ObjCMethodDecl& MD, QualType& ResultTy,
35 llvm::SmallVectorImpl<VarDecl*>& Params,
36 IdentifierInfo* NSErrorII);
37
38 bool CheckArgument(QualType ArgTy, IdentifierInfo* NSErrorII);
39
40public:
41 void EmitWarnings(BugReporter& BR) { EmitGRWarnings(cast<GRBugReporter>(BR));}
42 const char* getName() const { return "NSError** null dereference"; }
43};
44
45} // end anonymous namespace
46
47BugType* clang::CreateNSErrorCheck() {
48 return new NSErrorCheck();
49}
50
51void NSErrorCheck::EmitGRWarnings(GRBugReporter& BR) {
52 // Get the analysis engine and the exploded analysis graph.
53 GRExprEngine& Eng = BR.getEngine();
54 GRExprEngine::GraphTy& G = Eng.getGraph();
55
56 // Get the declaration of the method/function that was analyzed.
57 Decl& CodeDecl = G.getCodeDecl();
58
59 ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(&CodeDecl);
60 if (!MD)
61 return;
62
63 // Get the ASTContext, which is useful for querying type information.
Ted Kremenekf45d18c2008-09-18 06:33:41 +000064 ASTContext &Ctx = BR.getContext();
Ted Kremenekcfdf9b42008-09-18 21:25:13 +000065
66 QualType ResultTy;
67 llvm::SmallVector<VarDecl*, 5> Params;
68 CheckSignature(*MD, ResultTy, Params, &Ctx.Idents.get("NSError"));
Ted Kremenekf45d18c2008-09-18 06:33:41 +000069
Ted Kremenekcfdf9b42008-09-18 21:25:13 +000070 if (Params.empty())
71 return;
72
73 if (ResultTy == Ctx.VoidTy) {
74 BR.EmitBasicReport("Bad return type when passing NSError**",
75 "Method accepting NSError** argument should have "
76 "non-void return value to indicate that an error occurred.",
77 CodeDecl.getLocation());
Ted Kremenekf45d18c2008-09-18 06:33:41 +000078
Ted Kremenekf45d18c2008-09-18 06:33:41 +000079 }
80}
Ted Kremenekcfdf9b42008-09-18 21:25:13 +000081
82void NSErrorCheck::CheckSignature(ObjCMethodDecl& M, QualType& ResultTy,
83 llvm::SmallVectorImpl<VarDecl*>& Params,
84 IdentifierInfo* NSErrorII) {
85
86 ResultTy = M.getResultType();
87
88 for (ObjCMethodDecl::param_iterator I=M.param_begin(),
89 E=M.param_end(); I!=E; ++I)
90 if (CheckArgument((*I)->getType(), NSErrorII))
91 Params.push_back(*I);
92}
93
94bool NSErrorCheck::CheckArgument(QualType ArgTy, IdentifierInfo* NSErrorII) {
95 const PointerType* PPT = ArgTy->getAsPointerType();
96 if (!PPT) return false;
97
98 const PointerType* PT = PPT->getPointeeType()->getAsPointerType();
99 if (!PT) return false;
100
101 const ObjCInterfaceType *IT =
102 PT->getPointeeType()->getAsObjCInterfaceType();
103
104 if (!IT) return false;
105 return IT->getDecl()->getIdentifier() == NSErrorII;
106}