Skip to content

Commit e06f352

Browse files
[-Wunsafe-buffer-usage] Emit fixits for array decayed to pointer (#80347)
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 137bd78 commit e06f352

File tree

2 files changed

+50
-2
lines changed

2 files changed

+50
-2
lines changed

clang/lib/Analysis/UnsafeBufferUsage.cpp

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

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

Lines changed: 49 additions & 1 deletion
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"
@@ -177,4 +206,23 @@ void fixits_in_lambda_capture_rename() {
177206
};
178207

179208
p[5] = 10;
180-
}
209+
}
210+
211+
bool ptr_comparison(int* ptr, unsigned idx) {
212+
int arr[10];
213+
// CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:14}:"std::array<int, 10> arr"
214+
arr[idx] = idx;
215+
216+
return arr > ptr;
217+
// CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:13-[[@LINE-1]]:13}:".data()"
218+
}
219+
220+
int long long ptr_distance(int* ptr, unsigned idx) {
221+
int arr[10];
222+
// CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:14}:"std::array<int, 10> arr"
223+
arr[idx] = idx;
224+
225+
int long long dist = arr - ptr;
226+
// CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:27-[[@LINE-1]]:27}:".data()"
227+
return dist;
228+
}

0 commit comments

Comments
 (0)