forked from llvm-mirror/clang
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@288263 91177308-0d34-0410-b5e6-96231b3b80d8
- Loading branch information
Showing
2 changed files
with
95 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |