Skip to content

Commit 5b012bf

Browse files
committed
[-Wunsafe-buffer-usage] Improving insertion of the [[clang::unsafe_buffer_usage]] attribute
For a fix-it that inserts the `[[clang::unsafe_buffer_usage]]` attribute, it will lookup existing macros defined for the attribute and use the (last defined such) macro directly. Fix-its will use raw `[[clang::unsafe_buffer_usage]]` if no such macro is defined. The implementation mimics how a similar machine for the `[[fallthrough]]` attribute was implemented. Reviewed by: NoQ (Artem Dergachev) Differential revision: https://reviews.llvm.org/D150338
1 parent 2dbc532 commit 5b012bf

8 files changed

+153
-64
lines changed

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

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@
1616

1717
#include "clang/AST/Decl.h"
1818
#include "clang/AST/Stmt.h"
19+
#include "clang/Sema/Sema.h"
1920

2021
namespace clang {
22+
class Sema;
2123

2224
using DefMapTy = llvm::DenseMap<const VarDecl *, std::vector<const VarDecl *>>;
2325

@@ -45,21 +47,12 @@ class UnsafeBufferUsageHandler {
4547

4648
/// Returns a reference to the `Preprocessor`:
4749
virtual bool isSafeBufferOptOut(const SourceLocation &Loc) const = 0;
48-
49-
/// Returns the text indicating that the user needs to provide input there:
50-
virtual std::string
51-
getUserFillPlaceHolder(StringRef HintTextToUser = "placeholder") const {
52-
std::string s = std::string("<# ");
53-
s += HintTextToUser;
54-
s += " #>";
55-
return s;
56-
}
5750
};
5851

5952
// This function invokes the analysis and allows the caller to react to it
6053
// through the handler class.
6154
void checkUnsafeBufferUsage(const Decl *D, UnsafeBufferUsageHandler &Handler,
62-
bool EmitSuggestions);
55+
bool EmitSuggestions, Sema &Sema);
6356

