Skip to content

Commit 700baeb

Browse files
committed
[-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
1 parent e0be78b commit 700baeb

10 files changed

+117
-136
lines changed

clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ class VariableGroupsManager {
3535
/// variables, where `Var` is in, contains parameters.
3636
virtual VarGrpRef getGroupOfVar(const VarDecl *Var,
3737
bool *HasParm = nullptr) const =0;
38+
39+
/// Returns the non-empty group of variables that include parameters of the
40+
/// analyzing function, if such a group exists. An empty group, otherwise.
41+
virtual VarGrpRef getGroupOfParms() const =0;
3842
};
3943

4044
/// The interface that lets the caller handle unsafe buffer usage analysis

clang/lib/Analysis/UnsafeBufferUsage.cpp

Lines changed: 50 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1634,12 +1634,10 @@ PointerDereferenceGadget::getFixits(const Strategy &S) const {
16341634
CharSourceRange derefRange = clang::CharSourceRange::getCharRange(
16351635
Op->getBeginLoc(), Op->getBeginLoc().getLocWithOffset(1));
16361636
// Inserts the [0]
1637-
std::optional<SourceLocation> EndOfOperand =
1638-
getEndCharLoc(BaseDeclRefExpr, SM, Ctx.getLangOpts());
1639-
if (EndOfOperand) {
1637+
if (auto LocPastOperand =
1638+
getPastLoc(BaseDeclRefExpr, SM, Ctx.getLangOpts())) {
16401639
return FixItList{{FixItHint::CreateRemoval(derefRange),
1641-
FixItHint::CreateInsertion(
1642-
(*EndOfOperand).getLocWithOffset(1), "[0]")}};
1640+
FixItHint::CreateInsertion(*LocPastOperand, "[0]")}};
16431641
}
16441642
break;
16451643
}
@@ -1978,18 +1976,9 @@ static bool hasConflictingOverload(const FunctionDecl *FD) {
19781976
// return f(std::span(p, <# size #>));
19791977
// }
19801978
//
1981-
// The actual fix-its may contain more details, e.g., the attribute may be guard
1982-
// by a macro
1983-
// #if __has_cpp_attribute(clang::unsafe_buffer_usage)
1984-
// [[clang::unsafe_buffer_usage]]
1985-
// #endif
1986-
//
1987-
// `ParmsMask` is an array of size of `FD->getNumParams()` such
1988-
// that `ParmsMask[i]` is true iff the `i`-th parameter will be fixed with some
1989-
// strategy.
19901979
static std::optional<FixItList>
1991-
createOverloadsForFixedParams(const std::vector<bool> &ParmsMask, const Strategy &S,
1992-
const FunctionDecl *FD, const ASTContext &Ctx,
1980+
createOverloadsForFixedParams(const Strategy &S, const FunctionDecl *FD,
1981+
const ASTContext &Ctx,
19931982
UnsafeBufferUsageHandler &Handler) {
19941983
// FIXME: need to make this conflict checking better:
19951984
if (hasConflictingOverload(FD))
@@ -1999,21 +1988,33 @@ createOverloadsForFixedParams(const std::vector<bool> &ParmsMask, const Strategy
19991988
const LangOptions &LangOpts = Ctx.getLangOpts();
20001989
const unsigned NumParms = FD->getNumParams();
20011990
std::vector<std::string> NewTysTexts(NumParms);
1991+
std::vector<bool> ParmsMask(NumParms, false);
1992+
bool AtLeastOneParmToFix = false;
20021993

20031994
for (unsigned i = 0; i < NumParms; i++) {
2004-
if (!ParmsMask[i])
1995+
const ParmVarDecl *PVD = FD->getParamDecl(i);
1996+
1997+
if (S.lookup(PVD) == Strategy::Kind::Wontfix)
20051998
continue;
1999+
if (S.lookup(PVD) != Strategy::Kind::Span)
2000+
// Not supported, not suppose to happen:
2001+
return std::nullopt;
20062002

20072003
std::optional<Qualifiers> PteTyQuals = std::nullopt;
20082004
std::optional<std::string> PteTyText =
2009-
getPointeeTypeText(FD->getParamDecl(i), SM, LangOpts, &PteTyQuals);
2005+
getPointeeTypeText(PVD, SM, LangOpts, &PteTyQuals);
20102006

20112007
if (!PteTyText)
20122008
// something wrong in obtaining the text of the pointee type, give up
20132009
return std::nullopt;
20142010
// FIXME: whether we should create std::span type depends on the Strategy.
20152011
NewTysTexts[i] = getSpanTypeText(*PteTyText, PteTyQuals);
2012+
ParmsMask[i] = true;
2013+
AtLeastOneParmToFix = true;
20162014
}
2015+
if (!AtLeastOneParmToFix)
2016+
// No need to create function overloads:
2017+
return {};
20172018
// FIXME Respect indentation of the original code.
20182019

20192020
// A lambda that creates the text representation of a function declaration
@@ -2322,28 +2323,18 @@ static FixItList createFunctionOverloadsForParms(
23222323
const VariableGroupsManager &VarGrpMgr, const FunctionDecl *FD,
23232324
const Strategy &S, ASTContext &Ctx, UnsafeBufferUsageHandler &Handler) {
23242325
FixItList FixItsSharedByParms{};
2325-
std::vector<bool> ParmsNeedFixMask(FD->getNumParams(), false);
2326-
const VarDecl *FirstParmNeedsFix = nullptr;
23272326

2328-
for (unsigned i = 0; i < FD->getNumParams(); i++)
2329-
if (FixItsForVariable.count(FD->getParamDecl(i))) {
2330-
ParmsNeedFixMask[i] = true;
2331-
FirstParmNeedsFix = FD->getParamDecl(i);
2332-
}
2333-
if (FirstParmNeedsFix) {
2334-
// In case at least one parameter needs to be fixed:
2335-
std::optional<FixItList> OverloadFixes =
2336-
createOverloadsForFixedParams(ParmsNeedFixMask, S, FD, Ctx, Handler);
2327+
std::optional<FixItList> OverloadFixes =
2328+
createOverloadsForFixedParams(S, FD, Ctx, Handler);
23372329

2338-
if (OverloadFixes) {
2339-
FixItsSharedByParms.append(*OverloadFixes);
2340-
} else {
2341-
// Something wrong in generating `OverloadFixes`, need to remove the
2342-
// whole group, where parameters are in, from `FixItsForVariable` (Note
2343-
// that all parameters should be in the same group):
2344-
for (auto *Member : VarGrpMgr.getGroupOfVar(FirstParmNeedsFix))
2345-
FixItsForVariable.erase(Member);
2346-
}
2330+
if (OverloadFixes) {
2331+
FixItsSharedByParms.append(*OverloadFixes);
2332+
} else {
2333+
// Something wrong in generating `OverloadFixes`, need to remove the
2334+
// whole group, where parameters are in, from `FixItsForVariable` (Note
2335+
// that all parameters should be in the same group):
2336+
for (auto *Member : VarGrpMgr.getGroupOfParms())
2337+
FixItsForVariable.erase(Member);
23472338
}
23482339
return FixItsSharedByParms;
23492340
}
@@ -2448,8 +2439,9 @@ getFixIts(FixableGadgetSets &FixablesForAllVars, const Strategy &S,
24482439
return FinalFixItsForVariable;
24492440
}
24502441

2442+
template <typename VarDeclIterTy>
24512443
static Strategy
2452-
getNaiveStrategy(const llvm::SmallVectorImpl<const VarDecl *> &UnsafeVars) {
2444+
getNaiveStrategy(llvm::iterator_range<VarDeclIterTy> UnsafeVars) {
24532445
Strategy S;
24542446
for (const VarDecl *VD : UnsafeVars) {
24552447
S.set(VD, Strategy::Kind::Span);
@@ -2486,6 +2478,10 @@ class VariableGroupsManagerImpl : public VariableGroupsManager {
24862478
return std::nullopt;
24872479
return Groups[It->second];
24882480
}
2481+
2482+
VarGrpRef getGroupOfParms() const override {
2483+
return GrpsUnionForParms.getArrayRef();
2484+
}
24892485
};
24902486

24912487
void clang::checkUnsafeBufferUsage(const Decl *D,
@@ -2579,6 +2575,14 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
25792575
it->first, it->first->getBeginLoc(),
25802576
("failed to produce fixit for '" + it->first->getNameAsString() +
25812577
"' : neither local nor a parameter"));
2578+
#endif
2579+
it = FixablesForAllVars.byVar.erase(it);
2580+
} else if (it->first->getType().getCanonicalType()->isReferenceType()) {
2581+
#ifndef NDEBUG
2582+
Handler.addDebugNoteForVar(it->first, it->first->getBeginLoc(),
2583+
("failed to produce fixit for '" +
2584+
it->first->getNameAsString() +
2585+
"' : has a reference type"));
25822586
#endif
25832587
it = FixablesForAllVars.byVar.erase(it);
25842588
} else if (Tracker.hasUnclaimedUses(it->first)) {
@@ -2605,10 +2609,6 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
26052609
}
26062610
}
26072611

2608-
llvm::SmallVector<const VarDecl *, 16> UnsafeVars;
2609-
for (const auto &[VD, ignore] : FixablesForAllVars.byVar)
2610-
UnsafeVars.push_back(VD);
2611-
26122612
// Fixpoint iteration for pointer assignments
26132613
using DepMapTy = DenseMap<const VarDecl *, llvm::SetVector<const VarDecl *>>;
26142614
DepMapTy DependenciesMap{};
@@ -2737,7 +2737,13 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
27372737
++I;
27382738
}
27392739

2740-
Strategy NaiveStrategy = getNaiveStrategy(UnsafeVars);
2740+
// We assign strategies to variables that are 1) in the graph and 2) can be
2741+
// fixed. Other variables have the default "Won't fix" strategy.
2742+
Strategy NaiveStrategy = getNaiveStrategy(llvm::make_filter_range(
2743+
VisitedVars, [&FixablesForAllVars](const VarDecl *V) {
2744+
// If a warned variable has no "Fixable", it is considered unfixable:
2745+
return FixablesForAllVars.byVar.count(V);
2746+
}));
27412747
VariableGroupsManagerImpl VarGrpMgr(Groups, VarGrpMap, GrpsUnionForParms);
27422748

27432749
if (isa<NamedDecl>(D))

clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-multi-parm-span.cpp

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -68,18 +68,15 @@ void * multiParmAllFix(int *p, int **q, int a[], int * r);
6868

6969
// Fixing local variables implicates fixing parameters
7070
void multiParmLocalAllFix(int *p, int * r) {
71-
// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:28-[[@LINE-1]]:34}:"std::span<int> p"
72-
// CHECK: fix-it:{{.*}}:{[[@LINE-2]]:36-[[@LINE-2]]:43}:"std::span<int> r"
73-
// CHECK: fix-it:{{.*}}:{[[@LINE+1]]:3-[[@LINE+1]]:10}:"std::span<int> x"
74-
int * x; // expected-warning{{'x' is an unsafe pointer used for buffer access}} \
75-
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}}
76-
// CHECK: fix-it:{{.*}}:{[[@LINE+1]]:3-[[@LINE+1]]:10}:"std::span<int> z"
77-
int * z; // expected-warning{{'z' is an unsafe pointer used for buffer access}} \
78-
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}}
71+
// CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]:
72+
// CHECK-NOT: fix-it:{{.*}}:{[[@LINE+1]]:
73+
int * x; // expected-warning{{'x' is an unsafe pointer used for buffer access}}
74+
// CHECK-NOT: fix-it:{{.*}}:{[[@LINE+1]]:
75+
int * z; // expected-warning{{'z' is an unsafe pointer used for buffer access}}
7976
int * y;
8077

8178
x = p;
82-
y = x;
79+
y = x; // FIXME: we do not fix `y = x` here as the `.data()` fix-it is not generally correct
8380
// `x` needs to be fixed so does the pointer assigned to `x`, i.e.,`p`
8481
x[5] = 5; // expected-note{{used in buffer access here}}
8582
z = r;
@@ -89,33 +86,26 @@ void multiParmLocalAllFix(int *p, int * r) {
8986
// fixing `x` involves fixing all `p`, `r` and `z`. Similar for
9087
// fixing `z`.
9188
}
92-
// 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"
89+
// CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]:
9390

9491

9592
// Fixing parameters implicates fixing local variables
96-
// CHECK: fix-it:{{.*}}:{[[@LINE+2]]:29-[[@LINE+2]]:35}:"std::span<int> p"
97-
// CHECK: fix-it:{{.*}}:{[[@LINE+1]]:37-[[@LINE+1]]:44}:"std::span<int> r"
93+
// CHECK-NOT: fix-it:{{.*}}:{[[@LINE+1]]:
9894
void multiParmLocalAllFix2(int *p, int * r) { // expected-warning{{'p' is an unsafe pointer used for buffer access}} \
99-
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}} \
100-
expected-warning{{'r' is an unsafe pointer used for buffer access}} \
101-
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}}
95+
expected-warning{{'r' is an unsafe pointer used for buffer access}}
10296
int * x = new int[10];
103-
// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:12}:"std::span<int> x"
104-
// CHECK: fix-it:{{.*}}:{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"
105-
// CHECK: fix-it:{{.*}}:{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 10}"
97+
// CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]:
10698
int * z = new int[10];
107-
// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:12}:"std::span<int> z"
108-
// CHECK: fix-it:{{.*}}:{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"
109-
// CHECK: fix-it:{{.*}}:{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 10}"
99+
// CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]:
110100
int * y;
111101

