[clang] 700baeb - [-Wunsafe-buffer-usage] Use `Strategy` to determine whether to fix a parameter

Ziqing Luo via cfe-commits cfe-commits at lists.llvm.org
Thu Sep 21 15:07:54 PDT 2023


Author: Ziqing Luo
Date: 2023-09-21T15:06:22-07:00
New Revision: 700baeb765cfe8628eb68bc24319b3db0209dd84

URL: https://github.com/llvm/llvm-project/commit/700baeb765cfe8628eb68bc24319b3db0209dd84
DIFF: https://github.com/llvm/llvm-project/commit/700baeb765cfe8628eb68bc24319b3db0209dd84.diff

LOG: [-Wunsafe-buffer-usage] Use `Strategy` to determine whether to fix a parameter

- Use Strategy to determine whether to fix a parameter
- Fix the `Strategy` construction so that only variables on the graph
are assigned the `std::span` strategy

Reviewed by: t-rasmud (Rashmi Mudduluru), NoQ (Artem Dergachev)

Differential revision: https://reviews.llvm.org/D157441

Added: 
    

Modified: 
    clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h
    clang/lib/Analysis/UnsafeBufferUsage.cpp
    clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-multi-parm-span.cpp
    clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-fixits-test.cpp
    clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-ptr-init-fixits.cpp
    clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-ptr-init.cpp
    clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-uuc-fixits.cpp
    clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-uuc.cpp
    clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-warnings.cpp
    clang/test/SemaCXX/warn-unsafe-buffer-usage-pragma-fixit.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h
index e8a93164302a47d..8a2d56668e32f92 100644
--- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h
+++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h
@@ -35,6 +35,10 @@ class VariableGroupsManager {
   /// variables, where `Var` is in, contains parameters.
   virtual VarGrpRef getGroupOfVar(const VarDecl *Var,
                                   bool *HasParm = nullptr) const =0;
+
+  /// Returns the non-empty group of variables that include parameters of the
+  /// analyzing function, if such a group exists.  An empty group, otherwise.
+  virtual VarGrpRef getGroupOfParms() const =0;
 };
 
 /// The interface that lets the caller handle unsafe buffer usage analysis

diff  --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index 348585ef16e967b..a4a200469f70be3 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -1634,12 +1634,10 @@ PointerDereferenceGadget::getFixits(const Strategy &S) const {
     CharSourceRange derefRange = clang::CharSourceRange::getCharRange(
         Op->getBeginLoc(), Op->getBeginLoc().getLocWithOffset(1));
     // Inserts the [0]
-    std::optional<SourceLocation> EndOfOperand =
-        getEndCharLoc(BaseDeclRefExpr, SM, Ctx.getLangOpts());
-    if (EndOfOperand) {
+    if (auto LocPastOperand =
+            getPastLoc(BaseDeclRefExpr, SM, Ctx.getLangOpts())) {
       return FixItList{{FixItHint::CreateRemoval(derefRange),
-                        FixItHint::CreateInsertion(
-                            (*EndOfOperand).getLocWithOffset(1), "[0]")}};
+			FixItHint::CreateInsertion(*LocPastOperand, "[0]")}};
     }
     break;
   }
