diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/RegionStore.cpp | 10 | ||||
-rw-r--r-- | clang/test/Analysis/array-struct-region.cpp | 23 |
2 files changed, 32 insertions, 1 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index 2a3319bc042..8bc16bd4191 100644 --- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -1832,10 +1832,18 @@ NonLoc RegionStoreManager::createLazyBinding(RegionBindingsConstRef B, return svalBuilder.makeLazyCompoundVal(StoreRef(B.asStore(), *this), R); } +static bool isRecordEmpty(const RecordDecl *RD) { + if (!RD->field_empty()) + return false; + if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) + return CRD->getNumBases() == 0; + return true; +} + SVal RegionStoreManager::getBindingForStruct(RegionBindingsConstRef B, const TypedValueRegion *R) { const RecordDecl *RD = R->getValueType()->castAs<RecordType>()->getDecl(); - if (RD->field_empty()) + if (isRecordEmpty(RD)) return UnknownVal(); return createLazyBinding(B, R); diff --git a/clang/test/Analysis/array-struct-region.cpp b/clang/test/Analysis/array-struct-region.cpp index 12ae5d3eba6..a776d7da50b 100644 --- a/clang/test/Analysis/array-struct-region.cpp +++ b/clang/test/Analysis/array-struct-region.cpp @@ -173,4 +173,27 @@ void testImmediateUseOp() { clang_analyzer_eval(getConstrainedFieldRefOp(getS()) == 42); // expected-warning{{TRUE}} } +namespace EmptyClass { + struct Base { + int& x; + + Base(int& x) : x(x) {} + }; + + struct Derived : public Base { + Derived(int& x) : Base(x) {} + + void operator=(int a) { x = a; } + }; + + Derived ref(int& a) { return Derived(a); } + + // There used to be a warning here, because analyzer treated Derived as empty. + int test() { + int a; + ref(a) = 42; + return a; // no warning + } +} + #endif |