llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
@llvm/pr-subscribers-clang-temporal-safety
Author: Kashika Akhouri (kashika0112)
<details>
<summary>Changes</summary>
Adding Annotation Inference in Lifetime Analysis.
This PR implicitly adds lifetime bound annotations to the AST which is then
used by functions which are parsed later to detect UARs etc. Example:
```
std::string_view f1(std::string_view a) {
return a;
}
std::string_view f2(std::string_view a) {
return f1(a);
}
std::string_view ff(std::string_view a) {
std::string stack = "something on stack";
return f2(stack); // warning: return-stack-addr
}
```
Note:
1. We only add lifetime bound annotations to the functions being analyzed
currently.
2. Currently, both annotation suggestion and inference work simultaneously.
This can be modified based on requirements.
3. The current approach works given that functions are already present in the
correct order (callee-before-caller). For not so ideal cases, we can create a
CallGraph prior to calling the analysis. This can be done in the next PR.
---
Full diff: https://github.com/llvm/llvm-project/pull/171081.diff
3 Files Affected:
- (modified) clang/lib/Analysis/LifetimeSafety/Checker.cpp (+16-1)
- (modified) clang/test/Sema/warn-lifetime-safety-suggestions.cpp (+12)
- (modified) clang/test/Sema/warn-lifetime-safety.cpp (+15-1)
``````````diff
diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp
b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
index 74792768e2c57..f5236f63da34a 100644
--- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
@@ -55,13 +55,14 @@ class LifetimeChecker {
const LiveOriginsAnalysis &LiveOrigins;
const FactManager &FactMgr;
LifetimeSafetyReporter *Reporter;
+ AnalysisDeclContext &AC;
public:
LifetimeChecker(const LoanPropagationAnalysis &LoanPropagation,
const LiveOriginsAnalysis &LiveOrigins, const FactManager
&FM,
AnalysisDeclContext &ADC, LifetimeSafetyReporter *Reporter)
: LoanPropagation(LoanPropagation), LiveOrigins(LiveOrigins),
FactMgr(FM),
- Reporter(Reporter) {
+ Reporter(Reporter), AC(ADC) {
for (const CFGBlock *B : *ADC.getAnalysis<PostOrderCFGView>())
for (const Fact *F : FactMgr.getFacts(B))
if (const auto *EF = F->getAs<ExpireFact>())
@@ -70,6 +71,7 @@ class LifetimeChecker {
checkAnnotations(OEF);
issuePendingWarnings();
suggestAnnotations();
+ inferAnnotations();
}
/// Checks if an escaping origin holds a placeholder loan, indicating a
@@ -160,6 +162,19 @@ class LifetimeChecker {
for (const auto &[PVD, EscapeExpr] : AnnotationWarningsMap)
Reporter->suggestAnnotation(PVD, EscapeExpr);
}
+
+ void inferAnnotations() {
+ /// NOTE: This currently only adds the attribute to the function definition
+ /// being analyzed. For full inter-procedural inference to work reliably
+ /// (e.g., with out-of-order definitions), this attribute would also need
to
+ /// be added to all other redeclarations of the function.
+ for (const auto &[ConstPVD, EscapeExpr] : AnnotationWarningsMap) {
+ ParmVarDecl *PVD = const_cast<ParmVarDecl *>(ConstPVD);
+ ASTContext &Ctx = AC.getASTContext();
+ auto *Attr = LifetimeBoundAttr::CreateImplicit(Ctx, SourceLocation());
+ PVD->addAttr(Attr);
+ }
+ }
};
} // namespace
diff --git a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
index c0f675a301d14..087899b9f5d3f 100644
--- a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
+++ b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
@@ -89,6 +89,18 @@ void test_getView_on_temporary() {
(void)sv;
}
+//===----------------------------------------------------------------------===//
+// Annotation Inference Test Cases
+//===----------------------------------------------------------------------===//
+
+View return_view_by_func (View a) { // expected-warning {{param should be
marked [[clang::lifetimebound]]}}.
+ return return_view_directly(a); // expected-note {{param returned here}}
+}
+
+MyObj* return_pointer_by_func (MyObj* a) { // expected-warning {{param
should be marked [[clang::lifetimebound]]}}.
+ return return_pointer_object(a); // expected-note {{param
returned here}}
+}
+
//===----------------------------------------------------------------------===//
// Negative Test Cases
//===----------------------------------------------------------------------===//
diff --git a/clang/test/Sema/warn-lifetime-safety.cpp
b/clang/test/Sema/warn-lifetime-safety.cpp
index 1191469e23df1..251324f968acd 100644
--- a/clang/test/Sema/warn-lifetime-safety.cpp
+++ b/clang/test/Sema/warn-lifetime-safety.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -fexperimental-lifetime-safety
-Wexperimental-lifetime-safety -Wno-dangling -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fexperimental-lifetime-safety
-Wexperimental-lifetime-safety -Wno-dangling
-Wno-experimental-lifetime-safety-suggestions -verify %s
struct MyObj {
int id;
@@ -552,6 +552,20 @@ const int& get_ref_to_local() {
// expected-note@-1 {{returned here}}
}
+View inference_callee_return_identity(View a) {
+ return a;
+}
+
+View inference_caller_forwards_callee(View a) {
+ return inference_callee_return_identity(a);
+}
+
+View inference_top_level_return_stack_view() {
+ MyObj local_stack;
+ return inference_caller_forwards_callee(local_stack); //
expected-warning {{address of stack memory is returned later}}
+ //
expected-note@-1 {{returned here}}
+}
+
//===----------------------------------------------------------------------===//
// Use-After-Scope & Use-After-Return (Return-Stack-Address) Combined
// These are cases where the diagnostic kind is determined by location
``````````
</details>
https://github.com/llvm/llvm-project/pull/171081
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits