summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2012-09-07 01:19:42 +0000
committerJordan Rose <jordan_rose@apple.com>2012-09-07 01:19:42 +0000
commit81456d9f6ded304518a5ef0c28bd5f8865dc6852 (patch)
tree58aed3effecd9f2a4129bbe0ee33828bc3477e69
parentf02a2e96b89600d227d2b9abca5bbdfee22c74c1 (diff)
downloadbcm5719-llvm-81456d9f6ded304518a5ef0c28bd5f8865dc6852.tar.gz
bcm5719-llvm-81456d9f6ded304518a5ef0c28bd5f8865dc6852.zip
[analyzer] Fail gracefully when the dynamic type is outside the hierarchy.
With some particularly evil casts, we can get an object whose dynamic type is not actually a subclass of its static type. In this case, we won't even find the statically-resolved method as a devirtualization candidate. Rather than assert that this situation cannot occur, we now simply check that the dynamic type is not an ancestor or descendent of the static type, and leave it at that. This error actually occurred analyzing LLVM: CallEventManager uses a BumpPtrAllocator to allocate a concrete subclass of CallEvent (FunctionCall), but then casts it to the actual subclass requested (such as ObjCMethodCall) to perform the constructor. Yet another crash in PR13763. llvm-svn: 163367
-rw-r--r--clang/lib/StaticAnalyzer/Core/CallEvent.cpp10
-rw-r--r--clang/test/Analysis/inline.cpp32
2 files changed, 41 insertions, 1 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index 7d58e806a73..50d16f97283 100644
--- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -435,7 +435,15 @@ RuntimeDefinition CXXInstanceCall::getRuntimeDefinition() const {
// Find the decl for this method in that class.
const CXXMethodDecl *Result = MD->getCorrespondingMethodInClass(RD, true);
- assert(Result && "At the very least the static decl should show up.");
+ if (!Result) {
+ // We might not even get the original statically-resolved method due to
+ // some particularly nasty casting (e.g. casts to sister classes).
+ // However, we should at least be able to search up and down our own class
+ // hierarchy, and some real bugs have been caught by checking this.
+ assert(!MD->getParent()->isDerivedFrom(RD) && "Bad DynamicTypeInfo");
+ assert(!RD->isDerivedFrom(MD->getParent()) && "Couldn't find known method");
+ return RuntimeDefinition();
+ }
// Does the decl that we found have an implementation?
const FunctionDecl *Definition;
diff --git a/clang/test/Analysis/inline.cpp b/clang/test/Analysis/inline.cpp
index 573b1647a33..6491b12c585 100644
--- a/clang/test/Analysis/inline.cpp
+++ b/clang/test/Analysis/inline.cpp
@@ -267,3 +267,35 @@ namespace OperatorNew {
clang_analyzer_eval(obj->value == 42); // expected-warning{{UNKNOWN}}
}
}
+
+
+namespace VirtualWithSisterCasts {
+ struct Parent {
+ virtual int foo();
+ };
+
+ struct A : Parent {
+ virtual int foo() { return 42; }
+ };
+
+ struct B : Parent {
+ virtual int foo();
+ };
+
+ struct Unrelated {};
+
+ void testDowncast(Parent *b) {
+ A *a = (A *)(void *)b;
+ clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}}
+ }
+
+ void testRelated(B *b) {
+ A *a = (A *)(void *)b;
+ clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}}
+ }
+
+ void testUnrelated(Unrelated *b) {
+ A *a = (A *)(void *)b;
+ clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}}
+ }
+}
OpenPOWER on IntegriCloud