diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/lib/StaticAnalyzer/Core/CallEvent.cpp | 10 | ||||
| -rw-r--r-- | clang/test/Analysis/inline.cpp | 32 |
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}} + } +} |

