aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVille Voutilainen <ville.voutilainen@gmail.com>2018-04-05 17:37:18 +0300
committerVille Voutilainen <ville@gcc.gnu.org>2018-04-05 17:37:18 +0300
commit0fb90182d8698bf65774f25431567cd70be25faf (patch)
tree7ac1a0f9796b1dad39846a5caebc5f8dd9f53e12
parente99d77c97fbee5c17594374b978a0c4f9cd125f4 (diff)
downloadgcc-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/ChangeLog6
-rw-r--r--gcc/cp/decl.c22
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp10.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp37.C62
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;
+}