[llvm-branch-commits] [clang] UseFacts to consider only LValueToRValue and function calls (PR #181693)
Utkarsh Saxena via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Feb 20 10:27:58 PST 2026
https://github.com/usx95 updated https://github.com/llvm/llvm-project/pull/181693
>From 0edb353ec58d046cdb0c65c317a523335df9ecbb Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena <usx at google.com>
Date: Mon, 16 Feb 2026 15:52:33 +0000
Subject: [PATCH] UseFacts to consider only LValueToRValue and function calls
---
.../LifetimeSafety/FactsGenerator.cpp | 13 +-
.../Analysis/LifetimeSafety/LiveOrigins.cpp | 12 +-
.../Sema/warn-lifetime-analysis-nocfg.cpp | 2 +-
.../Sema/warn-lifetime-safety-dataflow.cpp | 5 -
.../Sema/warn-lifetime-safety-suggestions.cpp | 6 +-
clang/test/Sema/warn-lifetime-safety.cpp | 150 +++++++++---------
6 files changed, 96 insertions(+), 92 deletions(-)
diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
index df3ed3c4e8105..ae515cab15cec 100644
--- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
@@ -161,7 +161,7 @@ void FactsGenerator::VisitDeclRefExpr(const DeclRefExpr *DRE) {
// GLValues (like EnumConstants).
if (DRE->getFoundDecl()->isFunctionOrFunctionTemplate() || !DRE->isGLValue())
return;
- handleUse(DRE);
+ // handleUse(DRE);
// For all declarations with storage (non-references), we issue a loan
// representing the borrow of the variable's storage itself.
//
@@ -253,14 +253,15 @@ void FactsGenerator::VisitCXXNullPtrLiteralExpr(
void FactsGenerator::VisitImplicitCastExpr(const ImplicitCastExpr *ICE) {
OriginList *Dest = getOriginsList(*ICE);
- if (!Dest)
- return;
+ // if (!Dest)
+ // return;
const Expr *SubExpr = ICE->getSubExpr();
OriginList *Src = getOriginsList(*SubExpr);
switch (ICE->getCastKind()) {
case CK_LValueToRValue:
// TODO: Decide what to do for x-values here.
+ handleUse(SubExpr);
if (!SubExpr->isLValue())
return;
@@ -688,9 +689,9 @@ void FactsGenerator::handleUse(const Expr *E) {
// For DeclRefExpr: Remove the outer layer of origin which borrows from the
// decl directly (e.g., when this is not a reference). This is a use of the
// underlying decl.
- if (auto *DRE = dyn_cast<DeclRefExpr>(E);
- DRE && !DRE->getDecl()->getType()->isReferenceType())
- List = getRValueOrigins(DRE, List);
+ // if (auto *DRE = dyn_cast<DeclRefExpr>(E);
+ // DRE && !DRE->getDecl()->getType()->isReferenceType())
+ // List = getRValueOrigins(DRE, List);
// Skip if there is no inner origin (e.g., when it is not a pointer type).
if (!List)
return;
diff --git a/clang/lib/Analysis/LifetimeSafety/LiveOrigins.cpp b/clang/lib/Analysis/LifetimeSafety/LiveOrigins.cpp
index f210fb4d752d4..d37223feb9c59 100644
--- a/clang/lib/Analysis/LifetimeSafety/LiveOrigins.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/LiveOrigins.cpp
@@ -159,9 +159,15 @@ class AnalysisImpl
/// An OriginFlow kills the liveness of the destination origin if `KillDest`
/// is true. Otherwise, it propagates liveness from destination to source.
Lattice transfer(Lattice In, const OriginFlowFact &OF) {
- if (!OF.getKillDest())
- return In;
- return Lattice(Factory.remove(In.LiveOrigins, OF.getDestOriginID()));
+ // if (!OF.getKillDest())
+ // return In;
+ Lattice Out = In;
+ if (auto *DestLiveness = Out.LiveOrigins.lookup(OF.getDestOriginID()))
+ Out = Lattice(
+ Factory.add(Out.LiveOrigins, OF.getSrcOriginID(), *DestLiveness));
+ if (OF.getKillDest())
+ Out = Lattice(Factory.remove(Out.LiveOrigins, OF.getDestOriginID()));
+ return Out;
}
LivenessMap getLiveOriginsAt(ProgramPoint P) const {
diff --git a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
index c40c6a671e3ab..9fb77d395e17b 100644
--- a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
+++ b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
@@ -185,7 +185,7 @@ struct Unannotated {
void modelIterators() {
std::vector<int>::iterator it = std::vector<int>().begin(); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} \
// cfg-warning {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}}
- (void)it; // cfg-note {{later used here}}
+ (void)*it; // cfg-note {{later used here}}
}
std::vector<int>::iterator modelIteratorReturn() {
diff --git a/clang/test/Sema/warn-lifetime-safety-dataflow.cpp b/clang/test/Sema/warn-lifetime-safety-dataflow.cpp
index 7e2215b8deedc..ee2ae7ba1fa7c 100644
--- a/clang/test/Sema/warn-lifetime-safety-dataflow.cpp
+++ b/clang/test/Sema/warn-lifetime-safety-dataflow.cpp
@@ -19,7 +19,6 @@ MyObj* return_local_addr() {
// CHECK: OriginFlow:
// CHECK-NEXT: Dest: [[O_P:[0-9]+]] (Decl: p, Type : MyObj *)
// CHECK-NEXT: Src: [[O_ADDR_X]] (Expr: UnaryOperator, Type : MyObj *)
-// CHECK: Use ([[O_P]] (Decl: p, Type : MyObj *), Read)
return p;
// CHECK: Issue ({{[0-9]+}} (Path: p), ToOrigin: {{[0-9]+}} (Expr: DeclRefExpr, Decl: p))
// CHECK: OriginFlow:
@@ -81,7 +80,6 @@ void overwrite_origin() {
// CHECK: OriginFlow:
// CHECK-NEXT: Dest: [[O_ADDR_S2:[0-9]+]] (Expr: UnaryOperator, Type : MyObj *)
// CHECK-NEXT: Src: [[O_DRE_S2]] (Expr: DeclRefExpr, Decl: s2)
-// CHECK: Use ([[O_P]] (Decl: p, Type : MyObj *), Write)
// CHECK: Issue ({{[0-9]+}} (Path: p), ToOrigin: {{[0-9]+}} (Expr: DeclRefExpr, Decl: p))
// CHECK: OriginFlow:
// CHECK-NEXT: Dest: [[O_P]] (Decl: p, Type : MyObj *)
@@ -103,7 +101,6 @@ void reassign_to_null() {
// CHECK-NEXT: Dest: [[O_P:[0-9]+]] (Decl: p, Type : MyObj *)
// CHECK-NEXT: Src: [[O_ADDR_S1]] (Expr: UnaryOperator, Type : MyObj *)
p = nullptr;
-// CHECK: Use ([[O_P]] (Decl: p, Type : MyObj *), Write)
// CHECK: Issue ({{[0-9]+}} (Path: p), ToOrigin: {{[0-9]+}} (Expr: DeclRefExpr, Decl: p))
// CHECK: OriginFlow:
// CHECK-NEXT: Dest: [[O_P]] (Decl: p, Type : MyObj *)
@@ -126,7 +123,6 @@ void pointer_indirection() {
// CHECK-NEXT: Dest: [[O_P:[0-9]+]] (Decl: p, Type : int *)
// CHECK-NEXT: Src: [[O_ADDR_A]] (Expr: UnaryOperator, Type : int *)
int **pp = &p;
-// CHECK: Use ([[O_P]] (Decl: p, Type : int *), Read)
// CHECK: Issue ({{[0-9]+}} (Path: p), ToOrigin: {{[0-9]+}} (Expr: DeclRefExpr, Decl: p))
// CHECK: OriginFlow:
// CHECK-NEXT: Dest: {{[0-9]+}} (Expr: UnaryOperator, Type : int **)
@@ -143,7 +139,6 @@ void pointer_indirection() {
// FIXME: Propagate origins across dereference unary operator*
int *q = *pp;
-// CHECK: Use ([[O_PP_OUTER]] (Decl: pp, Type : int **), [[O_PP_INNER]] (Decl: pp, Type : int *), Read)
// CHECK: Issue ({{[0-9]+}} (Path: pp), ToOrigin: {{[0-9]+}} (Expr: DeclRefExpr, Decl: pp))
// CHECK: OriginFlow:
// CHECK-NEXT: Dest: {{[0-9]+}} (Expr: ImplicitCastExpr, Type : int **)
diff --git a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
index 4bd8a717d9d30..552f9ce3f7226 100644
--- a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
+++ b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
@@ -221,19 +221,19 @@ View return_view_field(const ViewProvider& v) { // expected-warning {{paramet
void test_get_on_temporary_pointer() {
const ReturnsSelf* s_ref = &ReturnsSelf().get(); // expected-warning {{object whose reference is captured does not live long enough}}.
// expected-note at -1 {{destroyed here}}
- (void)s_ref; // expected-note {{later used here}}
+ s_ref->get(); // expected-note {{later used here}}
}
void test_get_on_temporary_ref() {
const ReturnsSelf& s_ref = ReturnsSelf().get(); // expected-warning {{object whose reference is captured does not live long enough}}.
// expected-note at -1 {{destroyed here}}
- (void)s_ref; // expected-note {{later used here}}
+ s_ref.get(); // expected-note {{later used here}}
}
void test_getView_on_temporary() {
View sv = ViewProvider{1}.getView(); // expected-warning {{object whose reference is captured does not live long enough}}.
// expected-note at -1 {{destroyed here}}
- (void)sv; // expected-note {{later used here}}
+ sv.use(); // expected-note {{later used here}}
}
void test_get_on_temporary_copy() {
diff --git a/clang/test/Sema/warn-lifetime-safety.cpp b/clang/test/Sema/warn-lifetime-safety.cpp
index 8f52ff27bc6fd..2653f128fd882 100644
--- a/clang/test/Sema/warn-lifetime-safety.cpp
+++ b/clang/test/Sema/warn-lifetime-safety.cpp
@@ -3,6 +3,8 @@
#include "Inputs/lifetime-analysis.h"
+template <typename T> void use(T t); // Take by value
+
struct View;
struct [[gsl::Owner]] MyObj {
@@ -56,7 +58,7 @@ void definite_simple_case() {
MyObj s;
p = &s; // expected-warning {{object whose reference is captured does not live long enough}}
} // expected-note {{destroyed here}}
- (void)*p; // expected-note {{later used here}}
+ use(*p); // expected-note {{later used here}}
}
void definite_simple_case_gsl() {
@@ -94,7 +96,7 @@ void definite_pointer_chain() {
p = &s; // expected-warning {{does not live long enough}}
q = p;
} // expected-note {{destroyed here}}
- (void)*q; // expected-note {{later used here}}
+ use(*q); // expected-note {{later used here}}
}
void definite_propagation_gsl() {
@@ -113,11 +115,11 @@ void definite_multiple_uses_one_warning() {
MyObj s;
p = &s; // expected-warning {{does not live long enough}}
} // expected-note {{destroyed here}}
- (void)*p; // expected-note {{later used here}}
+ use(*p); // expected-note {{later used here}}
// No second warning for the same loan.
p->id = 1;
MyObj* q = p;
- (void)*q;
+ use(*q);
}
void definite_multiple_pointers() {
@@ -128,9 +130,9 @@ void definite_multiple_pointers() {
q = &s; // expected-warning {{does not live long enough}}
r = &s; // expected-warning {{does not live long enough}}
} // expected-note 3 {{destroyed here}}
- (void)*p; // expected-note {{later used here}}
- (void)*q; // expected-note {{later used here}}
- (void)*r; // expected-note {{later used here}}
+ use(*p); // expected-note {{later used here}}
+ use(*q); // expected-note {{later used here}}
+ use(*r); // expected-note {{later used here}}
}
void definite_single_pointer_multiple_loans(bool cond) {
@@ -143,7 +145,7 @@ void definite_single_pointer_multiple_loans(bool cond) {
MyObj t;
p = &t; // expected-warning {{does not live long enough}}
} // expected-note {{destroyed here}}
- (void)*p; // expected-note 2 {{later used here}}
+ use(*p); // expected-note 2 {{later used here}}
}
void definite_single_pointer_multiple_loans_gsl(bool cond) {
@@ -166,7 +168,7 @@ void definite_if_branch(bool cond) {
MyObj temp;
p = &temp; // expected-warning {{object whose reference is captured does not live long enough}}
} // expected-note {{destroyed here}}
- (void)*p; // expected-note {{later used here}}
+ use(*p); // expected-note {{later used here}}
}
void potential_if_branch(bool cond) {
@@ -177,7 +179,7 @@ void potential_if_branch(bool cond) {
p = &temp; // expected-warning {{object whose reference is captured may not live long enough}}
} // expected-note {{destroyed here}}
if (!cond)
- (void)*p; // expected-note {{later used here}}
+ use(*p); // expected-note {{later used here}}
else
p = &safe;
}
@@ -204,9 +206,9 @@ void definite_potential_together(bool cond) {
if (cond)
p_maybe = &s; // expected-warning {{may not live long enough}}
} // expected-note 2 {{destroyed here}}
- (void)*p_definite; // expected-note {{later used here}}
+ use(*p_definite); // expected-note {{later used here}}
if (!cond)
- (void)*p_maybe; // expected-note {{later used here}}
+ use(*p_maybe); // expected-note {{later used here}}
}
void definite_overrides_potential(bool cond) {
@@ -225,9 +227,9 @@ void definite_overrides_potential(bool cond) {
}
// The use of 'p' is a definite error because it was never rescued.
- (void)*q;
- (void)*p; // expected-note {{later used here}}
- (void)*q;
+ use(*q);
+ use(*p); // expected-note {{later used here}}
+ use(*q);
}
void potential_due_to_conditional_killing(bool cond) {
@@ -241,7 +243,7 @@ void potential_due_to_conditional_killing(bool cond) {
// 'q' is conditionally "rescued". 'p' is not.
q = &safe;
}
- (void)*q; // expected-note {{later used here}}
+ use(*q); // expected-note {{later used here}}
}
void potential_for_loop_use_after_loop_body(MyObj safe) {
@@ -250,7 +252,7 @@ void potential_for_loop_use_after_loop_body(MyObj safe) {
MyObj s;
p = &s; // expected-warning {{may not live long enough}}
} // expected-note {{destroyed here}}
- (void)*p; // expected-note {{later used here}}
+ use(*p); // expected-note {{later used here}}
}
void safe_for_loop_gsl() {
@@ -277,11 +279,11 @@ void potential_for_loop_use_before_loop_body(MyObj safe) {
MyObj* p = &safe;
// Prefer the earlier use for diagnsotics.
for (int i = 0; i < 1; ++i) {
- (void)*p; // expected-note {{later used here}}
+ use(*p); // expected-note {{later used here}}
MyObj s;
p = &s; // expected-warning {{does not live long enough}}
} // expected-note {{destroyed here}}
- (void)*p;
+ use(*p);
}
void definite_loop_with_break(bool cond) {
@@ -294,7 +296,7 @@ void definite_loop_with_break(bool cond) {
break; // expected-note {{destroyed here}}
}
}
- (void)*p; // expected-note {{later used here}}
+ use(*p); // expected-note {{later used here}}
}
void definite_loop_with_break_gsl(bool cond) {
@@ -321,7 +323,7 @@ void potential_multiple_expiry_of_same_loan(bool cond) {
break; // expected-note {{destroyed here}}
}
}
- (void)*p; // expected-note {{later used here}}
+ use(*p); // expected-note {{later used here}}
p = &safe;
for (int i = 0; i < 10; ++i) {
@@ -332,7 +334,7 @@ void potential_multiple_expiry_of_same_loan(bool cond) {
break; // expected-note {{destroyed here}}
}
}
- (void)*p; // expected-note {{later used here}}
+ use(*p); // expected-note {{later used here}}
p = &safe;
for (int i = 0; i < 10; ++i) {
@@ -347,7 +349,7 @@ void potential_multiple_expiry_of_same_loan(bool cond) {
// we only check for confidence of liveness and not the confidence of
// the loan contained in an origin. To deal with this, we can introduce
// a confidence in loan propagation analysis as well like liveness.
- (void)*p; // expected-note {{later used here}}
+ use(*p); // expected-note {{later used here}}
p = &safe;
for (int i = 0; i < 10; ++i) {
@@ -357,7 +359,7 @@ void potential_multiple_expiry_of_same_loan(bool cond) {
if (cond)
break; // expected-note {{destroyed here}}
}
- (void)*p; // expected-note {{later used here}}
+ use(*p); // expected-note {{later used here}}
}
void potential_switch(int mode) {
@@ -375,7 +377,7 @@ void potential_switch(int mode) {
}
}
if (mode == 2)
- (void)*p; // expected-note {{later used here}}
+ use(*p); // expected-note {{later used here}}
}
void definite_switch(int mode) {
@@ -399,7 +401,7 @@ void definite_switch(int mode) {
break; // expected-note {{destroyed here}}
}
}
- (void)*p; // expected-note 3 {{later used here}}
+ use(*p); // expected-note 3 {{later used here}}
}
void definite_switch_gsl(int mode) {
@@ -434,8 +436,8 @@ void loan_from_previous_iteration(MyObj safe, bool condition) {
if (condition)
q = p;
- (void)*p;
- (void)*q; // expected-note {{later used here}}
+ use(*p);
+ use(*q); // expected-note {{later used here}}
} // expected-note {{destroyed here}}
}
@@ -445,7 +447,7 @@ void trivial_int_uaf() {
int b = 1;
a = &b; // expected-warning {{object whose reference is captured does not live long enough}}
} // expected-note {{destroyed here}}
- (void)*a; // expected-note {{later used here}}
+ use(*a); // expected-note {{later used here}}
}
void trivial_class_uaf() {
@@ -454,7 +456,7 @@ void trivial_class_uaf() {
TriviallyDestructedClass s;
ptr = &s; // expected-warning {{object whose reference is captured does not live long enough}}
} // expected-note {{destroyed here}}
- (void)ptr; // expected-note {{later used here}}
+ use(*ptr); // expected-note {{later used here}}
}
void small_scope_reference_var_no_error() {
@@ -676,7 +678,7 @@ void test_lifetimebound_multi_level() {
int*** ppp = &pp; // expected-warning {{object whose reference is captured does not live long enough}}
result = return_inner_ptr_addr(ppp);
} // expected-note {{destroyed here}}
- (void)**result; // expected-note {{used here}}
+ use(**result); // expected-note {{used here}}
}
// FIXME: Assignment does not track the dereference of a pointer.
@@ -688,7 +690,7 @@ void test_assign_through_double_ptr() {
int c = 3;
*pp = &c;
}
- (void)**pp;
+ use(**pp);
}
int** test_ternary_double_ptr(bool cond) {
@@ -737,7 +739,7 @@ void no_error_if_dangle_then_rescue() {
p = &temp; // p is temporarily dangling.
}
p = &safe; // p is "rescued" before use.
- (void)*p; // This is safe.
+ use(*p); // This is safe.
}
void no_error_if_dangle_then_rescue_gsl() {
@@ -760,7 +762,7 @@ void no_error_loan_from_current_iteration(bool cond) {
if (cond) {
p = a;
}
- (void)p;
+ use(p);
}
}
@@ -872,7 +874,7 @@ void lifetimebound_with_pointers() {
MyObj obj;
ptr = GetPointer(obj); // expected-warning {{object whose reference is captured does not live long enough}}
} // expected-note {{destroyed here}}
- (void)*ptr; // expected-note {{later used here}}
+ use(*ptr); // expected-note {{later used here}}
}
void lifetimebound_no_error_safe_usage() {
@@ -905,7 +907,7 @@ void lifetimebound_return_reference() {
const MyObj& ref = GetObject(temp_v);
ptr = &ref;
} // expected-note {{destroyed here}}
- (void)*ptr; // expected-note {{later used here}}
+ use(*ptr); // expected-note {{later used here}}
}
// FIXME: No warning for non gsl::Pointer types. Origin tracking is only supported for pointer types.
@@ -920,7 +922,7 @@ void lifetimebound_ctor() {
MyObj obj;
v = obj;
}
- (void)v;
+ use(v);
}
View lifetimebound_return_of_local() {
@@ -1003,7 +1005,7 @@ void conditional_operator_one_unsafe_branch(bool cond) {
// ensures safety regardless of cond's value.
if (cond)
p = &safe;
- (void)*p; // expected-note {{later used here}}
+ use(*p); // expected-note {{later used here}}
}
void conditional_operator_two_unsafe_branches(bool cond) {
@@ -1013,7 +1015,7 @@ void conditional_operator_two_unsafe_branches(bool cond) {
p = cond ? &a // expected-warning {{object whose reference is captured does not live long enough}}
: &b; // expected-warning {{object whose reference is captured does not live long enough}}
} // expected-note 2 {{destroyed here}}
- (void)*p; // expected-note 2 {{later used here}}
+ use(*p); // expected-note 2 {{later used here}}
}
void conditional_operator_nested(bool cond) {
@@ -1025,7 +1027,7 @@ void conditional_operator_nested(bool cond) {
: cond ? &c // expected-warning {{object whose reference is captured does not live long enough}}.
: &d; // expected-warning {{object whose reference is captured does not live long enough}}.
} // expected-note 4 {{destroyed here}}
- (void)*p; // expected-note 4 {{later used here}}
+ use(*p); // expected-note 4 {{later used here}}
}
void conditional_operator_lifetimebound(bool cond) {
@@ -1035,7 +1037,7 @@ void conditional_operator_lifetimebound(bool cond) {
p = Identity(cond ? &a // expected-warning {{object whose reference is captured does not live long enough}}
: &b); // expected-warning {{object whose reference is captured does not live long enough}}
} // expected-note 2 {{destroyed here}}
- (void)*p; // expected-note 2 {{later used here}}
+ use(*p); // expected-note 2 {{later used here}}
}
void conditional_operator_lifetimebound_nested(bool cond) {
@@ -1045,7 +1047,7 @@ void conditional_operator_lifetimebound_nested(bool cond) {
p = Identity(cond ? Identity(&a) // expected-warning {{object whose reference is captured does not live long enough}}
: Identity(&b)); // expected-warning {{object whose reference is captured does not live long enough}}
} // expected-note 2 {{destroyed here}}
- (void)*p; // expected-note 2 {{later used here}}
+ use(*p); // expected-note 2 {{later used here}}
}
void conditional_operator_lifetimebound_nested_deep(bool cond) {
@@ -1057,7 +1059,7 @@ void conditional_operator_lifetimebound_nested_deep(bool cond) {
: Identity(cond ? &c // expected-warning {{object whose reference is captured does not live long enough}}
: &d)); // expected-warning {{object whose reference is captured does not live long enough}}
} // expected-note 4 {{destroyed here}}
- (void)*p; // expected-note 4 {{later used here}}
+ use(*p); // expected-note 4 {{later used here}}
}
void parentheses(bool cond) {
@@ -1066,13 +1068,13 @@ void parentheses(bool cond) {
MyObj a;
p = &((((a)))); // expected-warning {{object whose reference is captured does not live long enough}}
} // expected-note {{destroyed here}}
- (void)*p; // expected-note {{later used here}}
+ use(*p); // expected-note {{later used here}}
{
MyObj a;
p = ((GetPointer((a)))); // expected-warning {{object whose reference is captured does not live long enough}}
} // expected-note {{destroyed here}}
- (void)*p; // expected-note {{later used here}}
+ use(*p); // expected-note {{later used here}}
{
MyObj a, b, c, d;
@@ -1081,14 +1083,14 @@ void parentheses(bool cond) {
: (cond ? c // expected-warning {{object whose reference is captured does not live long enough}}.
: d)); // expected-warning {{object whose reference is captured does not live long enough}}.
} // expected-note 4 {{destroyed here}}
- (void)*p; // expected-note 4 {{later used here}}
+ use(*p); // expected-note 4 {{later used here}}
{
MyObj a, b, c, d;
p = ((cond ? (((cond ? &a : &b))) // expected-warning 2 {{object whose reference is captured does not live long enough}}.
: &(((cond ? c : d))))); // expected-warning 2 {{object whose reference is captured does not live long enough}}.
} // expected-note 4 {{destroyed here}}
- (void)*p; // expected-note 4 {{later used here}}
+ use(*p); // expected-note 4 {{later used here}}
}
@@ -1134,7 +1136,7 @@ void foo() {
StatusOr<View> view_or = getViewOr();
view = view_or.value();
}
- (void)view;
+ use(view);
}
void bar() {
@@ -1143,7 +1145,7 @@ void bar() {
StatusOr<MyObj*> pointer_or = getPointerOr();
pointer = pointer_or.value();
}
- (void)*pointer;
+ use(*pointer);
}
void foobar() {
@@ -1153,7 +1155,7 @@ void foobar() {
view = string_or. // expected-warning {{object whose reference is captured does not live long enough}}
value();
} // expected-note {{destroyed here}}
- (void)view; // expected-note {{later used here}}
+ use(view); // expected-note {{later used here}}
}
} // namespace GH162834
@@ -1226,7 +1228,7 @@ void test_user_defined_deref_uaf() {
SmartPtr<MyObj> smart_ptr(&obj);
p = &(*smart_ptr); // expected-warning {{object whose reference is captured does not live long enough}}
} // expected-note {{destroyed here}}
- (void)*p; // expected-note {{later used here}}
+ use(*p); // expected-note {{later used here}}
}
MyObj& test_user_defined_deref_uar() {
@@ -1253,7 +1255,7 @@ void test_user_defined_deref_arrow() {
SmartPtr<MyObj> smart_ptr(&obj);
p = smart_ptr.operator->(); // expected-warning {{object whose reference is captured does not live long enough}}
} // expected-note {{destroyed here}}
- (void)*p; // expected-note {{later used here}}
+ use(*p); // expected-note {{later used here}}
}
void test_user_defined_deref_chained() {
@@ -1263,7 +1265,7 @@ void test_user_defined_deref_chained() {
SmartPtr<SmartPtr<MyObj>> double_ptr;
p = &(**double_ptr); // expected-warning {{object whose reference is captured does not live long enough}}
} // expected-note {{destroyed here}}
- (void)*p; // expected-note {{later used here}}
+ use(*p); // expected-note {{later used here}}
}
} // namespace UserDefinedDereference
@@ -1415,7 +1417,7 @@ void strict_warn_on_move() {
v = a; // expected-warning-re {{object whose reference {{.*}} may have been moved}}
b = std::move(a); // expected-note {{potentially moved here}}
} // expected-note {{destroyed here}}
- (void)v; // expected-note {{later used here}}
+ use(v); // expected-note {{later used here}}
}
void flow_sensitive(bool c) {
@@ -1428,7 +1430,7 @@ void flow_sensitive(bool c) {
}
v = a; // expected-warning {{object whose reference}}
} // expected-note {{destroyed here}}
- (void)v; // expected-note {{later used here}}
+ use(*v); // expected-note {{later used here}}
}
void take(MyObj&&);
@@ -1439,7 +1441,7 @@ void detect_conditional(bool cond) {
v = cond ? a : b; // expected-warning-re 2 {{object whose reference {{.*}} may have been moved}}
take(std::move(cond ? a : b)); // expected-note 2 {{potentially moved here}}
} // expected-note 2 {{destroyed here}}
- (void)v; // expected-note 2 {{later used here}}
+ use(*v); // expected-note 2 {{later used here}}
}
void wrong_use_of_move_is_permissive() {
@@ -1448,13 +1450,13 @@ void wrong_use_of_move_is_permissive() {
MyObj a;
v = std::move(a); // expected-warning {{object whose reference is captured does not live long enough}}
} // expected-note {{destroyed here}}
- (void)v; // expected-note {{later used here}}
+ use(*v); // expected-note {{later used here}}
const int* p;
{
MyObj a;
p = std::move(a).getData(); // expected-warning {{object whose reference is captured does not live long enough}}
} // expected-note {{destroyed here}}
- (void)p; // expected-note {{later used here}}
+ use(*p); // expected-note {{later used here}}
}
void take(int*);
@@ -1466,7 +1468,7 @@ void test_release_no_uaf() {
r = p.get(); // expected-warning-re {{object whose reference {{.*}} may have been moved}}
take(p.release()); // expected-note {{potentially moved here}}
} // expected-note {{destroyed here}}
- (void)*r; // expected-note {{later used here}}
+ use(*r); // expected-note {{later used here}}
}
} // namespace strict_warn_on_move
@@ -1488,7 +1490,7 @@ void bar() {
x = s.x(); // expected-warning {{object whose reference is captured does not live long enough}}
View y = S().x(); // FIXME: Handle temporaries.
} // expected-note {{destroyed here}}
- (void)x; // expected-note {{used here}}
+ use(x); // expected-note {{used here}}
}
}
@@ -1574,10 +1576,10 @@ const S& identity(const S& in [[clang::lifetimebound]]);
void test_temporary() {
const std::string& x = S().x(); // expected-warning {{object whose reference is captured does not live long enough}} expected-note {{destroyed here}}
- (void)x; // expected-note {{later used here}}
+ use(x); // expected-note {{later used here}}
const std::string& y = identity(S().x()); // expected-warning {{object whose reference is captured does not live long enough}} expected-note {{destroyed here}}
- (void)y; // expected-note {{later used here}}
+ use(y); // expected-note {{later used here}}
std::string_view z;
{
@@ -1585,19 +1587,19 @@ void test_temporary() {
const std::string& zz = s.x(); // expected-warning {{object whose reference is captured does not live long enough}}
z = zz;
} // expected-note {{destroyed here}}
- (void)z; // expected-note {{later used here}}
+ use(z); // expected-note {{later used here}}
}
void test_lifetime_extension_ok() {
const S& x = S();
- (void)x;
+ use(x);
const S& y = identity(S()); // expected-warning {{object whose reference is captured does not live long enough}} expected-note {{destroyed here}}
- (void)y; // expected-note {{later used here}}
+ use(y); // expected-note {{later used here}}
}
const std::string& test_return() {
- const std::string& x = S().x(); // expected-warning {{object whose reference is captured does not live long enough}} expected-note {{destroyed here}}
- return x; // expected-note {{later used here}}
+ const std::string& x = S().x(); // expected-warning {{address of stack memory is returned later}}
+ return x; // expected-note {{returned here}}
}
} // namespace reference_type_decl_ref_expr
@@ -1615,7 +1617,7 @@ void uaf() {
S* p = &str; // expected-warning {{object whose reference is captured does not live long enough}}
view = p->s;
} // expected-note {{destroyed here}}
- (void)view; // expected-note {{later used here}}
+ use(view); // expected-note {{later used here}}
}
void not_uaf() {
@@ -1625,7 +1627,7 @@ void not_uaf() {
S* p = &str;
view = p->sv;
}
- (void)view;
+ use(view);
}
union U {
@@ -1641,7 +1643,7 @@ void uaf_union() {
U* up = &u; // expected-warning {{object whose reference is captured does not live long enough}}
view = up->s;
} // expected-note {{destroyed here}}
- (void)view; // expected-note {{later used here}}
+ use(view); // expected-note {{later used here}}
}
struct AnonymousUnion {
@@ -1658,7 +1660,7 @@ void uaf_anonymous_union() {
AnonymousUnion* up = &au; // expected-warning {{object whose reference is captured does not live long enough}}
ip = &up->x;
} // expected-note {{destroyed here}}
- (void)ip; // expected-note {{later used here}}
+ use(ip); // expected-note {{later used here}}
}
struct RefMember {
@@ -1717,9 +1719,9 @@ void test() {
const MyObj* pTMA = mtf.memberA(MyObj()); // expected-warning {{object whose reference is captured does not live long enough}} // expected-note {{destroyed here}}
const MyObj* pTMB = mtf.memberB(MyObj()); // tu-warning {{object whose reference is captured does not live long enough}} // tu-note {{destroyed here}}
const MyObj* pTMC = mtf.memberC(MyObj()); // expected-warning {{object whose reference is captured does not live long enough}} // expected-note {{destroyed here}}
- (void)pTMA; // expected-note {{later used here}}
- (void)pTMB; // tu-note {{later used here}}
- (void)pTMC; // expected-note {{later used here}}
+ use(pTMA); // expected-note {{later used here}}
+ use(pTMB); // tu-note {{later used here}}
+ use(pTMC); // expected-note {{later used here}}
}
} // namespace attr_on_template_params
More information about the llvm-branch-commits
mailing list