blob: faca8af43d50cb09cbe6da886910e1b5ee6cd5ca [file] [log] [blame]
// 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;
}