[clang] 3a67b91 - [-Wunsafe-buffer-usage] Refactor to let local variable fix-its and parameter fix-its share common code

Ziqing Luo via cfe-commits cfe-commits at lists.llvm.org
Mon Aug 21 14:50:31 PDT 2023


Author: Ziqing Luo
Date: 2023-08-21T14:50:04-07:00
New Revision: 3a67b912386e70073efcb2225c6354b85048b1ae

URL: https://github.com/llvm/llvm-project/commit/3a67b912386e70073efcb2225c6354b85048b1ae
DIFF: https://github.com/llvm/llvm-project/commit/3a67b912386e70073efcb2225c6354b85048b1ae.diff

LOG: [-Wunsafe-buffer-usage] Refactor to let local variable fix-its and parameter fix-its share common code

Refactor the code for local variable fix-its so that it reuses the
code for parameter fix-its, which is in general better. For example,
cv-qualifiers are supported.

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

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

Added: 
    

Modified: 
    clang/lib/Analysis/UnsafeBufferUsage.cpp
    clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-local-var-span.cpp
    clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-access.cpp
    clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-deref.cpp
    clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-unevaluated-context.cpp
    clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index 29543131dae230..7b8d758c60fa70 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -1716,7 +1716,7 @@ std::optional<FixItList> UPCPreIncrementGadget::getFixits(const Strategy &S) con
 //   `Init` a pointer to the initializer expression
 //   `Ctx` a reference to the ASTContext
 static FixItList