112102
p = x;
113-
y = x;
103+
y = x; // FIXME: we do not fix `y = x` here as the `.data()` fix-it is not generally correct
114104
p[5] = 5; // expected-note{{used in buffer access here}}
115105
r = z;
116106
r[5] = 5; // expected-note{{used in buffer access here}}
117107
}
118-
// 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"
108+
// CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]:
119109

120110

121111
// No fix emitted for any of the parameter since parameter `r` cannot be fixed

clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-fixits-test.cpp

Lines changed: 16 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,14 @@
22

33
void foo1a() {
44
int *r = new int[7];
5-
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> r"
6-
// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
7-
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:22-[[@LINE-3]]:22}:", 7}"
5+
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
86
int *p = new int[4];
9-
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p"
10-
// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
11-
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:22-[[@LINE-3]]:22}:", 4}"
7+
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
128
p = r;
139
int tmp = p[9];
1410
int *q;
15-
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> q"
16-
q = r;
11+
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
12+
q = r; // FIXME: we do not fix `q = r` here as the `.data()` fix-it is not generally correct
1713
}
1814

1915
void foo1b() {
@@ -37,15 +33,13 @@ void foo1b() {
3733

3834
void foo1c() {
3935
int *r = new int[7];
40-
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> r"
41-
// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
42-
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:22-[[@LINE-3]]:22}:", 7}"
36+
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
4337
int *p = new int[4];
44-
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p"
45-
p = r;
38+
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
39+
p = r; // FIXME: we do not fix `p = r` here as the `.data()` fix-it is not generally correct
4640
int tmp = r[9];
4741
int *q;
48-
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> q"
42+
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
4943
q = r;
5044
tmp = q[9];
5145
}
@@ -70,18 +64,12 @@ void foo2a() {
7064

7165
void foo2b() {
7266
int *r = new int[7];
73-
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> r"
74-
// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
75-
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:22-[[@LINE-3]]:22}:", 7}"
67+
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
7668
int *p = new int[5];
77-
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p"
78-
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
79-
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-3]]:22-[[@LINE-3]]:22}:", 5}"
69+
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
8070
int *q = new int[4];
81-
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> q"
82-
// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
83-
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:22-[[@LINE-3]]:22}:", 4}"
84-
p = q;
71+
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
72+
p = q; // FIXME: we do not fix `p = q` here as the `.data()` fix-it is not generally correct
8573
int tmp = q[8];
8674
q = r;
8775
}
@@ -107,14 +95,12 @@ void foo2c() {
10795

10896
void foo3a() {
10997
int *r = new int[7];
110-
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> r"
98+
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
11199
int *p = new int[5];
112-
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p"
113-
// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
114-
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:22-[[@LINE-3]]:22}:", 5}"
100+
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
115101
int *q = new int[4];
116-
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> q"
117-
q = p;
102+
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
103+
q = p; // FIXME: we do not fix `q = p` here as the `.data()` fix-it is not generally correct
118104
int tmp = p[8];
119105
q = r;
120106
}

clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-ptr-init-fixits.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,11 @@ void test_grouping() {
6262
int *z = new int[8];
6363
int tmp;
6464
int *y = new int[10];
65-
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> y"
66-
// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
67-
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
65+
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
6866
tmp = y[5];
6967

7068
int *x = new int[10];
71-
x = y;
69+
x = y; // FIXME: we do not fix `x = y` here as the `.data()` fix-it is not generally correct
7270

7371
int *w = z;
7472
}

clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-ptr-init.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,17 @@ void rhs_span3() {
2727
int *q = new int[6];
2828
int *p = q; // expected-warning{{'p' is an unsafe pointer used for buffer access}}
2929
p[5] = 10; // expected-note{{used in buffer access here}}
30-
int *r = q;
30+
int *r = q; // FIXME: we do not fix `int *r = q` here as the `.data()` fix-it is not generally correct
3131
}
3232

3333
void test_grouping() {
3434
int *z = new int[8];
3535
int tmp;
36-
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}}
36+
int *y = new int[10]; // expected-warning{{'y' is an unsafe pointer used for buffer access}}
3737
tmp = y[5]; // expected-note{{used in buffer access here}}
3838

3939
int *x = new int[10];
40-
x = y;
40+
x = y; // FIXME: we do not fix `x = y` here as the `.data()` fix-it is not generally correct
4141

4242
int *w = z;
4343
}

clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-uuc-fixits.cpp

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,13 @@ void bar(int * param) {}
66

77
void foo1a() {
88
int *r = new int[7];
9-
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> r"
10-
// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
11-
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:22-[[@LINE-3]]:22}:", 7}"
9+
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
1210
int *p = new int[4];
13-
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p"
14-
// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
15-
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:22-[[@LINE-3]]:22}:", 4}"
11+
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
1612
p = r;
1713
int tmp = p[9];
1814
int *q;
19-
q = r;
15+
q = r; // FIXME: we do not fix `q = r` here as the `.data()` fix-it is not generally correct
2016
}
2117

2218
void uuc_if_body() {

0 commit comments

Comments
 (0)