| // RUN: %clang_analyze_cc1 -std=c++17 -verify %s \ |
| // RUN: -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.IteratorModeling \ |
| // RUN: -analyzer-config aggressive-binary-operation-simplification=true \ |
| // RUN: -analyzer-config c++-container-inlining=false |
| |
| #include "Inputs/system-header-simulator-cxx.h" |
| |
| enum Target {MovedFromSource, Destination, storeIterator}; |
| |
| std::string gh137157_iteratorDerefList(Target trg) { |
| std::list<std::string> l1; |
| l1.push_back("l1"); |
| std::list<std::string> l2; |
| |
| switch (trg) { |
| case MovedFromSource: { |
| std::move(l1.begin(), l1.end(), std::back_inserter(l2)); |
| return *l1.cbegin(); // expected-warning {{Method called on moved-from object 'l1'}} |
| } |
| case Destination: { |
| std::move(l1.begin(), l1.end(), std::back_inserter(l2)); |
| return *l2.cbegin(); // no-warning: only l1 was invalidated and not l2! |
| } |
| case storeIterator: { |
| auto it = l1.begin(); |
| std::move(it, l1.end(), std::back_inserter(l2)); |
| return *l1.cbegin(); // expected-warning {{Method called on moved-from object 'l1'}} |
| } |
| } |
| return {}; |
| } |
| |
| std::string gh137157_iteratorDerefVector(Target trg) { |
| std::vector<std::string> l1; |
| l1.push_back("l1"); |
| std::vector<std::string> l2; |
| |
| switch (trg) { |
| case MovedFromSource: { |
| std::move(l1.begin(), l1.end(), std::back_inserter(l2)); |
| return *l1.cbegin(); // expected-warning {{Method called on moved-from object 'l1'}} |
| } |
| case Destination: { |
| std::move(l1.begin(), l1.end(), std::back_inserter(l2)); |
| return *l2.cbegin(); // no-warning: only l1 was invalidated and not l2! |
| } |
| case storeIterator: { |
| auto it = l1.begin(); |
| std::move(it, l1.end(), std::back_inserter(l2)); |
| return *l1.cbegin(); // expected-warning {{Method called on moved-from object 'l1'}} |
| } |
| } |
| return {}; |
| } |