Skip to content

Commit 0351010

Browse files
committed
[-Wunsafe-buffer-usage] Emit fixits for array used as a pointer
Covers cases where DeclRefExpr referring to a const-size array decays to a pointer and is used "as a pointer" (e. g. passed to a pointer type parameter). Since std::array<T, N> doesn't implicitly convert to pointer to its element type T* the cast needs to be done explicitly as part of the fixit when we retrofit std::array to code that previously worked with constant size array. std::array::data() method is used for the explicit cast. In terms of the fixit machine this covers the UPC(DRE) case for Array fixit strategy. The emitted fixit inserts call to std::array::data() method similarly to analogous fixit for Span strategy.
1 parent 7694a6d commit 0351010

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

clang/lib/Analysis/UnsafeBufferUsage.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1875,6 +1875,7 @@ std::optional<FixItList>
18751875
UPCStandalonePointerGadget::getFixits(const FixitStrategy &S) const {
18761876
const auto VD = cast<VarDecl>(Node->getDecl());
18771877
switch (S.lookup(VD)) {
1878+
case FixitStrategy::Kind::Array:
18781879
case FixitStrategy::Kind::Span: {
18791880
ASTContext &Ctx = VD->getASTContext();
18801881
SourceManager &SM = Ctx.getSourceManager();
@@ -1889,7 +1890,6 @@ UPCStandalonePointerGadget::getFixits(const FixitStrategy &S) const {
18891890
}
18901891
case FixitStrategy::Kind::Wontfix:
18911892
case FixitStrategy::Kind::Iterator:
1892-
case FixitStrategy::Kind::Array:
18931893
return std::nullopt;
18941894
case FixitStrategy::Kind::Vector:
18951895
llvm_unreachable("unsupported strategies for FixableGadgets");

clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-access.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,27 @@ void unsafe_method_invocation_single_param() {
8383

8484
}
8585

86+
void unsafe_method_invocation_single_param_array() {
87+
int p[32];
88+
// CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:12}:"std::array<int, 32> p"
89+
90+
int tmp = p[5];
91+
foo(p);
92+
// CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:8-[[@LINE-1]]:8}:".data()"
93+
}
94+
8695
void safe_method_invocation_single_param() {
8796
int* p = new int[10];
8897
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:{{.*}}-[[@LINE-1]]:{{.*}}}
8998
foo(p);
9099
}
91100

101+
void safe_method_invocation_single_param_array() {
102+
int p[10];
103+
foo(p);
104+
// CHECK-NO: fix-it:"{{.*}}":{[[@LINE-1]]:{{.*}}-[[@LINE-1]]:{{.*}}}:".data()"
105+
}
106+
92107
void unsafe_method_invocation_double_param() {
93108
int* p = new int[10];
94109
// CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p"
@@ -111,6 +126,20 @@ void unsafe_method_invocation_double_param() {
111126
m1(q, q, 8);
112127
}
113128

129+
void unsafe_method_invocation_double_param_array() {
130+
int p[14];
131+
// CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:12}:"std::array<int, 14> p"
132+
133+
int q[40];
134+
// CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:12}:"std::array<int, 40> q"
135+
136+
q[5] = p[5];
137+
138+
m1(p, p, 10);
139+
// CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:7-[[@LINE-1]]:7}:".data()"
140+
// CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:10-[[@LINE-2]]:10}:".data()"
141+
}
142+
114143
void unsafe_access_in_lamda() {
115144
int* p = new int[10];
116145
// CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p"

0 commit comments

Comments
 (0)