-populateInitializerFixItWithSpan(const Expr *Init, ASTContext &Ctx,
+FixVarInitializerWithSpan(const Expr *Init, ASTContext &Ctx,
                                  const StringRef UserFillPlaceHolder) {
   const SourceManager &SM = Ctx.getSourceManager();
   const LangOptions &LangOpts = Ctx.getLangOpts();
@@ -1827,59 +1827,67 @@ static std::optional<std::string> createSpanTypeForVarDecl(const VarDecl *VD,
 }
 
 // For a `VarDecl` of the form `T  * var (= Init)?`, this
-// function generates a fix-it for the declaration, which re-declares `var` to
-// be of `span<T>` type and transforms the initializer, if present, to a span
-// constructor---`span<T> var {Init, Extent}`, where `Extent` may need the user
-// to fill in.
+// function generates fix-its that
+//  1) replace `T * var` with `std::span<T> var`; and
+//  2) change `Init` accordingly to a span constructor, if it exists.
 //
 // FIXME: support Multi-level pointers
 //
 // Parameters:
 //   `D` a pointer the variable declaration node
 //   `Ctx` a reference to the ASTContext
+//   `UserFillPlaceHolder` the user-input placeholder text
 // Returns:
-//    the generated fix-it
-static FixItList fixVarDeclWithSpan(const VarDecl *D, ASTContext &Ctx,
-                                    const StringRef UserFillPlaceHolder,
-                                    UnsafeBufferUsageHandler &Handler) {
-  (void)Handler; // Suppress unused variable warning in release builds.
-  const QualType &SpanEltT = D->getType()->getPointeeType();
-  assert(!SpanEltT.isNull() && "Trying to fix a non-pointer type variable!");
-
+//    the non-empty fix-it list, if fix-its are successfuly generated; empty
+//    list otherwise.
+static FixItList fixLocalVarDeclWithSpan(const VarDecl *D, ASTContext &Ctx,
+                                         const StringRef UserFillPlaceHolder,
+                                         UnsafeBufferUsageHandler &Handler) {
   FixItList FixIts{};
-  std::optional<SourceLocation>
-      ReplacementLastLoc; // the inclusive end location of the replacement
-  const SourceManager &SM = Ctx.getSourceManager();
+  std::optional<std::string> SpanTyText = createSpanTypeForVarDecl(D, Ctx);
+
+  if (!SpanTyText) {
+    DEBUG_NOTE_DECL_FAIL(D, " : failed to generate 'std::span' type");
+    return {};
+  }
 
+  // Will hold the text for `std::span<T> Ident`:
+  std::stringstream SS;
+
+  SS << *SpanTyText;
+  // Append qualifiers to the type of `D`, if any:
+  if (D->getType().hasQualifiers())
+    SS << " " << D->getType().getQualifiers().getAsString();
+
+  // The end of the range of the original source that will be replaced
+  // by `std::span<T> ident`:
+  SourceLocation EndLocForReplacement = D->getEndLoc();
+  std::optional<StringRef> IdentText =
+      getVarDeclIdentifierText(D, Ctx.getSourceManager(), Ctx.getLangOpts());
+
+  if (!IdentText) {
+    DEBUG_NOTE_DECL_FAIL(D, " : failed to locate the identifier");
+    return {};
+  }
+  // Fix the initializer if it exists:
   if (const Expr *Init = D->getInit()) {
     FixItList InitFixIts =
-        populateInitializerFixItWithSpan(Init, Ctx, UserFillPlaceHolder);
-
-    if (InitFixIts.empty()) {
-      DEBUG_NOTE_DECL_FAIL(D, " : empty initializer");
+        FixVarInitializerWithSpan(Init, Ctx, UserFillPlaceHolder);
+    if (InitFixIts.empty())
       return {};
-    }
-
-    // The loc right before the initializer:
-    ReplacementLastLoc = Init->getBeginLoc().getLocWithOffset(-1);
     FixIts.insert(FixIts.end(), std::make_move_iterator(InitFixIts.begin()),
                   std::make_move_iterator(InitFixIts.end()));
-  } else
-    ReplacementLastLoc = getEndCharLoc(D, SM, Ctx.getLangOpts());
-
-  // Producing fix-it for variable declaration---make `D` to be of span type:
-  SmallString<32> Replacement;
-  raw_svector_ostream OS(Replacement);
-
-  OS << "std::span<" << SpanEltT.getAsString() << "> " << D->getName();
-
-  if (!ReplacementLastLoc) {
-    DEBUG_NOTE_DECL_FAIL(D, " : failed to get end char loc (macro)");
+    // If the declaration has the form `T *ident = init`, we want to replace
+    // `T *ident = ` with `std::span<T> ident`:
+    EndLocForReplacement = Init->getBeginLoc().getLocWithOffset(-1);
+  }
+  SS << " " << IdentText->str();
+  if (!EndLocForReplacement.isValid()) {
+    DEBUG_NOTE_DECL_FAIL(D, " : failed to locate the end of the declaration");
     return {};
   }
-
   FixIts.push_back(FixItHint::CreateReplacement(
-      SourceRange{D->getBeginLoc(), *ReplacementLastLoc}, OS.str()));
+      SourceRange(D->getBeginLoc(), EndLocForReplacement), SS.str()));
   return FixIts;
 }
 
@@ -2139,8 +2147,7 @@ static FixItList fixVariableWithSpan(const VarDecl *VD,
   (void)DS;
 
   // FIXME: handle cases where DS has multiple declarations
-  return fixVarDeclWithSpan(VD, Ctx, getUserFillPlaceHolder(),
-                            Handler);
+  return fixLocalVarDeclWithSpan(VD, Ctx, getUserFillPlaceHolder(), Handler);
 }
 
 // TODO: we should be consistent to use `std::nullopt` to represent no-fix due

diff  --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-local-var-span.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-local-var-span.cpp
index 07024ab71751b2..fcc798622918fa 100644
--- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-local-var-span.cpp
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-local-var-span.cpp
@@ -4,53 +4,66 @@
 typedef int * Int_ptr_t;
 typedef int Int_t;
 
-#define DEFINE_PTR(X) int* ptr = (X);
-
 void local_array_subscript_simple() {
   int tmp;
   int *p = new int[10];
-  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p"
-  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
-  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
+  // 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]]:23-[[@LINE-3]]:23}:", 10}"
   const int *q = new int[10];
-  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:17}:"std::span<const int> q"
-  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:18-[[@LINE-2]]:18}:"{"
-  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:29-[[@LINE-3]]:29}:", 10}"
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:17}:"std::span<int const> q"
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:18-[[@LINE-2]]:18}:"{"
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:29-[[@LINE-3]]:29}:", 10}"
   tmp = p[5];
   tmp = q[5];
 