6457
namespace internal {
6558
// Tests if any two `FixItHint`s in `FixIts` conflict. Two `FixItHint`s

clang/lib/Analysis/UnsafeBufferUsage.cpp

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1290,6 +1290,14 @@ static StringRef getEndOfLine() {
12901290
return EOL;
12911291
}
12921292

1293+
// Returns the text indicating that the user needs to provide input there:
1294+
std::string getUserFillPlaceHolder(StringRef HintTextToUser = "placeholder") {
1295+
std::string s = std::string("<# ");
1296+
s += HintTextToUser;
1297+
s += " #>";
1298+
return s;
1299+
}
1300+
12931301
// Return the text representation of the given `APInt Val`:
12941302
static std::string getAPIntText(APInt Val) {
12951303
SmallVector<char> Txt;
@@ -1756,11 +1764,28 @@ static bool hasConflictingOverload(const FunctionDecl *FD) {
17561764
}
17571765

17581766
// Returns the text representation of clang::unsafe_buffer_usage attribute.
1759-
static std::string getUnsafeBufferUsageAttributeText() {
1760-
static const char *const RawAttr = "[[clang::unsafe_buffer_usage]]";
1761-
std::stringstream SS;
1762-
SS << RawAttr << getEndOfLine().str();
1763-
return SS.str();
1767+
// `WSSuffix` holds customized "white-space"s, e.g., newline or whilespace
1768+
// characters.
1769+
static std::string
1770+
getUnsafeBufferUsageAttributeTextAt(SourceLocation Loc, Sema &S,
1771+
StringRef WSSuffix = "") {
1772+
Preprocessor &PP = S.getPreprocessor();
1773+
TokenValue ClangUnsafeBufferUsageTokens[] = {
1774+
tok::l_square,
1775+
tok::l_square,
1776+
PP.getIdentifierInfo("clang"),
1777+
tok::coloncolon,
1778+
PP.getIdentifierInfo("unsafe_buffer_usage"),
1779+
tok::r_square,
1780+
tok::r_square};
1781+
1782+
StringRef MacroName;
1783+
1784+
// The returned macro (it returns) is guaranteed not to be function-like:
1785+
MacroName = PP.getLastMacroWithSpelling(Loc, ClangUnsafeBufferUsageTokens);
1786+
if (MacroName.empty())
1787+
MacroName = "[[clang::unsafe_buffer_usage]]";
1788+
return MacroName.str() + WSSuffix.str();
17641789
}
17651790

17661791
// For a `FunDecl`, one of whose `ParmVarDecl`s is being changed to have a new
@@ -1805,11 +1830,11 @@ static std::string getUnsafeBufferUsageAttributeText() {
18051830
static std::optional<FixItList>
18061831
createOverloadsForFixedParams(unsigned ParmIdx, StringRef NewTyText,
18071832
const FunctionDecl *FD, const ASTContext &Ctx,
1808-
UnsafeBufferUsageHandler &Handler) {
1833+
UnsafeBufferUsageHandler &Handler, Sema &Sema) {
18091834
// FIXME: need to make this conflict checking better:
18101835
if (hasConflictingOverload(FD))
18111836
return std::nullopt;
1812-
1837+
18131838
const SourceManager &SM = Ctx.getSourceManager();
18141839
const LangOptions &LangOpts = Ctx.getLangOpts();
18151840
// FIXME Respect indentation of the original code.
@@ -1859,7 +1884,7 @@ createOverloadsForFixedParams(unsigned ParmIdx, StringRef NewTyText,
18591884
// A lambda that creates the text representation of a function definition with
18601885
// the original signature:
18611886
const auto OldOverloadDefCreator =
1862-
[&Handler, &SM,
1887+
[&SM, &Sema,
18631888
&LangOpts](const FunctionDecl *FD, unsigned ParmIdx,
18641889
StringRef NewTypeText) -> std::optional<std::string> {
18651890
std::stringstream SS;
@@ -1869,7 +1894,8 @@ createOverloadsForFixedParams(unsigned ParmIdx, StringRef NewTyText,
18691894
if (auto FDPrefix = getRangeText(
18701895
SourceRange(FD->getBeginLoc(), FD->getBody()->getBeginLoc()), SM,
18711896
LangOpts))
1872-
SS << getUnsafeBufferUsageAttributeText() << FDPrefix->str() << "{";
1897+
SS << getUnsafeBufferUsageAttributeTextAt(FD->getBeginLoc(), Sema, " ")
1898+
<< FDPrefix->str() << "{";
18731899
else
18741900
return std::nullopt;
18751901
// Append: "return" func-name "("
@@ -1890,7 +1916,7 @@ createOverloadsForFixedParams(unsigned ParmIdx, StringRef NewTyText,
18901916
if (i == ParmIdx)
18911917
// This is our spanified paramter!
18921918
SS << NewTypeText.str() << "(" << Parm->getIdentifier()->getName().str() << ", "
1893-
<< Handler.getUserFillPlaceHolder("size") << ")";
1919+
<< getUserFillPlaceHolder("size") << ")";
18941920
else
18951921
SS << Parm->getIdentifier()->getName().str();
18961922
if (i != NumParms - 1)
@@ -1921,7 +1947,8 @@ createOverloadsForFixedParams(unsigned ParmIdx, StringRef NewTyText,
19211947
// Adds the unsafe-buffer attribute (if not already there) to `FReDecl`:
19221948
if (!FReDecl->hasAttr<UnsafeBufferUsageAttr>()) {
19231949
FixIts.emplace_back(FixItHint::CreateInsertion(
1924-
FReDecl->getBeginLoc(), getUnsafeBufferUsageAttributeText()));
1950+
FReDecl->getBeginLoc(), getUnsafeBufferUsageAttributeTextAt(
1951+
FReDecl->getBeginLoc(), Sema, " ")));
19251952
}
19261953
// Inserts a declaration with the new signature to the end of `FReDecl`:
19271954
if (auto NewOverloadDecl =
@@ -1938,7 +1965,7 @@ createOverloadsForFixedParams(unsigned ParmIdx, StringRef NewTyText,
19381965
// new overload of the function so that the change is self-contained (see
19391966
// `createOverloadsForFixedParams`).
19401967
static FixItList fixParamWithSpan(const ParmVarDecl *PVD, const ASTContext &Ctx,
1941-
UnsafeBufferUsageHandler &Handler) {
1968+
UnsafeBufferUsageHandler &Handler, Sema &Sema) {
19421969
if (PVD->hasDefaultArg())
19431970
// FIXME: generate fix-its for default values:
19441971
return {};
@@ -1990,7 +2017,7 @@ static FixItList fixParamWithSpan(const ParmVarDecl *PVD, const ASTContext &Ctx,
19902017
}
19912018
if (ParmIdx < FD->getNumParams())
19922019
if (auto OverloadFix = createOverloadsForFixedParams(ParmIdx, SpanTyText,
1993-
FD, Ctx, Handler)) {
2020+
FD, Ctx, Handler, Sema)) {
19942021
Fixes.append(*OverloadFix);
19952022
return Fixes;
19962023
}
@@ -2013,7 +2040,7 @@ static FixItList fixVariableWithSpan(const VarDecl *VD,
20132040
(void)DS;
20142041

20152042
// FIXME: handle cases where DS has multiple declarations
2016-
return fixVarDeclWithSpan(VD, Ctx, Handler.getUserFillPlaceHolder());
2043+
return fixVarDeclWithSpan(VD, Ctx, getUserFillPlaceHolder());
20172044
}
20182045

20192046
// TODO: we should be consistent to use `std::nullopt` to represent no-fix due
@@ -2022,7 +2049,7 @@ static FixItList
20222049
fixVariable(const VarDecl *VD, Strategy::Kind K,
20232050
/* The function decl under analysis */ const Decl *D,
20242051
const DeclUseTracker &Tracker, ASTContext &Ctx,
2025-
UnsafeBufferUsageHandler &Handler) {
2052+
UnsafeBufferUsageHandler &Handler, Sema &Sema) {
20262053
if (const auto *PVD = dyn_cast<ParmVarDecl>(VD)) {
20272054
auto *FD = dyn_cast<clang::FunctionDecl>(PVD->getDeclContext());
20282055
if (!FD || FD != D)
@@ -2049,7 +2076,7 @@ fixVariable(const VarDecl *VD, Strategy::Kind K,
20492076
case Strategy::Kind::Span: {
20502077
if (VD->getType()->isPointerType()) {
20512078
if (const auto *PVD = dyn_cast<ParmVarDecl>(VD))
2052-
return fixParamWithSpan(PVD, Ctx, Handler);
2079+
return fixParamWithSpan(PVD, Ctx, Handler, Sema);
20532080

20542081
if (VD->isLocalVarDecl())
20552082
return fixVariableWithSpan(VD, Tracker, Ctx, Handler);
@@ -2097,11 +2124,11 @@ getFixIts(FixableGadgetSets &FixablesForAllVars, const Strategy &S,
20972124
ASTContext &Ctx,
20982125
/* The function decl under analysis */ const Decl *D,
20992126
const DeclUseTracker &Tracker, UnsafeBufferUsageHandler &Handler,
2100-
const DefMapTy &VarGrpMap) {
2127+
const DefMapTy &VarGrpMap, Sema &Sema) {
21012128
std::map<const VarDecl *, FixItList> FixItsForVariable;
21022129
for (const auto &[VD, Fixables] : FixablesForAllVars.byVar) {
21032130
FixItsForVariable[VD] =
2104-
fixVariable(VD, S.lookup(VD), D, Tracker, Ctx, Handler);
2131+
fixVariable(VD, S.lookup(VD), D, Tracker, Ctx, Handler, Sema);
21052132
// If we fail to produce Fix-It for the declaration we have to skip the
21062133
// variable entirely.
21072134
if (FixItsForVariable[VD].empty()) {
@@ -2171,7 +2198,7 @@ getFixIts(FixableGadgetSets &FixablesForAllVars, const Strategy &S,
21712198
FixItList GroupFix;
21722199
if (FixItsForVariable.find(Var) == FixItsForVariable.end()) {
21732200
GroupFix = fixVariable(Var, ReplacementTypeForVD, D,
2174-
Tracker, Var->getASTContext(), Handler);
2201+
Tracker, Var->getASTContext(), Handler, Sema);
21752202
} else {
21762203
GroupFix = FixItsForVariable[Var];
21772204
}
@@ -2197,7 +2224,7 @@ getNaiveStrategy(const llvm::SmallVectorImpl<const VarDecl *> &UnsafeVars) {
21972224

21982225
void clang::checkUnsafeBufferUsage(const Decl *D,
21992226
UnsafeBufferUsageHandler &Handler,
2200-
bool EmitSuggestions) {
2227+
bool EmitSuggestions, Sema &Sema) {
22012228
assert(D && D->getBody());
22022229

22032230
// Do not emit fixit suggestions for functions declared in an
@@ -2343,7 +2370,7 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
23432370

23442371
FixItsForVariableGroup =
23452372
getFixIts(FixablesForAllVars, NaiveStrategy, D->getASTContext(), D,
2346-
Tracker, Handler, VariableGroupsMap);
2373+
Tracker, Handler, VariableGroupsMap, Sema);
23472374

23482375
// FIXME Detect overlapping FixIts.
23492376

clang/lib/Sema/AnalysisBasedWarnings.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2423,7 +2423,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
24232423
!Diags.isIgnored(diag::warn_unsafe_buffer_variable,
24242424
Node->getBeginLoc())) {
24252425
clang::checkUnsafeBufferUsage(Node, R,
2426-
UnsafeBufferUsageShouldEmitSuggestions);
2426+
UnsafeBufferUsageShouldEmitSuggestions, S);
24272427
}
24282428

24292429
// More analysis ...
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits -fsafe-buffer-usage-suggestions -DCMD_UNSAFE_ATTR=[[clang::unsafe_buffer_usage]] %s 2>&1 | FileCheck %s
2+
3+
4+
// no need to check fix-its for definition in this test ...
5+
void foo(int *p) {
6+
int tmp = p[5];
7+
}
8+
9+
// Will use the macro defined from the command line:
10+
void foo(int *);
11+
// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:1-[[@LINE-1]]:1}:"CMD_UNSAFE_ATTR "
12+
// CHECK: fix-it:{{.*}}:{[[@LINE-2]]:16-[[@LINE-2]]:16}:";\nvoid foo(std::span<int>)"
13+
14+
15+
#undef CMD_UNSAFE_ATTR
16+
void foo(int *);
17+
// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:1-[[@LINE-1]]:1}:"{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} "
18+
// CHECK: fix-it:{{.*}}:{[[@LINE-2]]:16-[[@LINE-2]]:16}:";\nvoid foo(std::span<int>)"
19+
20+
21+
#define UNSAFE_ATTR [[clang::unsafe_buffer_usage]]
22+
23+
void foo(int *);
24+
// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:1-[[@LINE-1]]:1}:"UNSAFE_ATTR "
25+
// CHECK: fix-it:{{.*}}:{[[@LINE-2]]:16-[[@LINE-2]]:16}:";\nvoid foo(std::span<int>)"
26+
27+
#undef UNSAFE_ATTR
28+
29+
#if __has_cpp_attribute(clang::unsafe_buffer_usage)
30+
#define UNSAFE_ATTR [[clang::unsafe_buffer_usage]]
31+
#endif
32+
33+
void foo(int *);
34+
// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:1-[[@LINE-1]]:1}:"UNSAFE_ATTR "
35+
// CHECK: fix-it:{{.*}}:{[[@LINE-2]]:16-[[@LINE-2]]:16}:";\nvoid foo(std::span<int>)"
36+
37+
#undef UNSAFE_ATTR
38+
39+
#if __has_cpp_attribute(clang::unsafe_buffer_usage)
40+
// we don't know how to use this macro
41+
#define UNSAFE_ATTR(x) [[clang::unsafe_buffer_usage]]
42+
#endif
43+
44+
void foo(int *);
45+
// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:1-[[@LINE-1]]:1}:"{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} "
46+
// CHECK: fix-it:{{.*}}:{[[@LINE-2]]:16-[[@LINE-2]]:16}:";\nvoid foo(std::span<int>)"
47+
48+
#undef UNSAFE_ATTR
49+
50+
#define UNSAFE_ATTR_1 [[clang::unsafe_buffer_usage]]
51+
#define UNSAFE_ATTR_2 [[clang::unsafe_buffer_usage]]
52+
#define UNSAFE_ATTR_3 [[clang::unsafe_buffer_usage]]
53+
54+
// Should use the last defined macro (i.e., UNSAFE_ATTR_3) for
55+
// `[[clang::unsafe_buffer_usage]]`
56+
void foo(int *p);
57+
// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:1-[[@LINE-1]]:1}:"UNSAFE_ATTR_3 "
58+
// CHECK: fix-it:{{.*}}:{[[@LINE-2]]:17-[[@LINE-2]]:17}:";\nvoid foo(std::span<int> p)"
59+
60+
61+
#define WRONG_ATTR_1 [clang::unsafe_buffer_usage]]
62+
#define WRONG_ATTR_2 [[clang::unsafe_buffer_usage]
63+
#define WRONG_ATTR_3 [[clang::unsafe_buffer_usag]]
64+
65+
// The last defined macro for
66+
// `[[clang::unsafe_buffer_usage]]` is still UNSAFE_ATTR_3
67+
void foo(int *p);
68+
// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:1-[[@LINE-1]]:1}:"UNSAFE_ATTR_3 "
69+
// CHECK: fix-it:{{.*}}:{[[@LINE-2]]:17-[[@LINE-2]]:17}:";\nvoid foo(std::span<int> p)"

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,11 @@ namespace NS {
4646
int tmp;
4747
tmp = p[5];
4848
}
49-
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:4-[[@LINE-1]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid foo(int *p) {return foo(std::span<int>(p, <# size #>));}\n"
49+
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:4-[[@LINE-1]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void foo(int *p) {return foo(std::span<int>(p, <# size #>));}\n"
5050

5151
// Similarly, `NS::bar` is distinct from `bar`:
5252
void bar(int *p);
53-
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:3}:"{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\n"
53+
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:3}:"{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} "
5454
// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:19-[[@LINE-2]]:19}:";\nvoid bar(std::span<int> p)"
5555
} // end of namespace NS
5656

@@ -60,7 +60,7 @@ void NS::bar(int *p) {
6060
int tmp;
6161
tmp = p[5];
6262
}
63-
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid NS::bar(int *p) {return NS::bar(std::span<int>(p, <# size #>));}\n"
63+
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void NS::bar(int *p) {return NS::bar(std::span<int>(p, <# size #>));}\n"
6464

6565
namespace NESTED {
6666
void alpha(int);
@@ -74,7 +74,7 @@ namespace NESTED {
7474
int tmp;
7575
tmp = p[5];
7676
}
77-
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:6-[[@LINE-1]]:6}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid alpha(int *p) {return alpha(std::span<int>(p, <# size #>));}\n"
77+
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:6-[[@LINE-1]]:6}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void alpha(int *p) {return alpha(std::span<int>(p, <# size #>));}\n"
7878
}
7979
}
8080

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22

33
namespace NS1 {
44
void foo(int *);
5-
// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\n"
5+
// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} "
66
// CHECK-DAG: fix-it:"{{.*}}:{[[@LINE-2]]:18-[[@LINE-2]]:18}:";\nvoid foo(std::span<int>)"
77
namespace NS2 {
88
void foo(int *);
9-
// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:5-[[@LINE-1]]:5}:"{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\n"
9+
// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:5-[[@LINE-1]]:5}:"{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} "
1010
// CHECK-DAG: fix-it:"{{.*}}:{[[@LINE-2]]:20-[[@LINE-2]]:20}:";\nvoid foo(std::span<int>)"
1111
namespace NS3 {
1212
void foo(int *);
13-
// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:7-[[@LINE-1]]:7}:"{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\n"
13+
// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:7-[[@LINE-1]]:7}:"{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} "
1414
// CHECK-DAG: fix-it:"{{.*}}:{[[@LINE-2]]:22-[[@LINE-2]]:22}:";\nvoid foo(std::span<int>)"
1515
}
1616
}
@@ -23,26 +23,26 @@ void NS1::foo(int *p) {
2323
int tmp;
2424
tmp = p[5];
2525
}
26-
// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid NS1::foo(int *p) {return NS1::foo(std::span<int>(p, <# size #>));}\n"
26+
// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void NS1::foo(int *p) {return NS1::foo(std::span<int>(p, <# size #>));}\n"
2727

2828
void NS1::NS2::foo(int *p) {
2929
// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:20-[[@LINE-1]]:26}:"std::span<int> p"
3030
int tmp;
3131
tmp = p[5];
3232
}
33-
// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid NS1::NS2::foo(int *p) {return NS1::NS2::foo(std::span<int>(p, <# size #>));}\n"
33+
// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void NS1::NS2::foo(int *p) {return NS1::NS2::foo(std::span<int>(p, <# size #>));}\n"
3434

3535
void NS1::NS2::NS3::foo(int *p) {
3636
// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:25-[[@LINE-1]]:31}:"std::span<int> p"
3737
int tmp;
3838
tmp = p[5];
3939
}
40-
// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid NS1::NS2::NS3::foo(int *p) {return NS1::NS2::NS3::foo(std::span<int>(p, <# size #>));}\n"
40+
// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void NS1::NS2::NS3::foo(int *p) {return NS1::NS2::NS3::foo(std::span<int>(p, <# size #>));}\n"
4141

4242

4343
void f(NS1::MyType * x) {
4444
// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:8-[[@LINE-1]]:23}:"std::span<NS1::MyType> x"
4545
NS1::MyType tmp;
4646
tmp = x[5];
4747
}
48-
// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid f(NS1::MyType * x) {return f(std::span<NS1::MyType>(x, <# size #>));}\n"
48+
// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void f(NS1::MyType * x) {return f(std::span<NS1::MyType>(x, <# size #>));}\n"

0 commit comments

Comments
 (0)