@@ -1978,18 +1976,9 @@ static bool hasConflictingOverload(const FunctionDecl *FD) {
 //   return f(std::span(p, <# size #>));
 // }
 //
-// The actual fix-its may contain more details, e.g., the attribute may be guard
-// by a macro
-//   #if __has_cpp_attribute(clang::unsafe_buffer_usage)
-//   [[clang::unsafe_buffer_usage]]
-//   #endif
-//
-// `ParmsMask` is an array of size of `FD->getNumParams()` such
-// that `ParmsMask[i]` is true iff the `i`-th parameter will be fixed with some
-// strategy.
 static std::optional<FixItList>
-createOverloadsForFixedParams(const std::vector<bool> &ParmsMask, const Strategy &S,
-                              const FunctionDecl *FD, const ASTContext &Ctx,
+createOverloadsForFixedParams(const Strategy &S, const FunctionDecl *FD,
+                              const ASTContext &Ctx,
                               UnsafeBufferUsageHandler &Handler) {
   // FIXME: need to make this conflict checking better:
   if (hasConflictingOverload(FD))
@@ -1999,21 +1988,33 @@ createOverloadsForFixedParams(const std::vector<bool> &ParmsMask, const Strategy
   const LangOptions &LangOpts = Ctx.getLangOpts();
   const unsigned NumParms = FD->getNumParams();
   std::vector<std::string> NewTysTexts(NumParms);
+  std::vector<bool> ParmsMask(NumParms, false);
+  bool AtLeastOneParmToFix = false;
 
   for (unsigned i = 0; i < NumParms; i++) {
-    if (!ParmsMask[i])
+    const ParmVarDecl *PVD = FD->getParamDecl(i);
+
+    if (S.lookup(PVD) == Strategy::Kind::Wontfix)
       continue;
+    if (S.lookup(PVD) != Strategy::Kind::Span)
+      // Not supported, not suppose to happen:
+      return std::nullopt;
 
     std::optional<Qualifiers> PteTyQuals = std::nullopt;
     std::optional<std::string> PteTyText =
-        getPointeeTypeText(FD->getParamDecl(i), SM, LangOpts, &PteTyQuals);
+        getPointeeTypeText(PVD, SM, LangOpts, &PteTyQuals);
 
     if (!PteTyText)
       // something wrong in obtaining the text of the pointee type, give up
       return std::nullopt;
     // FIXME: whether we should create std::span type depends on the Strategy.
     NewTysTexts[i] = getSpanTypeText(*PteTyText, PteTyQuals);
+    ParmsMask[i] = true;
+    AtLeastOneParmToFix = true;
   }
+  if (!AtLeastOneParmToFix)
+    // No need to create function overloads:
+    return {};
   // FIXME Respect indentation of the original code.
 
   // A lambda that creates the text representation of a function declaration
@@ -2322,28 +2323,18 @@ static FixItList createFunctionOverloadsForParms(
     const VariableGroupsManager &VarGrpMgr, const FunctionDecl *FD,
     const Strategy &S, ASTContext &Ctx, UnsafeBufferUsageHandler &Handler) {
   FixItList FixItsSharedByParms{};
-  std::vector<bool> ParmsNeedFixMask(FD->getNumParams(), false);
-  const VarDecl *FirstParmNeedsFix = nullptr;
 
-  for (unsigned i = 0; i < FD->getNumParams(); i++)
-    if (FixItsForVariable.count(FD->getParamDecl(i))) {
-      ParmsNeedFixMask[i] = true;
-      FirstParmNeedsFix = FD->getParamDecl(i);
-    }
-  if (FirstParmNeedsFix) {
-    // In case at least one parameter needs to be fixed:
-    std::optional<FixItList> OverloadFixes =
-        createOverloadsForFixedParams(ParmsNeedFixMask, S, FD, Ctx, Handler);
+  std::optional<FixItList> OverloadFixes =
+      createOverloadsForFixedParams(S, FD, Ctx, Handler);
 
-    if (OverloadFixes) {
-      FixItsSharedByParms.append(*OverloadFixes);
-    } else {
-      // Something wrong in generating `OverloadFixes`, need to remove the
-      // whole group, where parameters are in, from `FixItsForVariable` (Note
-      // that all parameters should be in the same group):
-      for (auto *Member : VarGrpMgr.getGroupOfVar(FirstParmNeedsFix))
-        FixItsForVariable.erase(Member);
-    }
+  if (OverloadFixes) {
+    FixItsSharedByParms.append(*OverloadFixes);
+  } else {
+    // Something wrong in generating `OverloadFixes`, need to remove the
+    // whole group, where parameters are in, from `FixItsForVariable` (Note
+    // that all parameters should be in the same group):
+    for (auto *Member : VarGrpMgr.getGroupOfParms())
+      FixItsForVariable.erase(Member);
   }
   return FixItsSharedByParms;
 }
@@ -2448,8 +2439,9 @@ getFixIts(FixableGadgetSets &FixablesForAllVars, const Strategy &S,
   return FinalFixItsForVariable;
 }
 
+template <typename VarDeclIterTy>
 static Strategy
-getNaiveStrategy(const llvm::SmallVectorImpl<const VarDecl *> &UnsafeVars) {
+getNaiveStrategy(llvm::iterator_range<VarDeclIterTy> UnsafeVars) {
   Strategy S;
   for (const VarDecl *VD : UnsafeVars) {
     S.set(VD, Strategy::Kind::Span);
@@ -2486,6 +2478,10 @@ class VariableGroupsManagerImpl : public VariableGroupsManager {
       return std::nullopt;
     return Groups[It->second];
   }
+
+  VarGrpRef getGroupOfParms() const override {
+    return GrpsUnionForParms.getArrayRef();
+  }
 };
 
 void clang::checkUnsafeBufferUsage(const Decl *D,
@@ -2579,6 +2575,14 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
               it->first, it->first->getBeginLoc(),
               ("failed to produce fixit for '" + it->first->getNameAsString() +
                "' : neither local nor a parameter"));
+#endif
+        it = FixablesForAllVars.byVar.erase(it);
+      } else if (it->first->getType().getCanonicalType()->isReferenceType()) {
+#ifndef NDEBUG
+        Handler.addDebugNoteForVar(it->first, it->first->getBeginLoc(),
+                                   ("failed to produce fixit for '" +
+                                    it->first->getNameAsString() +
+                                    "' : has a reference type"));
 #endif
         it = FixablesForAllVars.byVar.erase(it);
       } else if (Tracker.hasUnclaimedUses(it->first)) {
@@ -2605,10 +2609,6 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
     }
   }
 
-  llvm::SmallVector<const VarDecl *, 16> UnsafeVars;
-  for (const auto &[VD, ignore] : FixablesForAllVars.byVar)
-    UnsafeVars.push_back(VD);
-
   // Fixpoint iteration for pointer assignments
   using DepMapTy = DenseMap<const VarDecl *, llvm::SetVector<const VarDecl *>>;
   DepMapTy DependenciesMap{};
@@ -2737,7 +2737,13 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
       ++I;
   }
 
-  Strategy NaiveStrategy = getNaiveStrategy(UnsafeVars);
+  // We assign strategies to variables that are 1) in the graph and 2) can be
+  // fixed. Other variables have the default "Won't fix" strategy.
+  Strategy NaiveStrategy = getNaiveStrategy(llvm::make_filter_range(
+      VisitedVars, [&FixablesForAllVars](const VarDecl *V) {
+        // If a warned variable has no "Fixable", it is considered unfixable:
+        return FixablesForAllVars.byVar.count(V);
+      }));
   VariableGroupsManagerImpl VarGrpMgr(Groups, VarGrpMap, GrpsUnionForParms);
 
   if (isa<NamedDecl>(D))

diff  --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-multi-parm-span.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-multi-parm-span.cpp
index b3210e93c98fa5d..887909e048f8fc2 100644
--- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-multi-parm-span.cpp
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-multi-parm-span.cpp
@@ -68,18 +68,15 @@ void * multiParmAllFix(int *p, int **q, int a[], int * r);
 
 // Fixing local variables implicates fixing parameters
 void  multiParmLocalAllFix(int *p, int * r) {
-  // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:28-[[@LINE-1]]:34}:"std::span<int> p"
-  // CHECK: fix-it:{{.*}}:{[[@LINE-2]]:36-[[@LINE-2]]:43}:"std::span<int> r"
-  // CHECK: fix-it:{{.*}}:{[[@LINE+1]]:3-[[@LINE+1]]:10}:"std::span<int> x"
-  int * x; // expected-warning{{'x' is an unsafe pointer used for buffer access}} \
-	      expected-note{{change type of 'x' to 'std::span' to preserve bounds information, and change 'p', 'z', and 'r' to safe types to make function 'multiParmLocalAllFix' bounds-safe}}
-  // CHECK: fix-it:{{.*}}:{[[@LINE+1]]:3-[[@LINE+1]]:10}:"std::span<int> z"
-  int * z; // expected-warning{{'z' is an unsafe pointer used for buffer access}} \
-              expected-note{{change type of 'z' to 'std::span' to preserve bounds information, and change 'x', 'p', and 'r' to safe types to make function 'multiParmLocalAllFix' bounds-safe}}
+  // CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]:
+  // CHECK-NOT: fix-it:{{.*}}:{[[@LINE+1]]:
+  int * x; // expected-warning{{'x' is an unsafe pointer used for buffer access}}
+  // CHECK-NOT: fix-it:{{.*}}:{[[@LINE+1]]:
+  int * z; // expected-warning{{'z' is an unsafe pointer used for buffer access}}
   int * y;
 
   x = p;
-  y = x;
+  y = x; // FIXME: we do not fix `y = x` here as the `.data()` fix-it is not generally correct
   // `x` needs to be fixed so does the pointer assigned to `x`, i.e.,`p`
   x[5] = 5; // expected-note{{used in buffer access here}}
   z = r;
@@ -89,33 +86,26 @@ void  multiParmLocalAllFix(int *p, int * r) {
   // fixing `x` involves fixing all `p`, `r` and `z`. Similar for
   // fixing `z`.
 }
-// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void  multiParmLocalAllFix(int *p, int * r) {return multiParmLocalAllFix(std::span<int>(p, <# size #>), std::span<int>(r, <# size #>));}\n"
+// CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]:
 
 
 // Fixing parameters implicates fixing local variables
-// CHECK: fix-it:{{.*}}:{[[@LINE+2]]:29-[[@LINE+2]]:35}:"std::span<int> p"
-// CHECK: fix-it:{{.*}}:{[[@LINE+1]]:37-[[@LINE+1]]:44}:"std::span<int> r"
+// CHECK-NOT: fix-it:{{.*}}:{[[@LINE+1]]:
 void  multiParmLocalAllFix2(int *p, int * r) { // expected-warning{{'p' is an unsafe pointer used for buffer access}} \
-                                                  expected-note{{change type of 'p' to 'std::span' to preserve bounds information, and change 'x', 'r', and 'z' to safe types to make function 'multiParmLocalAllFix2' bounds-safe}} \
-                                                  expected-warning{{'r' is an unsafe pointer used for buffer access}} \
-					          expected-note{{change type of 'r' to 'std::span' to preserve bounds information, and change 'p', 'x', and 'z' to safe types to make function 'multiParmLocalAllFix2' bounds-safe}}
+                                                  expected-warning{{'r' is an unsafe pointer used for buffer access}}
   int * x = new int[10];
-  // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:12}:"std::span<int> x"
-  // CHECK: fix-it:{{.*}}:{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"
-  // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 10}"
+  // CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]:
   int * z = new int[10];
-  // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:12}:"std::span<int> z"
-  // CHECK: fix-it:{{.*}}:{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"
-  // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 10}"
+  // CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]:
   int * y;
 
   p = x;
-  y = x;
+  y = x;    // FIXME: we do not fix `y = x` here as the `.data()` fix-it is not generally correct
   p[5] = 5; // expected-note{{used in buffer access here}}
   r = z;
   r[5] = 5; // expected-note{{used in buffer access here}}
 }
-// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void  multiParmLocalAllFix2(int *p, int * r) {return multiParmLocalAllFix2(std::span<int>(p, <# size #>), std::span<int>(r, <# size #>));}\n"
+// CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]:
 
 
 // No fix emitted for any of the parameter since parameter `r` cannot be fixed

diff  --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-fixits-test.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-fixits-test.cpp
index 2ab311295d343a1..0d7d117bca5c415 100644
--- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-fixits-test.cpp
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-fixits-test.cpp
@@ -2,18 +2,14 @@
 
 void foo1a() {
   int *r = new int[7];
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> r"
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:22-[[@LINE-3]]:22}:", 7}"
+  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
   int *p = new int[4];
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p"
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:22-[[@LINE-3]]:22}:", 4}"
+  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
   p = r;
   int tmp = p[9];
   int *q;
-  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> q"
-  q = r;
+  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
+  q = r;  // FIXME: we do not fix `q = r` here as the `.data()` fix-it is not generally correct
 }
 
 void foo1b() {
@@ -37,15 +33,13 @@ void foo1b() {
 
 void foo1c() {
   int *r = new int[7];
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> r"
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:22-[[@LINE-3]]:22}:", 7}"
+  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
   int *p = new int[4];
-  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p"
-  p = r;
+  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
+  p = r;  // FIXME: we do not fix `p = r` here as the `.data()` fix-it is not generally correct
   int tmp = r[9];
   int *q;
-  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> q"
+  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
   q = r;
   tmp = q[9];
 }
@@ -70,18 +64,12 @@ void foo2a() {
 
 void foo2b() {
   int *r = new int[7];
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> r"
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:22-[[@LINE-3]]:22}:", 7}"
+  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
   int *p = new int[5];
-  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p"
-  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
-  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-3]]:22-[[@LINE-3]]:22}:", 5}"
+  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
   int *q = new int[4];
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> q"
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:22-[[@LINE-3]]:22}:", 4}"
-  p = q;
+  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
+  p = q;  // FIXME: we do not fix `p = q` here as the `.data()` fix-it is not generally correct
   int tmp = q[8];
   q = r;
 }