+  // We do not fix the following declaration. Because if the
+  // definition of `Int_ptr_t` gets changed, the fixed code becomes
+  // incorrect and may NOT be noticed.
+  // FIXME: Fix with std::span<std::remove_pointer_t<Int_ptr_t>>?
   Int_ptr_t x = new int[10];
-  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:16}:"std::span<int> x"
-  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:17-[[@LINE-2]]:17}:"{"
-  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:28-[[@LINE-3]]:28}:", 10}"
-  Int_ptr_t y = new int;
-  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:16}:"std::span<int> y"
-  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:17-[[@LINE-2]]:17}:"{"
-  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 1}"
+  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]
   Int_t * z = new int[10];
-  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:14}:"std::span<Int_t> z"
-  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:15-[[@LINE-2]]:15}:"{"
-  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:26-[[@LINE-3]]:26}:", 10}"
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:14}:"std::span<Int_t> z"
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:15-[[@LINE-2]]:15}:"{"
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:26-[[@LINE-3]]:26}:", 10}"
   Int_t * w = new Int_t[10];
-  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:14}:"std::span<Int_t> w"
-  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:15-[[@LINE-2]]:15}:"{"
-  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:28-[[@LINE-3]]:28}:", 10}"
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:14}:"std::span<Int_t> w"
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:15-[[@LINE-2]]:15}:"{"
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:28-[[@LINE-3]]:28}:", 10}"
 
   tmp = x[5];
-  tmp = y[5]; // y[5] will crash after being span
   tmp = z[5];
   tmp = w[5];
 }
 
 void local_array_subscript_auto() {
   int tmp;
+  // We do not fix the following declaration because
+  // that'd cause us to hardcode the element type.
+  // FIXME: Can we use the C++17 class template argument deduction
+  // to avoid spelling out the element type?
   auto p = new int[10];
-  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p"
-  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
-  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
+  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]
   tmp = p[5];
 }
 
+void local_variable_qualifiers_specifiers() {
+  int a[10];
+  const int * p = a;
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:18}:"std::span<int const> p"
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:19-[[@LINE-2]]:19}:"{"
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:20-[[@LINE-3]]:20}:", 10}"
+  const int * const q = a;
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:24}:"std::span<int const> const q"
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:25-[[@LINE-2]]:25}:"{"
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:26-[[@LINE-3]]:26}:", 10}"
+  int tmp;
+  tmp = p[5];
+  tmp = q[5];
+}
+
+
 void local_array_subscript_variable_extent() {
   int n = 10;
   int tmp;
@@ -102,8 +115,8 @@ void decl_without_init() {
   int * p;
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<int> p"
   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-2]]:{{^3}}
-  Int_ptr_t q;
-  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:14}:"std::span<int> q"
+  Int_t * q;
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:12}:"std::span<Int_t> q"
   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-2]]:{{^3}}
   tmp = p[5];
   tmp = q[5];
@@ -168,15 +181,42 @@ void null_init() {
 
 void unsupported_multi_decl(int * x) {
   int * p = x, * q = new int[10];
-  // CHECK-NOT: fix-it:"{{.*}}":[[@LINE-1]]
+  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]
   *p = q[5];
 }
 
