Skip to content

Commit d49d5fd

Browse files
committed
[-Wunsafe-buffer-usage] Avoid type sugar in array fixits
The code that creates fixits from C array to std::array assumes the array type is not a sugared type like typedef as it would not produce correct fixits otherwise. The patch adds a note about the condition under which the code works and testcases. As a general precaution it also makes the format assumption explicit in iteration over tokens of the declaration. Contrary to that the higher layers need to use canonical (desugared) type in order to decide which function is responsible for fixing an array VarDecl.
1 parent 437a4f5 commit d49d5fd

File tree

2 files changed

+30
-3
lines changed

2 files changed

+30
-3
lines changed

clang/lib/Analysis/UnsafeBufferUsage.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2475,6 +2475,8 @@ static FixItList fixVarDeclWithArray(const VarDecl *D, const ASTContext &Ctx,
24752475
UnsafeBufferUsageHandler &Handler) {
24762476
FixItList FixIts{};
24772477

2478+
// Note: the code below expects the declaration to not use any type sugar like
2479+
// typedef.
24782480
if (auto CAT = dyn_cast<clang::ConstantArrayType>(D->getType())) {
24792481
const QualType &ArrayEltT = CAT->getElementType();
24802482
assert(!ArrayEltT.isNull() && "Trying to fix a non-array type variable!");
@@ -2496,7 +2498,8 @@ static FixItList fixVarDeclWithArray(const VarDecl *D, const ASTContext &Ctx,
24962498
// Find the '[' token.
24972499
std::optional<Token> NextTok = Lexer::findNextToken(
24982500
IdentifierLoc, Ctx.getSourceManager(), Ctx.getLangOpts());
2499-
while (NextTok && !NextTok->is(tok::l_square))
2501+
while (NextTok && !NextTok->is(tok::l_square) &&
2502+
NextTok->getLocation() <= D->getSourceRange().getEnd())
25002503
NextTok = Lexer::findNextToken(NextTok->getLocation(),
25012504
Ctx.getSourceManager(), Ctx.getLangOpts());
25022505
if (!NextTok)
@@ -2607,7 +2610,8 @@ fixVariable(const VarDecl *VD, FixitStrategy::Kind K,
26072610
return {};
26082611
}
26092612
case FixitStrategy::Kind::Array: {
2610-
if (VD->isLocalVarDecl() && isa<clang::ConstantArrayType>(VD->getType()))
2613+
if (VD->isLocalVarDecl() &&
2614+
isa<clang::ConstantArrayType>(VD->getType().getCanonicalType()))
26112615
return fixVariableWithArray(VD, Tracker, Ctx, Handler);
26122616

26132617
DEBUG_NOTE_DECL_FAIL(VD, " : not a local const-size array");
@@ -2801,7 +2805,7 @@ static FixitStrategy
28012805
getNaiveStrategy(llvm::iterator_range<VarDeclIterTy> UnsafeVars) {
28022806
FixitStrategy S;
28032807
for (const VarDecl *VD : UnsafeVars) {
2804-
if (isa<ConstantArrayType>(VD->getType()))
2808+
if (isa<ConstantArrayType>(VD->getType().getCanonicalType()))
28052809
S.set(VD, FixitStrategy::Kind::Array);
28062810
else
28072811
S.set(VD, FixitStrategy::Kind::Span);

clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-local-var-array.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,13 @@ void typedef_as_elem_type(unsigned idx) {
136136
buffer[idx] = 0;
137137
}
138138

139+
void decltype_as_elem_type(unsigned idx) {
140+
int a;
141+
decltype(a) buffer[10];
142+
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:25}:"std::array<decltype(a), 10> buffer"
143+
buffer[idx] = 0;
144+
}
145+
139146
void macro_as_elem_type(unsigned idx) {
140147
#define MY_INT int
141148
MY_INT buffer[10];
@@ -162,6 +169,22 @@ void macro_as_size(unsigned idx) {
162169
#undef MY_TEN
163170
}
164171

172+
typedef unsigned int my_array[42];
173+
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:.*-[[@LINE-1]]:.*}
174+
void typedef_as_array_type(unsigned idx) {
175+
my_array buffer;
176+
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:.*-[[@LINE-1]]:.*}
177+
buffer[idx] = 0;
178+
}
179+
180+
void decltype_as_array_type(unsigned idx) {
181+
int buffer[42];
182+
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:.*-[[@LINE-1]]:.*}
183+
decltype(buffer) buffer2;
184+
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:.*-[[@LINE-1]]:.*}
185+
buffer2[idx] = 0;
186+
}
187+
165188
void constant_as_size(unsigned idx) {
166189
const unsigned my_const = 10;
167190
int buffer[my_const];

0 commit comments

Comments
 (0)