diff options
| author | Artem Dergachev <artem.dergachev@gmail.com> | 2019-04-23 02:45:42 +0000 |
|---|---|---|
| committer | Artem Dergachev <artem.dergachev@gmail.com> | 2019-04-23 02:45:42 +0000 |
| commit | 8c6119a44275852b868c6df0c14ee85efeb2a9e5 (patch) | |
| tree | 86c6dca212d30da5c4768eeabb68af088ddf57b4 /clang/test | |
| parent | 32c0ebe615772f25b4cadb82bc3ad809afa62641 (diff) | |
| download | bcm5719-llvm-8c6119a44275852b868c6df0c14ee85efeb2a9e5.tar.gz bcm5719-llvm-8c6119a44275852b868c6df0c14ee85efeb2a9e5.zip | |
[analyzer] PR41269: Add a bit of C++ smart pointer modeling.
Implement cplusplus.SmartPtrModeling, a new checker that doesn't
emit any warnings but models methods of smart pointers more precisely.
For now the only thing it does is make `(bool) P` return false when `P`
is a freshly moved pointer. This addresses a false positive in the
use-after-move-checker.
Differential Revision: https://reviews.llvm.org/D60796
llvm-svn: 358944
Diffstat (limited to 'clang/test')
| -rw-r--r-- | clang/test/Analysis/Inputs/system-header-simulator-cxx.h | 1 | ||||
| -rw-r--r-- | clang/test/Analysis/smart-ptr.cpp | 18 | ||||
| -rw-r--r-- | clang/test/Analysis/use-after-move.cpp | 26 |
3 files changed, 39 insertions, 6 deletions
diff --git a/clang/test/Analysis/Inputs/system-header-simulator-cxx.h b/clang/test/Analysis/Inputs/system-header-simulator-cxx.h index cca9d7486ea..3b3ac83b427 100644 --- a/clang/test/Analysis/Inputs/system-header-simulator-cxx.h +++ b/clang/test/Analysis/Inputs/system-header-simulator-cxx.h @@ -789,6 +789,7 @@ namespace std { typename std::add_lvalue_reference<T>::type operator*() const; T *operator->() const; + operator bool() const; }; } #endif diff --git a/clang/test/Analysis/smart-ptr.cpp b/clang/test/Analysis/smart-ptr.cpp new file mode 100644 index 00000000000..3f1782480b4 --- /dev/null +++ b/clang/test/Analysis/smart-ptr.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection\ +// RUN: -analyzer-checker cplusplus.Move,cplusplus.SmartPtr\ +// RUN: -std=c++11 -verify %s + +#include "Inputs/system-header-simulator-cxx.h" + +void clang_analyzer_warnIfReached(); + +void derefAfterMove(std::unique_ptr<int> P) { + std::unique_ptr<int> Q = std::move(P); + if (Q) + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} + *Q.get() = 1; // no-warning + if (P) + clang_analyzer_warnIfReached(); // no-warning + // TODO: Report a null dereference (instead). + *P.get() = 1; // expected-warning {{Method called on moved-from object 'P'}} +} diff --git a/clang/test/Analysis/use-after-move.cpp b/clang/test/Analysis/use-after-move.cpp index 29e62f8c28e..5e4179b1f13 100644 --- a/clang/test/Analysis/use-after-move.cpp +++ b/clang/test/Analysis/use-after-move.cpp @@ -1,36 +1,36 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.Move %s\ // RUN: -std=c++11 -analyzer-output=text -analyzer-config eagerly-assume=false\ // RUN: -analyzer-config exploration_strategy=unexplored_first_queue\ -// RUN: -analyzer-checker debug.ExprInspection\ +// RUN: -analyzer-checker core,cplusplus.SmartPtr,debug.ExprInspection\ // RUN: -verify=expected,peaceful,non-aggressive // RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.Move %s\ // RUN: -std=c++11 -analyzer-output=text -analyzer-config eagerly-assume=false\ // RUN: -analyzer-config exploration_strategy=dfs -DDFS\ -// RUN: -analyzer-checker debug.ExprInspection\ +// RUN: -analyzer-checker core,cplusplus.SmartPtr,debug.ExprInspection\ // RUN: -verify=expected,peaceful,non-aggressive // RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.Move %s\ // RUN: -std=c++11 -analyzer-output=text -analyzer-config eagerly-assume=false\ // RUN: -analyzer-config exploration_strategy=unexplored_first_queue\ // RUN: -analyzer-config cplusplus.Move:WarnOn=KnownsOnly\ -// RUN: -analyzer-checker debug.ExprInspection\ +// RUN: -analyzer-checker core,cplusplus.SmartPtr,debug.ExprInspection\ // RUN: -verify=expected,non-aggressive // RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.Move -verify %s\ // RUN: -std=c++11 -analyzer-output=text -analyzer-config eagerly-assume=false\ // RUN: -analyzer-config exploration_strategy=dfs -DDFS\ // RUN: -analyzer-config cplusplus.Move:WarnOn=KnownsOnly\ -// RUN: -analyzer-checker debug.ExprInspection\ +// RUN: -analyzer-checker core,cplusplus.SmartPtr,debug.ExprInspection\ // RUN: -verify=expected,non-aggressive // RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.Move %s\ // RUN: -std=c++11 -analyzer-output=text -analyzer-config eagerly-assume=false\ // RUN: -analyzer-config exploration_strategy=unexplored_first_queue\ // RUN: -analyzer-config cplusplus.Move:WarnOn=All\ -// RUN: -analyzer-checker debug.ExprInspection\ +// RUN: -analyzer-checker core,cplusplus.SmartPtr,debug.ExprInspection\ // RUN: -verify=expected,peaceful,aggressive // RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.Move %s\ // RUN: -std=c++11 -analyzer-output=text -analyzer-config eagerly-assume=false\ // RUN: -analyzer-config exploration_strategy=dfs -DDFS\ // RUN: -analyzer-config cplusplus.Move:WarnOn=All\ -// RUN: -analyzer-checker debug.ExprInspection\ +// RUN: -analyzer-checker core,cplusplus.SmartPtr,debug.ExprInspection\ // RUN: -verify=expected,peaceful,aggressive // RUN: not %clang_analyze_cc1 -verify %s \ @@ -933,3 +933,17 @@ void localUniquePtrWithArrow(std::unique_ptr<A> P) { P->foo(); // expected-warning{{Dereference of null smart pointer 'P' of type 'std::unique_ptr'}} // expected-note@-1{{Dereference of null smart pointer 'P' of type 'std::unique_ptr'}} } + +void getAfterMove(std::unique_ptr<A> P) { + std::unique_ptr<A> Q = std::move(P); // peaceful-note {{Object 'P' is moved}} + + // TODO: Explain why (bool)P is false. + if (P) // peaceful-note{{Taking false branch}} + clang_analyzer_warnIfReached(); // no-warning + + A *a = P.get(); // peaceful-warning {{Method called on moved-from object 'P'}} + // peaceful-note@-1 {{Method called on moved-from object 'P'}} + + // TODO: Warn on a null dereference here. + a->foo(); +} |

