[PATCH] D142739: Standalone checker for use of _Optional qualifier

2023-01-29 Thread Christopher Bazley via Phabricator via cfe-commits
chrisbazley added a comment.

Please refer to 
https://discourse.llvm.org/t/rfc-optional-a-type-qualifier-to-indicate-pointer-nullability/
 and https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3089.pdf for the wider 
context of this commit.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142739/new/

https://reviews.llvm.org/D142739

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D142739: Standalone checker for use of _Optional qualifier

2023-01-27 Thread Christopher Bazley via Phabricator via cfe-commits
chrisbazley created this revision.
Herald added subscribers: steakhal, martong.
Herald added a reviewer: NoQ.
Herald added a project: All.
chrisbazley requested review of this revision.
Herald added projects: clang, LLVM.
Herald added subscribers: llvm-commits, cfe-commits.

This checker tries to find violations in use of
pointers to _Optional objects which cannot be
detected by the type system alone. This requires
detection of null pointer dereferences at the
expression level, rather than at the level of
simulated memory accesses (which is already
implemented by other checkers).

Such expressions include those which implicitly
remove the _Optional qualifier from pointer
targets without actually accessing the pointed-to
object.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D142739

Files:
  clang/docs/analyzer/checkers.rst
  clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
  clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
  clang/lib/StaticAnalyzer/Checkers/OptionalityChecker.cpp
  llvm/utils/gn/secondary/clang/lib/StaticAnalyzer/Checkers/BUILD.gn

Index: llvm/utils/gn/secondary/clang/lib/StaticAnalyzer/Checkers/BUILD.gn
===
--- llvm/utils/gn/secondary/clang/lib/StaticAnalyzer/Checkers/BUILD.gn
+++ llvm/utils/gn/secondary/clang/lib/StaticAnalyzer/Checkers/BUILD.gn
@@ -97,6 +97,7 @@
 "ObjCSelfInitChecker.cpp",
 "ObjCSuperDeallocChecker.cpp",
 "ObjCUnusedIVarsChecker.cpp",
+"OptionalityChecker.cpp",
 "PaddingChecker.cpp",
 "PointerArithChecker.cpp",
 "PointerIterationChecker.cpp",
Index: clang/lib/StaticAnalyzer/Checkers/OptionalityChecker.cpp
===
--- /dev/null
+++ clang/lib/StaticAnalyzer/Checkers/OptionalityChecker.cpp
@@ -0,0 +1,138 @@
+//===-- OptionalityChecker.cpp - Optionality checker --===//
+//
+// 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 tries to find violations in use of pointers to _Optional
+// objects which cannot be detected by the type system alone. This requires
+// detection of null pointer dereferences at the expression level, rather than
+// at the level of simulated memory accesses (which is already implemented by
+// other checkers).
+//
+// Such expressions include those which implicitly remove the _Optional
+// qualifier from pointer targets without actually accessing the pointed-to
+// object.
+//
+//===--===//
+
+#include "Iterator.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
+
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/Path.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+class OptionalityChecker
+: public Checker<
+  check::PreStmt, check::PreStmt,
+  check::PreStmt, check::PreStmt> {
+
+  void verifyAccess(CheckerContext , const Expr *E) const;
+
+public:
+  void checkPreStmt(const UnaryOperator *UO, CheckerContext ) const;
+  void checkPreStmt(const BinaryOperator *BO, CheckerContext ) const;
+  void checkPreStmt(const ArraySubscriptExpr *ASE, CheckerContext ) const;
+  void checkPreStmt(const MemberExpr *ME, CheckerContext ) const;
+
+  CheckerNameRef CheckName;
+  mutable std::unique_ptr BT;
+
+  const std::unique_ptr () const {
+if (!BT)
+  BT.reset(new BugType(CheckName, "Optionality", categories::MemoryError));
+return BT;
+  }
+
+private:
+  void reportBug(StringRef Msg, ExplodedNode *N, BugReporter ) const {
+const std::unique_ptr  = getBugType();
+auto R = std::make_unique(*BT, Msg, N);
+BR.emitReport(std::move(R));
+  }
+};
+
+} // end anonymous namespace
+
+void OptionalityChecker::checkPreStmt(const UnaryOperator *UO,
+  CheckerContext ) const {
+  if (isa(UO->getSubExpr()))
+return;
+
+  UnaryOperatorKind OK = UO->getOpcode();
+
+  if (clang::ento::iterator::isAccessOperator(OK)) {
+verifyAccess(C, UO->getSubExpr());
+  }
+}
+
+void OptionalityChecker::checkPreStmt(const BinaryOperator *BO,
+  CheckerContext ) const {
+  BinaryOperatorKind OK = BO->getOpcode();
+
+  if (clang::ento::iterator::isAccessOperator(OK)) {
+verifyAccess(C, BO->getLHS());
+  }
+}
+
+void OptionalityChecker::checkPreStmt(const ArraySubscriptExpr *ASE,
+