From 707983ea1f326ae9c8499ca585785c7679e3f7e1 Mon Sep 17 00:00:00 2001 From: Artem Dergachev Date: Mon, 25 Jun 2018 23:55:07 +0000 Subject: [PATCH] [analyzer] Track null and undef values through expressions with cleanups. ExprWithCleanups wraps full-expressions that require temporary destructors and highlights the moment of time in which these destructors need to be called (i.e., "at the end of the full-expression..."). Such expressions don't necessarily return an object; they may return anything, including a null or undefined value. When the analyzer tries to understand where the null or undefined value came from in order to present better diagnostics to the user, it will now skip any ExprWithCleanups it encounters and look into the expression itself. Differential Revision: https://reviews.llvm.org/D48204 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335559 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | 2 ++ .../inlining/inline-defensive-checks.cpp | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index 4765db0741..fc31d3c1fb 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -141,6 +141,8 @@ const Expr *bugreporter::getDerefExpr(const Stmt *S) { E = AE->getBase(); } else if (const auto *PE = dyn_cast(E)) { E = PE->getSubExpr(); + } else if (const auto *EWC = dyn_cast(E)) { + E = EWC->getSubExpr(); } else { // Other arbitrary stuff. break; diff --git a/test/Analysis/inlining/inline-defensive-checks.cpp b/test/Analysis/inlining/inline-defensive-checks.cpp index eaae8d2ae2..6fb0e1cd70 100644 --- a/test/Analysis/inlining/inline-defensive-checks.cpp +++ b/test/Analysis/inlining/inline-defensive-checks.cpp @@ -84,3 +84,20 @@ void testRefToField(Bar *b) { int &x = b->x; // no-warning x = 5; } + +namespace get_deref_expr_with_cleanups { +struct S { +~S(); +}; +S *conjure(); +// The argument won't be used, but it'll cause cleanups +// to appear around the call site. +S *get_conjured(S _) { + S *s = conjure(); + if (s) {} + return s; +} +void test_conjured() { + S &s = *get_conjured(S()); // no-warning +} +} // namespace get_deref_expr_with_cleanups -- 2.40.0