]> granicus.if.org Git - clang/commitdiff
[analyzer] Track null and undef values through expressions with cleanups.
authorArtem Dergachev <artem.dergachev@gmail.com>
Mon, 25 Jun 2018 23:55:07 +0000 (23:55 +0000)
committerArtem Dergachev <artem.dergachev@gmail.com>
Mon, 25 Jun 2018 23:55:07 +0000 (23:55 +0000)
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
test/Analysis/inlining/inline-defensive-checks.cpp

index 4765db07411549bc05ccfbe095e2fd5bb5a58420..fc31d3c1fb57847d8785821b081d1a148b8dfa64 100644 (file)
@@ -141,6 +141,8 @@ const Expr *bugreporter::getDerefExpr(const Stmt *S) {
       E = AE->getBase();
     } else if (const auto *PE = dyn_cast<ParenExpr>(E)) {
       E = PE->getSubExpr();
+    } else if (const auto *EWC = dyn_cast<ExprWithCleanups>(E)) {
+      E = EWC->getSubExpr();
     } else {
       // Other arbitrary stuff.
       break;
index eaae8d2ae28f2a2ab5ab4c4c897aaae8946fd50b..6fb0e1cd70b053425fcb3089617ce206f58fb11b 100644 (file)
@@ -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