[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