From 3f4fad92fee80ad64f306ca5cd7f1e875c940d08 Mon Sep 17 00:00:00 2001 From: Anna Zaks Date: Tue, 19 Mar 2013 22:38:09 +0000 Subject: [PATCH] [analyzer] Do not believe lazy binding when symbolic region types do not match MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This fixes a crash when analyzing LLVM that was exposed by r177220 (modeling of trivial copy/move assignment operators). When we look up a lazy binding for “Builder”, we see the direct binding of Loc at offset 0. Previously, we believed the binding, which led to a crash. Now, we do not believe it as the types do not match. llvm-svn: 177453 --- clang/lib/StaticAnalyzer/Core/RegionStore.cpp | 21 +++++++++++++++----- clang/test/Analysis/region-store.cpp | 28 +++++++++++++++++++++++++++ clang/test/Analysis/uninit-vals.m | 8 ++------ 3 files changed, 46 insertions(+), 11 deletions(-) create mode 100644 clang/test/Analysis/region-store.cpp diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index 82db23d..731c3ed 100644 --- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -1265,6 +1265,17 @@ SVal RegionStoreManager::getBinding(RegionBindingsConstRef B, Loc L, QualType T) return svalBuilder.getRegionValueSymbolVal(R); } +static QualType getUnderlyingType(const SubRegion *R) { + QualType RegionTy; + if (const TypedValueRegion *TVR = dyn_cast(R)) + RegionTy = TVR->getValueType(); + + if (const SymbolicRegion *SR = dyn_cast(R)) + RegionTy = SR->getSymbol()->getType(); + + return RegionTy; +} + /// Checks to see if store \p B has a lazy binding for region \p R. /// /// If \p AllowSubregionBindings is \c false, a lazy binding will be rejected @@ -1283,11 +1294,11 @@ getExistingLazyBinding(SValBuilder &SVB, RegionBindingsConstRef B, if (!LCV) return None; - // If the LCV is for a subregion, the types won't match, and we shouldn't - // reuse the binding. Unfortuately we can only check this if the destination - // region is a TypedValueRegion. - if (const TypedValueRegion *TVR = dyn_cast(R)) { - QualType RegionTy = TVR->getValueType(); + // If the LCV is for a subregion, the types might not match, and we shouldn't + // reuse the binding. + QualType RegionTy = getUnderlyingType(R); + if (!RegionTy.isNull() && + !RegionTy->isVoidPointerType()) { QualType SourceRegionTy = LCV->getRegion()->getValueType(); if (!SVB.getContext().hasSameUnqualifiedType(RegionTy, SourceRegionTy)) return None; diff --git a/clang/test/Analysis/region-store.cpp b/clang/test/Analysis/region-store.cpp new file mode 100644 index 0000000..5ea5c3f --- /dev/null +++ b/clang/test/Analysis/region-store.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix -verify %s +// expected-no-diagnostics + +class Loc { + int x; +}; +class P1 { +public: + Loc l; + void setLoc(Loc L) { + l = L; + } + +}; +class P2 { +public: + int m; + int accessBase() { + return m; + } +}; +class Derived: public P1, public P2 { +}; +int radar13445834(Derived *Builder, Loc l) { + Builder->setLoc(l); + return Builder->accessBase(); + +} \ No newline at end of file diff --git a/clang/test/Analysis/uninit-vals.m b/clang/test/Analysis/uninit-vals.m index 6813b8e..9f611ad 100644 --- a/clang/test/Analysis/uninit-vals.m +++ b/clang/test/Analysis/uninit-vals.m @@ -80,12 +80,8 @@ void PR14765_incorrectBehavior(Circle *testObj) { testObj->origin = makePoint(0.0, 0.0); - // FIXME: Assigning to 'testObj->origin' kills the default binding for the - // whole region, meaning that we've forgotten that testObj->size should also - // default to 0. Tracked by . - // This should be TRUE. - clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{UNKNOWN}} - + clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}} + free(testObj); } -- 2.7.4