1 //==- ObjCPropertyChecker.cpp - Check ObjC properties ------------*- C++ -*-==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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.
16 //===----------------------------------------------------------------------===//
18 #include "ClangSACheckers.h"
19 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
20 #include "clang/StaticAnalyzer/Core/Checker.h"
22 using namespace clang;
26 class ObjCPropertyChecker
27 : public Checker<check::ASTDecl<ObjCPropertyDecl>> {
28 void checkCopyMutable(const ObjCPropertyDecl *D, BugReporter &BR) const;
31 void checkASTDecl(const ObjCPropertyDecl *D, AnalysisManager &Mgr,
32 BugReporter &BR) const;
34 } // end anonymous namespace.
36 void ObjCPropertyChecker::checkASTDecl(const ObjCPropertyDecl *D,
38 BugReporter &BR) const {
39 checkCopyMutable(D, BR);
42 void ObjCPropertyChecker::checkCopyMutable(const ObjCPropertyDecl *D,
43 BugReporter &BR) const {
44 if (D->isReadOnly() || D->getSetterKind() != ObjCPropertyDecl::Copy)
47 QualType T = D->getType();
48 if (!T->isObjCObjectPointerType())
51 const std::string &PropTypeName(T->getPointeeType().getCanonicalType()
54 if (!StringRef(PropTypeName).startswith("NSMutable"))
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();
65 if (!ImplD || ImplD->HasUserDeclaredSetterMethod(D))
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";
74 D, this, "Objective-C property misuse", "Logic error", OS.str(),
75 PathDiagnosticLocation::createBegin(D, BR.getSourceManager()),
79 void ento::registerObjCPropertyChecker(CheckerManager &Mgr) {
80 Mgr.registerChecker<ObjCPropertyChecker>();