]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCPropertyChecker.cpp
Update clang to trunk r290819 and resolve conflicts.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / lib / StaticAnalyzer / Checkers / ObjCPropertyChecker.cpp
1 //==- ObjCPropertyChecker.cpp - Check ObjC properties ------------*- 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 checker finds issues with Objective-C properties.
11 //  Currently finds only one kind of issue:
12 //  - Find synthesized properties with copy attribute of mutable NS collection
13 //    types. Calling -copy on such collections produces an immutable copy,
14 //    which contradicts the type of the property.
15 //
16 //===----------------------------------------------------------------------===//
17
18 #include "ClangSACheckers.h"
19 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
20 #include "clang/StaticAnalyzer/Core/Checker.h"
21
22 using namespace clang;
23 using namespace ento;
24
25 namespace {
26 class ObjCPropertyChecker
27     : public Checker<check::ASTDecl<ObjCPropertyDecl>> {
28   void checkCopyMutable(const ObjCPropertyDecl *D, BugReporter &BR) const;
29
30 public:
31   void checkASTDecl(const ObjCPropertyDecl *D, AnalysisManager &Mgr,
32                     BugReporter &BR) const;
33 };
34 } // end anonymous namespace.
35
36 void ObjCPropertyChecker::checkASTDecl(const ObjCPropertyDecl *D,
37                                        AnalysisManager &Mgr,
38                                        BugReporter &BR) const {
39   checkCopyMutable(D, BR);
40 }
41
42 void ObjCPropertyChecker::checkCopyMutable(const ObjCPropertyDecl *D,
43                                            BugReporter &BR) const {
44   if (D->isReadOnly() || D->getSetterKind() != ObjCPropertyDecl::Copy)
45     return;
46
47   QualType T = D->getType();
48   if (!T->isObjCObjectPointerType())
49     return;
50
51   const std::string &PropTypeName(T->getPointeeType().getCanonicalType()
52                                                      .getUnqualifiedType()
53                                                      .getAsString());
54   if (!StringRef(PropTypeName).startswith("NSMutable"))
55     return;
56
57   const ObjCImplDecl *ImplD = nullptr;
58   if (const ObjCInterfaceDecl *IntD =
59           dyn_cast<ObjCInterfaceDecl>(D->getDeclContext())) {
60     ImplD = IntD->getImplementation();
61   } else {
62     const ObjCCategoryDecl *CatD = cast<ObjCCategoryDecl>(D->getDeclContext());
63     ImplD = CatD->getClassInterface()->getImplementation();
64   }
65
66   if (!ImplD || ImplD->HasUserDeclaredSetterMethod(D))
67     return;
68
69   SmallString<128> Str;
70   llvm::raw_svector_ostream OS(Str);
71   OS << "Property of mutable type '" << PropTypeName
72      << "' has 'copy' attribute; an immutable object will be stored instead";
73
74   BR.EmitBasicReport(
75       D, this, "Objective-C property misuse", "Logic error", OS.str(),
76       PathDiagnosticLocation::createBegin(D, BR.getSourceManager()),
77       D->getSourceRange());
78 }
79
80 void ento::registerObjCPropertyChecker(CheckerManager &Mgr) {
81   Mgr.registerChecker<ObjCPropertyChecker>();
82 }