From 86089be5e1d4ac721b0b161877368eaca237b96f Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Mon, 5 Nov 2007 18:42:22 +0000 Subject: [PATCH] Index... Index: testsuite/g++.dg/cpp0x/pr33996.C =================================================================== --- testsuite/g++.dg/cpp0x/pr33996.C (revision 0) +++ testsuite/g++.dg/cpp0x/pr33996.C (revision 0) @@ -0,0 +1,52 @@ +// { dg-options "-std=c++0x" } + +#define BUG +struct type +{ + type() { } + type(const type&) { } + +private: + type(type&&); +}; + +template + struct identity + { + typedef _Tp type; + }; + +template + inline _Tp&& + forward(typename identity<_Tp>::type&& __t) + { return __t; } + +struct vec +{ + template + void + bar(_Args&& __args) +#ifdef BUG + ; +#else + { + type(forward<_Args>(__args)); + } +#endif +}; + +#ifdef BUG +template + void + vec::bar(_Args&& __args) + { + type(forward<_Args>(__args)); + } +#endif + +int main() +{ + vec v; + type c; + v.bar(c); +} Index: testsuite/g++.dg/cpp0x/rv-trivial-bug.C =================================================================== --- testsuite/g++.dg/cpp0x/rv-trivial-bug.C (revision 0) +++ testsuite/g++.dg/cpp0x/rv-trivial-bug.C (revision 0) @@ -0,0 +1,33 @@ +// { dg-do "run" } +// { dg-options "-std=c++0x" } +// PR c++/33235 +#include + +int move_construct = 0; +int move_assign = 0; + +struct base2 +{ + base2() {} + base2(base2&&) {++move_construct;} + base2& operator=(base2&&) {++move_assign; return *this;} +}; + +int test2() +{ + base2 b; + base2 b2(b); + assert(move_construct == 0); + base2 b3(static_cast(b)); + assert(move_construct == 1); + b = b2; + assert(move_assign == 0); + b = static_cast(b2); + assert(move_assign == 1); +} + +int main() +{ + test2(); + return 0; +} Index: testsuite/g++.dg/cpp0x/pr33930.C =================================================================== --- testsuite/g++.dg/cpp0x/pr33930.C (revision 0) +++ testsuite/g++.dg/cpp0x/pr33930.C (revision 0) @@ -0,0 +1,10 @@ +// { dg-options "-std=c++0x" } +typedef const int* type; + +float& foo( const type& ggg ); +int& foo( type&& ggg ); + +void bar( int* someptr ) +{ + int& x = foo( someptr ); +} Index: cp/typeck.c =================================================================== --- cp/typeck.c (revision 129899) +++ cp/typeck.c (working copy) @@ -620,7 +620,7 @@ merge_types (tree t1, tree t2) if (code1 == POINTER_TYPE) t1 = build_pointer_type (target); else - t1 = build_reference_type (target); + t1 = cp_build_reference_type (target, TYPE_REF_IS_RVALUE (t1)); t1 = build_type_attribute_variant (t1, attributes); t1 = cp_build_qualified_type (t1, quals); Index: cp/call.c =================================================================== --- cp/call.c (revision 129899) +++ cp/call.c (working copy) @@ -5076,7 +5076,8 @@ build_over_call (struct z_candidate *can return build_target_expr_with_type (arg, DECL_CONTEXT (fn)); } else if (TREE_CODE (arg) == TARGET_EXPR - || TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn))) + || (TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)) + && !move_fn_p (fn))) { tree to = stabilize_reference (build_indirect_ref (TREE_VALUE (args), 0)); @@ -6118,7 +6119,11 @@ compare_ics (conversion *ics1, conversio if (ics1->kind == ck_qual && ics2->kind == ck_qual && same_type_p (from_type1, from_type2)) - return comp_cv_qual_signature (to_type1, to_type2); + { + int result = comp_cv_qual_signature (to_type1, to_type2); + if (result != 0) + return result; + } /* [over.ics.rank] From-SVN: r129905 --- gcc/cp/ChangeLog | 12 +++++ gcc/cp/call.c | 9 +++- gcc/cp/typeck.c | 2 +- gcc/testsuite/ChangeLog | 9 ++++ gcc/testsuite/g++.dg/cpp0x/pr33930.C | 10 ++++ gcc/testsuite/g++.dg/cpp0x/pr33996.C | 52 +++++++++++++++++++++ gcc/testsuite/g++.dg/cpp0x/rv-trivial-bug.C | 33 +++++++++++++ 7 files changed, 124 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/pr33930.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/pr33996.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/rv-trivial-bug.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8923b24a21f..36b7726ee5b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,15 @@ +2007-11-05 Douglas Gregor + + PR c++/33996 + PR c++/33235 + PR c++/33930 + * typeck.c (merge_types): Don't lose rvalue references when + merging types. + * call.c (build_over_call): Don't elide move constructors just + because the copy constructor is trivial (!). + (compare_ics): If comparing cv-qualifiers fails, we can still order + based on binding lvalues vs. rvalues. + 2007-11-05 Douglas Gregor PR c++/33939 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 297a3724201..e9d3a94aa41 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -5076,7 +5076,8 @@ build_over_call (struct z_candidate *cand, int flags) return build_target_expr_with_type (arg, DECL_CONTEXT (fn)); } else if (TREE_CODE (arg) == TARGET_EXPR - || TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn))) + || (TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)) + && !move_fn_p (fn))) { tree to = stabilize_reference (build_indirect_ref (TREE_VALUE (args), 0)); @@ -6118,7 +6119,11 @@ compare_ics (conversion *ics1, conversion *ics2) if (ics1->kind == ck_qual && ics2->kind == ck_qual && same_type_p (from_type1, from_type2)) - return comp_cv_qual_signature (to_type1, to_type2); + { + int result = comp_cv_qual_signature (to_type1, to_type2); + if (result != 0) + return result; + } /* [over.ics.rank] diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 17bb6b68ce0..862787a10c8 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -620,7 +620,7 @@ merge_types (tree t1, tree t2) if (code1 == POINTER_TYPE) t1 = build_pointer_type (target); else - t1 = build_reference_type (target); + t1 = cp_build_reference_type (target, TYPE_REF_IS_RVALUE (t1)); t1 = build_type_attribute_variant (t1, attributes); t1 = cp_build_qualified_type (t1, quals); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6f505ed7a9a..6f7718aaac9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2007-11-05 Douglas Gregor + + PR c++/33996 + PR c++/33235 + PR c++/33930 + * g++.dg/cpp0x/pr33996.C: New + * g++.dg/cpp0x/rv-trivial-bug.C: New + * g++.dg/cpp0x/pr33930.C: New + 2007-11-05 Nick Clifton Sebastian Pop diff --git a/gcc/testsuite/g++.dg/cpp0x/pr33930.C b/gcc/testsuite/g++.dg/cpp0x/pr33930.C new file mode 100644 index 00000000000..d1e6fa56b1d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr33930.C @@ -0,0 +1,10 @@ +// { dg-options "-std=c++0x" } +typedef const int* type; + +float& foo( const type& ggg ); +int& foo( type&& ggg ); + +void bar( int* someptr ) +{ + int& x = foo( someptr ); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/pr33996.C b/gcc/testsuite/g++.dg/cpp0x/pr33996.C new file mode 100644 index 00000000000..07590f06f95 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr33996.C @@ -0,0 +1,52 @@ +// { dg-options "-std=c++0x" } + +#define BUG +struct type +{ + type() { } + type(const type&) { } + +private: + type(type&&); +}; + +template + struct identity + { + typedef _Tp type; + }; + +template + inline _Tp&& + forward(typename identity<_Tp>::type&& __t) + { return __t; } + +struct vec +{ + template + void + bar(_Args&& __args) +#ifdef BUG + ; +#else + { + type(forward<_Args>(__args)); + } +#endif +}; + +#ifdef BUG +template + void + vec::bar(_Args&& __args) + { + type(forward<_Args>(__args)); + } +#endif + +int main() +{ + vec v; + type c; + v.bar(c); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-trivial-bug.C b/gcc/testsuite/g++.dg/cpp0x/rv-trivial-bug.C new file mode 100644 index 00000000000..de52d0f48f6 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/rv-trivial-bug.C @@ -0,0 +1,33 @@ +// { dg-do "run" } +// { dg-options "-std=c++0x" } +// PR c++/33235 +#include + +int move_construct = 0; +int move_assign = 0; + +struct base2 +{ + base2() {} + base2(base2&&) {++move_construct;} + base2& operator=(base2&&) {++move_assign; return *this;} +}; + +int test2() +{ + base2 b; + base2 b2(b); + assert(move_construct == 0); + base2 b3(static_cast(b)); + assert(move_construct == 1); + b = b2; + assert(move_assign == 0); + b = static_cast(b2); + assert(move_assign == 1); +} + +int main() +{ + test2(); + return 0; +}