From 05119c345797bc04cc34e6973ebd921b4dcb0326 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 9 Nov 2022 11:39:22 +0100 Subject: [PATCH] c++: Minimal handling of carries_dependency attribute A comment in D2552R1: "The only questionable (but still conforming) case we found was [[carries_dependency(some_argument)]] on GCC, where the emitted diagnostic said that the carries_dependency attribute is not supported, but did not specifically call out the syntax error in the argument clause." made me try the following patch, where we'll error at least for arguments to the attribute and for some uses of the attribute appertaining to something not mentioned in the standard warn with different diagnostics (or should that be an error?; clang++ does that, but I think we never do for any attribute, standard or not). The diagnostics on toplevel attribute declaration is still an attribute ignored warning and on empty statement different wording. The paper additionally mentions struct X { [[nodiscard]]; }; // no diagnostic on GCC and 2 cases of missing diagnostics on [[fallthrough]] (guess I should file a PR about those; one problem is that do { ... } while (0); there is replaced during genericization just by ... and another that [[fallthrough]] there is followed by a label, but not user/case/default label, but an artificial one created from while loop genericization. 2022-11-09 Jakub Jelinek * tree.cc (handle_carries_dependency_attribute): New function. (std_attribute_table): Add carries_dependency attribute. * parser.cc (cp_parser_check_std_attribute): Add carries_dependency attribute. * g++.dg/cpp0x/attr-carries_dependency1.C: New test. --- gcc/cp/parser.cc | 5 ++-- gcc/cp/tree.cc | 28 +++++++++++++++++++ .../g++.dg/cpp0x/attr-carries_dependency1.C | 17 +++++++++++ 3 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/attr-carries_dependency1.C diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 9523f73d9a3..e4021835ed5 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -29239,8 +29239,7 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns) /* Warn if the attribute ATTRIBUTE appears more than once in the attribute-list ATTRIBUTES. This used to be enforced for certain - attributes, but the restriction was removed in P2156. Note that - carries_dependency ([dcl.attr.depend]) isn't implemented yet in GCC. + attributes, but the restriction was removed in P2156. LOC is the location of ATTRIBUTE. Returns true if ATTRIBUTE was not found in ATTRIBUTES. */ @@ -29249,7 +29248,7 @@ cp_parser_check_std_attribute (location_t loc, tree attributes, tree attribute) { static auto alist = { "noreturn", "deprecated", "nodiscard", "maybe_unused", "likely", "unlikely", "fallthrough", - "no_unique_address" }; + "no_unique_address", "carries_dependency" }; if (attributes) for (const auto &a : alist) if (is_attribute_p (a, get_attribute_name (attribute)) diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc index c30bbeb0839..954c6de2fcd 100644 --- a/gcc/cp/tree.cc +++ b/gcc/cp/tree.cc @@ -4923,6 +4923,32 @@ structural_type_p (tree t, bool explain) return true; } +/* Partially handle the C++11 [[carries_dependency]] attribute. + Just emit a different diagnostics when it is used on something the + spec doesn't allow vs. where it allows and we just choose to ignore + it. */ + +static tree +handle_carries_dependency_attribute (tree *node, tree name, + tree ARG_UNUSED (args), + int ARG_UNUSED (flags), + bool *no_add_attrs) +{ + if (TREE_CODE (*node) != FUNCTION_DECL + && TREE_CODE (*node) != PARM_DECL) + { + warning (OPT_Wattributes, "%qE attribute can only be applied to " + "functions or parameters", name); + *no_add_attrs = true; + } + else + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + return NULL_TREE; +} + /* Handle the C++17 [[nodiscard]] attribute, which is similar to the GNU warn_unused_result attribute. */ @@ -5036,6 +5062,8 @@ const struct attribute_spec std_attribute_table[] = handle_likeliness_attribute, attr_cold_hot_exclusions }, { "noreturn", 0, 0, true, false, false, false, handle_noreturn_attribute, attr_noreturn_exclusions }, + { "carries_dependency", 0, 0, true, false, false, false, + handle_carries_dependency_attribute, NULL }, { NULL, 0, 0, false, false, false, false, NULL, NULL } }; diff --git a/gcc/testsuite/g++.dg/cpp0x/attr-carries_dependency1.C b/gcc/testsuite/g++.dg/cpp0x/attr-carries_dependency1.C new file mode 100644 index 00000000000..bf0f9cb3645 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/attr-carries_dependency1.C @@ -0,0 +1,17 @@ +// { dg-do compile { target c++11 } } + +[[carries_dependency]] int *f1 (); // { dg-warning "attribute ignored" } +int f2 (int *x [[carries_dependency]]); // { dg-warning "attribute ignored" } +[[carries_dependency]] int f3 (); // { dg-warning "attribute ignored" } +int f4 (int x [[carries_dependency]]); // { dg-warning "attribute ignored" } +[[carries_dependency(1)]] int f5 (); // { dg-error "'carries_dependency' attribute does not take any arguments" } +[[carries_dependency]] int v; // { dg-warning "'carries_dependency' attribute can only be applied to functions or parameters" } +[[carries_dependency]]; // { dg-warning "attribute ignored" } +void +f6 () +{ + [[carries_dependency]]; // { dg-warning "attributes at the beginning of statement are ignored" } +} +#if __has_cpp_attribute(carries_dependency) +#error carries_dependency attribute is not actually implemented +#endif