diff options
author | JeanHeyd Meneide <phdofthehouse@gmail.com> | 2019-10-19 04:51:59 +0000 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2019-10-19 00:51:59 -0400 |
commit | 8ad0c477e888d34c8fc6dbcc008ef66505071d65 (patch) | |
tree | 9b2f5e5c5d3601b9c42221f4e30c262c62a681b4 /gcc/cp | |
parent | 9299523c9aad158f5276df2bfe777044bb144230 (diff) | |
download | gcc-8ad0c477e888d34c8fc6dbcc008ef66505071d65.zip gcc-8ad0c477e888d34c8fc6dbcc008ef66505071d65.tar.gz gcc-8ad0c477e888d34c8fc6dbcc008ef66505071d65.tar.bz2 |
Implement C++20 P1301 [[nodiscard("should have a reason")]].
2019-10-17 JeanHeyd Meneide <phdofthehouse@gmail.com>
gcc/
* escaped_string.h (escaped_string): New header.
* tree.c (escaped_string): Remove escaped_string class.
gcc/c-family
* c-lex.c (c_common_has_attribute): Update nodiscard value.
gcc/cp/
* tree.c (handle_nodiscard_attribute) Added C++2a nodiscard
string message.
(std_attribute_table) Increase nodiscard argument handling
max_length from 0 to 1.
* parser.c (cp_parser_check_std_attribute): Add requirement
that nodiscard only be seen once in attribute-list.
(cp_parser_std_attribute): Check that empty parenthesis lists are
not specified for attributes that have max_length > 0 (e.g.
[[attr()]]).
* cvt.c (maybe_warn_nodiscard): Add nodiscard message to
output, if applicable.
(convert_to_void): Allow constructors to be nodiscard-able (P1771).
gcc/testsuite/g++.dg/cpp0x
* gen-attrs-67.C: Test new error message for empty-parenthesis-list.
gcc/testsuite/g++.dg/cpp2a
* nodiscard-construct.C: New test.
* nodiscard-once.C: New test.
* nodiscard-reason-nonstring.C: New test.
* nodiscard-reason-only-one.C: New test.
* nodiscard-reason.C: New test.
Reviewed-by: Jason Merrill <jason@redhat.com>
From-SVN: r277200
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 36 | ||||
-rw-r--r-- | gcc/cp/parser.c | 15 | ||||
-rw-r--r-- | gcc/cp/tree.c | 9 |
4 files changed, 62 insertions, 14 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ba533d5f..30accc5 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,19 @@ +2019-10-17 JeanHeyd Meneide <phdofthehouse@gmail.com> + + Implement p1301 [[nodiscard("should have a reason")]] + p1771 DR + * tree.c (handle_nodiscard_attribute): Handle C++2a nodiscard + string message. + (std_attribute_table) Increase nodiscard argument handling + max_length from 0 to 1. + * parser.c (cp_parser_check_std_attribute): Add requirement + that nodiscard only be seen once in attribute-list. + (cp_parser_std_attribute): Check that empty parenthesis lists are + not specified for attributes that have max_length > 0 (e.g. + [[attr()]]). + * cvt.c (maybe_warn_nodiscard): Add nodiscard message to + output, if applicable. + (convert_to_void): Allow constructors to be nodiscard-able (P1771). + 2019-10-18 Nathan Sidwell <nathan@acm.org> * cp-tree.h (struct lang_type): Remove was_anonymous. diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 364af72..d41aeb8 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see #include "convert.h" #include "stringpool.h" #include "attribs.h" +#include "escaped_string.h" static tree convert_to_pointer_force (tree, tree, tsubst_flags_t); static tree build_type_conversion (tree, tree); @@ -1026,22 +1027,39 @@ maybe_warn_nodiscard (tree expr, impl_conv_void implicit) tree rettype = TREE_TYPE (type); tree fn = cp_get_fndecl_from_callee (callee); + tree attr; if (implicit != ICV_CAST && fn - && lookup_attribute ("nodiscard", DECL_ATTRIBUTES (fn))) + && (attr = lookup_attribute ("nodiscard", DECL_ATTRIBUTES (fn)))) { + escaped_string msg; + tree args = TREE_VALUE (attr); + if (args) + msg.escape (TREE_STRING_POINTER (TREE_VALUE (args))); + const char* format = (msg ? + G_("ignoring return value of %qD, " + "declared with attribute %<nodiscard%>: %<%s%>") : + G_("ignoring return value of %qD, " + "declared with attribute %<nodiscard%>%s")); + const char* raw_msg = msg ? msg : ""; auto_diagnostic_group d; - if (warning_at (loc, OPT_Wunused_result, - "ignoring return value of %qD, " - "declared with attribute nodiscard", fn)) + if (warning_at (loc, OPT_Wunused_result, format, fn, raw_msg)) inform (DECL_SOURCE_LOCATION (fn), "declared here"); } else if (implicit != ICV_CAST - && lookup_attribute ("nodiscard", TYPE_ATTRIBUTES (rettype))) + && (attr = lookup_attribute ("nodiscard", TYPE_ATTRIBUTES (rettype)))) { + escaped_string msg; + tree args = TREE_VALUE (attr); + if (args) + msg.escape (TREE_STRING_POINTER (TREE_VALUE (args))); + const char* format = msg ? + G_("ignoring returned value of type %qT, " + "declared with attribute %<nodiscard%>: %<%s%>") : + G_("ignoring returned value of type %qT, " + "declared with attribute %<nodiscard%>%s"); + const char* raw_msg = msg ? msg : ""; auto_diagnostic_group d; - if (warning_at (loc, OPT_Wunused_result, - "ignoring returned value of type %qT, " - "declared with attribute nodiscard", rettype)) + if (warning_at (loc, OPT_Wunused_result, format, rettype, raw_msg)) { if (fn) inform (DECL_SOURCE_LOCATION (fn), @@ -1180,7 +1198,7 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain) instantiations be affected by an ABI property that is, or at least ought to be transparent to the language. */ if (tree fn = cp_get_callee_fndecl_nofold (expr)) - if (DECL_CONSTRUCTOR_P (fn) || DECL_DESTRUCTOR_P (fn)) + if (DECL_DESTRUCTOR_P (fn)) return expr; maybe_warn_nodiscard (expr, implicit); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index b29ed0c..450b144 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -26551,6 +26551,11 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns) arguments = error_mark_node; else { + if (vec->is_empty()) + /* e.g. [[attr()]]. */ + error_at (token->location, "parentheses must be omitted if " + "%qE attribute argument list is empty", + attr_id); arguments = build_tree_list_vec (vec); release_tree_vector (vec); } @@ -26565,9 +26570,9 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns) } /* Check that the attribute ATTRIBUTE appears at most once in the - attribute-list ATTRIBUTES. This is enforced for noreturn (7.6.3) - and deprecated (7.6.5). Note that carries_dependency (7.6.4) - isn't implemented yet in GCC. */ + attribute-list ATTRIBUTES. This is enforced for noreturn (7.6.3), + nodiscard, and deprecated (7.6.5). Note that + carries_dependency (7.6.4) isn't implemented yet in GCC. */ static void cp_parser_check_std_attribute (tree attributes, tree attribute) @@ -26583,6 +26588,10 @@ cp_parser_check_std_attribute (tree attributes, tree attribute) && lookup_attribute ("deprecated", attributes)) error ("attribute %<deprecated%> can appear at most once " "in an attribute-list"); + else if (is_attribute_p ("nodiscard", name) + && lookup_attribute ("nodiscard", attributes)) + error ("attribute %<nodiscard%> can appear at most once " + "in an attribute-list"); } } diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 7f71891..a004bb1 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -4369,9 +4369,14 @@ zero_init_p (const_tree t) warn_unused_result attribute. */ static tree -handle_nodiscard_attribute (tree *node, tree name, tree /*args*/, +handle_nodiscard_attribute (tree *node, tree name, tree args, int /*flags*/, bool *no_add_attrs) { + if (args && TREE_CODE (TREE_VALUE (args)) != STRING_CST) + { + error ("%qE attribute argument must be a string constant", name); + *no_add_attrs = true; + } if (TREE_CODE (*node) == FUNCTION_DECL) { if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (*node))) @@ -4461,7 +4466,7 @@ const struct attribute_spec std_attribute_table[] = affects_type_identity, handler, exclude } */ { "maybe_unused", 0, 0, false, false, false, false, handle_unused_attribute, NULL }, - { "nodiscard", 0, 0, false, false, false, false, + { "nodiscard", 0, 1, false, false, false, false, handle_nodiscard_attribute, NULL }, { "no_unique_address", 0, 0, true, false, false, false, handle_no_unique_addr_attribute, NULL }, |