aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorEdwin Vane <edwin.vane@intel.com>2013-02-28 16:29:24 +0000
committerEdwin Vane <edwin.vane@intel.com>2013-02-28 16:29:24 +0000
commit290465d62516cada52b47ee57077b66f8bc2343a (patch)
tree8bd4c9fb2c91fce7ea2f38c23c547f70bb9363cc /test
parentc00b26c491095032a47bd869816a3c202d4e697a (diff)
Introducing Use-Auto transform for cpp11-migrate
The new Use-Auto transform replaces the type specifier for variable declarations with the special C++11 'auto' type specifier. For now, the replacement is done only for variables that are iterators of any of the std containers and only if the type used is one of those explicitly allowed by the standard (i.e. not an implementation-specific type). Reviewers: gribozavr, silvas, klimek git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/trunk@176266 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test')
-rw-r--r--test/cpp11-migrate/UseAuto/Inputs/gen_my_std.h.py170
-rw-r--r--test/cpp11-migrate/UseAuto/gen_basic_std_iterator_tests.cpp.py21
-rw-r--r--test/cpp11-migrate/UseAuto/iterator.cpp139
3 files changed, 286 insertions, 44 deletions
diff --git a/test/cpp11-migrate/UseAuto/Inputs/gen_my_std.h.py b/test/cpp11-migrate/UseAuto/Inputs/gen_my_std.h.py
index 06709abc..3f8be586 100644
--- a/test/cpp11-migrate/UseAuto/Inputs/gen_my_std.h.py
+++ b/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/test/cpp11-migrate/UseAuto/gen_basic_std_iterator_tests.cpp.py b/test/cpp11-migrate/UseAuto/gen_basic_std_iterator_tests.cpp.py
index 56b6f5c4..8f118245 100644
--- a/test/cpp11-migrate/UseAuto/gen_basic_std_iterator_tests.cpp.py
+++ b/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/test/cpp11-migrate/UseAuto/iterator.cpp b/test/cpp11-migrate/UseAuto/iterator.cpp
new file mode 100644
index 00000000..a6d00c7b
--- /dev/null
+++ b/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;
+}