summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Labath <labath@google.com>2013-07-26 11:50:42 +0000
committerPavel Labath <labath@google.com>2013-07-26 11:50:42 +0000
commitcf878bbe65b9f4b4b5ca96f5f6f33f8ff31349d6 (patch)
treef00c5294fa6452b542d3d8caf1f33ade145f5183
parent240d480c5f6ae6cbfe40bfb40d83164008a99b09 (diff)
downloadbcm5719-llvm-cf878bbe65b9f4b4b5ca96f5f6f33f8ff31349d6.tar.gz
bcm5719-llvm-cf878bbe65b9f4b4b5ca96f5f6f33f8ff31349d6.zip
[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 llvm-svn: 187196
-rw-r--r--clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h5
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngine.cpp13
-rw-r--r--clang/lib/StaticAnalyzer/Core/MemRegion.cpp6
-rw-r--r--clang/test/Analysis/stack-addr-ps.cpp4
-rw-r--r--clang/test/Analysis/temporaries.cpp16
5 files changed, 43 insertions, 1 deletions
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
index 9b4f77dd679..a8946b817e0 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -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);
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 04629dc0170..552b2eca26e 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -209,7 +209,18 @@ ExprEngine::createTemporaryRegionIfNeeded(ProgramStateRef State,
// 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())
diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
index 0102f9237c2..3c9e9e45645 100644
--- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -864,6 +864,12 @@ MemRegionManager::getBlockDataRegion(const BlockTextRegion *BC,
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) {
diff --git a/clang/test/Analysis/stack-addr-ps.cpp b/clang/test/Analysis/stack-addr-ps.cpp
index 65d757154c8..a39f9c7dc72 100644
--- a/clang/test/Analysis/stack-addr-ps.cpp
+++ b/clang/test/Analysis/stack-addr-ps.cpp
@@ -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}}
diff --git a/clang/test/Analysis/temporaries.cpp b/clang/test/Analysis/temporaries.cpp
index ebfbfe9bee3..ddad855d338 100644
--- a/clang/test/Analysis/temporaries.cpp
+++ b/clang/test/Analysis/temporaries.cpp
@@ -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
+}
OpenPOWER on IntegriCloud