summaryrefslogtreecommitdiffstats
path: root/clang/test/Analysis/inline.cpp
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2012-10-03 01:08:35 +0000
committerJordan Rose <jordan_rose@apple.com>2012-10-03 01:08:35 +0000
commit1dd2afd8762cdfc2da9e0c1d4dd5ee9b580c5634 (patch)
tree731cd788ed63d4322f43f56465604233c8a43ba1 /clang/test/Analysis/inline.cpp
parent9aa99802172234d1f21d7c30c59d96cbaf6d3cfa (diff)
downloadbcm5719-llvm-1dd2afd8762cdfc2da9e0c1d4dd5ee9b580c5634.tar.gz
bcm5719-llvm-1dd2afd8762cdfc2da9e0c1d4dd5ee9b580c5634.zip
[analyzer] Adjust the return type of an inlined devirtualized method call.
In C++, overriding virtual methods are allowed to specify a covariant return type -- that is, if the return type of the base method is an object pointer type (or reference type), the overriding method's return type can be a pointer to a subclass of the original type. The analyzer was failing to take this into account when devirtualizing a method call, and anything that relied on the return value having the proper type later would crash. In Objective-C, overriding methods are allowed to specify ANY return type, meaning we can NEVER be sure that devirtualizing will give us a "safe" return value. Of course, a program that does this will most likely crash at runtime, but the analyzer at least shouldn't crash. The solution is to check and see if the function/method being inlined is the function that static binding would have picked. If not, check that the return value has the same type. If the types don't match, see if we can fix it with a derived-to-base cast (the C++ case). If we can't, return UnknownVal to avoid crashing later. <rdar://problem/12409977> llvm-svn: 165079
Diffstat (limited to 'clang/test/Analysis/inline.cpp')
-rw-r--r--clang/test/Analysis/inline.cpp27
1 files changed, 27 insertions, 0 deletions
diff --git a/clang/test/Analysis/inline.cpp b/clang/test/Analysis/inline.cpp
index b39b87101a5..ddcf5d01c34 100644
--- a/clang/test/Analysis/inline.cpp
+++ b/clang/test/Analysis/inline.cpp
@@ -340,3 +340,30 @@ namespace QualifiedCalls {
clang_analyzer_eval(object->A::getZero() == 0); // expected-warning{{TRUE}}
}
}
+
+
+namespace rdar12409977 {
+ struct Base {
+ int x;
+ };
+
+ struct Parent : public Base {
+ virtual Parent *vGetThis();
+ Parent *getThis() { return vGetThis(); }
+ };
+
+ struct Child : public Parent {
+ virtual Child *vGetThis() { return this; }
+ };
+
+ void test() {
+ Child obj;
+ obj.x = 42;
+
+ // Originally, calling a devirtualized method with a covariant return type
+ // caused a crash because the return value had the wrong type. When we then
+ // go to layer a CXXBaseObjectRegion on it, the base isn't a direct base of
+ // the object region and we get an assertion failure.
+ clang_analyzer_eval(obj.getThis()->x == 42); // expected-warning{{TRUE}}
+ }
+}
OpenPOWER on IntegriCloud