summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorArtem Dergachev <artem.dergachev@gmail.com>2018-12-14 20:47:58 +0000
committerArtem Dergachev <artem.dergachev@gmail.com>2018-12-14 20:47:58 +0000
commit87fae78f666cda8a567d98080858cfad013a2589 (patch)
treee7e6373ae72d0f0270701d3befa258311c193c67 /test
parentb53ab0e23fc3229a6e9815c0602165114591a911 (diff)
downloadclang-87fae78f666cda8a567d98080858cfad013a2589.tar.gz
[analyzer] MoveChecker: Improve invalidation policies.
If a moved-from object is passed into a conservatively evaluated function by pointer or by reference, we assume that the function may reset its state. Make sure it doesn't apply to const pointers and const references. Add a test that demonstrates that it does apply to rvalue references. Additionally, make sure that the object is invalidated when its contents change for reasons other than invalidation caused by evaluating a call conservatively. In particular, when the object's fields are manipulated directly, we should assume that some sort of reset may be happening. Differential Revision: https://reviews.llvm.org/D55289 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@349190 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test')
-rw-r--r--test/Analysis/use-after-move.cpp49
1 files changed, 44 insertions, 5 deletions
diff --git a/test/Analysis/use-after-move.cpp b/test/Analysis/use-after-move.cpp
index 3134720e4d..1ef04a0f5a 100644
--- a/test/Analysis/use-after-move.cpp
+++ b/test/Analysis/use-after-move.cpp
@@ -116,6 +116,19 @@ public:
bool empty() const;
bool isEmpty() const;
operator bool() const;
+
+ void testUpdateField() {
+ A a;
+ A b = std::move(a);
+ a.i = 1;
+ a.foo(); // no-warning
+ }
+ void testUpdateFieldDouble() {
+ A a;
+ A b = std::move(a);
+ a.d = 1.0;
+ a.foo(); // no-warning
+ }
};
int bignum();
@@ -594,24 +607,50 @@ void paramEvaluateOrderTest() {
foobar(a.getI(), std::move(a)); //no-warning
}
-void not_known(A &a);
-void not_known(A *a);
+void not_known_pass_by_ref(A &a);
+void not_known_pass_by_const_ref(const A &a);
+void not_known_pass_by_rvalue_ref(A &&a);
+void not_known_pass_by_ptr(A *a);
+void not_known_pass_by_const_ptr(const A *a);
void regionAndPointerEscapeTest() {
{
A a;
A b;
b = std::move(a);
- not_known(a);
- a.foo(); //no-warning
+ not_known_pass_by_ref(a);
+ a.foo(); // no-warning
+ }
+ {
+ A a;
+ A b;
+ b = std::move(a); // expected-note{{Object 'a' is moved}}
+ not_known_pass_by_const_ref(a);
+ a.foo(); // expected-warning{{Method called on moved-from object 'a'}}
+ // expected-note@-1{{Method called on moved-from object 'a'}}
+ }
+ {
+ A a;
+ A b;
+ b = std::move(a);
+ not_known_pass_by_rvalue_ref(std::move(a));
+ a.foo(); // no-warning
}
{
A a;
A b;
b = std::move(a);
- not_known(&a);
+ not_known_pass_by_ptr(&a);
a.foo(); // no-warning
}
+ {
+ A a;
+ A b;
+ b = std::move(a); // expected-note{{Object 'a' is moved}}
+ not_known_pass_by_const_ptr(&a);
+ a.foo(); // expected-warning{{Method called on moved-from object 'a'}}
+ // expected-note@-1{{Method called on moved-from object 'a'}}
+ }
}
// A declaration statement containing multiple declarations sequences the