aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2018-11-05 02:47:05 -0500
committerJason Merrill <jason@gcc.gnu.org>2018-11-05 02:47:05 -0500
commitb008f16b7a279da845070dce786ea3afd5925364 (patch)
treefecb35ba45ea46dcb0a2b02194e8b1b54ed0e467 /gcc
parent4be5c72cf3ea3ee98a97ac2e53d21122ad224b10 (diff)
downloadgcc-b008f16b7a279da845070dce786ea3afd5925364.zip
gcc-b008f16b7a279da845070dce786ea3afd5925364.tar.gz
gcc-b008f16b7a279da845070dce786ea3afd5925364.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/cp-tree.h28
-rw-r--r--gcc/cp/mangle.c24
-rw-r--r--gcc/cp/parser.c70
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-overflow.C36
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/pr58708.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/pr59867.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/udlit-char-template-sfinae.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/udlit-char-template-vs-std-literal-operator.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/udlit-char-template.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/udlit-char-template2.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/nontype-class6.C17
12 files changed, 121 insertions, 69 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 95149b1..b0dc668 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,14 @@
2018-11-04 Jason Merrill <jason@redhat.com>
+ 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 61b431e..a895d00 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -871,6 +871,34 @@ struct named_decl_hash : ggc_remove <tree>
static void mark_deleted (value_type) { gcc_unreachable (); }
};
+/* Simplified unique_ptr clone to release a tree vec on exit. */
+
+struct releasing_vec
+{
+ typedef vec<tree, va_gc> 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 1b32301..b9d8ee2 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<tree, va_gc> 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 5ea8e8c..30a4766 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<tree, va_gc> *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<tree, va_gc> *&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 <char...>"
- " or <typename CharT, CharT...>",
+ if (cxx_dialect > cxx17)
+ error ("literal operator template %qD has invalid parameter list;"
+ " Expected non-type template parameter pack <char...> "
+ " 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 <char...>",
+ " Expected non-type template parameter pack <char...>",
decl);
}
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-overflow.C b/gcc/testsuite/g++.dg/cpp0x/udlit-overflow.C
index 057978c..1b9888b 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<char...>
- 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<char...>
+ 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 b46e54b..f1fc3b4 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<typename, typename>
struct is_same
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr59867.C b/gcc/testsuite/g++.dg/cpp1y/pr59867.C
index 2c4f1d0..ee468aa 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 a9c577f..b523858 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 <cassert>
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 6e3ffe4..c5a67c9 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 <cassert>
diff --git a/gcc/testsuite/g++.dg/cpp1y/udlit-char-template.C b/gcc/testsuite/g++.dg/cpp1y/udlit-char-template.C
index 989b9ba..6b7b5ec 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<typename CharT, CharT... String>
int
diff --git a/gcc/testsuite/g++.dg/cpp1y/udlit-char-template2.C b/gcc/testsuite/g++.dg/cpp1y/udlit-char-template2.C
index 06c1326..d3c4c67 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<class T, T... S> 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 0000000..246fab6
--- /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 <A a> constexpr A operator "" _sh() { return a; }
+
+constexpr auto a = "foo"_sh;
+static_assert (a.ar[0] == 'f');