aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp235
1 files changed, 0 insertions, 235 deletions
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp
deleted file mode 100644
index 0058f3d3881f..000000000000
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp
+++ /dev/null
@@ -1,235 +0,0 @@
-//=- DirectIvarAssignment.cpp - Check rules on 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
-//
-//===----------------------------------------------------------------------===//
-//
-// Check that Objective C properties are set with the setter, not though a
-// direct assignment.
-//
-// Two versions of a checker exist: one that checks all methods and the other
-// that only checks the methods annotated with
-// __attribute__((annotate("objc_no_direct_instance_variable_assignment")))
-//
-// The checker does not warn about assignments to Ivars, annotated with
-// __attribute__((objc_allow_direct_instance_variable_assignment"))). This
-// annotation serves as a false positive suppression mechanism for the
-// checker. The annotation is allowed on properties and Ivars.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
-#include "clang/AST/Attr.h"
-#include "clang/AST/DeclObjC.h"
-#include "clang/AST/StmtVisitor.h"
-#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
-#include "clang/StaticAnalyzer/Core/Checker.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
-#include "llvm/ADT/DenseMap.h"
-
-using namespace clang;
-using namespace ento;
-
-namespace {
-
-/// The default method filter, which is used to filter out the methods on which
-/// the check should not be performed.
-///
-/// Checks for the init, dealloc, and any other functions that might be allowed
-/// to perform direct instance variable assignment based on their name.
-static bool DefaultMethodFilter(const ObjCMethodDecl *M) {
- return M->getMethodFamily() == OMF_init ||
- M->getMethodFamily() == OMF_dealloc ||
- M->getMethodFamily() == OMF_copy ||
- M->getMethodFamily() == OMF_mutableCopy ||
- M->getSelector().getNameForSlot(0).find("init") != StringRef::npos ||
- M->getSelector().getNameForSlot(0).find("Init") != StringRef::npos;
-}
-
-class DirectIvarAssignment :
- public Checker<check::ASTDecl<ObjCImplementationDecl> > {
-
- typedef llvm::DenseMap<const ObjCIvarDecl*,
- const ObjCPropertyDecl*> IvarToPropertyMapTy;
-
- /// A helper class, which walks the AST and locates all assignments to ivars
- /// in the given function.
- class MethodCrawler : public ConstStmtVisitor<MethodCrawler> {
- const IvarToPropertyMapTy &IvarToPropMap;
- const ObjCMethodDecl *MD;
- const ObjCInterfaceDecl *InterfD;
- BugReporter &BR;
- const CheckerBase *Checker;
- LocationOrAnalysisDeclContext DCtx;
-
- public:
- MethodCrawler(const IvarToPropertyMapTy &InMap, const ObjCMethodDecl *InMD,
- const ObjCInterfaceDecl *InID, BugReporter &InBR,
- const CheckerBase *Checker, AnalysisDeclContext *InDCtx)
- : IvarToPropMap(InMap), MD(InMD), InterfD(InID), BR(InBR),
- Checker(Checker), DCtx(InDCtx) {}
-
- void VisitStmt(const Stmt *S) { VisitChildren(S); }
-
- void VisitBinaryOperator(const BinaryOperator *BO);
-
- void VisitChildren(const Stmt *S) {
- for (const Stmt *Child : S->children())
- if (Child)
- this->Visit(Child);
- }
- };
-
-public:
- bool (*ShouldSkipMethod)(const ObjCMethodDecl *);
-
- DirectIvarAssignment() : ShouldSkipMethod(&DefaultMethodFilter) {}
-
- void checkASTDecl(const ObjCImplementationDecl *D, AnalysisManager& Mgr,
- BugReporter &BR) const;
-};
-
-static const ObjCIvarDecl *findPropertyBackingIvar(const ObjCPropertyDecl *PD,
- const ObjCInterfaceDecl *InterD,
- ASTContext &Ctx) {
- // Check for synthesized ivars.
- ObjCIvarDecl *ID = PD->getPropertyIvarDecl();
- if (ID)
- return ID;
-
- ObjCInterfaceDecl *NonConstInterD = const_cast<ObjCInterfaceDecl*>(InterD);
-
- // Check for existing "_PropName".
- ID = NonConstInterD->lookupInstanceVariable(PD->getDefaultSynthIvarName(Ctx));
- if (ID)
- return ID;
-
- // Check for existing "PropName".
- IdentifierInfo *PropIdent = PD->getIdentifier();
- ID = NonConstInterD->lookupInstanceVariable(PropIdent);
-
- return ID;
-}
-
-void DirectIvarAssignment::checkASTDecl(const ObjCImplementationDecl *D,
- AnalysisManager& Mgr,
- BugReporter &BR) const {
- const ObjCInterfaceDecl *InterD = D->getClassInterface();
-
-
- IvarToPropertyMapTy IvarToPropMap;
-
- // Find all properties for this class.
- for (const auto *PD : InterD->instance_properties()) {
- // Find the corresponding IVar.
- const ObjCIvarDecl *ID = findPropertyBackingIvar(PD, InterD,
- Mgr.getASTContext());
-
- if (!ID)
- continue;
-
- // Store the IVar to property mapping.
- IvarToPropMap[ID] = PD;
- }
-
- if (IvarToPropMap.empty())
- return;
-
- for (const auto *M : D->instance_methods()) {
- AnalysisDeclContext *DCtx = Mgr.getAnalysisDeclContext(M);
-
- if ((*ShouldSkipMethod)(M))
- continue;
-
- const Stmt *Body = M->getBody();
- assert(Body);
-
- MethodCrawler MC(IvarToPropMap, M->getCanonicalDecl(), InterD, BR, this,
- DCtx);
- MC.VisitStmt(Body);
- }
-}
-
-static bool isAnnotatedToAllowDirectAssignment(const Decl *D) {
- for (const auto *Ann : D->specific_attrs<AnnotateAttr>())
- if (Ann->getAnnotation() ==
- "objc_allow_direct_instance_variable_assignment")
- return true;
- return false;
-}
-
-void DirectIvarAssignment::MethodCrawler::VisitBinaryOperator(
- const BinaryOperator *BO) {
- if (!BO->isAssignmentOp())
- return;
-
- const ObjCIvarRefExpr *IvarRef =
- dyn_cast<ObjCIvarRefExpr>(BO->getLHS()->IgnoreParenCasts());
-
- if (!IvarRef)
- return;
-
- if (const ObjCIvarDecl *D = IvarRef->getDecl()) {
- IvarToPropertyMapTy::const_iterator I = IvarToPropMap.find(D);
-
- if (I != IvarToPropMap.end()) {
- const ObjCPropertyDecl *PD = I->second;
- // Skip warnings on Ivars, annotated with
- // objc_allow_direct_instance_variable_assignment. This annotation serves
- // as a false positive suppression mechanism for the checker. The
- // annotation is allowed on properties and ivars.
- if (isAnnotatedToAllowDirectAssignment(PD) ||
- isAnnotatedToAllowDirectAssignment(D))
- return;
-
- ObjCMethodDecl *GetterMethod =
- InterfD->getInstanceMethod(PD->getGetterName());
- ObjCMethodDecl *SetterMethod =
- InterfD->getInstanceMethod(PD->getSetterName());
-
- if (SetterMethod && SetterMethod->getCanonicalDecl() == MD)
- return;
-
- if (GetterMethod && GetterMethod->getCanonicalDecl() == MD)
- return;
-
- BR.EmitBasicReport(
- MD, Checker, "Property access", categories::CoreFoundationObjectiveC,
- "Direct assignment to an instance variable backing a property; "
- "use the setter instead",
- PathDiagnosticLocation(IvarRef, BR.getSourceManager(), DCtx));
- }
- }
-}
-}
-
-// Register the checker that checks for direct accesses in functions annotated
-// with __attribute__((annotate("objc_no_direct_instance_variable_assignment"))).
-static bool AttrFilter(const ObjCMethodDecl *M) {
- for (const auto *Ann : M->specific_attrs<AnnotateAttr>())
- if (Ann->getAnnotation() == "objc_no_direct_instance_variable_assignment")
- return false;
- return true;
-}
-
-// Register the checker that checks for direct accesses in all functions,
-// except for the initialization and copy routines.
-void ento::registerDirectIvarAssignment(CheckerManager &mgr) {
- mgr.registerChecker<DirectIvarAssignment>();
-}
-
-bool ento::shouldRegisterDirectIvarAssignment(const LangOptions &LO) {
- return true;
-}
-
-void ento::registerDirectIvarAssignmentForAnnotatedFunctions(
- CheckerManager &mgr) {
- mgr.getChecker<DirectIvarAssignment>()->ShouldSkipMethod = &AttrFilter;
-}
-
-bool ento::shouldRegisterDirectIvarAssignmentForAnnotatedFunctions(
- const LangOptions &LO) {
- return true;
-}