Skip to content

Commit 0dcb0ac

Browse files
malavikasamakMalavikaSamak
and
MalavikaSamak
authored
[-Wunsafe-buffer-usage] Fix false positives in warning againt 2-parameter std::span constructor (#115797)
Do not warn when two parameter constructor receives pointer address from a std::addressof method and the span size is set to 1. (rdar://139298119) Co-authored-by: MalavikaSamak <malavika2@apple.com>
1 parent 98c4f4f commit 0dcb0ac

File tree

2 files changed

+27
-0
lines changed

2 files changed

+27
-0
lines changed

clang/lib/Analysis/UnsafeBufferUsage.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,7 @@ isInUnspecifiedUntypedContext(internal::Matcher<Stmt> InnerMatcher) {
366366
// 4. `std::span<T>{a, n}`, where `a` is of an array-of-T with constant size
367367
// `n`
368368
// 5. `std::span<T>{any, 0}`
369+
// 6. `std::span<T>{std::addressof(...), 1}`
369370
AST_MATCHER(CXXConstructExpr, isSafeSpanTwoParamConstruct) {
370371
assert(Node.getNumArgs() == 2 &&
371372
"expecting a two-parameter std::span constructor");
@@ -410,6 +411,15 @@ AST_MATCHER(CXXConstructExpr, isSafeSpanTwoParamConstruct) {
410411
// Check form 3:
411412
return Arg1CV && Arg1CV->isOne();
412413
break;
414+
case Stmt::CallExprClass:
415+
if (const auto *CE = dyn_cast<CallExpr>(Arg0)) {
416+
const auto FnDecl = CE->getDirectCallee();
417+
if (FnDecl && FnDecl->getNameAsString() == "addressof" &&
418+
FnDecl->isInStdNamespace()) {
419+
return Arg1CV && Arg1CV->isOne();
420+
}
421+
}
422+
break;
413423
default:
414424
break;
415425
}

clang/test/SemaCXX/warn-unsafe-buffer-usage-in-container-span-construct.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ namespace std {
2121

2222
template< class T >
2323
T&& move( T&& t ) noexcept;
24+
25+
template <class _Tp>
26+
_Tp* addressof(_Tp& __x) {
27+
return &__x;
28+
}
29+
2430
}
2531

2632
namespace irrelevant_constructors {
@@ -74,15 +80,26 @@ namespace construct_wt_ptr_size {
7480
return std::span<int>{p, 10}; // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}
7581
}
7682

83+
// addressof method defined outside std namespace.
84+
template <class _Tp>
85+
_Tp* addressof(_Tp& __x) {
86+
return &__x;
87+
}
88+
7789
void notWarnSafeCases(unsigned n, int *p) {
7890
int X;
7991
unsigned Y = 10;
8092
std::span<int> S = std::span{&X, 1}; // no-warning
93+
S = std::span{std::addressof(X), 1}; // no-warning
8194
int Arr[10];
8295
typedef int TenInts_t[10];
8396
TenInts_t Arr2;
8497

8598
S = std::span{&X, 2}; // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}
99+
S = std::span{std::addressof(X), 2}; // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}
100+
// Warn when a non std method also named addressof
101+
S = std::span{addressof(X), 1}; // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}
102+
86103
S = std::span{new int[10], 10}; // no-warning
87104
S = std::span{new int[n], n}; // no-warning
88105
S = std::span{new int, 1}; // no-warning

0 commit comments

Comments
 (0)