[cfe-commits] r161710 - in /cfe/trunk: lib/StaticAnalyzer/Core/CallEvent.cpp test/Analysis/inline.cpp
Jordan Rose
jordan_rose at apple.com
Fri Aug 10 15:26:46 PDT 2012
Author: jrose
Date: Fri Aug 10 17:26:46 2012
New Revision: 161710
URL: http://llvm.org/viewvc/llvm-project?rev=161710&view=rev
Log:
[analyzer] Strip CXXBaseObjectRegions when devirtualizing method calls.
This was causing a crash when we tried to re-apply a base object region to
itself. It probably also caused incorrect offset calculations in RegionStore.
PR13569 / <rdar://problem/12076683>
Modified:
cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp
cfe/trunk/test/Analysis/inline.cpp
Modified: cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp?rev=161710&r1=161709&r2=161710&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp Fri Aug 10 17:26:46 2012
@@ -15,6 +15,7 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/Analysis/ProgramPoint.h"
+#include "clang/AST/CXXInheritance.h"
#include "clang/AST/ParentMap.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringExtras.h"
@@ -408,11 +409,34 @@
BindingsTy &Bindings) const {
AnyFunctionCall::getInitialStackFrameContents(CalleeCtx, Bindings);
+ // Handle the binding of 'this' in the new stack frame.
+ // We need to make sure we have the proper layering of CXXBaseObjectRegions.
SVal ThisVal = getCXXThisVal();
if (!ThisVal.isUnknown()) {
- SValBuilder &SVB = getState()->getStateManager().getSValBuilder();
+ ProgramStateManager &StateMgr = getState()->getStateManager();
+ SValBuilder &SVB = StateMgr.getSValBuilder();
+
const CXXMethodDecl *MD = cast<CXXMethodDecl>(CalleeCtx->getDecl());
Loc ThisLoc = SVB.getCXXThis(MD, CalleeCtx);
+
+ if (const MemRegion *ThisReg = ThisVal.getAsRegion()) {
+ const CXXRecordDecl *Class = MD->getParent();
+
+ // We may be downcasting to call a devirtualized virtual method.
+ // Search through the base casts we already have to see if we can just
+ // strip them off.
+ const CXXBaseObjectRegion *BaseReg;
+ while ((BaseReg = dyn_cast<CXXBaseObjectRegion>(ThisReg))) {
+ if (BaseReg->getDecl() == Class)
+ break;
+ ThisReg = BaseReg->getSuperRegion();
+ }
+
+ // Either we found the right base class, or we stripped all the casts to
+ // the most derived type. Either one is good.
+ ThisVal = loc::MemRegionVal(ThisReg);
+ }
+
Bindings.push_back(std::make_pair(ThisLoc, ThisVal));
}
}
Modified: cfe/trunk/test/Analysis/inline.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/inline.cpp?rev=161710&r1=161709&r2=161710&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/inline.cpp (original)
+++ cfe/trunk/test/Analysis/inline.cpp Fri Aug 10 17:26:46 2012
@@ -71,3 +71,41 @@
}
+namespace PR13569 {
+ class Parent {
+ protected:
+ int m_parent;
+ virtual int impl() const = 0;
+
+ Parent() : m_parent(0) {}
+
+ public:
+ int interface() const {
+ clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
+ return impl();
+ }
+ };
+
+ class Child : public Parent {
+ protected:
+ virtual int impl() const {
+ clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
+ return m_parent + m_child;
+ }
+
+ public:
+ Child() : m_child(0) {}
+
+ int m_child;
+ };
+
+ void testVirtual() {
+ Child x;
+ x.m_child = 42;
+
+ // Don't crash when inlining and devirtualizing.
+ x.interface();
+ }
+}
+
+
More information about the cfe-commits
mailing list