[clang] a91c739 - [Lifetime Safety] Name operator calls in alias-chain diagnostics (#221803)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 10 00:04:39 PDT 2026
Author: PushkarSingh
Date: 2026-09-10T08:04:35+01:00
New Revision: a91c7395c3fb1a37f69f7d8fb0e78c048faf6cb7
URL: https://github.com/llvm/llvm-project/commit/a91c7395c3fb1a37f69f7d8fb0e78c048faf6cb7
DIFF: https://github.com/llvm/llvm-project/commit/a91c7395c3fb1a37f69f7d8fb0e78c048faf6cb7.diff
LOG: [Lifetime Safety] Name operator calls in alias-chain diagnostics (#221803)
This updates Lifetime Safety alias-chain diagnostics to identify
overloaded operator and conversion calls instead of describing them
generically as an `expression`.
Previously, these calls were reported as `expression aliases the storage
of ...`, which could make it unclear which operation introduced the
alias. The diagnostic now reports the callee using the existing
diagnostic name printer, producing descriptions such as:
- `result of call to 'operator->'`
- `result of call to 'operator()'`
- `result of call to 'operator basic_string_view'`
Template arguments are preserved for operator function-template
specializations. For example:
- `result of call to 'operator+<const int>'`
- `result of call to 'operator-<__gnu_cxx::basic_iterator<const int>>'`
This makes each aliasing step explicit and identifies the particular
call responsible for propagating the alias.
References to
[#220248#discussion_r3905817437](https://github.com/llvm/llvm-project/pull/220248#discussion_r3905817437)
Added:
Modified:
clang/lib/Sema/SemaLifetimeSafety.h
clang/test/Sema/LifetimeSafety/invalidations.cpp
clang/test/Sema/LifetimeSafety/nocfg.cpp
clang/test/Sema/LifetimeSafety/safety.cpp
Removed:
################################################################################
diff --git a/clang/lib/Sema/SemaLifetimeSafety.h b/clang/lib/Sema/SemaLifetimeSafety.h
index 0fd3486bcee46..620032c27f955 100644
--- a/clang/lib/Sema/SemaLifetimeSafety.h
+++ b/clang/lib/Sema/SemaLifetimeSafety.h
@@ -687,8 +687,6 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
const auto *FD = CE->getDirectCallee();
if (!FD)
return "result of call";
- if (FD->isOverloadedOperator() || isa<CXXConversionDecl>(FD))
- return "expression";
std::string Name;
llvm::raw_string_ostream OS(Name);
FD->getNameForDiagnostic(OS, S.getPrintingPolicy(),
diff --git a/clang/test/Sema/LifetimeSafety/invalidations.cpp b/clang/test/Sema/LifetimeSafety/invalidations.cpp
index 127e375bc023c..593ba92cf7443 100644
--- a/clang/test/Sema/LifetimeSafety/invalidations.cpp
+++ b/clang/test/Sema/LifetimeSafety/invalidations.cpp
@@ -271,7 +271,7 @@ void IteratorUsedAfterPreIncrement() {
std::vector<int> v;
auto it = v.begin(); // expected-warning {{local variable 'v' is later invalidated}} \
// expected-note {{result of call to 'begin' aliases the storage of local variable 'v'}}
- auto next = ++it; // expected-note {{expression aliases the storage of local variable 'v'}}
+ auto next = ++it; // expected-note {{result of call to 'operator++' aliases the storage of local variable 'v'}}
v.push_back(1); // expected-note {{local variable 'v' is invalidated here}}
(void)*next; // expected-note {{later used here}}
}
@@ -279,7 +279,7 @@ void IteratorUsedAfterPreIncrement() {
void IteratorUsedAfterPostDecrement(std::vector<int> v) {
auto it = v.rbegin(); // expected-warning {{parameter 'v' is later invalidated}} \
// expected-note {{result of call to 'rbegin' aliases the storage of parameter 'v'}}
- auto prev = it--; // expected-note {{expression aliases the storage of parameter 'v'}}
+ auto prev = it--; // expected-note {{result of call to 'operator--' aliases the storage of parameter 'v'}}
v.push_back(1); // expected-note {{parameter 'v' is invalidated here}}
(void)*prev; // expected-note {{later used here}}
}
@@ -288,7 +288,7 @@ void IteratorUsedAfterAddition() {
std::vector<int> v;
auto it = v.cbegin(); // expected-warning {{local variable 'v' is later invalidated}} \
// expected-note {{result of call to 'cbegin' aliases the storage of local variable 'v'}}
- auto next = it + 5; // expected-note {{expression aliases the storage of local variable 'v'}}
+ auto next = it + 5; // expected-note {{result of call to 'operator+' aliases the storage of local variable 'v'}}
v.push_back(1); // expected-note {{local variable 'v' is invalidated here}}
(void)*next; // expected-note {{later used here}}
}
@@ -297,7 +297,7 @@ void IteratorUsedAfterReverseSubtraction(std::vector<int> v) {
auto it = v.crbegin(); // expected-warning {{parameter 'v' is later invalidated}} \
// expected-note {{result of call to 'crbegin' aliases the storage of parameter 'v'}}
auto prev = 5 - it; // expected-note {{local variable 'it' aliases the storage of parameter 'v'}} \
- // expected-note {{expression aliases the storage of parameter 'v'}}
+ // expected-note {{result of call to 'operator-<__gnu_cxx::basic_iterator<const int>>' aliases the storage of parameter 'v'}}
v.push_back(1); // expected-note {{parameter 'v' is invalidated here}}
(void)*prev; // expected-note {{later used here}}
}
@@ -305,7 +305,7 @@ void IteratorUsedAfterReverseSubtraction(std::vector<int> v) {
void IteratorUsedAfterAddAdd(std::vector<int> v) {
auto it = v.cbegin(); // expected-warning {{parameter 'v' is later invalidated}} \
// expected-note {{result of call to 'cbegin' aliases the storage of parameter 'v'}}
- auto next = (it + 5) + 5; // expected-note 2 {{expression aliases the storage of parameter 'v'}}
+ auto next = (it + 5) + 5; // expected-note 2 {{result of call to 'operator+' aliases the storage of parameter 'v'}}
v.push_back(1); // expected-note {{parameter 'v' is invalidated here}}
(void)*next; // expected-note {{later used here}}
}
@@ -314,7 +314,8 @@ void IteratorUsedAfterMixedAddition() {
std::vector<int> v;
auto it = v.cbegin(); // expected-warning {{local variable 'v' is later invalidated}} \
// expected-note {{result of call to 'cbegin' aliases the storage of local variable 'v'}}
- auto next = 1 + it + 2 + 3; // expected-note 3 {{expression aliases the storage of local variable 'v'}} \
+ auto next = 1 + it + 2 + 3; // expected-note {{result of call to 'operator+<const int>' aliases the storage of local variable 'v'}} \
+ // expected-note 2 {{result of call to 'operator+' aliases the storage of local variable 'v'}} \
// expected-note {{local variable 'it' aliases the storage of local variable 'v'}}
v.push_back(1); // expected-note {{local variable 'v' is invalidated here}}
(void)*next; // expected-note {{later used here}}
@@ -323,7 +324,8 @@ void IteratorUsedAfterMixedAddition() {
void IteratorUsedAfterPreIncrementAddAssign(std::vector<int> v) {
auto it = v.begin(); // expected-warning {{parameter 'v' is later invalidated}} \
// expected-note {{result of call to 'begin' aliases the storage of parameter 'v'}}
- it = ++it + 1 + 2; // expected-note 3 {{expression aliases the storage of parameter 'v'}}
+ it = ++it + 1 + 2; // expected-note {{result of call to 'operator++' aliases the storage of parameter 'v'}} \
+ // expected-note 2 {{result of call to 'operator+' aliases the storage of parameter 'v'}}
v.push_back(1); // expected-note {{parameter 'v' is invalidated here}}
(void)*it; // expected-note {{later used here}}
}
@@ -331,7 +333,7 @@ void IteratorUsedAfterPreIncrementAddAssign(std::vector<int> v) {
void IteratorUsedAfterBeginAddAssign() {
std::vector<int> v;
auto it = v.begin() + 1; // expected-warning {{local variable 'v' is later invalidated}} \
- // expected-note {{expression aliases the storage of local variable 'v'}} \
+ // expected-note {{result of call to 'operator+' aliases the storage of local variable 'v'}} \
// expected-note {{result of call to 'begin' aliases the storage of local variable 'v'}}
v.push_back(1); // expected-note {{local variable 'v' is invalidated here}}
(void)*it; // expected-note {{later used here}}
@@ -341,7 +343,7 @@ void IteratorUsedAfterStdBeginAddAssign() {
std::vector<int> v;
std::vector<int>::iterator it;
it = std::begin(v) + 1; // expected-warning {{local variable 'v' is later invalidated}} \
- // expected-note {{expression aliases the storage of local variable 'v'}} \
+ // expected-note {{result of call to 'operator+' aliases the storage of local variable 'v'}} \
// expected-note {{result of call to 'begin<std::vector<int>>' aliases the storage of local variable 'v'}}
v.push_back(1); // expected-note {{local variable 'v' is invalidated here}}
(void)*it; // expected-note {{later used here}}
@@ -404,7 +406,7 @@ namespace ElementReferences {
void ReferenceToVectorElement() {
std::vector<int> v = {1, 2, 3};
int& ref = v[0]; // expected-warning {{local variable 'v' is later invalidated}} \
- // expected-note {{expression aliases the storage of local variable 'v'}}
+ // expected-note {{result of call to 'operator[]' aliases the storage of local variable 'v'}}
v.push_back(4); // expected-note {{local variable 'v' is invalidated here}}
ref = 10; // expected-note {{later used here}}
(void)ref;
@@ -413,7 +415,7 @@ void ReferenceToVectorElement() {
void PointerRefToVectorElement() {
std::vector<int*> v = {nullptr, nullptr};
int*& ref = v[0]; // expected-warning {{local variable 'v' is later invalidated}} \
- // expected-note {{expression aliases the storage of local variable 'v'}}
+ // expected-note {{result of call to 'operator[]' aliases the storage of local variable 'v'}}
v.push_back(nullptr); // expected-note {{local variable 'v' is invalidated here}}
ref = nullptr; // expected-note {{later used here}}
}
@@ -421,7 +423,7 @@ void PointerRefToVectorElement() {
void PointerToVectorElement() {
std::vector<int> v = {1, 2, 3};
int* ptr = &v[0]; // expected-warning {{local variable 'v' is later invalidated}} \
- // expected-note {{expression aliases the storage of local variable 'v'}}
+ // expected-note {{result of call to 'operator[]' aliases the storage of local variable 'v'}}
v.resize(100); // expected-note {{local variable 'v' is invalidated here}}
*ptr = 10; // expected-note {{later used here}}
}
@@ -447,7 +449,7 @@ void SelfInvalidatingMap() {
// expected-note {{local variable 'mp' is invalidated here}} \
// expected-note {{later used here}} \
// expected-note {{local variable 'mp' is invalidated here}} \
- // expected-note {{expression aliases the storage of local variable 'mp'}} \
+ // expected-note {{result of call to 'operator[]' aliases the storage of local variable 'mp'}} \
// expected-note {{later used here}}
}
@@ -798,7 +800,7 @@ void FlatMapSubscriptMultipleCallsInvalidate(std::flat_map<int, int> mp, int a,
// expected-note {{parameter 'mp' is invalidated here}} \
// expected-note {{later used here}} \
// expected-note {{parameter 'mp' is invalidated here}} \
- // expected-note 2 {{expression aliases the storage of parameter 'mp'}} \
+ // expected-note 2 {{result of call to 'operator[]' aliases the storage of parameter 'mp'}} \
// expected-note {{later used here}}
}
@@ -851,7 +853,7 @@ struct S {
void baz(){
std::vector<std::string> vec = {"42"};
v = vec[0]; // expected-warning {{local variable 'vec' is later invalidated}} \
- // expected-note {{expression aliases the storage of local variable 'vec'}}
+ // expected-note {{result of call to 'operator[]' aliases the storage of local variable 'vec'}}
vec.push_back("1"); // expected-note {{local variable 'vec' is invalidated here}}
bar(); // expected-note {{later used here}}
v = nullptr;
@@ -865,7 +867,7 @@ void function_captured_ref_invalidated() {
std::vector<int> v;
v.push_back(1);
std::function<void()> f = [&r = v[0]]() { (void)r; }; // expected-warning {{local variable 'v' is later invalidated}} \
- // expected-note {{expression aliases the storage of local variable 'v'}}
+ // expected-note {{result of call to 'operator[]' aliases the storage of local variable 'v'}}
v.push_back(2); // expected-note {{local variable 'v' is invalidated here}}
(void)f; // expected-note {{later used here}}
}
diff --git a/clang/test/Sema/LifetimeSafety/nocfg.cpp b/clang/test/Sema/LifetimeSafety/nocfg.cpp
index 5c5f0e6f7ce52..7ef209572c437 100644
--- a/clang/test/Sema/LifetimeSafety/nocfg.cpp
+++ b/clang/test/Sema/LifetimeSafety/nocfg.cpp
@@ -310,11 +310,11 @@ std::string_view danglingRefToOptionalFromTemp4() {
void danglingReferenceFromTempOwner() {
int &&r = *std::optional<int>(); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} \
// cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \
- // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}}
+ // cfg-note {{result of call to 'operator*' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}}
// https://github.com/llvm/llvm-project/issues/175893
int &&r2 = *std::optional<int>(5); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} \
// cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \
- // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}}
+ // cfg-note {{result of call to 'operator*' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}}
// https://github.com/llvm/llvm-project/issues/175893
int &&r3 = std::optional<int>(5).value(); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} \
@@ -331,7 +331,7 @@ void danglingReferenceFromTempOwner() {
std::string_view sv = *getTempOptStr(); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} \
// cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \
- // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}}
+ // cfg-note {{result of call to 'operator*' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}}
use(sv); // cfg-note {{later used here}}
}
@@ -343,7 +343,7 @@ void testLoops() {
;
for (auto i : *getTempOptVec()) // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} \
// cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} cfg-note {{later used here}} \
- // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}}
+ // cfg-note {{result of call to 'operator*' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}}
;
}
@@ -1050,15 +1050,15 @@ void operator_star_arrow_reference() {
auto temporary = []() { return std::vector<std::string>{{"1"}}; };
const char* x = temporary().begin()->data(); // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \
// cfg-note {{result of call to 'begin' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \
- // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \
+ // cfg-note {{result of call to 'operator->' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \
// cfg-note {{result of call to 'data' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}}
const char* y = (*temporary().begin()).data(); // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \
// cfg-note {{result of call to 'begin' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \
- // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \
+ // cfg-note {{result of call to 'operator*' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \
// cfg-note {{result of call to 'data' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}}
const std::string& z = (*temporary().begin()); // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \
// cfg-note {{result of call to 'begin' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \
- // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}}
+ // cfg-note {{result of call to 'operator*' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}}
use(p, q, r, x, y, z); // cfg-note 3 {{later used here}}
}
@@ -1072,15 +1072,15 @@ void operator_star_arrow_of_iterators_false_positive_no_cfg_analysis() {
auto temporary = []() { return std::vector<std::pair<int, std::string>>{{1, "1"}}; };
const char* x = temporary().begin()->second.data(); // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \
// cfg-note {{result of call to 'begin' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \
- // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \
+ // cfg-note {{result of call to 'operator->' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \
// cfg-note {{result of call to 'data' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}}
const char* y = (*temporary().begin()).second.data(); // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \
// cfg-note {{result of call to 'begin' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \
- // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \
+ // cfg-note {{result of call to 'operator*' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \
// cfg-note {{result of call to 'data' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}}
const std::string& z = (*temporary().begin()).second; // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \
// cfg-note {{result of call to 'begin' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \
- // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}}
+ // cfg-note {{result of call to 'operator*' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}}
use(p, q, r, x, y, z); // cfg-note 3 {{later used here}}
}
@@ -1131,23 +1131,23 @@ void test1() {
std::string_view k1 = S().sv; // OK
std::string_view k2 = S().s; // expected-warning {{object backing the pointer will}} \
// cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \
- // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}}
+ // cfg-note {{result of call to 'operator basic_string_view' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}}
std::string_view k3 = Q().get()->sv; // OK
std::string_view k4 = Q().get()->s; // expected-warning {{object backing the pointer will}} \
// cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \
// cfg-note {{result of call to 'get' aliases the storage of temporary object because the implicit object parameter is marked as lifetimebound}} \
- // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}}
+ // cfg-note {{result of call to 'operator basic_string_view' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}}
std::string_view lb1 = foo(S().s); // expected-warning {{object backing the pointer will}} \
// cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \
- // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \
+ // cfg-note {{result of call to 'operator basic_string_view' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \
// cfg-note {{result of call to 'foo' aliases the storage of temporary object because parameter 'sv' is marked as lifetimebound}}
std::string_view lb2 = foo(Q().get()->s); // expected-warning {{object backing the pointer will}} \
// cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \
// cfg-note {{result of call to 'get' aliases the storage of temporary object because the implicit object parameter is marked as lifetimebound}} \
- // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \
+ // cfg-note {{result of call to 'operator basic_string_view' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \
// cfg-note {{result of call to 'foo' aliases the storage of temporary object because parameter 'sv' is marked as lifetimebound}}
use(k1, k2, k3, k4, lb1, lb2); // cfg-note 4 {{later used here}}
diff --git a/clang/test/Sema/LifetimeSafety/safety.cpp b/clang/test/Sema/LifetimeSafety/safety.cpp
index 1b269b265acb1..851f558c85dcd 100644
--- a/clang/test/Sema/LifetimeSafety/safety.cpp
+++ b/clang/test/Sema/LifetimeSafety/safety.cpp
@@ -1677,7 +1677,7 @@ void test_user_defined_deref_uaf() {
MyObj obj;
SmartPtr<MyObj> smart_ptr(&obj);
p = &(*smart_ptr); // expected-warning {{local variable 'smart_ptr' does not live long enough}} \
- // expected-note {{expression aliases the storage of local variable 'smart_ptr' because the implicit object parameter is marked as lifetimebound}}
+ // expected-note {{result of call to 'operator*' aliases the storage of local variable 'smart_ptr' because the implicit object parameter is marked as lifetimebound}}
} // expected-note {{local variable 'smart_ptr' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -1695,7 +1695,7 @@ void test_user_defined_deref_with_view() {
MyObj obj;
SmartPtr<MyObj> smart_ptr(&obj);
v = *smart_ptr; // expected-warning {{local variable 'smart_ptr' does not live long enough}} \
- // expected-note {{expression aliases the storage of local variable 'smart_ptr' because the implicit object parameter is marked as lifetimebound}}
+ // expected-note {{result of call to 'operator*' aliases the storage of local variable 'smart_ptr' because the implicit object parameter is marked as lifetimebound}}
} // expected-note {{local variable 'smart_ptr' is destroyed here}}
v.use(); // expected-note {{later used here}}
}
@@ -1706,7 +1706,7 @@ void test_user_defined_deref_arrow() {
MyObj obj;
SmartPtr<MyObj> smart_ptr(&obj);
p = smart_ptr.operator->(); // expected-warning {{local variable 'smart_ptr' does not live long enough}} \
- // expected-note {{expression aliases the storage of local variable 'smart_ptr' because the implicit object parameter is marked as lifetimebound}}
+ // expected-note {{result of call to 'operator->' aliases the storage of local variable 'smart_ptr' because the implicit object parameter is marked as lifetimebound}}
} // expected-note {{local variable 'smart_ptr' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -1717,7 +1717,7 @@ void test_user_defined_deref_chained() {
MyObj obj;
SmartPtr<SmartPtr<MyObj>> double_ptr;
p = &(**double_ptr); // expected-warning {{local variable 'double_ptr' does not live long enough}} \
- // expected-note 2 {{expression aliases the storage of local variable 'double_ptr' because the implicit object parameter is marked as lifetimebound}}
+ // expected-note 2 {{result of call to 'operator*' aliases the storage of local variable 'double_ptr' because the implicit object parameter is marked as lifetimebound}}
} // expected-note {{local variable 'double_ptr' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -2052,7 +2052,7 @@ void test_temporary() {
S s;
const std::string& zz = s.x(); // expected-warning {{local variable 's' does not live long enough}} \
// expected-note {{result of call to 'x' aliases the storage of local variable 's' because the implicit object parameter is marked as lifetimebound}}
- z = zz; // expected-note {{expression aliases the storage of local variable 's'}}
+ z = zz; // expected-note {{result of call to 'operator basic_string_view' aliases the storage of local variable 's'}}
} // expected-note {{local variable 's' is destroyed here}}
(void)z; // expected-note {{later used here}}
}
@@ -2085,7 +2085,7 @@ void uaf() {
S str;
S* p = &str; // expected-warning {{local variable 'str' does not live long enough}}
view = p->s; // expected-note {{local variable 'p' aliases the storage of local variable 'str'}} \
- // expected-note {{expression aliases the storage of local variable 'str' because the implicit object parameter is inferred as lifetimebound}}
+ // expected-note {{result of call to 'operator basic_string_view' aliases the storage of local variable 'str' because the implicit object parameter is inferred as lifetimebound}}
} // expected-note {{local variable 'str' is destroyed here}}
(void)view; // expected-note {{later used here}}
}
@@ -2112,7 +2112,7 @@ void uaf_union() {
U u = U{"hello"};
U* up = &u; // expected-warning {{local variable 'u' does not live long enough}}
view = up->s; // expected-note {{local variable 'up' aliases the storage of local variable 'u'}} \
- // expected-note {{expression aliases the storage of local variable 'u' because the implicit object parameter is inferred as lifetimebound}}
+ // expected-note {{result of call to 'operator basic_string_view' aliases the storage of local variable 'u' because the implicit object parameter is inferred as lifetimebound}}
} // expected-note {{local variable 'u' is destroyed here}}
(void)view; // expected-note {{later used here}}
}
@@ -2288,7 +2288,7 @@ void test_optional_arrow() {
{
std::optional<std::string> opt;
p = opt->data(); // expected-warning {{local variable 'opt' does not live long enough}} \
- // expected-note {{expression aliases the storage of local variable 'opt' because the implicit object parameter is inferred as lifetimebound}} \
+ // expected-note {{result of call to 'operator->' aliases the storage of local variable 'opt' because the implicit object parameter is inferred as lifetimebound}} \
// expected-note {{result of call to 'data' aliases the storage of local variable 'opt' because the implicit object parameter is inferred as lifetimebound}}
} // expected-note {{local variable 'opt' is destroyed here}}
(void)*p; // expected-note {{later used here}}
@@ -2299,7 +2299,7 @@ void test_optional_arrow_lifetimebound() {
{
std::optional<MyObj> opt;
v = opt->getView(); // expected-warning {{local variable 'opt' does not live long enough}} \
- // expected-note {{expression aliases the storage of local variable 'opt' because the implicit object parameter is inferred as lifetimebound}} \
+ // expected-note {{result of call to 'operator->' aliases the storage of local variable 'opt' because the implicit object parameter is inferred as lifetimebound}} \
// expected-note {{result of call to 'getView' aliases the storage of local variable 'opt' because the implicit object parameter is marked as lifetimebound}}
} // expected-note {{local variable 'opt' is destroyed here}}
v.use(); // expected-note {{later used here}}
@@ -2310,7 +2310,7 @@ void test_unique_ptr_arrow() {
{
std::unique_ptr<std::string> up;
p = up->data(); // expected-warning {{local variable 'up' does not live long enough}} \
- // expected-note {{expression aliases the storage of local variable 'up' because the implicit object parameter is inferred as lifetimebound}} \
+ // expected-note {{result of call to 'operator->' aliases the storage of local variable 'up' because the implicit object parameter is inferred as lifetimebound}} \
// expected-note {{result of call to 'data' aliases the storage of local variable 'up' because the implicit object parameter is inferred as lifetimebound}}
} // expected-note {{local variable 'up' is destroyed here}}
(void)*p; // expected-note {{later used here}}
@@ -2701,8 +2701,8 @@ struct S {
void indexing_with_static_operator() {
S()(1, 2);
- S& x = S()("1", // expected-note {{expression aliases the storage of temporary object because parameter 'a' is marked as lifetimebound}} \
- // expected-note {{expression aliases the storage of temporary object because parameter 'b' is marked as lifetimebound}}
+ S& x = S()("1", // expected-note {{result of call to 'operator()' aliases the storage of temporary object because parameter 'a' is marked as lifetimebound}} \
+ // expected-note {{result of call to 'operator()' aliases the storage of temporary object because parameter 'b' is marked as lifetimebound}}
2, // expected-warning {{temporary object does not live long enough}}
3); // expected-warning {{temporary object does not live long enough}} expected-note 2 {{temporary object is destroyed here}}
@@ -2810,7 +2810,7 @@ void chained_defaulted_assignment_propagation() {
S a = getS(str); // expected-warning {{local variable 'str' does not live long enough}} \
// expected-note {{result of call to 'getS' aliases the storage of local variable 'str' because parameter 's' is marked as lifetimebound}}
c = b = a; // expected-note {{local variable 'a' aliases the storage of local variable 'str'}} \
- // expected-note {{expression aliases the storage of local variable 'str'}}
+ // expected-note {{result of call to 'operator=' aliases the storage of local variable 'str'}}
} // expected-note {{local variable 'str' is destroyed here}}
use(c); // expected-note {{later used here}}
}
@@ -3873,7 +3873,7 @@ void deref_use_after_scope() {
{
optional<MyObj> opt;
p = &*opt; // expected-warning {{local variable 'opt' does not live long enough}} \
- // expected-note {{expression aliases the storage of local variable 'opt' because the implicit object parameter is inferred as lifetimebound}}
+ // expected-note {{result of call to 'operator*' aliases the storage of local variable 'opt' because the implicit object parameter is inferred as lifetimebound}}
} // expected-note {{local variable 'opt' is destroyed here}}
(void)p->id; // expected-note {{later used here}}
}
More information about the cfe-commits
mailing list