diff options
author | Pavel Labath <labath@google.com> | 2013-08-30 08:52:28 +0000 |
---|---|---|
committer | Pavel Labath <labath@google.com> | 2013-08-30 08:52:28 +0000 |
commit | 66ea35d9f3d93cab3ca6d735c8eb19a5f701b86f (patch) | |
tree | e291af416a42b64bf3b84c25e5650c67c4c90ede /test/Analysis | |
parent | 13d2aa5c8fbb62abf8531bc6e1b7aa89c60fba4f (diff) | |
download | clang-66ea35d9f3d93cab3ca6d735c8eb19a5f701b86f.tar.gz |
Sema: avoid reuse of Exprs when synthesizing operator=
Summary:
Previously, Sema was reusing parts of the AST when synthesizing an assignment
operator, turning it into a AS-dag. This caused problems for the static
analyzer, which assumed an expression appears in the tree only once.
Here I make sure to always create a fresh Expr, when inserting something into
the AST, fixing PR16745 in the process.
Reviewers: doug.gregor
CC: cfe-commits, jordan_rose
Differential Revision: http://llvm-reviews.chandlerc.com/D1425
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@189659 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/Analysis')
-rw-r--r-- | test/Analysis/operator-calls.cpp | 47 |
1 files changed, 46 insertions, 1 deletions
diff --git a/test/Analysis/operator-calls.cpp b/test/Analysis/operator-calls.cpp index 7461d75f67..4bd7c12fad 100644 --- a/test/Analysis/operator-calls.cpp +++ b/test/Analysis/operator-calls.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -verify %s +// RUN: %clang_cc1 -std=c++11 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -verify %s void clang_analyzer_eval(bool); struct X0 { }; @@ -85,3 +85,48 @@ namespace RValues { clang_analyzer_eval(+(coin ? getLargeOpaque() : getLargeOpaque())); // expected-warning{{UNKNOWN}} } } + +namespace SynthesizedAssignment { + struct A { + int a; + A& operator=(A& other) { a = -other.a; return *this; } + A& operator=(A&& other) { a = other.a+1; return *this; } + }; + + struct B { + int x; + A a[3]; + B& operator=(B&) = default; + B& operator=(B&&) = default; + }; + + // This used to produce a warning about the iteration variable in the + // synthesized assignment operator being undefined. + void testNoWarning() { + B v, u; + u = v; + } + + void testNoWarningMove() { + B v, u; + u = static_cast<B &&>(v); + } + + void testConsistency() { + B v, u; + v.a[1].a = 47; + v.a[2].a = 42; + u = v; + clang_analyzer_eval(u.a[1].a == -47); // expected-warning{{TRUE}} + clang_analyzer_eval(u.a[2].a == -42); // expected-warning{{TRUE}} + } + + void testConsistencyMove() { + B v, u; + v.a[1].a = 47; + v.a[2].a = 42; + u = static_cast<B &&>(v); + clang_analyzer_eval(u.a[1].a == 48); // expected-warning{{TRUE}} + clang_analyzer_eval(u.a[2].a == 43); // expected-warning{{TRUE}} + } +} |