diff options
author | Edwin Vane <edwin.vane@intel.com> | 2013-07-03 13:21:24 +0000 |
---|---|---|
committer | Edwin Vane <edwin.vane@intel.com> | 2013-07-03 13:21:24 +0000 |
commit | 5ee6110817632f0e883305ad9f17ce850e96c83e (patch) | |
tree | b68deea8c56b29c1edd883d8a153e6e19bb92ab0 /clang-tools-extra/test/cpp11-migrate | |
parent | 4eca75df00fe2e52b4be5ee4952872ec460641a2 (diff) | |
download | bcm5719-llvm-5ee6110817632f0e883305ad9f17ce850e96c83e.tar.gz bcm5719-llvm-5ee6110817632f0e883305ad9f17ce850e96c83e.zip |
cpp11-migrate: Add Replace-AutoPtr Transform
Add a new transform to replace uses of 'std::auto_ptr' by 'std::unique_ptr'.
Copy-ctor and assign-operator are wrapped with a call to 'std::move()'.
Note that until header modification is ready it is not that useful, that's why
it's marked as (EXPERIMENTAL) in the command line description and a "Known
Limitations" section is present in the transform documentation.
Author: Guillaume Papin <guillaume.papin@epitech.eu>
llvm-svn: 185535
Diffstat (limited to 'clang-tools-extra/test/cpp11-migrate')
5 files changed, 365 insertions, 0 deletions
diff --git a/clang-tools-extra/test/cpp11-migrate/ReplaceAutoPtr/Inputs/basic.h b/clang-tools-extra/test/cpp11-migrate/ReplaceAutoPtr/Inputs/basic.h new file mode 100644 index 00000000000..48b0ee4f67c --- /dev/null +++ b/clang-tools-extra/test/cpp11-migrate/ReplaceAutoPtr/Inputs/basic.h @@ -0,0 +1,56 @@ +#ifndef INPUTS_BASIC_H +#define INPUTS_BASIC_H + +#include "memory_stub.h" + +// Instrumentation for auto_ptr_ref test +// @{ +struct Base {}; +struct Derived : Base {}; +std::auto_ptr<Derived> create_derived_ptr(); +// CHECK: std::unique_ptr<Derived> create_derived_ptr(); +// } + +// Test function return values (declaration) +std::auto_ptr<char> f_5(); +// CHECK: std::unique_ptr<char> f_5() + +// Test function parameters +void f_6(std::auto_ptr<int>); +// CHECK: void f_6(std::unique_ptr<int>); +void f_7(const std::auto_ptr<int> &); +// CHECK: void f_7(const std::unique_ptr<int> &); + +// Test on record type fields +struct A { + std::auto_ptr<int> field; + // CHECK: std::unique_ptr<int> field; + + typedef std::auto_ptr<int> int_ptr_type; + // CHECK: typedef std::unique_ptr<int> int_ptr_type; +}; + +// Test template WITH instantiation +template <typename T> struct B { + typedef typename std::auto_ptr<T> created_type; + // CHECK: typedef typename std::unique_ptr<T> created_type; + + created_type create() { return std::auto_ptr<T>(new T()); } + // CHECK: created_type create() { return std::unique_ptr<T>(new T()); } +}; + +// Test 'using' in a namespace (declaration) +namespace ns_1 { +// Test multiple using declarations +using std::auto_ptr; +using std::auto_ptr; +// CHECK: using std::unique_ptr; +// CHECK-NEXT: using std::unique_ptr; +} + +namespace ns_2 { +template <typename T> struct auto_ptr {}; +// CHECK: template <typename T> struct auto_ptr {}; +} + +#endif // INPUTS_BASIC_H diff --git a/clang-tools-extra/test/cpp11-migrate/ReplaceAutoPtr/Inputs/memory_stub.h b/clang-tools-extra/test/cpp11-migrate/ReplaceAutoPtr/Inputs/memory_stub.h new file mode 100644 index 00000000000..89e4e0ec533 --- /dev/null +++ b/clang-tools-extra/test/cpp11-migrate/ReplaceAutoPtr/Inputs/memory_stub.h @@ -0,0 +1,61 @@ +//===-----------------------------------------------------------*- C++ -*--===// +// +// This file contains a shell implementation of the 'auto_ptr' type from the +// standard library. This shell aims to support the variations between standard +// library implementations. +// +// Variations for how 'auto_ptr' is presented: +// 1. Defined directly in namespace std +// 2. Use a versioned inline namespace in std (default on libc++). +// +// Use the preprocessor to define USE_INLINE_NAMESPACE=1 and use the second +// variation. +// +//===----------------------------------------------------------------------===// + +namespace std { + +#if USE_INLINE_NAMESPACE +inline namespace _1 { +#endif + +template <class Y> struct auto_ptr_ref { + Y *y_; +}; + +template <class X> class auto_ptr { +public: + typedef X element_type; + // D.10.1.1 construct/copy/destroy: + explicit auto_ptr(X *p = 0) throw() {} + auto_ptr(auto_ptr &) throw() {} + template <class Y> auto_ptr(auto_ptr<Y> &) throw() {} + auto_ptr &operator=(auto_ptr &) throw() { return *this; } + template <class Y> auto_ptr &operator=(auto_ptr<Y> &) throw() { + return *this; + } + auto_ptr &operator=(auto_ptr_ref<X> r) throw() { return *this; } + ~auto_ptr() throw() {} + // D.10.1.3 conversions: + auto_ptr(auto_ptr_ref<X> r) throw() : x_(r.y_) {} + template <class Y> operator auto_ptr_ref<Y>() throw() { + auto_ptr_ref<Y> r; + r.y_ = x_; + return r; + } + template <class Y> operator auto_ptr<Y>() throw() { return auto_ptr<Y>(x_); } + +private: + X *x_; +}; + +template <> class auto_ptr<void> { +public: + typedef void element_type; +}; + +#if USE_INLINE_NAMESPACE +} // namespace _1 +#endif + +} // end namespace std diff --git a/clang-tools-extra/test/cpp11-migrate/ReplaceAutoPtr/basic.cpp b/clang-tools-extra/test/cpp11-migrate/ReplaceAutoPtr/basic.cpp new file mode 100644 index 00000000000..690ede26533 --- /dev/null +++ b/clang-tools-extra/test/cpp11-migrate/ReplaceAutoPtr/basic.cpp @@ -0,0 +1,154 @@ +// RUN: mkdir -p %T/Inputs +// +// Without inline namespace: +// +// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp +// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/basic.h > %T/Inputs/basic.h +// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/memory_stub.h > %T/Inputs/memory_stub.h +// RUN: cpp11-migrate -headers -include=%T -replace-auto_ptr %t.cpp -- \ +// RUN: -std=c++11 -I %T +// RUN: FileCheck -input-file=%t.cpp %s +// RUN: FileCheck -input-file=%T/Inputs/basic.h %S/Inputs/basic.h +// +// With inline namespace: +// +// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp +// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/basic.h > %T/Inputs/basic.h +// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/memory_stub.h > %T/Inputs/memory_stub.h +// RUN: cpp11-migrate -headers -include=%T -replace-auto_ptr %t.cpp -- \ +// RUN: -DUSE_INLINE_NAMESPACE=1 -std=c++11 -I %T +// RUN: FileCheck -input-file=%t.cpp %s +// RUN: FileCheck -input-file=%T/Inputs/basic.h %S/Inputs/basic.h + +#include "Inputs/basic.h" + +void f_1() { + std::auto_ptr<int> a; + // CHECK: std::unique_ptr<int> a; + + // check that spaces aren't modified unnecessarily + std:: auto_ptr <int> b; + // CHECK: std:: unique_ptr <int> b; + std :: auto_ptr < char > c(new char()); + // CHECK: std :: unique_ptr < char > c(new char()); + + // Test construction from a temporary + std::auto_ptr<char> d = std::auto_ptr<char>(); + // CHECK: std::unique_ptr<char> d = std::unique_ptr<char>(); + + typedef std::auto_ptr<int> int_ptr_t; + // CHECK: typedef std::unique_ptr<int> int_ptr_t; + int_ptr_t e(new int()); + // CHECK: int_ptr_t e(new int()); + + // Test pointers + std::auto_ptr<int> *f; + // CHECK: std::unique_ptr<int> *f; + + // Test 'static' declarations + static std::auto_ptr<int> g; + // CHECK: static std::unique_ptr<int> g; + + // Test with cv-qualifiers + const std::auto_ptr<int> h; + // CHECK: const std::unique_ptr<int> h; + volatile std::auto_ptr<int> i; + // CHECK: volatile std::unique_ptr<int> i; + const volatile std::auto_ptr<int> j; + // CHECK: const volatile std::unique_ptr<int> j; + + // Test auto and initializer-list + auto k = std::auto_ptr<int>{}; + // CHECK: auto k = std::unique_ptr<int>{}; + std::auto_ptr<int> l{std::auto_ptr<int>()}; + // CHECK: std::unique_ptr<int> l{std::unique_ptr<int>()}; + + // Test interlocked auto_ptr + std::auto_ptr<std::auto_ptr<int> > m; + // CHECK: std::unique_ptr<std::unique_ptr<int> > m; + + // Test temporaries + std::auto_ptr<char>(); + // CHECK: std::unique_ptr<char>(); + + // Test void-specialization + std::auto_ptr<void> n; + // CHECK: std::unique_ptr<void> n; + + // Test template WITH instantiation (instantiation) + B<double> o; + std::auto_ptr<double> p(o.create()); + // CHECK: std::unique_ptr<double> p(o.create()); + + // Test 'using' in a namespace ("definition") + ns_1::auto_ptr<int> q; + // CHECK: ns_1::unique_ptr<int> q; + + // Test construction with an 'auto_ptr_ref' + std::auto_ptr<Base> r(create_derived_ptr()); + // CHECK: std::unique_ptr<Base> r(create_derived_ptr()); +} + +// Test without the nested name specifiers +void f_2() { + using namespace std; + + auto_ptr<int> a; + // CHECK: unique_ptr<int> a; +} + +// Test using declaration +void f_3() { + using std::auto_ptr; + // CHECK: using std::unique_ptr; + + auto_ptr<int> a; + // CHECK: unique_ptr<int> a; +} + +// Test messing-up with macros +void f_4() { +#define MACRO_1 <char> + std::auto_ptr MACRO_1 p(new char()); +// CHECK: std::unique_ptr MACRO_1 p(new char()); +#define MACRO_2 auto_ptr + std::MACRO_2<int> q; +// CHECK: #define MACRO_2 unique_ptr +#define MACRO_3(Type) std::auto_ptr<Type> + MACRO_3(float)r(new float()); +// CHECK: #define MACRO_3(Type) std::unique_ptr<Type> +#define MACRO_4 std::auto_ptr + using MACRO_4; +// CHECK: #define MACRO_4 std::unique_ptr +#undef MACRO_1 +#undef MACRO_2 +#undef MACRO_3 +#undef MACRO_4 +} + +// Test function return values (definition) +std::auto_ptr<char> f_5() +// CHECK: std::unique_ptr<char> f_5() +{ + // Test constructor + return std::auto_ptr<char>(new char()); + // CHECK: return std::unique_ptr<char>(new char()); +} + +// Test that non-std auto_ptr aren't replaced +void f_8() { + ns_2::auto_ptr<char> a; + // CHECK: ns_2::auto_ptr<char> a; + using namespace ns_2; + auto_ptr<int> b; + // CHECK: auto_ptr<int> b; +} + +namespace std { +template <typename T> using aaaaaaaa = auto_ptr<T>; +} +// We want to avoid replacing 'aaaaaaaa' by unique_ptr here. It's better to +// change the type alias directly. +// XXX: maybe another test will be more relevant to test this potential error. +std::aaaaaaaa<int> d; +// CHECK: std::aaaaaaaa<int> d; diff --git a/clang-tools-extra/test/cpp11-migrate/ReplaceAutoPtr/move.cpp b/clang-tools-extra/test/cpp11-migrate/ReplaceAutoPtr/move.cpp new file mode 100644 index 00000000000..d0e9ce14098 --- /dev/null +++ b/clang-tools-extra/test/cpp11-migrate/ReplaceAutoPtr/move.cpp @@ -0,0 +1,63 @@ +// Without inline namespace: +// +// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp +// RUN: cpp11-migrate -replace-auto_ptr %t.cpp -- -I %S/Inputs std=c++11 +// RUN: FileCheck -input-file=%t.cpp %s +// +// With inline namespace: +// +// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp +// RUN: cpp11-migrate -replace-auto_ptr %t.cpp -- -I %S/Inputs std=c++11 \ +// RUN: -DUSE_INLINE_NAMESPACE=1 +// RUN: FileCheck -input-file=%t.cpp %s + +#include "memory_stub.h" + +void takes_ownership_fn(std::auto_ptr<int> x); +// CHECK: void takes_ownership_fn(std::unique_ptr<int> x); + +std::auto_ptr<int> get_by_value(); +// CHECK: std::unique_ptr<int> get_by_value(); + +class Wrapper { +public: + std::auto_ptr<int> &get_wrapped(); + +private: + std::auto_ptr<int> wrapped; +}; + +void f() { + std::auto_ptr<int> a, b, c; + // CHECK: std::unique_ptr<int> a, b, c; + Wrapper wrapper_a, wrapper_b; + + a = b; + // CHECK: a = std::move(b); + + wrapper_a.get_wrapped() = wrapper_b.get_wrapped(); + // CHECK: wrapper_a.get_wrapped() = std::move(wrapper_b.get_wrapped()); + + // Test that 'std::move()' is inserted when call to the + // copy-constructor are made. + takes_ownership_fn(c); + // CHECK: takes_ownership_fn(std::move(c)); + takes_ownership_fn(wrapper_a.get_wrapped()); + // CHECK: takes_ownership_fn(std::move(wrapper_a.get_wrapped())); + + std::auto_ptr<int> d[] = { std::auto_ptr<int>(new int(1)), + std::auto_ptr<int>(new int(2)) }; + std::auto_ptr<int> e = d[0]; + // CHECK: std::unique_ptr<int> d[] = { std::unique_ptr<int>(new int(1)), + // CHECK-NEXT: std::unique_ptr<int>(new int(2)) }; + // CHECK-NEXT: std::unique_ptr<int> e = std::move(d[0]); + + // Test that std::move() is not used when assigning an rvalue + std::auto_ptr<int> f; + f = std::auto_ptr<int>(new int(0)); + // CHECK: std::unique_ptr<int> f; + // CHECK-NEXT: f = std::unique_ptr<int>(new int(0)); + + std::auto_ptr<int> g = get_by_value(); + // CHECK: std::unique_ptr<int> g = get_by_value(); +} diff --git a/clang-tools-extra/test/cpp11-migrate/ReplaceAutoPtr/template_fail.cpp b/clang-tools-extra/test/cpp11-migrate/ReplaceAutoPtr/template_fail.cpp new file mode 100644 index 00000000000..cdbf272c26b --- /dev/null +++ b/clang-tools-extra/test/cpp11-migrate/ReplaceAutoPtr/template_fail.cpp @@ -0,0 +1,31 @@ +// XFAIL: * +// +// Without inline namespace: +// +// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp +// RUN: cpp11-migrate -replace-auto_ptr %t.cpp -- -I %S/Inputs std=c++11 +// RUN: FileCheck -input-file=%t.cpp %s +// +// With inline namespace: +// +// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp +// RUN: cpp11-migrate -replace-auto_ptr %t.cpp -- -I %S/Inputs std=c++11 \ +// RUN: -DUSE_INLINE_NAMESPACE=1 +// RUN: FileCheck -input-file=%t.cpp %s + +#include "memory_stub.h" + +// Fail to modify when the template is never instantiated. +// +// This might not be an issue. If it's never used it doesn't really matter if +// it's changed or not. If it's a header and one of the source use it, then it +// will still be changed. +template <typename X> +void f() { + std::auto_ptr<X> p; + // CHECK: std::unique_ptr<X> p; +} + +// Alias template could be replaced if a matcher existed. +template <typename T> using aaaaaaaa = auto_ptr<T>; +// CHECK: template <typename T> using aaaaaaaa = unique_ptr<T>; |