]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCPropertyChecker.cpp
Merge clang trunk r351319, resolve conflicts, and update FREEBSD-Xlist.
[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 "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.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 if (auto *CatD = dyn_cast<ObjCCategoryDecl>(D->getDeclContext())) {
62     ImplD = CatD->getClassInterface()->getImplementation();
63   }
64
65   if (!ImplD || ImplD->HasUserDeclaredSetterMethod(D))
66     return;
67
68   SmallString<128> Str;
69   llvm::raw_svector_ostream OS(Str);
70   OS << "Property of mutable type '" << PropTypeName
71      << "' has 'copy' attribute; an immutable object will be stored instead";
72
73   BR.EmitBasicReport(
74       D, this, "Objective-C property misuse", "Logic error", OS.str(),
75       PathDiagnosticLocation::createBegin(D, BR.getSourceManager()),
76       D->getSourceRange());
77 }
78
79 void ento::registerObjCPropertyChecker(CheckerManager &Mgr) {
80   Mgr.registerChecker<ObjCPropertyChecker>();
81 }