Index: tools/clang/plugins/tests/base_passed.cpp |
diff --git a/tools/clang/plugins/tests/base_passed.cpp b/tools/clang/plugins/tests/base_passed.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..7dc65d14b442ed439cb7703cb18d46f7e36ed13c |
--- /dev/null |
+++ b/tools/clang/plugins/tests/base_passed.cpp |
@@ -0,0 +1,58 @@ |
+#define MOVE_ONLY_TYPE_FOR_CPP_03(type, rvalue_type) \ |
+ public: \ |
+ struct rvalue_type { \ |
+ explicit rvalue_type(type* object) : object(object) {} \ |
+ type* object; \ |
+ }; \ |
+ type(type&); \ |
+ void operator=(type&); \ |
+ operator rvalue_type() { return rvalue_type(this); } \ |
+ type Pass() { return type(rvalue_type(this)); } \ |
+ typedef void MoveOnlyTypeForCPP03; \ |
+ private: |
+ |
+namespace base { |
+template <class T> |
+class scoped_ptr { |
+ MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue) |
+ public: |
+ typedef T element_type; |
+ scoped_ptr() { } |
+ explicit scoped_ptr(element_type* p) { } |
+ scoped_ptr(RValue rvalue) { } |
+ template <typename U> |
+ scoped_ptr& operator=(scoped_ptr<U> rhs) { return *this; } |
+ element_type* get() const { return 0; } |
+}; |
+ |
+template <typename T> |
+static inline T Passed(T scoper) { |
+ return scoper.Pass(); |
+} |
+template <typename T> |
+static inline T Passed(T* scoper) { |
+ return scoper->Pass(); |
+} |
+ |
+} |
+ |
+void f_bad(base::scoped_ptr<int> i, int* p) {} |
+ |
+void f_ok(base::scoped_ptr<int> i) {} |
+ |
+int h_bad1(base::scoped_ptr<int> i) { return 0; } |
+int h_bad2(int* i) { return 0; } |
+int h(int a, int b) { return 0; } |
+ |
+void g() { |
+ base::scoped_ptr<int> s; |
+ |
+ f_bad(base::Passed(&s), s.get()); |
+ f_bad(base::Passed(s.Pass()), s.get()); |
+ |
+ // Shouldn't warn. |
+ f_ok(base::Passed(&s)); |
+ |
+ h(h_bad1(base::Passed(&s)), |
+ h_bad2(s.get())); |
+} |