+void macroVariableIdentifier() {
+#define MY_NAME p
+#define MY_NAME_ARG(x) q
+
+  // Although fix-its include macros, the macros do not overlap with
+  // the bounds of the source range of these fix-its. So these fix-its
+  // are valid.
+
+  int * MY_NAME = new int[10];
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:18}:"std::span<int> MY_NAME"
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:19-[[@LINE-2]]:19}:"{"
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:30-[[@LINE-3]]:30}:", 10}"
+  int * MY_NAME_ARG( 'x' ) = new int[10];
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:29}:"std::span<int> MY_NAME_ARG( 'x' )"
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:30-[[@LINE-2]]:30}:"{"
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:41-[[@LINE-3]]:41}:", 10}"
+  p[5] = 5;
+  q[5] = 5;
+#undef MY_NAME
+#undef MY_NAME_ARG
+}
+
 void unsupported_fixit_overlapping_macro(int * x) {
   int tmp;
   // In the case below, a tentative fix-it replaces `MY_INT * p =` with `std::span<MY_INT> p `.
-  // It overlaps with the use of the macro `MY_INT`.  The fix-it is
-  // discarded then.
+  // The bounds of the source range of the fix-it overlap with the use of the macro
+  // `MY_INT`.  The fix-it is discarded then.
+
+  // FIXME: we do not have to discard a fix-it if its begin location
+  // overlaps with the begin location of a macro. Similar for end
+  // locations.
+
 #define MY_INT int
   MY_INT * p = new int[10];
   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]
@@ -227,6 +267,8 @@ void unsupported_subscript_negative(int i, unsigned j, unsigned long k) {
   tmp = r[(unsigned int)-1]; // a cast-to-unsigned-expression is also non-negative
 }
 
+#define DEFINE_PTR(X) int* ptr = (X);
+
 void all_vars_in_macro() {
   int* local;
   DEFINE_PTR(local)
@@ -239,10 +281,10 @@ void few_vars_in_macro() {
   ptr[1] = 0;
   int tmp;
   ptr[2] = 30;
-  auto p = new int[10];
-  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p"
-  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
-  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
+  int * p = new int[10];
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:12}:"std::span<int> p"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 10}"
   tmp = p[5];
   int val = *p;
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:13-[[@LINE-1]]:14}:""

diff  --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-access.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-access.cpp
index f1b92ae8d82bcf..20d9d33195a6bd 100644
--- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-access.cpp
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-access.cpp
@@ -10,7 +10,7 @@ void m1(int* v1, int* v2, int) {
 }
 
 void condition_check_nullptr() {
-  auto p = new int[10];
+  int* p = new int[10];
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
@@ -21,7 +21,7 @@ void condition_check_nullptr() {
 }
 
 void condition_check() {
-  auto p = new int[10];
+  int* p = new int[10];
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
@@ -53,12 +53,12 @@ void condition_check() {
 }
 
 void condition_check_two_usafe_buffers() {
-  auto p = new int[10];
+  int* p = new int[10];
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
 
-  auto q = new int[10];
+  int* q = new int[10];
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> q"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
@@ -72,7 +72,7 @@ void condition_check_two_usafe_buffers() {
 }
 
 void unsafe_method_invocation_single_param() {
-  auto p = new int[10];
+  int* p = new int[10];
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
@@ -84,12 +84,12 @@ void unsafe_method_invocation_single_param() {
 }
 
 void safe_method_invocation_single_param() {
-  auto p = new int[10];
+  int* p = new int[10];
   foo(p);
 }
 
 void unsafe_method_invocation_double_param() {
-  auto p = new int[10];
+  int* p = new int[10];
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
@@ -111,7 +111,7 @@ void unsafe_method_invocation_double_param() {
 }
 
 void unsafe_access_in_lamda() {
-  auto p = new int[10];
+  int* p = new int[10];
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
@@ -125,7 +125,7 @@ void unsafe_access_in_lamda() {
 }
 
 void fixits_in_lamda() {
-  auto p = new int[10];
+  int* p = new int[10];
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"

diff  --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-deref.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-deref.cpp
index 4e2d861b11e6a4..91ec3fef6760d0 100644
--- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-deref.cpp
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-deref.cpp
@@ -4,7 +4,7 @@
 
 void basic_dereference() {
   int tmp;
-  auto p = new int[10];
+  int* p = new int[10];
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
@@ -15,7 +15,7 @@ void basic_dereference() {
 }
 
 int return_method() {
-  auto p = new int[10];
+  int* p = new int[10];
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
@@ -29,7 +29,7 @@ void foo(int v) {
 }
 
 void method_invocation() {
-  auto p = new int[10];
+  int* p = new int[10];
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
@@ -42,7 +42,7 @@ void method_invocation() {
 }
 
 void binary_operation() {
-  auto p = new int[10];
+  int* p = new int[10];
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"

diff  --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-unevaluated-context.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-unevaluated-context.cpp
index b493e45b4c74ab..9f9520ee33a6fa 100644
--- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-unevaluated-context.cpp
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-unevaluated-context.cpp
@@ -15,7 +15,7 @@ void foo(...);
 int bar(int *ptr);
 
 void uneval_context_fix_pointer_dereference() {
-  auto p = new int[10];
+  int* p = new int[10];
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
@@ -30,7 +30,7 @@ void uneval_context_fix_pointer_dereference() {
 }
 
 void uneval_context_fix_pointer_array_access() {
-  auto p = new int[10];
+  int* p = new int[10];
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
@@ -41,7 +41,7 @@ void uneval_context_fix_pointer_array_access() {
 }
 
 void uneval_context_fix_pointer_reference() {
-  auto p = new int[10];
+  int* p = new int[10];
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
@@ -63,7 +63,7 @@ void uneval_context_fix_pointer_reference() {
 
 // FIXME: Emit fixits for each of the below use.
 void uneval_context_fix_pointer_dereference_not_handled() {
-  auto p = new int[10];
+  int* p = new int[10];
   int tmp = p[5];
 
   foo(sizeof(*p), sizeof(decltype(*p)));

diff  --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp
index fd3d6cbdf5d93d..06c852c2fab41b 100644
--- a/clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp
@@ -80,28 +80,16 @@ void testArraySubscripts(int *p, int **pp) { // expected-note{{change type of 'p
       );
 }
 
-void testArraySubscriptsWithAuto(int *p, int **pp) {
+void testArraySubscriptsWithAuto() {
   int a[10];
-  auto ap1 = a;   // expected-warning{{'ap1' is an unsafe pointer used for buffer access}} \
-		     expected-note{{change type of 'ap1' to 'std::span' to preserve bounds information}}
-
+  // We do not fix a declaration if the type is `auto`. Because the actual type may change later.
+  auto ap1 = a;   // expected-warning{{'ap1' is an unsafe pointer used for buffer access}}
   foo(ap1[1]);    // expected-note{{used in buffer access here}}
 
-  auto ap2 = p;   // expected-warning{{'ap2' is an unsafe pointer used for buffer access}} \
-  		     expected-note{{change type of 'ap2' to 'std::span' to preserve bounds information}}
-
+  // In case the type is `auto *`, we know it must be a pointer. We can fix it.
+  auto * ap2 = a; // expected-warning{{'ap2' is an unsafe pointer used for buffer access}} \
+                     expected-note{{change type of 'ap2' to 'std::span' to preserve bounds information}}
   foo(ap2[1]);    // expected-note{{used in buffer access here}}
-
-  auto ap3 = pp;  // expected-warning{{'ap3' is an unsafe pointer used for buffer access}} \
-		     expected-note{{change type of 'ap3' to 'std::span' to preserve bounds information}}
-
-  foo(ap3[1][1]); // expected-note{{used in buffer access here}}
-                  // expected-warning at -1{{unsafe buffer access}}
-
-  auto ap4 = *pp; // expected-warning{{'ap4' is an unsafe pointer used for buffer access}} \
-  		     expected-note{{change type of 'ap4' to 'std::span' to preserve bounds information}}
-
-  foo(ap4[1]);    // expected-note{{used in buffer access here}}
 }
 
 void testUnevaluatedContext(int * p) {// no-warning
@@ -395,8 +383,9 @@ void testArrayPtrArithmetic(int x[]) { // expected-warning{{'x' is an unsafe poi
 }
 
 void testMultiLineDeclStmt(int * p) {
-  auto
+  int
 
+  *
 
   ap1 = p;      // expected-warning{{'ap1' is an unsafe pointer used for buffer access}} \
          	   expected-note{{change type of 'ap1' to 'std::span' to preserve bounds information}}


        


More information about the cfe-commits mailing list