diff options
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/ObjCPropertyChecker.cpp')
| -rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/ObjCPropertyChecker.cpp | 84 | 
1 files changed, 84 insertions, 0 deletions
| diff --git a/clang/lib/StaticAnalyzer/Checkers/ObjCPropertyChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ObjCPropertyChecker.cpp new file mode 100644 index 000000000000..9a49200545e3 --- /dev/null +++ b/clang/lib/StaticAnalyzer/Checkers/ObjCPropertyChecker.cpp @@ -0,0 +1,84 @@ +//==- ObjCPropertyChecker.cpp - Check ObjC properties ------------*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +//  This checker finds issues with Objective-C properties. +//  Currently finds only one kind of issue: +//  - Find synthesized properties with copy attribute of mutable NS collection +//    types. Calling -copy on such collections produces an immutable copy, +//    which contradicts the type of the property. +// +//===----------------------------------------------------------------------===// + +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" +#include "clang/StaticAnalyzer/Core/Checker.h" + +using namespace clang; +using namespace ento; + +namespace { +class ObjCPropertyChecker +    : public Checker<check::ASTDecl<ObjCPropertyDecl>> { +  void checkCopyMutable(const ObjCPropertyDecl *D, BugReporter &BR) const; + +public: +  void checkASTDecl(const ObjCPropertyDecl *D, AnalysisManager &Mgr, +                    BugReporter &BR) const; +}; +} // end anonymous namespace. + +void ObjCPropertyChecker::checkASTDecl(const ObjCPropertyDecl *D, +                                       AnalysisManager &Mgr, +                                       BugReporter &BR) const { +  checkCopyMutable(D, BR); +} + +void ObjCPropertyChecker::checkCopyMutable(const ObjCPropertyDecl *D, +                                           BugReporter &BR) const { +  if (D->isReadOnly() || D->getSetterKind() != ObjCPropertyDecl::Copy) +    return; + +  QualType T = D->getType(); +  if (!T->isObjCObjectPointerType()) +    return; + +  const std::string &PropTypeName(T->getPointeeType().getCanonicalType() +                                                     .getUnqualifiedType() +                                                     .getAsString()); +  if (!StringRef(PropTypeName).startswith("NSMutable")) +    return; + +  const ObjCImplDecl *ImplD = nullptr; +  if (const ObjCInterfaceDecl *IntD = +          dyn_cast<ObjCInterfaceDecl>(D->getDeclContext())) { +    ImplD = IntD->getImplementation(); +  } else if (auto *CatD = dyn_cast<ObjCCategoryDecl>(D->getDeclContext())) { +    ImplD = CatD->getClassInterface()->getImplementation(); +  } + +  if (!ImplD || ImplD->HasUserDeclaredSetterMethod(D)) +    return; + +  SmallString<128> Str; +  llvm::raw_svector_ostream OS(Str); +  OS << "Property of mutable type '" << PropTypeName +     << "' has 'copy' attribute; an immutable object will be stored instead"; + +  BR.EmitBasicReport( +      D, this, "Objective-C property misuse", "Logic error", OS.str(), +      PathDiagnosticLocation::createBegin(D, BR.getSourceManager()), +      D->getSourceRange()); +} + +void ento::registerObjCPropertyChecker(CheckerManager &Mgr) { +  Mgr.registerChecker<ObjCPropertyChecker>(); +} + +bool ento::shouldRegisterObjCPropertyChecker(const LangOptions &LO) { +  return true; +} | 