@@ -107,14 +95,12 @@ void foo2c() {
 
 void foo3a() {
   int *r = new int[7];
-  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> r"
+  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
   int *p = new int[5];
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p"
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:22-[[@LINE-3]]:22}:", 5}"
+  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
   int *q = new int[4];
-  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> q"
-  q = p;
+  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
+  q = p;  // FIXME: we do not fix `q = p` here as the `.data()` fix-it is not generally correct
   int tmp = p[8];
   q = r;
 }

diff  --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-ptr-init-fixits.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-ptr-init-fixits.cpp
index 4a40d3159627c3e..8ad6e11df301a47 100644
--- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-ptr-init-fixits.cpp
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-ptr-init-fixits.cpp
@@ -62,13 +62,11 @@ void test_grouping() {
   int *z = new int[8];
   int tmp;
   int *y = new int[10];
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> y"
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
+  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
   tmp = y[5];
 
   int *x = new int[10];
-  x = y;
+  x = y; // FIXME: we do not fix `x = y` here as the `.data()` fix-it is not generally correct
 
   int *w = z;
 }

diff  --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-ptr-init.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-ptr-init.cpp
index 10ef66edce2be74..45d2bff77696355 100644
--- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-ptr-init.cpp
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-ptr-init.cpp
@@ -27,17 +27,17 @@ void rhs_span3() {
   int *q = new int[6];
   int *p = q;  // expected-warning{{'p' is an unsafe pointer used for buffer access}}
   p[5] = 10;  // expected-note{{used in buffer access here}}
-  int *r = q;
+  int *r = q; // FIXME: we do not fix `int *r = q` here as the `.data()` fix-it is not generally correct
 }
 
 void test_grouping() {
   int *z = new int[8];
   int tmp;
-  int *y = new int[10];  // expected-warning{{'y' is an unsafe pointer used for buffer access}} expected-note{{change type of 'y' to 'std::span' to preserve bounds information}}
+  int *y = new int[10];  // expected-warning{{'y' is an unsafe pointer used for buffer access}}
   tmp = y[5]; // expected-note{{used in buffer access here}}
 
   int *x = new int[10];
-  x = y;
+  x = y;      // FIXME: we do not fix `x = y` here as the `.data()` fix-it is not generally correct
 
   int *w = z;
 }

