[clang-tools-extra] 98550df - [clang-tidy] Add configuration option to bugprone-unchecked-optional-access check.

Yitzhak Mandelbaum via cfe-commits cfe-commits at lists.llvm.org
Thu Dec 15 07:43:36 PST 2022


Author: Yitzhak Mandelbaum
Date: 2022-12-15T15:43:21Z
New Revision: 98550df7b7bbce0e38a1ec558287d759163c64ba

URL: https://github.com/llvm/llvm-project/commit/98550df7b7bbce0e38a1ec558287d759163c64ba
DIFF: https://github.com/llvm/llvm-project/commit/98550df7b7bbce0e38a1ec558287d759163c64ba.diff

LOG: [clang-tidy] Add configuration option to bugprone-unchecked-optional-access check.

The underlying model already supports ignoring accesses to optionals through
smart pointers. This patch exposes that option through ClangTidy's configuration
options.

Differential Revision: https://reviews.llvm.org/D140021

Added: 
    clang-tools-extra/test/clang-tidy/checkers/bugprone/unchecked-optional-access-ignore-smart.cpp

Modified: 
    clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.cpp
    clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.h

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.cpp
index 7137b78640ff2..c97917ebc3e05 100644
--- a/clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.cpp
@@ -9,18 +9,15 @@
 #include "UncheckedOptionalAccessCheck.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclTemplate.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Analysis/CFG.h"
 #include "clang/Analysis/FlowSensitive/ControlFlowContext.h"
 #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
-#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
 #include "clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h"
 #include "clang/Analysis/FlowSensitive/WatchedLiteralsSolver.h"
 #include "clang/Basic/SourceLocation.h"
-#include "llvm/ADT/Any.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/Error.h"
@@ -33,12 +30,14 @@ namespace bugprone {
 using ast_matchers::MatchFinder;
 using dataflow::UncheckedOptionalAccessDiagnoser;
 using dataflow::UncheckedOptionalAccessModel;
+using dataflow::UncheckedOptionalAccessModelOptions;
 using llvm::Optional;
 
 static constexpr llvm::StringLiteral FuncID("fun");
 
 static Optional<std::vector<SourceLocation>>
-analyzeFunction(const FunctionDecl &FuncDecl, ASTContext &ASTCtx) {
+analyzeFunction(const FunctionDecl &FuncDecl, ASTContext &ASTCtx,
+                UncheckedOptionalAccessModelOptions ModelOptions) {
   using dataflow::ControlFlowContext;
   using dataflow::DataflowAnalysisState;
   using llvm::Expected;
@@ -52,7 +51,7 @@ analyzeFunction(const FunctionDecl &FuncDecl, ASTContext &ASTCtx) {
       std::make_unique<dataflow::WatchedLiteralsSolver>());
   dataflow::Environment Env(AnalysisContext, FuncDecl);
   UncheckedOptionalAccessModel Analysis(ASTCtx);
-  UncheckedOptionalAccessDiagnoser Diagnoser;
+  UncheckedOptionalAccessDiagnoser Diagnoser(ModelOptions);
   std::vector<SourceLocation> Diagnostics;
   Expected<std::vector<
       Optional<DataflowAnalysisState<UncheckedOptionalAccessModel::Lattice>>>>
@@ -98,7 +97,7 @@ void UncheckedOptionalAccessCheck::check(
     return;
 
   if (Optional<std::vector<SourceLocation>> Errors =
-          analyzeFunction(*FuncDecl, *Result.Context))
+          analyzeFunction(*FuncDecl, *Result.Context, ModelOptions))
     for (const SourceLocation &Loc : *Errors)
       diag(Loc, "unchecked access to optional value");
 }

diff  --git a/clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.h b/clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.h
index c00b0d7b14d19..ae583fd0e940f 100644
--- a/clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.h
+++ b/clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.h
@@ -11,6 +11,7 @@
 
 #include "../ClangTidyCheck.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h"
 
 namespace clang {
 namespace tidy {
@@ -24,12 +25,21 @@ namespace bugprone {
 class UncheckedOptionalAccessCheck : public ClangTidyCheck {
 public:
   UncheckedOptionalAccessCheck(StringRef Name, ClangTidyContext *Context)
-      : ClangTidyCheck(Name, Context) {}
+      : ClangTidyCheck(Name, Context),
+        ModelOptions{
+            Options.getLocalOrGlobal("IgnoreSmartPointerDereference", false)} {}
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
   bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
     return LangOpts.CPlusPlus;
   }
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override {
+    Options.store(Opts, "IgnoreSmartPointerDereference",
+                  ModelOptions.IgnoreSmartPointerDereference);
+  }
+
+private:
+  dataflow::UncheckedOptionalAccessModelOptions ModelOptions;
 };
 
 } // namespace bugprone

diff  --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unchecked-optional-access-ignore-smart.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unchecked-optional-access-ignore-smart.cpp
new file mode 100644
index 0000000000000..d29153b3b7bbe
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unchecked-optional-access-ignore-smart.cpp
@@ -0,0 +1,51 @@
+// RUN: %check_clang_tidy %s bugprone-unchecked-optional-access %t -- \
+// RUN:   -config="{CheckOptions: [ \
+// RUN:     {key: bugprone-unchecked-optional-access.IgnoreSmartPointerDereference, value: true}]}" -- \
+// RUN:   -I %S/Inputs/unchecked-optional-access
+
+#include "absl/types/optional.h"
+
+// Include some basic cases to ensure that IgnoreSmartPointerDereference doesn't
+// disable everything. Then check the relevant smart-pointer cases.
+
+void unchecked_deref_operator_access(const absl::optional<int> &opt) {
+  *opt;
+  // CHECK-MESSAGES: :[[@LINE-1]]:4: warning: unchecked access to optional value
+}
+
+void unchecked_value_access(const absl::optional<int> &opt) {
+  opt.value();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: unchecked access to optional value [bugprone-unchecked-optional-access]
+}
+
+struct Foo {
+  void foo() const {}
+};
+
+void unchecked_arrow_operator_access(const absl::optional<Foo> &opt) {
+  opt->foo();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: unchecked access to optional value
+}
+
+template <typename T>
+struct SmartPtr {
+  T& operator*() &;
+  T* operator->();
+};
+
+struct Bar {
+  absl::optional<int> opt;
+};
+
+
+void unchecked_value_access_through_smart_ptr(SmartPtr<absl::optional<int>> s) {
+  s->value();
+  (*s).value();
+
+}
+
+void unchecked_value_access_through_smart_ptr_field(SmartPtr<Bar> s) {
+  s->opt.value();
+  (*s).opt.value();
+
+}


        


More information about the cfe-commits mailing list