diff --git a/README.md b/README.md index e512491..4005e0a 100644 --- a/README.md +++ b/README.md @@ -445,17 +445,6 @@ void bar(std::vector>& cont, std::unique_ptr& p) } ``` -You can use `-Wlifetime-container-move` to enable check for it. But it's always better to introduce a helper function to state your intent: - -```cpp -// pset(container) = {*container} -move_each(std::move(container), [](auto&& elem){ - // use elem -}); -// pset(container) = {invalid} -assert(container.empty()); -``` - # Difference from the original implementation ## Output variable ### Return check diff --git a/include/cppsafe/Options.h b/include/cppsafe/Options.h index 206d1ca..3889f28 100644 --- a/include/cppsafe/Options.h +++ b/include/cppsafe/Options.h @@ -10,7 +10,6 @@ struct CppsafeOptions { bool LifetimeDisabled = false; bool LifetimeGlobal = false; bool LifetimeOutput = false; - bool LifetimeContainerMove = false; }; } diff --git a/integration_test/feature/move_container.cpp b/integration_test/feature/move_container.cpp deleted file mode 100644 index e8fbce9..0000000 --- a/integration_test/feature/move_container.cpp +++ /dev/null @@ -1,78 +0,0 @@ -// ARGS: -Wlifetime-container-move -Wlifetime-move - -#include "common.h" - -namespace std { - -template -class [[gsl::Owner(T)]] vector { -public: - using iterator = T*; - using value_type = T; - using reference_type = T&; - - iterator begin(); - iterator end(); - - reference_type operator[](int x); - - reference_type back(); - void pop_back(); - - ~vector(); -}; - -} - -struct Dummy {}; - -void test_loop() -{ - std::vector vec; - __lifetime_pset(vec); // expected-warning {{pset(vec) = (*vec)}} - - for (auto& x: vec) { - // expected-warning@-1 {{dereferencing a possibly dangling pointer}} - // expected-warning@+1 {{dereferencing a possibly dangling pointer}} - auto y = std::move(x); - // expected-note@-1 {{moved here}} - // expected-note@-2 {{moved here}} - } - - __lifetime_pset(vec); - // expected-warning@-1 {{pset(vec) = (*vec)}} - // expected-warning@-2 {{pset(vec) = ((invalid), *vec)}} -} - -void test_iterator() -{ - std::vector vec; - - for (auto it = vec.begin(), end = vec.end(); it != end; ++it) { - auto y = std::move(*it); - // expected-warning@-1 {{dereferencing a possibly dangling pointer}} - // expected-note@-2 2 {{moved here}} - // expected-warning@-3 {{passing a possibly dangling pointer as argument}} - } -} - -void test_index() -{ - std::vector vec; - - for (int i = 0; i < 10; ++i) { - auto y = std::move(vec[i]); - // expected-warning@-1 {{use a moved-from object}} - // expected-note@-2 {{moved here}} - } -} - -void test_back() -{ - std::vector vec; - - auto x = std::move(vec.back()); - // expected-note@-1 {{moved here}} - - vec.pop_back(); // expected-warning {{use a moved-from object}} -} \ No newline at end of file diff --git a/lib/lifetime/LifetimePsetBuilder.cpp b/lib/lifetime/LifetimePsetBuilder.cpp index b62fd91..5f1022e 100644 --- a/lib/lifetime/LifetimePsetBuilder.cpp +++ b/lib/lifetime/LifetimePsetBuilder.cpp @@ -841,12 +841,24 @@ class PSetsBuilder final : public ConstStmtVisitor, public P } if (PS.containsParent(V)) { + // WORKAROUND: https://github.com/qqiangwu/cppsafe/issues/82 + // // when move var with pset {*container}, only invalidate the var itself, - // containers and iterators are not invalidated - if (!Reporter.getOptions().LifetimeContainerMove) { - if (V.isDeref() && isIteratorOrContainer(Var.getType())) { - continue; - } + // containers and iterators are not invalidated. + // + // void foo(std::vector>& cont, std::unique_ptr& p) + //{ + // for (auto& x : cont) { + // p = std::move(x); + //} + + // for (auto& x: cont) { + // use(x); + //} + //} + // + if (V.isDeref() && isIteratorOrContainer(Var.getType())) { + continue; } setPSet(PSet::singleton(Var), PSet::invalid(Reason), Reason.getRange()); } diff --git a/src/main.cpp b/src/main.cpp index a354be3..1cdcbd8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -62,9 +62,6 @@ static const cl::opt WarnLifetimeDisabled("Wlifetime-disabled", static const cl::opt WarnLifetimeOutput("Wlifetime-output", desc("Enforce output parameter validity check in all paths"), cl::init(false), cl::cat(CppSafeCategory)); -static const cl::opt WarnLifetimeContainerMove("Wlifetime-container-move", - desc("Enable strict check on element move of containers"), cl::init(false), cl::cat(CppSafeCategory)); - struct DetectSystemIncludesError : public std::runtime_error { using std::runtime_error::runtime_error; }; @@ -132,7 +129,6 @@ class LifetimeFrontendAction : public clang::ASTFrontendAction { .LifetimeDisabled = WarnLifetimeDisabled, .LifetimeGlobal = WarnLifetimeGlobal, .LifetimeOutput = WarnLifetimeOutput, - .LifetimeContainerMove = WarnLifetimeContainerMove, }; return std::make_unique(Options);