[clang] 8b6ae9b - [-Wunsafe-buffer-usage] Emit Fix-Its only for C++20 and later standards

Jan Korous via cfe-commits cfe-commits at lists.llvm.org
Thu Feb 9 17:28:45 PST 2023


Author: Jan Korous
Date: 2023-02-09T17:28:27-08:00
New Revision: 8b6ae9bd7466bd3ceefcd8bd0262b9b085481697

URL: https://github.com/llvm/llvm-project/commit/8b6ae9bd7466bd3ceefcd8bd0262b9b085481697
DIFF: https://github.com/llvm/llvm-project/commit/8b6ae9bd7466bd3ceefcd8bd0262b9b085481697.diff

LOG: [-Wunsafe-buffer-usage] Emit Fix-Its only for C++20 and later standards

The transformation strategy we are bringing up heavily relies on std::span which was introduced as part of C++20.

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

Added: 
    clang/test/SemaCXX/warn-unsafe-buffer-usage-no-fixits.cpp

Modified: 
    clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h
    clang/lib/Analysis/UnsafeBufferUsage.cpp
    clang/lib/Sema/AnalysisBasedWarnings.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h
index 926a4fce3ae74..8957ab664ed93 100644
--- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h
+++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h
@@ -53,7 +53,8 @@ class UnsafeBufferUsageHandler {
 
 // This function invokes the analysis and allows the caller to react to it
 // through the handler class.
-void checkUnsafeBufferUsage(const Decl *D, UnsafeBufferUsageHandler &Handler);
+void checkUnsafeBufferUsage(const Decl *D, UnsafeBufferUsageHandler &Handler,
+                            bool EmitFixits);
 
 namespace internal {
 // Tests if any two `FixItHint`s in `FixIts` conflict.  Two `FixItHint`s

diff  --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index ebf9b352e7bc7..61c2c4e4b52ad 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -1008,7 +1008,8 @@ getNaiveStrategy(const llvm::SmallVectorImpl<const VarDecl *> &UnsafeVars) {
 }
 
 void clang::checkUnsafeBufferUsage(const Decl *D,
-                                   UnsafeBufferUsageHandler &Handler) {
+                                   UnsafeBufferUsageHandler &Handler,
+                                   bool EmitFixits) {
   assert(D && D->getBody());
 
   WarningGadgetSets UnsafeOps;
@@ -1016,40 +1017,46 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
   DeclUseTracker Tracker;
 
   {
+    // FIXME: We could skip even matching Fixables' matchers if EmitFixits ==
+    // false.
     auto [FixableGadgets, WarningGadgets, TrackerRes] = findGadgets(D, Handler);
     UnsafeOps = groupWarningGadgetsByVar(std::move(WarningGadgets));
     FixablesForUnsafeVars = groupFixablesByVar(std::move(FixableGadgets));
     Tracker = std::move(TrackerRes);
   }
 
-  // Filter out non-local vars and vars with unclaimed DeclRefExpr-s.
-  for (auto it = FixablesForUnsafeVars.byVar.cbegin();
-       it != FixablesForUnsafeVars.byVar.cend();) {
-    // FIXME: Support ParmVarDecl as well.
-    if (!it->first->isLocalVarDecl() || Tracker.hasUnclaimedUses(it->first)) {
-      it = FixablesForUnsafeVars.byVar.erase(it);
-    } else {
-      ++it;
+  std::map<const VarDecl *, FixItList> FixItsForVariable;
+
+  if (EmitFixits) {
+    // Filter out non-local vars and vars with unclaimed DeclRefExpr-s.
+    for (auto it = FixablesForUnsafeVars.byVar.cbegin();
+         it != FixablesForUnsafeVars.byVar.cend();) {
+      // FIXME: Support ParmVarDecl as well.
+      if (!it->first->isLocalVarDecl() || Tracker.hasUnclaimedUses(it->first)) {
+        it = FixablesForUnsafeVars.byVar.erase(it);
+      } else {
+        ++it;
+      }
     }
-  }
 
-  llvm::SmallVector<const VarDecl *, 16> UnsafeVars;
-  for (const auto &[VD, ignore] : FixablesForUnsafeVars.byVar)
-    UnsafeVars.push_back(VD);
+    llvm::SmallVector<const VarDecl *, 16> UnsafeVars;
+    for (const auto &[VD, ignore] : FixablesForUnsafeVars.byVar)
+      UnsafeVars.push_back(VD);
 
-  Strategy NaiveStrategy = getNaiveStrategy(UnsafeVars);
-  std::map<const VarDecl *, FixItList> FixItsForVariable =
-      getFixIts(FixablesForUnsafeVars, NaiveStrategy, Tracker,
-                D->getASTContext(), Handler);
+    Strategy NaiveStrategy = getNaiveStrategy(UnsafeVars);
+    FixItsForVariable = getFixIts(FixablesForUnsafeVars, NaiveStrategy, Tracker,
+                                  D->getASTContext(), Handler);
 
-  // FIXME Detect overlapping FixIts.
+    // FIXME Detect overlapping FixIts.
+  }
 
   for (const auto &G : UnsafeOps.noVar) {
     Handler.handleUnsafeOperation(G->getBaseStmt(), /*IsRelatedToDecl=*/false);
   }
 
   for (const auto &[VD, WarningGadgets] : UnsafeOps.byVar) {
-    auto FixItsIt = FixItsForVariable.find(VD);
+    auto FixItsIt =
+        EmitFixits ? FixItsForVariable.find(VD) : FixItsForVariable.end();
     Handler.handleFixableVariable(VD, FixItsIt != FixItsForVariable.end()
                                           ? std::move(FixItsIt->second)
                                           : FixItList{});

diff  --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 1ec6d798e3594..85dc3a7eb9507 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -2516,7 +2516,9 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
   if (!Diags.isIgnored(diag::warn_unsafe_buffer_operation, D->getBeginLoc()) ||
       !Diags.isIgnored(diag::warn_unsafe_buffer_variable, D->getBeginLoc())) {
     UnsafeBufferUsageReporter R(S);
-    checkUnsafeBufferUsage(D, R);
+    checkUnsafeBufferUsage(
+        D, R,
+        /*EmitFixits=*/S.getLangOpts().CPlusPlus20);
   }
 
   // If none of the previous checks caused a CFG build, trigger one here

diff  --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-no-fixits.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-no-fixits.cpp
new file mode 100644
index 0000000000000..b69e20cd4eba3
--- /dev/null
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-no-fixits.cpp
@@ -0,0 +1,82 @@
+// RUN: %clang_cc1 -x c -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+
+// RUN: %clang_cc1 -x c -std=c89 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -x c -std=gnu89 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -x c -std=iso9899:1990 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+
+// RUN: %clang_cc1 -x c -std=c17 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -x c -std=gnu17 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -x c -std=iso9899:2017 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -x c -std=c2x -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+
+// RUN: %clang_cc1 -x c++ -std=c++98 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -x c++ -std=gnu++98 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -x c++ -std=c++17 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -x c++ -std=gnu++17 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+
+// RUN: %clang_cc1 -x objective-c++ -std=c++98 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -x objective-c++ -std=gnu++98 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -x objective-c++ -std=c++17 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -x objective-c++ -std=gnu++17 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+
+// CHECK-NOT: fix-it:
+
+typedef int * Int_ptr_t;
+typedef int Int_t;
+
+void local_array_subscript_simple() {
+  int tmp;
+  int *p;
+  const int *q;
+  tmp = p[5];
+  tmp = q[5];
+
+  Int_ptr_t x;
+  Int_ptr_t y;
+  Int_t * z;
+  Int_t * w;
+
+  tmp = x[5];
+  tmp = y[5];
+  tmp = z[5];
+  tmp = w[5];
+}
+
+void local_ptr_to_array() {
+  int tmp;
+  int n = 10;
+  int a[10];
+  int b[n];
+  int *p = a;
+  int *q = b;
+  tmp = p[5];
+  tmp = q[5];
+}
+
+void local_ptr_addrof_init() {
+  int var;
+  int * q = &var;
+  var = q[5];
+}
+
+void decl_without_init() {
+  int tmp;
+  int * p;
+  Int_ptr_t q;
+  tmp = p[5];
+  tmp = q[5];
+}
+
+void explict_cast() {
+  int tmp;
+  int * p;
+  tmp = p[5];
+
+  int a;
+  char * q = (char *)&a;
+  tmp = (int) q[5];
+
+  void * r = &a;
+  char * s = (char *) r;
+  tmp = (int) s[5];
+}


        


More information about the cfe-commits mailing list