================
@@ -0,0 +1,131 @@
+// RUN: %clang_analyze_cc1 
-analyzer-checker=alpha.cplusplus.LifetimeAnnotations \
+// RUN:   -verify %s
+// RUN: %clang_analyze_cc1 
-analyzer-checker=alpha.cplusplus.LifetimeAnnotations \
+// RUN:   -analyzer-config c++-container-inlining=false -verify %s
+
+struct A {};
+
+void clang_analyzer_lifetime_bound(int*);
+void clang_analyzer_lifetime_bound(int&);
+void clang_analyzer_lifetime_bound(A*);
+void clang_analyzer_lifetime_bound(A&);
+
+// These are the cases when the result of function calls are MemRegions.
+
+// Ref type parameter annotated case
+struct X {
+  int& choose(int& a [[clang::lifetimebound]]) { return a; }
+};
+
+void caller() {
+  int v = 0;
+  X obj;
+  int& r = obj.choose(v);
+  clang_analyzer_lifetime_bound(r); // expected-warning {{bound to v}}
+}
+
+// Obj ref type function return annotated case
+struct Y {
+  A a;
+  A& getA() [[clang::lifetimebound]] { return a; }
+};
+
+void caller_two() {
+  // Return statement is annotated case.
+  Y y;
+  A& f = y.getA();
+  clang_analyzer_lifetime_bound(f); // expected-warning {{bound to y}}
+}
+
+// Obj ptr type function return annotated case
+struct Z {
+  A a;
+  A* getA() [[clang::lifetimebound]] { return &a; }
+};
+
+void caller_three() {
+  Z z;
+  A* func = z.getA();
+  clang_analyzer_lifetime_bound(func); // expected-warning {{bound to z}}
+}
+
+// Free function with annotated param and ref return
+int& foo(int& num [[clang::lifetimebound]]) { return num; }
+
+void caller_four() {
+  int num = 5;
+  int& s = foo(num);
+  clang_analyzer_lifetime_bound(s); // expected-warning {{bound to num}}
+}
+
+// Free function with annotated param and ptr return
+int* boo(int* num [[clang::lifetimebound]]) { return num; }
+
+void caller_five() {
+  int n = 55;
+  int* n_ptr = &n;
+  int* s = boo(n_ptr);
+
+  clang_analyzer_lifetime_bound(s); // expected-warning {{bound to n}}
+}
+
+// Free function with both annotated and non-annotated parameters.
+int& fn(int& f, int& s [[clang::lifetimebound]]) { return s; }
+
+void caller_six() {
+  int even = 50;
+  int odd = 55;
+  int& s = fn(even, odd);
+
+  clang_analyzer_lifetime_bound(s); // expected-warning {{bound to odd}}
+}
+
+
+
+// These are the cases when the result of function calls are SymbolRefs.
+
+// Function returns ptr and has an annotated parameter
+int* foo(int* n [[clang::lifetimebound]]);
+
+void caller_seven() {
+  int y = 15;
+  int* y_ptr = &y;
+  auto* bind = foo(y_ptr);
+
+  clang_analyzer_lifetime_bound(bind); // expected-warning {{bound to y}}
+                                       // expected-warning@-1 {{contains loan 
y}}
+// FIXME: The full warning does look like this:
+// Origin SymRegion{conj_$5{int *, LC1, S847, #1}} bound to n
+// Origin conj_$5{int *, LC1, S847, #1} contains loan n
+// Since the conj sym number and the ID can change across runs I have decided 
to just include
+// string parts of the error message since that is the only consistent part of 
the emitted report.
+// This does not apply to the test cases above this test case.
+}
----------------
benedekaibas wrote:

Currently in cases when both `RetValSym` and `RetValRegion` are non-null I 
write into both maps which leads to two dumps. As @isuckatcs pointed out here: 
https://github.com/llvm/llvm-project/pull/200145#discussion_r3370443681. I will 
fix this since we do not need to insert into both maps.

> Also the test contains y and y_ptr, and your comment refers to bound to n and 
> contains loan n - so what is n here?

I have run each test in a standalone file to see the actual emitted warning and 
copy-pasted the warning from there. After rewriting `n` to `y` and `y_ptr` for 
more clarity I did not update the comment, I will do that.

https://github.com/llvm/llvm-project/pull/200145
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to