diff options
| author | Artem Dergachev <artem.dergachev@gmail.com> | 2016-11-30 19:02:44 +0000 |
|---|---|---|
| committer | Artem Dergachev <artem.dergachev@gmail.com> | 2016-11-30 19:02:44 +0000 |
| commit | 28ee2d1b0973df3295cd7eadb45473037e530ed9 (patch) | |
| tree | d5e0db825484edad850da932427927fd3fb207c5 /clang/test | |
| parent | 387afc937544c353bd55e753a9d63acd5150b404 (diff) | |
| download | bcm5719-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.cpp | 46 |
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 |

