brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.0 KiB · 08ad687 Raw
85 lines · cpp
1//==- ObjCPropertyChecker.cpp - Check ObjC properties ------------*- C++ -*-==//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9//  This checker finds issues with Objective-C properties.10//  Currently finds only one kind of issue:11//  - Find synthesized properties with copy attribute of mutable NS collection12//    types. Calling -copy on such collections produces an immutable copy,13//    which contradicts the type of the property.14//15//===----------------------------------------------------------------------===//16 17#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"18#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"19#include "clang/StaticAnalyzer/Core/Checker.h"20 21using namespace clang;22using namespace ento;23 24namespace {25class ObjCPropertyChecker26    : public Checker<check::ASTDecl<ObjCPropertyDecl>> {27  void checkCopyMutable(const ObjCPropertyDecl *D, BugReporter &BR) const;28 29public:30  void checkASTDecl(const ObjCPropertyDecl *D, AnalysisManager &Mgr,31                    BugReporter &BR) const;32};33} // end anonymous namespace.34 35void ObjCPropertyChecker::checkASTDecl(const ObjCPropertyDecl *D,36                                       AnalysisManager &Mgr,37                                       BugReporter &BR) const {38  checkCopyMutable(D, BR);39}40 41void ObjCPropertyChecker::checkCopyMutable(const ObjCPropertyDecl *D,42                                           BugReporter &BR) const {43  if (D->isReadOnly() || D->getSetterKind() != ObjCPropertyDecl::Copy)44    return;45 46  QualType T = D->getType();47  if (!T->isObjCObjectPointerType())48    return;49 50  const std::string &PropTypeName(T->getPointeeType().getCanonicalType()51                                                     .getUnqualifiedType()52                                                     .getAsString());53  if (!StringRef(PropTypeName).starts_with("NSMutable"))54    return;55 56  const ObjCImplDecl *ImplD = nullptr;57  if (const ObjCInterfaceDecl *IntD =58          dyn_cast<ObjCInterfaceDecl>(D->getDeclContext())) {59    ImplD = IntD->getImplementation();60  } else if (auto *CatD = dyn_cast<ObjCCategoryDecl>(D->getDeclContext())) {61    ImplD = CatD->getClassInterface()->getImplementation();62  }63 64  if (!ImplD || ImplD->HasUserDeclaredSetterMethod(D))65    return;66 67  SmallString<128> Str;68  llvm::raw_svector_ostream OS(Str);69  OS << "Property of mutable type '" << PropTypeName70     << "' has 'copy' attribute; an immutable object will be stored instead";71 72  BR.EmitBasicReport(73      D, this, "Objective-C property misuse", "Logic error", OS.str(),74      PathDiagnosticLocation::createBegin(D, BR.getSourceManager()),75      D->getSourceRange());76}77 78void ento::registerObjCPropertyChecker(CheckerManager &Mgr) {79  Mgr.registerChecker<ObjCPropertyChecker>();80}81 82bool ento::shouldRegisterObjCPropertyChecker(const CheckerManager &mgr) {83  return true;84}85