summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/test/cpp11-migrate/UseAuto
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/test/cpp11-migrate/UseAuto')
-rw-r--r--clang-tools-extra/test/cpp11-migrate/UseAuto/Inputs/gen_my_std.h.py170
-rw-r--r--clang-tools-extra/test/cpp11-migrate/UseAuto/gen_basic_std_iterator_tests.cpp.py21
-rw-r--r--clang-tools-extra/test/cpp11-migrate/UseAuto/iterator.cpp139
3 files changed, 286 insertions, 44 deletions
diff --git a/clang-tools-extra/test/cpp11-migrate/UseAuto/Inputs/gen_my_std.h.py b/clang-tools-extra/test/cpp11-migrate/UseAuto/Inputs/gen_my_std.h.py
index 06709abcb4c..3f8be5862da 100644
--- a/clang-tools-extra/test/cpp11-migrate/UseAuto/Inputs/gen_my_std.h.py
+++ b/clang-tools-extra/test/cpp11-migrate/UseAuto/Inputs/gen_my_std.h.py
@@ -1,47 +1,57 @@
#!/usr/bin/python
+# Each std container is represented below. To test the various ways in which
+# a type may be defined, the containers are split into categories:
+# * Define iterator types with typedefs
+# * Define iterator types as nested classes
+# * Define iterator types with using declarations
+#
+# Further, one class in each category is chosen to be defined in a way mimicing
+# libc++: The container is actually defined in a different namespace (std::_1
+# is used here) and then imported into the std namespace with a using
+# declaration. This is controlled with the 'using' key in the dictionary
+# describing each container.
typedef_containers = [
- "array",
- "deque",
- "forward_list",
- "list",
- "vector"
+ {"name" : "array",
+ "using" : True},
+ {"name" : "deque",
+ "using" : False},
+ {"name" : "forward_list",
+ "using" : False},
+ {"name" : "list",
+ "using" : False},
+ {"name" : "vector",
+ "using" : False}
]
subclass_containers = [
- "map",
- "multimap",
- "set",
- "multiset",
+ {"name" : "map",
+ "using" : True},
+ {"name" : "multimap",
+ "using" : False},
+ {"name" : "set",
+ "using" : False},
+ {"name" : "multiset",
+ "using" : False},
]
using_containers = [
- "unordered_map",
- "unordered_multimap",
- "unordered_set",
- "unordered_multiset",
- "queue",
- "priority_queue",
- "stack"
+ {"name" : "unordered_map",
+ "using" : True},
+ {"name" : "unordered_multimap",
+ "using" : False},
+ {"name" : "unordered_set",
+ "using" : False},
+ {"name" : "unordered_multiset",
+ "using" : False},
+ {"name" : "queue",
+ "using" : False},
+ {"name" : "priority_queue",
+ "using" : False},
+ {"name" : "stack",
+ "using" : False}
]
-print """namespace internal {
-
-template <typename T, int i>
-struct iterator_wrapper {
-};
-
-template <typename T>
-class iterator_provider {
-public:
- class iterator {};
- class const_iterator {};
- class reverse_iterator {};
- class const_reverse_iterator {};
-};
-
-} // namespace internal
-
-namespace std {"""
+# Every class requires these functions.
iterator_generators = """
iterator begin() { return iterator(); }
iterator end() { return iterator(); }
@@ -56,21 +66,97 @@ iterator_generators = """
const_reverse_iterator rend() const { return const_reverse_iterator(); }
"""
+
+# Convenience function for nested class definition within a special namespace
+# to mimic libc++ style std container definitions.
+def outputClassDef(Definition, ClassName, Import):
+ if Import:
+ print "namespace _1 {"
+
+ print Definition
+
+ if Import:
+ print """
+}} // namespace _1
+using _1::{0};""".format(ClassName)
+
+
+# Output preamble and common functionality
+print """
+//===-----------------------------------------------------------*- C++ -*--===//
+//
+// This file was automatically generated from gen_my_std.h.py by the build
+// system as a dependency for cpp11-migrate's test suite.
+//
+// This file contains a shell implementation of std containers and iterators for
+// testing the use-auto transform of cpp11-migrate. All std containers and
+// iterators are present. Container and iterator implementations vary to cover
+// various ways the std container and iterator types are made available:
+//
+// Variations for how iterator types are presented:
+// * Typedef (array, deque, forward_list, list, vector)
+// * Nested class (map, multimap, set, multiset)
+// * Using declaration {unordered_} X {map, multimap, set, multiset}
+//
+// Variations for how container types are presented:
+// * Defined directly in namespace std
+// * Imported into namespace std with using declarations (a la libc++).
+//
+//===----------------------------------------------------------------------===//
+
+namespace internal {
+
+template <typename T, int i>
+struct iterator_wrapper {
+ iterator_wrapper() {}
+
+ // These are required for tests using iteration statements.
+ bool operator!=(const iterator_wrapper<T, i>&) { return false; }
+ iterator_wrapper& operator++() { return *this; }
+ typename T::value_type operator*() { return typename T::value_type(); }
+};
+
+template <typename T>
+class iterator_provider {
+public:
+ class iterator {
+ public:
+ iterator() {}
+ iterator(const iterator&) {}
+ };
+ class const_iterator {
+ public:
+ const_iterator(int i=0) {}
+ const_iterator(const iterator &) {}
+ const_iterator(const const_iterator &) {}
+ operator iterator() { return iterator(); }
+ };
+ class reverse_iterator {};
+ class const_reverse_iterator {};
+};
+
+} // namespace internal
+
+namespace std {""".lstrip() # Take off leading newline
+
for c in typedef_containers:
- print """
+ Definition = """
template <typename T>
class {0} {{
public:
+ typedef T value_type;
typedef typename internal::iterator_wrapper<{0}<T>, 0> iterator;
typedef typename internal::iterator_wrapper<{0}<T>, 1> const_iterator;
typedef typename internal::iterator_wrapper<{0}<T>, 3> reverse_iterator;
typedef typename internal::iterator_wrapper<{0}<T>, 2> const_reverse_iterator;
{0}() {{}}
- {1}}};""".format(c, iterator_generators)
+ {1}}};""".format(c['name'], iterator_generators)
+
+ outputClassDef(Definition, c['name'], c['using'])
for c in subclass_containers:
- print """
+ Definition = """
template <typename T>
class {0} {{
public:
@@ -80,10 +166,12 @@ public:
class const_reverse_iterator {{}};
{0}() {{}}
- {1}}};""".format(c, iterator_generators)
+ {1}}};""".format(c['name'], iterator_generators)
+
+ outputClassDef(Definition, c['name'], c['using'])
for c in using_containers:
- print """
+ Definition = """
template <typename T>
class {0} : internal::iterator_provider<{0}<T> > {{
public:
@@ -93,6 +181,8 @@ public:
using typename internal::iterator_provider<{0}<T> >::const_reverse_iterator;
{0}() {{}}
- {1}}};""".format(c, iterator_generators)
+ {1}}};""".format(c['name'], iterator_generators)
+
+ outputClassDef(Definition, c['name'], c['using'])
print "} // namespace std"
diff --git a/clang-tools-extra/test/cpp11-migrate/UseAuto/gen_basic_std_iterator_tests.cpp.py b/clang-tools-extra/test/cpp11-migrate/UseAuto/gen_basic_std_iterator_tests.cpp.py
index 56b6f5c41d2..8f118245db1 100644
--- a/clang-tools-extra/test/cpp11-migrate/UseAuto/gen_basic_std_iterator_tests.cpp.py
+++ b/clang-tools-extra/test/cpp11-migrate/UseAuto/gen_basic_std_iterator_tests.cpp.py
@@ -19,13 +19,26 @@ containers = [
"stack"
]
-print """// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
-// RUN: cpp11-migrate -use-auto %t.cpp -- --std=c++11 -I %S/Inputs
+print """
+//===----------------------------------------------------------------------===//
+//
+// This file was automatically generated from
+// gen_basic_std_iterator_tests.cpp.py by the build system as a dependency for
+// cpp11-migrate's test suite.
+//
+// This file contains basic positive tests for the use-auto transform's ability
+// to replace standard iterators. Variables considered:
+// * All std container names
+// * All std iterator names
+//
+//===----------------------------------------------------------------------===//
+
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
+// RUN: cpp11-migrate -use-auto %t.cpp -- -I %S/Inputs
// RUN: FileCheck -input-file=%t.cpp %s
-// XFAIL: *
#include "my_std.h"
-int main(int argc, char **argv) {"""
+int main(int argc, char **argv) {""".lstrip() # Strip leading newline
for c in containers:
print """
diff --git a/clang-tools-extra/test/cpp11-migrate/UseAuto/iterator.cpp b/clang-tools-extra/test/cpp11-migrate/UseAuto/iterator.cpp
new file mode 100644
index 00000000000..a6d00c7bf96
--- /dev/null
+++ b/clang-tools-extra/test/cpp11-migrate/UseAuto/iterator.cpp
@@ -0,0 +1,139 @@
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
+// RUN: cpp11-migrate -use-auto %t.cpp -- --std=c++11 -I %gen_root/UseAuto/Inputs
+// RUN: FileCheck -input-file=%t.cpp %s
+#include "my_std.h"
+
+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();
+ }
+
+ return 0;
+}
OpenPOWER on IntegriCloud