clang 8.0.0

ObjCPropertyChecker.cpp
Go to the documentation of this file.
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 }
ento
clang::ObjCPropertyDecl::Copy
Definition: DeclObjC.h:760
clang::QualType
A (possibly-)qualified type.
Definition: Type.h:638
clang::Type::getPointeeType
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
Definition: Type.cpp:505
clang::ObjCPropertyDecl::getSetterKind
SetterKind getSetterKind() const
getSetterKind - Return the method used for doing assignment in the property setter.
Definition: DeclObjC.h:894
Checker.h
clang::ObjCPropertyDecl::isReadOnly
bool isReadOnly() const
isReadOnly - Return true iff the property has a setter.
Definition: DeclObjC.h:863
clang::ObjCInterfaceDecl
Represents an ObjC class declaration.
Definition: DeclObjC.h:1172
llvm::SmallString
Definition: LLVM.h:35
BugReporter.h
clang::ObjCContainerDecl::HasUserDeclaredSetterMethod
bool HasUserDeclaredSetterMethod(const ObjCPropertyDecl *P) const
This routine returns &#39;true&#39; if a user declared setter method was found in the class, its protocols, its super classes or categories.
Definition: DeclObjC.cpp:124
clang::Decl::getDeclContext
DeclContext * getDeclContext()
Definition: DeclBase.h:427
BuiltinCheckerRegistration.h
clang::ObjCPropertyDecl::getType
QualType getType() const
Definition: DeclObjC.h:829
clang::ento::PathDiagnosticLocation::createBegin
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
Definition: PathDiagnostic.cpp:636
clang::QualType::getCanonicalType
QualType getCanonicalType() const
Definition: Type.h:6111
clang::Type::isObjCObjectPointerType
bool isObjCObjectPointerType() const
Definition: Type.h:6393
clang::ObjCPropertyDecl
Represents one property declaration in an Objective-C interface.
Definition: DeclObjC.h:729
clang::ObjCInterfaceDecl::getImplementation
ObjCImplementationDecl * getImplementation() const
Definition: DeclObjC.cpp:1549
clang::ObjCImplDecl::getClassInterface
const ObjCInterfaceDecl * getClassInterface() const
Definition: DeclObjC.h:2440
clang
Dataflow Directional Tag Classes.
Definition: CFGReachabilityAnalysis.h:22
clang::ObjCImplDecl
Definition: DeclObjC.h:2425
clang::ObjCPropertyDecl::getSourceRange
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition: DeclObjC.h:949
clang::QualType::getAsString
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
Definition: Type.h:971
clang::ento::ObjKind::OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject, used in the Darwin kernel.
clang::QualType::getUnqualifiedType
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition: Type.h:6152