r364870 - [analyzer] Fix invalidation when returning into a ctor initializer.

Artem Dergachev via cfe-commits cfe-commits at lists.llvm.org
Mon Jul 1 16:02:18 PDT 2019


Author: dergachev
Date: Mon Jul  1 16:02:18 2019
New Revision: 364870

URL: http://llvm.org/viewvc/llvm-project?rev=364870&view=rev
Log:
[analyzer] Fix invalidation when returning into a ctor initializer.

Due to RVO the target region of a function that returns an object by
value isn't necessarily a temporary object region; it may be an
arbitrary memory region. In particular, it may be a field of a bigger
object.

Make sure we don't invalidate the bigger object when said function is
evaluated conservatively.

Differential Revision: https://reviews.llvm.org/D63968

Added:
    cfe/trunk/test/Analysis/rvo.cpp
Modified:
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp?rev=364870&r1=364869&r2=364870&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp Mon Jul  1 16:02:18 2019
@@ -634,12 +634,19 @@ ProgramStateRef ExprEngine::bindReturnVa
     std::tie(State, Target) =
         prepareForObjectConstruction(Call.getOriginExpr(), State, LCtx,
                                      RTC->getConstructionContext(), CallOpts);
-    assert(Target.getAsRegion());
-    // Invalidate the region so that it didn't look uninitialized. Don't notify
-    // the checkers.
-    State = State->invalidateRegions(Target.getAsRegion(), E, Count, LCtx,
+    const MemRegion *TargetR = Target.getAsRegion();
+    assert(TargetR);
+    // Invalidate the region so that it didn't look uninitialized. If this is
+    // a field or element constructor, we do not want to invalidate
+    // the whole structure. Pointer escape is meaningless because
+    // the structure is a product of conservative evaluation
+    // and therefore contains nothing interesting at this point.
+    RegionAndSymbolInvalidationTraits ITraits;
+    ITraits.setTrait(TargetR,
+        RegionAndSymbolInvalidationTraits::TK_DoNotInvalidateSuperRegion);
+    State = State->invalidateRegions(TargetR, E, Count, LCtx,
                                      /* CausedByPointerEscape=*/false, nullptr,
-                                     &Call, nullptr);
+                                     &Call, &ITraits);
 
     R = State->getSVal(Target.castAs<Loc>(), E->getType());
   } else {

Added: cfe/trunk/test/Analysis/rvo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/rvo.cpp?rev=364870&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/rvo.cpp (added)
+++ cfe/trunk/test/Analysis/rvo.cpp Mon Jul  1 16:02:18 2019
@@ -0,0 +1,25 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker core,cplusplus \
+// RUN:                    -analyzer-checker debug.ExprInspection -verify %s
+
+void clang_analyzer_eval(bool);
+
+struct A {
+  int x;
+};
+
+A getA();
+
+struct B {
+  int *p;
+  A a;
+
+  B(int *p) : p(p), a(getA()) {}
+};
+
+void foo() {
+  B b1(nullptr);
+  clang_analyzer_eval(b1.p == nullptr); // expected-warning{{TRUE}}
+  B b2(new int); // No leak yet!
+  clang_analyzer_eval(b2.p == nullptr); // expected-warning{{FALSE}}
+  // expected-warning at -1{{Potential leak of memory pointed to by 'b2.p'}}
+}




More information about the cfe-commits mailing list