// expected-note@-1 {{Potential leak of memory pointed to by 'v'}}
} // namespace refkind_from_unoallocated_to_allocated
+
+// Check that memory leak is reported against a symbol if the last place it's
+// mentioned is a base region of a lazy compound value, as the program cannot
+// possibly free that memory.
+namespace symbol_reaper_lifetime {
+struct Nested {
+ int buf[2];
+};
+struct Wrapping {
+ Nested data;
+};
+
+Nested allocateWrappingAndReturnNested() {
+ // expected-note@+1 {{Memory is allocated}}
+ Wrapping const* p = new Wrapping();
+ // expected-warning@+2 {{Potential leak of memory pointed to by 'p'}}
+ // expected-note@+1 {{Potential leak of memory pointed to by 'p'}}
+ return p->data;
+}
+
+void caller() {
+ // expected-note@+1 {{Calling 'allocateWrappingAndReturnNested'}}
+ Nested n = allocateWrappingAndReturnNested();
+ (void)n;
+} // no-warning: No potential memory leak here, because that's been already reported.
+} // namespace symbol_reaper_lifetime
--- /dev/null
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s
+// expected-no-diagnostics
+
+template <typename... Ts>
+void escape(Ts&...);
+struct Dummy {};
+
+int strange(Dummy param) {
+ Dummy local_pre_lambda;
+ int ref_captured = 0;
+
+ // LambdaExpr is modeled as lazyCompoundVal of tempRegion, that contains
+ // all captures. In this instance, this region contains a pointer/reference
+ // to ref_captured variable.
+ auto fn = [&] {
+ escape(param, local_pre_lambda);
+ return ref_captured; // no-warning: The value is not garbage.
+ };
+
+ int local_defined_after_lambda; // Unused, but necessary! Important that it's before the call.
+
+ // The ref_captured binding should not be pruned at this point, as it is still
+ // accessed via reference captured in operator() of fn.
+ return fn();
+}
+
// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s
template <typename T> void clang_analyzer_dump(T);
+template <typename T> void clang_analyzer_value(T);
void clang_analyzer_warnIfReached();
struct Node { int* ptr; };
(void)(n1->ptr);
(void)(n2->ptr);
}
+
+struct List {
+ List* next;
+ int value;
+ int padding;
+};
+
+void deadCode(List orig) {
+ List c = orig;
+ clang_analyzer_dump(c.value);
+ // expected-warning-re@-1 {{reg_${{[0-9]+}}<int orig.value>}}
+ if (c.value == 42)
+ return;
+ clang_analyzer_value(c.value);
+ // expected-warning@-1 {{32s:{ [-2147483648, 2147483647] }}}
+ // The symbol was garbage collected too early, hence we lose the constraints.
+ if (c.value != 42)
+ return;
+
+ // Dead code should be unreachable
+ clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
+}