summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
authorArtem Dergachev <artem.dergachev@gmail.com>2019-04-23 02:45:42 +0000
committerArtem Dergachev <artem.dergachev@gmail.com>2019-04-23 02:45:42 +0000
commit8c6119a44275852b868c6df0c14ee85efeb2a9e5 (patch)
tree86c6dca212d30da5c4768eeabb68af088ddf57b4 /clang/test
parent32c0ebe615772f25b4cadb82bc3ad809afa62641 (diff)
downloadbcm5719-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.h1
-rw-r--r--clang/test/Analysis/smart-ptr.cpp18
-rw-r--r--clang/test/Analysis/use-after-move.cpp26
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();
+}
OpenPOWER on IntegriCloud