diff options
author | Ville Voutilainen <ville.voutilainen@gmail.com> | 2018-04-05 17:37:18 +0300 |
---|---|---|
committer | Ville Voutilainen <ville@gcc.gnu.org> | 2018-04-05 17:37:18 +0300 |
commit | 0fb90182d8698bf65774f25431567cd70be25faf (patch) | |
tree | 7ac1a0f9796b1dad39846a5caebc5f8dd9f53e12 | |
parent | e99d77c97fbee5c17594374b978a0c4f9cd125f4 (diff) | |
download | gcc-0fb90182d8698bf65774f25431567cd70be25faf.zip gcc-0fb90182d8698bf65774f25431567cd70be25faf.tar.gz gcc-0fb90182d8698bf65774f25431567cd70be25faf.tar.bz2 |
Implement P0961
gcc/cp
Implement P0961
* decl.c (get_tuple_decomp_init): Check the templatedness
of a member get.
testsuite/
Implement P0961
* g++.dg/cpp1z/decomp10.C: Adjust.
* g++.dg/cpp1z/decomp37.C: New.
From-SVN: r259128
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/decl.c | 22 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1z/decomp10.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1z/decomp37.C | 62 |
4 files changed, 90 insertions, 2 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 99ec3ea..0901906 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2018-04-05 Ville Voutilainen <ville.voutilainen@gmail.com> + + Implement P0961 + * decl.c (get_tuple_decomp_init): Check the templatedness + of a member get. + 2018-04-05 Jason Merrill <jason@redhat.com> PR c++/85200 - ICE with constexpr if in generic lambda. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 746084c..31d9c98 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -7432,7 +7432,27 @@ get_tuple_decomp_init (tree decl, unsigned i) tree fns = lookup_qualified_name (TREE_TYPE (e), get_id, /*type*/false, /*complain*/false); - if (fns != error_mark_node) + bool use_member_get = false; + + /* To use a member get, member lookup must find at least one + declaration that is a function template + whose first template parameter is a non-type parameter. */ + for (lkp_iterator iter (MAYBE_BASELINK_FUNCTIONS (fns)); iter; ++iter) + { + tree fn = *iter; + if (TREE_CODE (fn) == TEMPLATE_DECL) + { + tree tparms = DECL_TEMPLATE_PARMS (fn); + tree parm = TREE_VEC_ELT (INNERMOST_TEMPLATE_PARMS (tparms), 0); + if (TREE_CODE (TREE_VALUE (parm)) == PARM_DECL) + { + use_member_get = true; + break; + } + } + } + + if (use_member_get) { fns = lookup_template_function (fns, targs); return build_new_method_call (e, fns, /*args*/NULL, diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp10.C b/gcc/testsuite/g++.dg/cpp1z/decomp10.C index 6ed9272..b4169d3 100644 --- a/gcc/testsuite/g++.dg/cpp1z/decomp10.C +++ b/gcc/testsuite/g++.dg/cpp1z/decomp10.C @@ -20,7 +20,7 @@ void f3() { auto [ x ] = a3; } // { dg-error "get" } struct A3a { int i,j; int get(); } a3a; template<> struct std::tuple_size<A3a> { enum { value = 1 }; }; -void f3a() { auto [ x ] = a3a; } // { dg-error "get<0>" } +void f3a() { auto [ x ] = a3a; } // { dg-error "get" } struct A3b { int i,j; } a3b; int get(A3b&&); diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp37.C b/gcc/testsuite/g++.dg/cpp1z/decomp37.C new file mode 100644 index 0000000..dc47908 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/decomp37.C @@ -0,0 +1,62 @@ +// { dg-additional-options -std=c++17 } +// { dg-do compile } + +#include <memory> +#include <tuple> +#include <string> + +struct X : private std::shared_ptr<int> +{ + std::string fun_payload; +}; + +template<int N> std::string& get(X& x) +{ + if constexpr(N==0) return x.fun_payload; +} + +namespace std { + template<> class tuple_size<X> : public std::integral_constant<int, 1> {}; + template<> class tuple_element<0, X> {public: using type = std::string;}; +} + +struct X2 : private std::shared_ptr<int> +{ + int fun_payload; + template <class T> void get(); +}; + +template<int N> int& get(X2& x) +{ + if constexpr(N==0) return x.fun_payload; +} + +namespace std { + template<> class tuple_size<X2> : public std::integral_constant<int, 1> {}; + template<> class tuple_element<0, X2> {public: using type = int;}; +} + +class X3 +{ + double fun_payload; +public: + template <int N> double& get() + { + if constexpr(N==0) return fun_payload; + } +}; + +namespace std { + template<> class tuple_size<X3> : public std::integral_constant<int, 1> {}; + template<> class tuple_element<0, X3> {public: using type = double;}; +} + +int main() +{ + X x; + auto& [b1] = x; + X2 x2; + auto& [b2] = x2; + X3 x3; + auto& [b3] = x3; +} |