| // RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp |
| // RUN: clang-modernize -use-auto %t.cpp -- --std=c++11 -I %S/Inputs |
| // RUN: FileCheck -input-file=%t.cpp %s |
| // |
| // RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp |
| // RUN: clang-modernize -use-auto %t.cpp -- --std=c++11 -I %S/Inputs \ |
| // RUN: -DUSE_INLINE_NAMESPACE=1 |
| // RUN: FileCheck -input-file=%t.cpp %s |
| |
| |
| #define CONTAINER array |
| #include "test_std_container.h" |
| #undef CONTAINER |
| |
| #define CONTAINER vector |
| #include "test_std_container.h" |
| #undef CONTAINER |
| |
| #define CONTAINER unordered_map |
| #define USE_BASE_CLASS_ITERATORS 1 |
| #include "test_std_container.h" |
| #undef USE_BASE_CLASS_ITERATORS |
| #undef CONTAINER |
| |
| typedef std::vector<int>::iterator int_iterator; |
| |
| namespace foo { |
| template <typename T> |
| class vector { |
| public: |
| class iterator {}; |
| |
| iterator begin() { return iterator(); } |
| }; |
| } // namespace foo |
| |
| int main(int argc, char **argv) { |
| std::vector<int> Vec; |
| // CHECK: std::vector<int> Vec; |
| |
| std::unordered_map<int> Map; |
| // CHECK: std::unordered_map<int> Map; |
| |
| // Types with more sugar should work. Types with less should not. |
| { |
| int_iterator more_sugar = Vec.begin(); |
| // CHECK: auto more_sugar = Vec.begin(); |
| |
| internal::iterator_wrapper<std::vector<int>, 0> less_sugar = Vec.begin(); |
| // CHECK: internal::iterator_wrapper<std::vector<int>, 0> less_sugar = Vec.begin(); |
| } |
| |
| // Initialization from initializer lists isn't allowed. Using 'auto' |
| // would result in std::initializer_list being deduced for the type. |
| { |
| std::unordered_map<int>::iterator I{Map.begin()}; |
| // CHECK: std::unordered_map<int>::iterator I{Map.begin()}; |
| |
| std::unordered_map<int>::iterator I2 = {Map.begin()}; |
| // CHECK: std::unordered_map<int>::iterator I2 = {Map.begin()}; |
| } |
| |
| // Various forms of construction. Default constructors and constructors with |
| // all-default parameters shouldn't get transformed. Construction from other |
| // types is also not allowed. |
| { |
| std::unordered_map<int>::iterator copy(Map.begin()); |
| // CHECK: auto copy(Map.begin()); |
| |
| std::unordered_map<int>::iterator def; |
| // CHECK: std::unordered_map<int>::iterator def; |
| |
| // const_iterator has no default constructor, just one that has >0 params |
| // with defaults. |
| std::unordered_map<int>::const_iterator constI; |
| // CHECK: std::unordered_map<int>::const_iterator constI; |
| |
| // Uses iterator_provider::const_iterator's conversion constructor. |
| |
| std::unordered_map<int>::const_iterator constI2 = def; |
| // CHECK: std::unordered_map<int>::const_iterator constI2 = def; |
| |
| std::unordered_map<int>::const_iterator constI3(def); |
| // CHECK: std::unordered_map<int>::const_iterator constI3(def); |
| |
| // Explicit use of conversion constructor |
| |
| std::unordered_map<int>::const_iterator constI4 = std::unordered_map<int>::const_iterator(def); |
| // CHECK: auto constI4 = std::unordered_map<int>::const_iterator(def); |
| |
| // Uses iterator_provider::iterator's const_iterator conversion operator. |
| |
| std::unordered_map<int>::iterator I = constI; |
| // CHECK: std::unordered_map<int>::iterator I = constI; |
| |
| std::unordered_map<int>::iterator I2(constI); |
| // CHECK: std::unordered_map<int>::iterator I2(constI); |
| } |
| |
| // Weird cases of pointers and references to iterators are not transformed. |
| { |
| int_iterator I = Vec.begin(); |
| |
| int_iterator *IPtr = &I; |
| // CHECK: int_iterator *IPtr = &I; |
| |
| int_iterator &IRef = I; |
| // CHECK: int_iterator &IRef = I; |
| } |
| |
| { |
| // Variable declarations in iteration statements. |
| for (std::vector<int>::iterator I = Vec.begin(); I != Vec.end(); ++I) { |
| // CHECK: for (auto I = Vec.begin(); I != Vec.end(); ++I) { |
| } |
| |
| // Range-based for loops. |
| std::array<std::vector<int>::iterator> iter_arr; |
| for (std::vector<int>::iterator I: iter_arr) { |
| // CHECK: for (auto I: iter_arr) { |
| } |
| |
| // Test with init-declarator-list. |
| for (int_iterator I = Vec.begin(), |
| E = Vec.end(); I != E; ++I) { |
| // CHECK: for (auto I = Vec.begin(), |
| // CHECK-NEXT: E = Vec.end(); I != E; ++I) { |
| } |
| } |
| |
| // Only std containers should be changed. |
| { |
| using namespace foo; |
| vector<int> foo_vec; |
| vector<int>::iterator I = foo_vec.begin(); |
| // CHECK: vector<int>::iterator I = foo_vec.begin(); |
| } |
| |
| // Ensure using directives don't interfere with replacement. |
| { |
| using namespace std; |
| vector<int> std_vec; |
| vector<int>::iterator I = std_vec.begin(); |
| // CHECK: auto I = std_vec.begin(); |
| } |
| |
| // Make sure references and cv qualifiers don't get removed (i.e. replaced |
| // with just 'auto'). |
| { |
| const auto & I = Vec.begin(); |
| // CHECK: const auto & I = Vec.begin(); |
| |
| auto && I2 = Vec.begin(); |
| // CHECK: auto && I2 = Vec.begin(); |
| } |
| |
| // Passing a string as an argument to introduce a temporary object |
| // that will create an expression with cleanups. Bugzilla: 15550 |
| { |
| std::unordered_map<int> MapFind; |
| std::unordered_map<int>::iterator I = MapFind.find("foo"); |
| // CHECK: auto I = MapFind.find("foo"); |
| } |
| |
| // Test for declaration lists |
| { |
| // Ensusre declaration lists that matches the declaration type with written |
| // no-list initializer are transformed. |
| std::vector<int>::iterator I = Vec.begin(), E = Vec.end(); |
| // CHECK: auto I = Vec.begin(), E = Vec.end(); |
| |
| // Declaration lists with non-initialized variables should not be |
| // transformed. |
| std::vector<int>::iterator J = Vec.begin(), K; |
| // CHECK: std::vector<int>::iterator J = Vec.begin(), K; |
| } |
| return 0; |
| } |