r187196 - [analyzer] Fix FP warnings when binding a temporary to a local static variable

Pavel Labath labath at google.com
Fri Jul 26 04:50:42 PDT 2013


Author: labath
Date: Fri Jul 26 06:50:42 2013
New Revision: 187196

URL: http://llvm.org/viewvc/llvm-project?rev=187196&view=rev
Log:
[analyzer] Fix FP warnings when binding a temporary to a local static variable

Summary:
When binding a temporary object to a static local variable, the analyzer would
complain about a dangling reference even though the temporary's lifetime should
be extended past the end of the function. This commit tries to detect these
cases and construct them in a global memory region instead of a local one.

Reviewers: jordan_rose

CC: cfe-commits

Differential Revision: http://llvm-reviews.chandlerc.com/D1133

Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp
    cfe/trunk/test/Analysis/stack-addr-ps.cpp
    cfe/trunk/test/Analysis/temporaries.cpp

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h?rev=187196&r1=187195&r2=187196&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h Fri Jul 26 06:50:42 2013
@@ -1272,6 +1272,11 @@ public:
   const BlockDataRegion *getBlockDataRegion(const BlockTextRegion *bc,
                                             const LocationContext *lc = NULL);
 
+  /// Create a CXXTempObjectRegion for temporaries which are lifetime-extended
+  /// by static references. This differs from getCXXTempObjectRegion in the
+  /// super-region used.
+  const CXXTempObjectRegion *getCXXStaticTempObjectRegion(const Expr *Ex);
+
 private:
   template <typename RegionTy, typename A1>
   RegionTy* getRegion(const A1 a1);

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=187196&r1=187195&r2=187196&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Fri Jul 26 06:50:42 2013
@@ -209,7 +209,18 @@ ExprEngine::createTemporaryRegionIfNeede
 
   // Create a temporary object region for the inner expression (which may have
   // a more derived type) and bind the value into it.
-  const TypedValueRegion *TR = MRMgr.getCXXTempObjectRegion(Inner, LC);
+  const TypedValueRegion *TR = NULL;
+  if (const MaterializeTemporaryExpr *MT =
+          dyn_cast<MaterializeTemporaryExpr>(Result)) {
+    StorageDuration SD = MT->getStorageDuration();
+    // If this object is bound to a reference with static storage duration, we
+    // put it in a different region to prevent "address leakage" warnings.
+    if (SD == SD_Static || SD == SD_Thread)
+        TR = MRMgr.getCXXStaticTempObjectRegion(Inner);
+  }
+  if (!TR)
+    TR = MRMgr.getCXXTempObjectRegion(Inner, LC);
+
   SVal Reg = loc::MemRegionVal(TR);
 
   if (V.isUnknown())

Modified: cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp?rev=187196&r1=187195&r2=187196&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp Fri Jul 26 06:50:42 2013
@@ -864,6 +864,12 @@ MemRegionManager::getBlockDataRegion(con
   return getSubRegion<BlockDataRegion>(BC, LC, sReg);
 }
 
+const CXXTempObjectRegion *
+MemRegionManager::getCXXStaticTempObjectRegion(const Expr *Ex) {
+  return getSubRegion<CXXTempObjectRegion>(
+      Ex, getGlobalsRegion(MemRegion::GlobalInternalSpaceRegionKind, NULL));
+}
+
 const CompoundLiteralRegion*
 MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr *CL,
                                            const LocationContext *LC) {

Modified: cfe/trunk/test/Analysis/stack-addr-ps.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/stack-addr-ps.cpp?rev=187196&r1=187195&r2=187196&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/stack-addr-ps.cpp (original)
+++ cfe/trunk/test/Analysis/stack-addr-ps.cpp Fri Jul 26 06:50:42 2013
@@ -20,6 +20,10 @@ const int& g3() {
   return s3; // expected-warning{{Address of stack memory associated with local variable 's1' returned}} expected-warning {{reference to stack memory associated with local variable 's1' returned}}
 }
 
+void g4() {
+  static const int &x = 3; // no warning
+}
+
 int get_value();
 
 const int &get_reference1() { return get_value(); } // expected-warning{{Address of stack memory associated with temporary object of type 'int' returned}} expected-warning {{returning reference to local temporary}}

Modified: cfe/trunk/test/Analysis/temporaries.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/temporaries.cpp?rev=187196&r1=187195&r2=187196&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/temporaries.cpp (original)
+++ cfe/trunk/test/Analysis/temporaries.cpp Fri Jul 26 06:50:42 2013
@@ -141,3 +141,19 @@ namespace destructors {
     }
   }
 }
+
+void testStaticMaterializeTemporaryExpr() {
+  static const Trivial &ref = getTrivial();
+  clang_analyzer_eval(ref.value == 42); // expected-warning{{TRUE}}
+
+  static const Trivial &directRef = Trivial(42);
+  clang_analyzer_eval(directRef.value == 42); // expected-warning{{TRUE}}
+
+#if __cplusplus >= 201103L
+  thread_local static const Trivial &threadRef = getTrivial();
+  clang_analyzer_eval(threadRef.value == 42); // expected-warning{{TRUE}}
+
+  thread_local static const Trivial &threadDirectRef = Trivial(42);
+  clang_analyzer_eval(threadDirectRef.value == 42); // expected-warning{{TRUE}}
+#endif
+}





More information about the cfe-commits mailing list