summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
authorArtem Dergachev <artem.dergachev@gmail.com>2016-11-30 19:02:44 +0000
committerArtem Dergachev <artem.dergachev@gmail.com>2016-11-30 19:02:44 +0000
commit28ee2d1b0973df3295cd7eadb45473037e530ed9 (patch)
treed5e0db825484edad850da932427927fd3fb207c5 /clang/test
parent387afc937544c353bd55e753a9d63acd5150b404 (diff)
downloadbcm5719-llvm-28ee2d1b0973df3295cd7eadb45473037e530ed9.tar.gz
bcm5719-llvm-28ee2d1b0973df3295cd7eadb45473037e530ed9.zip
[analyzer] Construct temporary objects of correct types, destroy them properly.
When constructing a temporary object region, which represents the result of MaterializeTemporaryExpr, track down the sub-expression for which the temporary is necessary with a trick similar to the approach used in CodeGen, namely by using Expr::skipRValueSubobjectAdjustments(). Then, create the temporary object region with type of that sub-expression. That type would propagate further in a path-sensitive manner. During destruction of lifetime-extened temporaries, consult the type of the temporary object region, rather than the type of the lifetime-extending variable, in order to call the correct destructor (fixes pr17001) and, at least, not to crash by trying to call a destructor of a plain type (fixes pr19539). rdar://problem/29131302 rdar://problem/29131576 Differential Revision: https://reviews.llvm.org/D26839 llvm-svn: 288263
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/Analysis/lifetime-extension.cpp46
1 files changed, 46 insertions, 0 deletions
diff --git a/clang/test/Analysis/lifetime-extension.cpp b/clang/test/Analysis/lifetime-extension.cpp
new file mode 100644
index 00000000000..124eef32fde
--- /dev/null
+++ b/clang/test/Analysis/lifetime-extension.cpp
@@ -0,0 +1,46 @@
+// RUN: %clang_cc1 -Wno-unused -std=c++11 -analyze -analyzer-checker=debug.ExprInspection -verify %s
+
+void clang_analyzer_eval(bool);
+
+namespace pr17001_call_wrong_destructor {
+bool x;
+struct A {
+ int *a;
+ A() {}
+ ~A() {}
+};
+struct B : public A {
+ B() {}
+ ~B() { x = true; }
+};
+
+void f() {
+ {
+ const A &a = B();
+ }
+ clang_analyzer_eval(x); // expected-warning{{TRUE}}
+}
+} // end namespace pr17001_call_wrong_destructor
+
+namespace pr19539_crash_on_destroying_an_integer {
+struct A {
+ int i;
+ int j[2];
+ A() : i(1) {
+ j[0] = 2;
+ j[1] = 3;
+ }
+ ~A() {}
+};
+
+void f() {
+ const int &x = A().i; // no-crash
+ const int &y = A().j[1]; // no-crash
+ const int &z = (A().j[1], A().j[0]); // no-crash
+
+ // FIXME: All of these should be TRUE, but constructors aren't inlined.
+ clang_analyzer_eval(x == 1); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(y == 3); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(z == 2); // expected-warning{{UNKNOWN}}
+}
+} // end namespace pr19539_crash_on_destroying_an_integer
OpenPOWER on IntegriCloud