From: Jason Merrill Date: Mon, 5 Nov 2018 07:47:05 +0000 (-0500) Subject: Implement UDL changes from P0732R2. X-Git-Tag: basepoints/gcc-10~3324 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b008f16b7a279da845070dce786ea3afd5925364;p=thirdparty%2Fgcc.git Implement UDL changes from P0732R2. Implementing the UDL changes was pretty straightforward; I simplified cp_parser_userdef_string_literal using the releasing_vec type from mangle.c. While looking at this, I realized that the string UDL template taking a character pack that we implemented for C++14 didn't actually make it into C++14, so I've added a pedwarn for it and no longer suggest it in the diagnostic about an invalid UDL template. * cp-tree.h (struct releasing_vec): Move from mangle.c. Add get_ref method. * parser.c (cp_parser_userdef_string_literal): Use it. Handle passing the string to a single template parameter of class type. (cp_parser_template_declaration_after_parameters): Allow it. Pedwarn about the character pack template that was proposed but not accepted for C++14, and don't suggest it. From-SVN: r265790 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 95149b19656a..b0dc668d9df4 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,14 @@ 2018-11-04 Jason Merrill + Implement UDL changes from P0732R2. + * cp-tree.h (struct releasing_vec): Move from mangle.c. + Add get_ref method. + * parser.c (cp_parser_userdef_string_literal): Use it. Handle + passing the string to a single template parameter of class type. + (cp_parser_template_declaration_after_parameters): Allow it. + Pedwarn about the character pack template that was proposed but not + accepted for C++14, and don't suggest it. + Implement P0732R2, class types in non-type template parameters. * error.c (dump_simple_decl): Look through a template parm object. * mangle.c (write_template_arg): Likewise. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 61b431e5f9d8..a895d0042aba 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -871,6 +871,34 @@ struct named_decl_hash : ggc_remove static void mark_deleted (value_type) { gcc_unreachable (); } }; +/* Simplified unique_ptr clone to release a tree vec on exit. */ + +struct releasing_vec +{ + typedef vec vec_t; + + releasing_vec (vec_t *v): v(v) { } + releasing_vec (): v(make_tree_vector ()) { } + + /* Copy ops are deliberately declared but not defined, + copies must always be elided. */ + releasing_vec (const releasing_vec &); + releasing_vec &operator= (const releasing_vec &); + + vec_t &operator* () const { return *v; } + vec_t *operator-> () const { return v; } + vec_t *get() const { return v; } + operator vec_t *() const { return v; } + tree& operator[] (unsigned i) const { return (*v)[i]; } + + /* Necessary for use with vec** and vec*& interfaces. */ + vec_t *&get_ref () { return v; } + + ~releasing_vec() { release_tree_vector (v); } +private: + vec_t *v; +}; + struct GTY(()) tree_template_decl { struct tree_decl_common common; tree arguments; diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 1b323015dedf..b9d8ee201160 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -1545,30 +1545,6 @@ write_abi_tags (tree tags) release_tree_vector (vec); } -/* Simplified unique_ptr clone to release a tree vec on exit. */ - -struct releasing_vec -{ - typedef vec vec_t; - - releasing_vec (vec_t *v): v(v) { } - releasing_vec (): v(make_tree_vector ()) { } - - /* Copy constructor is deliberately declared but not defined, - copies must always be elided. */ - releasing_vec (const releasing_vec &); - - vec_t &operator* () const { return *v; } - vec_t *operator-> () const { return v; } - vec_t *get () const { return v; } - operator vec_t *() const { return v; } - tree& operator[] (unsigned i) const { return (*v)[i]; } - - ~releasing_vec() { release_tree_vector (v); } -private: - vec_t *v; -}; - /* True iff the TREE_LISTS T1 and T2 of ABI tags are equivalent. */ static bool diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 5ea8e8ca0124..30a47662f556 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -4565,40 +4565,47 @@ cp_parser_userdef_string_literal (tree literal) tree value = USERDEF_LITERAL_VALUE (literal); int len = TREE_STRING_LENGTH (value) / TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (value)))) - 1; - tree decl, result; - vec *args; + tree decl; /* Build up a call to the user-defined operator. */ /* Lookup the name we got back from the id-expression. */ - args = make_tree_vector (); + releasing_vec rargs; + vec *&args = rargs.get_ref(); vec_safe_push (args, value); vec_safe_push (args, build_int_cst (size_type_node, len)); decl = lookup_literal_operator (name, args); if (decl && decl != error_mark_node) - { - result = finish_call_expr (decl, &args, false, true, - tf_warning_or_error); - release_tree_vector (args); - return result; - } - release_tree_vector (args); + return finish_call_expr (decl, &args, false, true, + tf_warning_or_error); - /* Look for a template function with typename parameter CharT - and parameter pack CharT... Call the function with - template parameter characters representing the string. */ - args = make_tree_vector (); + /* Look for a suitable template function, either (C++20) with a single + parameter of class type, or (N3599) with typename parameter CharT and + parameter pack CharT... */ + args->truncate (0); decl = lookup_literal_operator (name, args); if (decl && decl != error_mark_node) { - tree tmpl_args = make_string_pack (value); + /* Use resolve_nondeduced_context to try to choose one form of template + or the other. */ + tree tmpl_args = make_tree_vec (1); + TREE_VEC_ELT (tmpl_args, 0) = value; decl = lookup_template_function (decl, tmpl_args); - result = finish_call_expr (decl, &args, false, true, - tf_warning_or_error); - release_tree_vector (args); - return result; + tree res = resolve_nondeduced_context (decl, tf_none); + if (DECL_P (res)) + decl = res; + else + { + TREE_OPERAND (decl, 1) = make_string_pack (value); + res = resolve_nondeduced_context (decl, tf_none); + if (DECL_P (res)) + decl = res; + } + if (!DECL_P (decl) && cxx_dialect > cxx17) + TREE_OPERAND (decl, 1) = tmpl_args; + return finish_call_expr (decl, &args, false, true, + tf_warning_or_error); } - release_tree_vector (args); error ("unable to find string literal operator %qD with %qT, %qT arguments", name, TREE_TYPE (value), size_type_node); @@ -27222,8 +27229,12 @@ cp_parser_template_declaration_after_parameters (cp_parser* parser, { tree parm_list = TREE_VEC_ELT (parameter_list, 0); tree parm = INNERMOST_TEMPLATE_PARMS (parm_list); - if (TREE_TYPE (parm) != char_type_node - || !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))) + if (CLASS_TYPE_P (TREE_TYPE (parm))) + /* OK, C++20 string literal operator template. We don't need + to warn in lower dialects here because we will have already + warned about the template parameter. */; + else if (TREE_TYPE (parm) != char_type_node + || !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))) ok = false; } else if (num_parms == 2 && cxx_dialect >= cxx14) @@ -27236,20 +27247,25 @@ cp_parser_template_declaration_after_parameters (cp_parser* parser, || TREE_TYPE (parm) != TREE_TYPE (type) || !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))) ok = false; + else + /* http://cplusplus.github.io/EWG/ewg-active.html#66 */ + pedwarn (DECL_SOURCE_LOCATION (decl), OPT_Wpedantic, + "ISO C++ did not adopt string literal operator templa" + "tes taking an argument pack of characters"); } else ok = false; } if (!ok) { - if (cxx_dialect >= cxx14) - error ("literal operator template %qD has invalid parameter list." - " Expected non-type template argument pack " - " or ", + if (cxx_dialect > cxx17) + error ("literal operator template %qD has invalid parameter list;" + " Expected non-type template parameter pack " + " or single non-type parameter of class type", decl); else error ("literal operator template %qD has invalid parameter list." - " Expected non-type template argument pack ", + " Expected non-type template parameter pack ", decl); } } diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-overflow.C b/gcc/testsuite/g++.dg/cpp0x/udlit-overflow.C index 057978c32752..1b9888b7159d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-overflow.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-overflow.C @@ -1,19 +1,19 @@ // { dg-do compile { target c++11 } } -// PR c++/52654 - -int -operator"" _w(const char*) -{ return 0; } - -template - int - operator"" _tw() - { return 0; } - -int i = 12345678901234567890123456789012345678901234567890_w; -int j = 12345678901234567890123456789.012345678901234567890e+1234567890_w; -int k = 12345678901234567890123456789.012345678901234567890e-1234567890_w; - -int ti = 12345678901234567890123456789012345678901234567890_tw; -int tj = 12345678901234567890123456789.012345678901234567890e+1234567890_tw; -int tk = 12345678901234567890123456789.012345678901234567890e-1234567890_tw; +// PR c++/52654 + +int +operator"" _w(const char*) +{ return 0; } + +template + int + operator"" _tw() + { return 0; } + +int i = 12345678901234567890123456789012345678901234567890_w; +int j = 12345678901234567890123456789.012345678901234567890e+1234567890_w; +int k = 12345678901234567890123456789.012345678901234567890e-1234567890_w; + +int ti = 12345678901234567890123456789012345678901234567890_tw; +int tj = 12345678901234567890123456789.012345678901234567890e+1234567890_tw; +int tk = 12345678901234567890123456789.012345678901234567890e-1234567890_tw; diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58708.C b/gcc/testsuite/g++.dg/cpp1y/pr58708.C index b46e54bbca3e..f1fc3b462276 100644 --- a/gcc/testsuite/g++.dg/cpp1y/pr58708.C +++ b/gcc/testsuite/g++.dg/cpp1y/pr58708.C @@ -1,4 +1,5 @@ // { dg-do run { target c++14 } } +// { dg-options -w } template struct is_same diff --git a/gcc/testsuite/g++.dg/cpp1y/pr59867.C b/gcc/testsuite/g++.dg/cpp1y/pr59867.C index 2c4f1d046bf3..ee468aabb2b4 100644 --- a/gcc/testsuite/g++.dg/cpp1y/pr59867.C +++ b/gcc/testsuite/g++.dg/cpp1y/pr59867.C @@ -1,5 +1,6 @@ // PR c++/59867 // { dg-do compile { target c++14 } } +// { dg-options -w } using namespace std; diff --git a/gcc/testsuite/g++.dg/cpp1y/udlit-char-template-sfinae.C b/gcc/testsuite/g++.dg/cpp1y/udlit-char-template-sfinae.C index a9c577fd110f..b523858e9c09 100644 --- a/gcc/testsuite/g++.dg/cpp1y/udlit-char-template-sfinae.C +++ b/gcc/testsuite/g++.dg/cpp1y/udlit-char-template-sfinae.C @@ -1,4 +1,5 @@ // { dg-do run { target c++14 } } +// { dg-options -w } #include diff --git a/gcc/testsuite/g++.dg/cpp1y/udlit-char-template-vs-std-literal-operator.C b/gcc/testsuite/g++.dg/cpp1y/udlit-char-template-vs-std-literal-operator.C index 6e3ffe4ecd35..c5a67c96cf6b 100644 --- a/gcc/testsuite/g++.dg/cpp1y/udlit-char-template-vs-std-literal-operator.C +++ b/gcc/testsuite/g++.dg/cpp1y/udlit-char-template-vs-std-literal-operator.C @@ -1,4 +1,5 @@ // { dg-do run { target c++14 } } +// { dg-options -w } #include diff --git a/gcc/testsuite/g++.dg/cpp1y/udlit-char-template.C b/gcc/testsuite/g++.dg/cpp1y/udlit-char-template.C index 989b9babd1f6..6b7b5ecec6ff 100644 --- a/gcc/testsuite/g++.dg/cpp1y/udlit-char-template.C +++ b/gcc/testsuite/g++.dg/cpp1y/udlit-char-template.C @@ -1,4 +1,5 @@ // { dg-do compile { target c++14 } } +// { dg-options -w } template int diff --git a/gcc/testsuite/g++.dg/cpp1y/udlit-char-template2.C b/gcc/testsuite/g++.dg/cpp1y/udlit-char-template2.C index 06c13261156e..d3c4c67ea26b 100644 --- a/gcc/testsuite/g++.dg/cpp1y/udlit-char-template2.C +++ b/gcc/testsuite/g++.dg/cpp1y/udlit-char-template2.C @@ -1,5 +1,6 @@ // PR c++/85864 // { dg-do compile { target c++14 } } +// { dg-options -w } template struct String_template {}; diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class6.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class6.C new file mode 100644 index 000000000000..246fab6c1786 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class6.C @@ -0,0 +1,17 @@ +// { dg-do compile { target c++2a } } + +struct A { + char ar[10]; + constexpr A (const char *p) : ar() + { + for (int i = 0; i < 10; ++i) + if ((ar[i] = p[i]) == 0) + break; + } + // auto operator<=> (const A&) = default; +}; + +template constexpr A operator "" _sh() { return a; } + +constexpr auto a = "foo"_sh; +static_assert (a.ar[0] == 'f');