diff  --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-uuc-fixits.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-uuc-fixits.cpp
index fab8d659ba65ce9..409a03fc0aad9b7 100644
--- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-uuc-fixits.cpp
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-uuc-fixits.cpp
@@ -6,17 +6,13 @@ void bar(int * param) {}
 
 void foo1a() {
   int *r = new int[7];
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> r"
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:22-[[@LINE-3]]:22}:", 7}"
+  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
   int *p = new int[4];
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p"
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:22-[[@LINE-3]]:22}:", 4}"
+  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
   p = r;
   int tmp = p[9];
   int *q;
-  q = r;
+  q = r; // FIXME: we do not fix `q = r` here as the `.data()` fix-it is not generally correct
 }
 
 void uuc_if_body() {

diff  --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-uuc.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-uuc.cpp
index 9f6deac6683ba97..73fe20552d41017 100644
--- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-uuc.cpp
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-uuc.cpp
@@ -3,11 +3,11 @@ void bar(int * param) {}
 
 void foo1a() {
   int *r = new int[7];
-  int *p = new int[4];  // expected-warning{{'p' is an unsafe pointer used for buffer access}} expected-note{{change type of 'p' to 'std::span' to preserve bounds information, and change 'r' to 'std::span' to propagate bounds information between them}}
+  int *p = new int[4];  // expected-warning{{'p' is an unsafe pointer used for buffer access}}
   p = r;
   int tmp = p[9];  // expected-note{{used in buffer access here}}
   int *q;
-  q = r;
+  q = r;           // FIXME: we do not fix `q = r` here as the `.data()` fix-it is not generally correct
 }
 
 void uuc_if_body() {

diff  --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-warnings.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-warnings.cpp
index 0f2491888d297a6..917aa9520347d34 100644
--- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-warnings.cpp
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-warnings.cpp
@@ -18,9 +18,9 @@ void local_assign_both_span() {
 void local_assign_rhs_span() {
   int tmp;
   int* p = new int[10];
-  int* q = new int[10];  // expected-warning{{'q' is an unsafe pointer used for buffer access}} expected-note{{change type of 'q' to 'std::span' to preserve bounds information}}
+  int* q = new int[10];  // expected-warning{{'q' is an unsafe pointer used for buffer access}}
   tmp = q[4];  // expected-note{{used in buffer access here}}
-  p = q;
+  p = q;  // FIXME: we do not fix `p = q` here as the `.data()` fix-it is not generally correct
 }
 
 void local_assign_no_span() {
@@ -49,10 +49,10 @@ void lhs_span_multi_assign() {
 
 void rhs_span() {
   int *x = new int[3];
-  int *y;  // expected-warning{{'y' is an unsafe pointer used for buffer access}} expected-note{{change type of 'y' to 'std::span' to preserve bounds information}}
+  int *y;  // expected-warning{{'y' is an unsafe pointer used for buffer access}}
   y[5] = 10;  // expected-note{{used in buffer access here}}
 
-  x = y;
+  x = y; // FIXME: we do not fix `x = y` here as the `.data()` fix-it is not generally correct
 }
 
 void rhs_span1() {
@@ -65,43 +65,43 @@ void rhs_span1() {
 
 void rhs_span2() {
   int *q = new int[6];
-  int *p = q;  // expected-warning{{'p' is an unsafe pointer used for buffer access}}
+  int *p = q; // expected-warning{{'p' is an unsafe pointer used for buffer access}}
   p[5] = 10;  // expected-note{{used in buffer access here}}
-  int *r = q;
+  int *r = q; // FIXME: we do not fix `int *r = q` here as the `.data()` fix-it is not generally correct
 }
 
 void test_grouping() {
   int *z = new int[8];
   int tmp;
-  int *y = new int[10];  // expected-warning{{'y' is an unsafe pointer used for buffer access}} expected-note{{change type of 'y' to 'std::span' to preserve bounds information}}
+  int *y = new int[10];  // expected-warning{{'y' is an unsafe pointer used for buffer access}}
   tmp = y[5]; // expected-note{{used in buffer access here}}
 
   int *x = new int[10];
-  x = y;
+  x = y;      // FIXME: we do not fix `x = y` here as the `.data()` fix-it is not generally correct
 
   int *w = z;
 }
 
 void test_grouping1() {
   int tmp;
-  int *y = new int[10];  // expected-warning{{'y' is an unsafe pointer used for buffer access}} expected-note{{change type of 'y' to 'std::span' to preserve bounds information}}
+  int *y = new int[10];  // expected-warning{{'y' is an unsafe pointer used for buffer access}}
   tmp = y[5];  // expected-note{{used in buffer access here}}
   int *x = new int[10];
-  x = y;
+  x = y;       // FIXME: we do not fix `x = y` here as the `.data()` fix-it is not generally correct
 
-  int *w = new int[10];  // expected-warning{{'w' is an unsafe pointer used for buffer access}} expected-note{{change type of 'w' to 'std::span' to preserve bounds information}}
+  int *w = new int[10];  // expected-warning{{'w' is an unsafe pointer used for buffer access}}
   tmp = w[5];  // expected-note{{used in buffer access here}}
   int *z = new int[10];
-  z = w;
+  z = w;       // FIXME: we do not fix `z = w` here as the `.data()` fix-it is not generally correct
 }
 
 void foo1a() {
   int *r = new int[7];
-  int *p = new int[4];  // expected-warning{{'p' is an unsafe pointer used for buffer access}} expected-note{{change type of 'p' to 'std::span' to preserve bounds information, and change 'r' to 'std::span' to propagate bounds information between them}}
+  int *p = new int[4];  // expected-warning{{'p' is an unsafe pointer used for buffer access}}
   p = r;
   int tmp = p[9];  // expected-note{{used in buffer access here}}
   int *q;
-  q = r;
+  q = r;  // FIXME: we do not fix `q = r` here as the `.data()` fix-it is not generally correct
 }
 
 void foo1b() {
@@ -115,12 +115,12 @@ void foo1b() {
 }
 
 void foo1c() {
-  int *r = new int[7];  // expected-warning{{'r' is an unsafe pointer used for buffer access}} expected-note{{change type of 'r' to 'std::span' to preserve bounds information, and change 'q' to 'std::span' to propagate bounds information between them}}
+  int *r = new int[7];  // expected-warning{{'r' is an unsafe pointer used for buffer access}}
   int *p = new int[4];
-  p = r;
+  p = r;   // FIXME: we do not fix `p = r` here as the `.data()` fix-it is not generally correct
   int tmp = r[9];  // expected-note{{used in buffer access here}}
-  int *q;  // expected-warning{{'q' is an unsafe pointer used for buffer access}} expected-note{{change type of 'q' to 'std::span' to preserve bounds information, and change 'r' to 'std::span' to propagate bounds information between them}}
-  q = r;
+  int *q;  // expected-warning{{'q' is an unsafe pointer used for buffer access}}
+  q = r;   // FIXME: we do not fix `q = r` here as the `.data()` fix-it is not generally correct
   tmp = q[9];  // expected-note{{used in buffer access here}}
 }
 
@@ -136,8 +136,8 @@ void foo2a() {
 void foo2b() {
   int *r = new int[7];
   int *p = new int[5];
-  int *q = new int[4];  // expected-warning{{'q' is an unsafe pointer used for buffer access}} expected-note{{change type of 'q' to 'std::span' to preserve bounds information, and change 'r' to 'std::span' to propagate bounds information between them}}
-  p = q;
+  int *q = new int[4];  // expected-warning{{'q' is an unsafe pointer used for buffer access}}
+  p = q;           // FIXME: we do not fix `p = q` here as the `.data()` fix-it is not generally correct
   int tmp = q[8];  // expected-note{{used in buffer access here}}
   q = r;
 }
@@ -154,9 +154,9 @@ void foo2c() {
 
 void foo3a() {
   int *r = new int[7];
-  int *p = new int[5];  // expected-warning{{'p' is an unsafe pointer used for buffer access}} expected-note{{change type of 'p' to 'std::span' to preserve bounds information}}
+  int *p = new int[5];  // expected-warning{{'p' is an unsafe pointer used for buffer access}}
   int *q = new int[4];
-  q = p;
+  q = p;           // FIXME: we do not fix `q = p` here as the `.data()` fix-it is not generally correct
   int tmp = p[8];  // expected-note{{used in buffer access here}}
   q = r;
 }

diff  --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-pragma-fixit.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-pragma-fixit.cpp
index 6bd1065e1e2be2a..74ec70b630486f9 100644
--- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-pragma-fixit.cpp
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-pragma-fixit.cpp
@@ -174,7 +174,7 @@ void suppressedVarInGroup3() {
   int * b;
   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
   int * c;
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<int> c"
+  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
 
   c[5] = 5;
 #pragma clang unsafe_buffer_usage begin
@@ -182,6 +182,7 @@ void suppressedVarInGroup3() {
 #pragma clang unsafe_buffer_usage end
   a = b;
   b = c;
+// FIXME: we do not fix `a = b` and `b = c` because the `.data()`  fix-it is not generally correct.
 }
 
 // The implication edges are: `a` -> `b` -> `c` -> `a`.


        


More information about the cfe-commits mailing list