Ping. On Mon, Oct 11, 2021 at 11:17:11AM -0400, Marek Polacek wrote: > Ping. > > On Tue, Sep 28, 2021 at 04:20:46PM -0400, Marek Polacek wrote: > > On Thu, Sep 23, 2021 at 02:25:16PM -0400, Jason Merrill wrote: > > > On 9/20/21 18:59, Marek Polacek via Gcc-patches wrote: > > > > +void > > > > +handle_ignored_attributes_option (vec<char *> *v) > > > > +{ > > > > + if (v == nullptr) > > > > + return; > > > > + > > > > + for (auto opt : v) > > > > + { > > > > + if (strcmp (opt, "clang") == 0) > > > > + { > > > > + // TODO > > > > + continue; > > > > + } > > > > > > If this doesn't work yet, let's not accept it at all for now. > > > > Ok. > > > > > > + char *q = strstr (opt, "::"); > > > > + /* We don't accept '::attr'. */ > > > > + if (q == nullptr || q == opt) > > > > + { > > > > + error ("wrong argument to ignored attributes"); > > > > + inform (input_location, "valid format is %<ns::attr%>, > > > > %<ns::%>, " > > > > + "or %<clang%>"); > > > > > > ...or even mention it. Users can ignore clang:: instead, it doesn't > > > matter > > > to us if clang attributes are misspelled. > > > > Removed. > > > > > > + continue; > > > > + } > > > > + /* Cut off the vendor part. */ > > > > + *q = '\0'; > > > > + char *vendor = opt; > > > > + char *attr = q + 2; > > > > + /* Verify that they look valid. */ > > > > + auto valid_p = [](const char *s) { > > > > + for (; *s != '\0'; ++s) > > > > + if (!ISALNUM (*s) && *s != '_') > > > > + return false; > > > > + return true; > > > > + }; > > > > + if (!valid_p (vendor) || !valid_p (attr)) > > > > + { > > > > + error ("wrong argument to ignored attributes"); > > > > + continue; > > > > + } > > > > + /* Turn "__attr__" into "attr" so that we have a canonical form > > > > of > > > > + attribute names. Likewise for vendor. */ > > > > + auto strip = [](char *&s) { > > > > + const size_t l = strlen (s); > > > > + if (l > 4 && s[0] == '_' && s[1] == '_' > > > > + && s[l - 1] == '_' && s[l - 2] == '_') > > > > + { > > > > + s[l - 2] = '\0'; > > > > + s += 2; > > > > + } > > > > + }; > > > > + strip (attr); > > > > + strip (vendor); > > > > + /* If we've already seen this vendor::attr, ignore it. > > > > Attempting to > > > > + register it twice would lead to a crash. */ > > > > + if (lookup_scoped_attribute_spec (get_identifier (vendor), > > > > + get_identifier (attr))) > > > > + continue; > > > > + /* In the "vendor::" case, we should ignore *any* attribute > > > > coming > > > > + from this attribute namespace. */ > > > > + const bool ignored_ns = attr[0] == '\0'; > > > > > > Maybe set attr to nullptr instead of declaring ignored_ns? > > > > > > > + /* Create a table with extra attributes which we will register. > > > > + We can't free it here, so squirrel away the pointers. */ > > > > + attribute_spec *table = new attribute_spec[2]; > > > > + ignored_attributes_table.safe_push (table); > > > > + table[0] = { ignored_ns ? nullptr : attr, 0, 0, false, false, > > > > > > ...so this can just use attr. > > > > I also need ignored_ns... > > > > > > + false, false, nullptr, nullptr }; > > > > + table[1] = { nullptr, 0, 0, false, false, false, false, nullptr, > > > > nullptr }; > > > > + register_scoped_attributes (table, vendor, ignored_ns); > > > > ...here, but I tweaked this a bit to get rid of the bool. > > > > > > + } > > > > +} > > > > + > > > > +/* Free data we might have allocated when adding extra attributes. */ > > > > + > > > > +void > > > > +free_attr_data () > > > > +{ > > > > + for (auto x : ignored_attributes_table) > > > > + delete[] x; > > > > +} > > > > > > You probably also want to zero out ignored_attributes_table at this point. > > > > Done. > > > > > > /* Initialize attribute tables, and make some sanity checks if > > > > checking is > > > > enabled. */ > > > > @@ -252,6 +353,9 @@ init_attributes (void) > > > > /* Put all the GNU attributes into the "gnu" namespace. */ > > > > register_scoped_attributes (attribute_tables[i], "gnu"); > > > > + vec<char *> *ignored = (vec<char *> *) flag_ignored_attributes; > > > > + handle_ignored_attributes_option (ignored); > > > > + > > > > invoke_plugin_callbacks (PLUGIN_ATTRIBUTES, NULL); > > > > attributes_initialized = true; > > > > } > > > > @@ -456,6 +560,19 @@ diag_attr_exclusions (tree last_decl, tree node, > > > > tree attrname, > > > > return found; > > > > } > > > > +/* Return true iff we should not complain about unknown attributes > > > > + coming from the attribute namespace NS. This is the case for > > > > + the -Wno-attributes=ns:: command-line option. */ > > > > + > > > > +static bool > > > > +attr_namespace_ignored_p (tree ns) > > > > +{ > > > > + if (ns == NULL_TREE) > > > > + return false; > > > > + scoped_attributes *r = find_attribute_namespace (IDENTIFIER_POINTER > > > > (ns)); > > > > + return r && r->ignored_p; > > > > +} > > > > + > > > > /* Process the attributes listed in ATTRIBUTES and install them in > > > > *NODE, > > > > which is either a DECL (including a TYPE_DECL) or a TYPE. If a > > > > DECL, > > > > it should be modified in place; if a TYPE, a copy should be created > > > > @@ -556,7 +673,8 @@ decl_attributes (tree *node, tree attributes, int > > > > flags, > > > > if (spec == NULL) > > > > { > > > > - if (!(flags & (int) ATTR_FLAG_BUILT_IN)) > > > > + if (!(flags & (int) ATTR_FLAG_BUILT_IN) > > > > + && !attr_namespace_ignored_p (ns)) > > > > { > > > > if (ns == NULL_TREE || !cxx11_attr_p) > > > > warning (OPT_Wattributes, "%qE attribute directive > > > > ignored", > > > > diff --git a/gcc/attribs.h b/gcc/attribs.h > > > > index 138c509bce1..96a527f67a9 100644 > > > > --- a/gcc/attribs.h > > > > +++ b/gcc/attribs.h > > > > @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see > > > > #define GCC_ATTRIBS_H > > > > extern const struct attribute_spec *lookup_attribute_spec > > > > (const_tree); > > > > +extern void free_attr_data (); > > > > extern void init_attributes (void); > > > > /* Process the attributes listed in ATTRIBUTES and install them in > > > > *NODE, > > > > @@ -40,12 +41,14 @@ extern void apply_tm_attr (tree, tree); > > > > extern tree make_attribute (const char *, const char *, tree); > > > > extern struct scoped_attributes* register_scoped_attributes (const > > > > struct attribute_spec *, > > > > - const char > > > > *); > > > > + const char > > > > *, > > > > + bool = > > > > false); > > > > extern char *sorted_attr_string (tree); > > > > extern bool common_function_versions (tree, tree); > > > > extern tree make_dispatcher_decl (const tree); > > > > extern bool is_function_default_version (const tree); > > > > +extern void handle_ignored_attributes_option (vec<char *> *); > > > > /* Return a type like TTYPE except that its TYPE_ATTRIBUTES > > > > is ATTRIBUTE. > > > > diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c > > > > index a9be8df0384..6beba5503f0 100644 > > > > --- a/gcc/c-family/c-pragma.c > > > > +++ b/gcc/c-family/c-pragma.c > > > > @@ -764,7 +764,7 @@ handle_pragma_diagnostic(cpp_reader > > > > *ARG_UNUSED(dummy)) > > > > if (token != CPP_NAME) > > > > { > > > > warning_at (loc, OPT_Wpragmas, > > > > - "missing [error|warning|ignored|push|pop]" > > > > + "missing > > > > [error|warning|ignored|push|pop|ignored_attributes]" > > > > " after %<#pragma GCC diagnostic%>"); > > > > return; > > > > } > > > > @@ -787,10 +787,43 @@ handle_pragma_diagnostic(cpp_reader > > > > *ARG_UNUSED(dummy)) > > > > diagnostic_pop_diagnostics (global_dc, input_location); > > > > return; > > > > } > > > > + else if (strcmp (kind_string, "ignored_attributes") == 0) > > > > + { > > > > + token = pragma_lex (&x, &loc); > > > > + if (token != CPP_STRING) > > > > + { > > > > + warning_at (loc, OPT_Wpragmas, > > > > + "missing attribute name after %<#pragma GCC > > > > diagnostic " > > > > + "ignored_attributes%>"); > > > > + return; > > > > + } > > > > + char *args = xstrdup (TREE_STRING_POINTER (x)); > > > > + const size_t l = strlen (args); > > > > + if (l == 0) > > > > + { > > > > + warning_at (loc, OPT_Wpragmas, "missing argument to %<#pragma > > > > GCC " > > > > + "diagnostic ignored_attributes%>"); > > > > + free (args); > > > > + return; > > > > + } > > > > + else if (args[l - 1] == ',') > > > > + { > > > > + warning_at (loc, OPT_Wpragmas, "trailing %<,%> in arguments > > > > for " > > > > + "%<#pragma GCC diagnostic ignored_attributes%>"); > > > > + free (args); > > > > + return; > > > > + } > > > > + auto_vec<char *> v; > > > > + for (char *p = strtok (args, ","); p; p = strtok (NULL, ",")) > > > > + v.safe_push (p); > > > > + handle_ignored_attributes_option (&v); > > > > + /* ??? We can't free (args); here. */ > > > > > > Perhaps we want to copy strings in handle_ignored_attributes_option rather > > > than here? > > > > Well, the other use doesn't need copying, so I left it be. > > > > > > + return; > > > > + } > > > > else > > > > { > > > > warning_at (loc, OPT_Wpragmas, > > > > - "expected [error|warning|ignored|push|pop]" > > > > + "expected > > > > [error|warning|ignored|push|pop|ignored_attributes]" > > > > " after %<#pragma GCC diagnostic%>"); > > > > return; > > > > } > > > > diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c > > > > index 771efa3eadf..345c8f9d620 100644 > > > > --- a/gcc/c/c-decl.c > > > > +++ b/gcc/c/c-decl.c > > > > @@ -12295,6 +12295,8 @@ c_parse_final_cleanups (void) > > > > c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t))); > > > > c_write_global_declarations_1 (BLOCK_VARS (ext_block)); > > > > + free_attr_data (); > > > > > > Since handle_ignored_attributes_option is in language-independent code, > > > shouldn't this call be as well? > > > > Good point, I've moved it into compile_file. I don't where else it could > > have gone. > > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? > > > > -- >8 -- > > It is desirable for -Wattributes to warn about e.g. > > > > [[deprecate]] void g(); // typo, should warn > > > > However, -Wattributes also warns about vendor-specific attributes > > (that's because lookup_scoped_attribute_spec -> find_attribute_namespace > > finds nothing), which, with -Werror, causes grief. We don't want the > > -Wattributes warning for > > > > [[company::attr]] void f(); > > > > GCC warns because it doesn't know the "company" namespace; it only knows > > the "gnu" and "omp" namespaces. We could entirely disable warning about > > attributes in unknown scopes but then the compiler would also miss typos > > like > > > > [[company::attrx]] void f(); > > > > or > > > > [[gmu::warn_used_result]] int write(); > > > > so that is not a viable solution. A workaround is to use a #pragma: > > > > #pragma GCC diagnostic push > > #pragma GCC diagnostic ignored "-Wattributes" > > [[company::attr]] void f() {} > > #pragma GCC diagnostic pop > > > > but that's a mouthful and awkward to use and could also hide typos. In > > fact, any macro-based solution doesn't seem like a way forward. > > > > This patch implements -Wno-attributes=, which takes these arguments: > > > > company::attr > > company:: > > > > This option should go well with using @file: the user could have a file > > containing > > -Wno-attributes=vendor::attr1,vendor::attr2 > > and then invoke gcc with '@attrs' or similar. > > > > I've also added a new pragma which has the same effect: > > > > The pragma along with the new option should help with various static > > analysis tools. > > > > PR c++/101940 > > > > gcc/ChangeLog: > > > > * attribs.c (struct scoped_attributes): Add a bool member. > > (lookup_scoped_attribute_spec): Forward declare. > > (register_scoped_attributes): New bool parameter, defaulted to > > false. Use it. > > (handle_ignored_attributes_option): New function. > > (free_attr_data): New function. > > (init_attributes): Call handle_ignored_attributes_option. > > (attr_namespace_ignored_p): New function. > > (decl_attributes): Check attr_namespace_ignored_p before > > warning. > > * attribs.h (free_attr_data): Declare. > > (register_scoped_attributes): Adjust declaration. > > (handle_ignored_attributes_option): Declare. > > * common.opt (Wattributes=): New option with a variable. > > * doc/extend.texi: Document #pragma GCC diagnostic ignored_attributes. > > * doc/invoke.texi: Document -Wno-attributes=. > > * opts.c (common_handle_option) <case OPT_Wattributes_>: Handle. > > * plugin.h (register_scoped_attributes): Adjust declaration. > > > > gcc/c-family/ChangeLog: > > > > * c-pragma.c (handle_pragma_diagnostic): Handle #pragma GCC diagnostic > > ignored_attributes. > > > > gcc/c/ChangeLog: > > > > * c-decl.c (c_parse_final_cleanups): Call free_attr_data. > > > > gcc/cp/ChangeLog: > > > > * decl2.c (c_parse_final_cleanups): Call free_attr_data. > > > > gcc/testsuite/ChangeLog: > > > > * c-c++-common/Wno-attributes-1.c: New test. > > * c-c++-common/Wno-attributes-2.c: New test. > > --- > > gcc/attribs.c | 120 +++++++++++++++++- > > gcc/attribs.h | 5 +- > > gcc/c-family/c-pragma.c | 37 +++++- > > gcc/common.opt | 9 +- > > gcc/doc/extend.texi | 19 +++ > > gcc/doc/invoke.texi | 20 +++ > > gcc/opts.c | 20 +++ > > gcc/plugin.h | 4 +- > > gcc/testsuite/c-c++-common/Wno-attributes-1.c | 55 ++++++++ > > gcc/testsuite/c-c++-common/Wno-attributes-2.c | 56 ++++++++ > > gcc/toplev.c | 2 + > > 11 files changed, 338 insertions(+), 9 deletions(-) > > create mode 100644 gcc/testsuite/c-c++-common/Wno-attributes-1.c > > create mode 100644 gcc/testsuite/c-c++-common/Wno-attributes-2.c > > > > diff --git a/gcc/attribs.c b/gcc/attribs.c > > index 83fafc98b7d..d5fba7f4bbb 100644 > > --- a/gcc/attribs.c > > +++ b/gcc/attribs.c > > @@ -87,6 +87,8 @@ struct scoped_attributes > > const char *ns; > > vec<attribute_spec> attributes; > > hash_table<attribute_hasher> *attribute_hash; > > + /* True if we should not warn about unknown attributes in this NS. */ > > + bool ignored_p; > > }; > > > > /* The table of scope attributes. */ > > @@ -95,6 +97,8 @@ static vec<scoped_attributes> attributes_table; > > static scoped_attributes* find_attribute_namespace (const char*); > > static void register_scoped_attribute (const struct attribute_spec *, > > scoped_attributes *); > > +static const struct attribute_spec *lookup_scoped_attribute_spec > > (const_tree, > > + const_tree); > > > > static bool attributes_initialized = false; > > > > @@ -121,12 +125,14 @@ extract_attribute_substring (struct substring *str) > > > > /* Insert an array of attributes ATTRIBUTES into a namespace. This > > array must be NULL terminated. NS is the name of attribute > > - namespace. The function returns the namespace into which the > > - attributes have been registered. */ > > + namespace. IGNORED_P is true iff all unknown attributes in this > > + namespace should be ignored for the purposes of -Wattributes. The > > + function returns the namespace into which the attributes have been > > + registered. */ > > > > scoped_attributes * > > register_scoped_attributes (const struct attribute_spec *attributes, > > - const char *ns) > > + const char *ns, bool ignored_p /*=false*/) > > { > > scoped_attributes *result = NULL; > > > > @@ -144,9 +150,12 @@ register_scoped_attributes (const struct > > attribute_spec *attributes, > > memset (&sa, 0, sizeof (sa)); > > sa.ns = ns; > > sa.attributes.create (64); > > + sa.ignored_p = ignored_p; > > result = attributes_table.safe_push (sa); > > result->attribute_hash = new hash_table<attribute_hasher> (200); > > } > > + else > > + result->ignored_p |= ignored_p; > > > > /* Really add the attributes to their namespace now. */ > > for (unsigned i = 0; attributes[i].name != NULL; ++i) > > @@ -224,6 +233,92 @@ check_attribute_tables (void) > > attribute_tables[j][l].name)); > > } > > > > +/* Used to stash pointers to allocated memory so that we can free them at > > + the end of parsing of all TUs. */ > > +static vec<attribute_spec *> ignored_attributes_table; > > + > > +/* Parse arguments ARGS of -Wno-attributes=. > > + Currently we accept: > > + vendor::attr > > + vendor:: > > + This functions also registers the parsed attributes so that we don't > > + warn that we don't recognize them. */ > > + > > +void > > +handle_ignored_attributes_option (vec<char *> *v) > > +{ > > + if (v == nullptr) > > + return; > > + > > + for (auto opt : v) > > + { > > + char *q = strstr (opt, "::"); > > + /* We don't accept '::attr'. */ > > + if (q == nullptr || q == opt) > > + { > > + error ("wrong argument to ignored attributes"); > > + inform (input_location, "valid format is %<ns::attr%> or %<ns::%>"); > > + continue; > > + } > > + /* Cut off the vendor part. */ > > + *q = '\0'; > > + char *vendor = opt; > > + char *attr = q + 2; > > + /* Verify that they look valid. */ > > + auto valid_p = [](const char *s) { > > + for (; *s != '\0'; ++s) > > + if (!ISALNUM (*s) && *s != '_') > > + return false; > > + return true; > > + }; > > + if (!valid_p (vendor) || !valid_p (attr)) > > + { > > + error ("wrong argument to ignored attributes"); > > + continue; > > + } > > + /* Turn "__attr__" into "attr" so that we have a canonical form of > > + attribute names. Likewise for vendor. */ > > + auto strip = [](char *&s) { > > + const size_t l = strlen (s); > > + if (l > 4 && s[0] == '_' && s[1] == '_' > > + && s[l - 1] == '_' && s[l - 2] == '_') > > + { > > + s[l - 2] = '\0'; > > + s += 2; > > + } > > + }; > > + strip (attr); > > + strip (vendor); > > + /* If we've already seen this vendor::attr, ignore it. Attempting to > > + register it twice would lead to a crash. */ > > + if (lookup_scoped_attribute_spec (get_identifier (vendor), > > + get_identifier (attr))) > > + continue; > > + /* In the "vendor::" case, we should ignore *any* attribute coming > > + from this attribute namespace. */ > > + if (attr[0] == '\0') > > + attr = nullptr; > > + /* Create a table with extra attributes which we will register. > > + We can't free it here, so squirrel away the pointers. */ > > + attribute_spec *table = new attribute_spec[2]; > > + ignored_attributes_table.safe_push (table); > > + table[0] = { attr, 0, 0, false, false, false, false, nullptr, > > nullptr }; > > + table[1] = { nullptr, 0, 0, false, false, false, false, nullptr, > > + nullptr }; > > + register_scoped_attributes (table, vendor, !attr); > > + } > > +} > > + > > +/* Free data we might have allocated when adding extra attributes. */ > > + > > +void > > +free_attr_data () > > +{ > > + for (auto x : ignored_attributes_table) > > + delete[] x; > > + ignored_attributes_table.release (); > > +} > > + > > /* Initialize attribute tables, and make some sanity checks if checking is > > enabled. */ > > > > @@ -252,6 +347,9 @@ init_attributes (void) > > /* Put all the GNU attributes into the "gnu" namespace. */ > > register_scoped_attributes (attribute_tables[i], "gnu"); > > > > + vec<char *> *ignored = (vec<char *> *) flag_ignored_attributes; > > + handle_ignored_attributes_option (ignored); > > + > > invoke_plugin_callbacks (PLUGIN_ATTRIBUTES, NULL); > > attributes_initialized = true; > > } > > @@ -456,6 +554,19 @@ diag_attr_exclusions (tree last_decl, tree node, tree > > attrname, > > return found; > > } > > > > +/* Return true iff we should not complain about unknown attributes > > + coming from the attribute namespace NS. This is the case for > > + the -Wno-attributes=ns:: command-line option. */ > > + > > +static bool > > +attr_namespace_ignored_p (tree ns) > > +{ > > + if (ns == NULL_TREE) > > + return false; > > + scoped_attributes *r = find_attribute_namespace (IDENTIFIER_POINTER > > (ns)); > > + return r && r->ignored_p; > > +} > > + > > /* Process the attributes listed in ATTRIBUTES and install them in *NODE, > > which is either a DECL (including a TYPE_DECL) or a TYPE. If a DECL, > > it should be modified in place; if a TYPE, a copy should be created > > @@ -556,7 +667,8 @@ decl_attributes (tree *node, tree attributes, int flags, > > > > if (spec == NULL) > > { > > - if (!(flags & (int) ATTR_FLAG_BUILT_IN)) > > + if (!(flags & (int) ATTR_FLAG_BUILT_IN) > > + && !attr_namespace_ignored_p (ns)) > > { > > if (ns == NULL_TREE || !cxx11_attr_p) > > warning (OPT_Wattributes, "%qE attribute directive ignored", > > diff --git a/gcc/attribs.h b/gcc/attribs.h > > index 138c509bce1..96a527f67a9 100644 > > --- a/gcc/attribs.h > > +++ b/gcc/attribs.h > > @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see > > #define GCC_ATTRIBS_H > > > > extern const struct attribute_spec *lookup_attribute_spec (const_tree); > > +extern void free_attr_data (); > > extern void init_attributes (void); > > > > /* Process the attributes listed in ATTRIBUTES and install them in *NODE, > > @@ -40,12 +41,14 @@ extern void apply_tm_attr (tree, tree); > > extern tree make_attribute (const char *, const char *, tree); > > > > extern struct scoped_attributes* register_scoped_attributes (const struct > > attribute_spec *, > > - const char *); > > + const char *, > > + bool = false); > > > > extern char *sorted_attr_string (tree); > > extern bool common_function_versions (tree, tree); > > extern tree make_dispatcher_decl (const tree); > > extern bool is_function_default_version (const tree); > > +extern void handle_ignored_attributes_option (vec<char *> *); > > > > /* Return a type like TTYPE except that its TYPE_ATTRIBUTES > > is ATTRIBUTE. > > diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c > > index a9be8df0384..6beba5503f0 100644 > > --- a/gcc/c-family/c-pragma.c > > +++ b/gcc/c-family/c-pragma.c > > @@ -764,7 +764,7 @@ handle_pragma_diagnostic(cpp_reader *ARG_UNUSED(dummy)) > > if (token != CPP_NAME) > > { > > warning_at (loc, OPT_Wpragmas, > > - "missing [error|warning|ignored|push|pop]" > > + "missing [error|warning|ignored|push|pop|ignored_attributes]" > > " after %<#pragma GCC diagnostic%>"); > > return; > > } > > @@ -787,10 +787,43 @@ handle_pragma_diagnostic(cpp_reader > > *ARG_UNUSED(dummy)) > > diagnostic_pop_diagnostics (global_dc, input_location); > > return; > > } > > + else if (strcmp (kind_string, "ignored_attributes") == 0) > > + { > > + token = pragma_lex (&x, &loc); > > + if (token != CPP_STRING) > > + { > > + warning_at (loc, OPT_Wpragmas, > > + "missing attribute name after %<#pragma GCC diagnostic " > > + "ignored_attributes%>"); > > + return; > > + } > > + char *args = xstrdup (TREE_STRING_POINTER (x)); > > + const size_t l = strlen (args); > > + if (l == 0) > > + { > > + warning_at (loc, OPT_Wpragmas, "missing argument to %<#pragma GCC " > > + "diagnostic ignored_attributes%>"); > > + free (args); > > + return; > > + } > > + else if (args[l - 1] == ',') > > + { > > + warning_at (loc, OPT_Wpragmas, "trailing %<,%> in arguments for " > > + "%<#pragma GCC diagnostic ignored_attributes%>"); > > + free (args); > > + return; > > + } > > + auto_vec<char *> v; > > + for (char *p = strtok (args, ","); p; p = strtok (NULL, ",")) > > + v.safe_push (p); > > + handle_ignored_attributes_option (&v); > > + /* ??? We can't free (args); here. */ > > + return; > > + } > > else > > { > > warning_at (loc, OPT_Wpragmas, > > - "expected [error|warning|ignored|push|pop]" > > + "expected [error|warning|ignored|push|pop|ignored_attributes]" > > " after %<#pragma GCC diagnostic%>"); > > return; > > } > > diff --git a/gcc/common.opt b/gcc/common.opt > > index a9644cae4f0..c429e43c6c1 100644 > > --- a/gcc/common.opt > > +++ b/gcc/common.opt > > @@ -83,7 +83,7 @@ int flag_gen_aux_info = 0 > > Variable > > int flag_shlib > > > > -; These two are really VEC(char_p,heap) *. > > +; These three are really VEC(char_p,heap) *. > > > > Variable > > void *flag_instrument_functions_exclude_functions > > @@ -91,6 +91,9 @@ void *flag_instrument_functions_exclude_functions > > Variable > > void *flag_instrument_functions_exclude_files > > > > +Variable > > +void *flag_ignored_attributes > > + > > ; Generic structs (e.g. templates not explicitly specialized) > > ; may not have a compilation unit associated with them, and so > > ; may need to be treated differently from ordinary structs. > > @@ -549,6 +552,10 @@ Wattributes > > Common Var(warn_attributes) Init(1) Warning > > Warn about inappropriate attribute usage. > > > > +Wattributes= > > +Common Joined > > +Do not warn about specified attributes. > > + > > Wattribute-alias > > Common Alias(Wattribute_alias=, 1, 0) Warning > > Warn about type safety and similar errors and mismatches in declarations > > with alias attributes. > > diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi > > index b4c5376223a..28fd0cc6dd5 100644 > > --- a/gcc/doc/extend.texi > > +++ b/gcc/doc/extend.texi > > @@ -23761,6 +23761,25 @@ restored. > > foo(d); /* depends on command-line options */ > > @end smallexample > > > > +@item #pragma GCC diagnostic ignored_attributes > > + > > +Similarly to @option{-Wno-attributes=}, this pragma allows users to > > suppress > > +warnings about unknown scoped attributes (in C++11 and C2X). For example, > > +@code{#pragma GCC diagnostic ignored_attributes "vendor::attr"} disables > > +warning about the following declaration: > > + > > +@smallexample > > +[[vendor::attr]] void f(); > > +@end smallexample > > + > > +whereas @code{#pragma GCC diagnostic ignored_attributes "vendor::"} > > prevents > > +warning about both of these declarations: > > + > > +@smallexample > > +[[vendor::safe]] void f(); > > +[[vendor::unsafe]] void f2(); > > +@end smallexample > > + > > @end table > > > > GCC also offers a simple mechanism for printing messages during > > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi > > index 5b016166972..fe2cb768c61 100644 > > --- a/gcc/doc/invoke.texi > > +++ b/gcc/doc/invoke.texi > > @@ -8623,6 +8623,26 @@ unrecognized attributes, function attributes applied > > to variables, > > etc. This does not stop errors for incorrect use of supported > > attributes. > > > > +Additionally, using @option{-Wno-attributes=}, it is possible to suppress > > +warnings about unknown scoped attributes (in C++11 and C2X). For example, > > +@option{-Wno-attributes=vendor::attr} disables warning about the following > > +declaration: > > + > > +@smallexample > > +[[vendor::attr]] void f(); > > +@end smallexample > > + > > +It is also possible to disable warning about all attributes in a namespace > > +using @option{-Wno-attributes=vendor::} which prevents warning about both > > +of these declarations: > > + > > +@smallexample > > +[[vendor::safe]] void f(); > > +[[vendor::unsafe]] void f2(); > > +@end smallexample > > + > > +Note that @option{-Wno-attributes=} does not imply > > @option{-Wno-attributes}. > > + > > @item -Wno-builtin-declaration-mismatch > > @opindex Wno-builtin-declaration-mismatch > > @opindex Wbuiltin-declaration-mismatch > > diff --git a/gcc/opts.c b/gcc/opts.c > > index 6503980cd33..e3b66ad0d43 100644 > > --- a/gcc/opts.c > > +++ b/gcc/opts.c > > @@ -2558,6 +2558,26 @@ common_handle_option (struct gcc_options *opts, > > /* Currently handled in a prescan. */ > > break; > > > > + case OPT_Wattributes_: > > + if (lang_mask == CL_DRIVER) > > + break; > > + > > + if (value) > > + { > > + error_at (loc, "arguments ignored for %<-Wattributes=%>; use " > > + "%<-Wno-attributes=%> instead"); > > + break; > > + } > > + else if (arg[strlen (arg) - 1] == ',') > > + { > > + error_at (loc, "trailing %<,%> in arguments for " > > + "%<-Wno-attributes=%>"); > > + break; > > + } > > + > > + add_comma_separated_to_vector (&opts->x_flag_ignored_attributes, > > arg); > > + break; > > + > > case OPT_Werror: > > dc->warning_as_error_requested = value; > > break; > > diff --git a/gcc/plugin.h b/gcc/plugin.h > > index 1640e253ca5..5556763d1bf 100644 > > --- a/gcc/plugin.h > > +++ b/gcc/plugin.h > > @@ -197,7 +197,9 @@ invoke_plugin_callbacks (int event ATTRIBUTE_UNUSED, > > /* In attribs.c. */ > > > > extern void register_attribute (const struct attribute_spec *attr); > > +/* The default argument for the third parameter is given in attribs.h. */ > > extern struct scoped_attributes* register_scoped_attributes (const struct > > attribute_spec *, > > - const char *); > > + const char *, > > + bool); > > > > #endif /* PLUGIN_H */ > > diff --git a/gcc/testsuite/c-c++-common/Wno-attributes-1.c > > b/gcc/testsuite/c-c++-common/Wno-attributes-1.c > > new file mode 100644 > > index 00000000000..aac1a69fd85 > > --- /dev/null > > +++ b/gcc/testsuite/c-c++-common/Wno-attributes-1.c > > @@ -0,0 +1,55 @@ > > +/* PR c++/101940 */ > > +/* { dg-do compile } */ > > +/* { dg-additional-options "-std=c++11" { target c++ } } */ > > +/* { dg-additional-options "-Wno-attributes=company::,yoyodyne::attr" } */ > > +/* { dg-additional-options > > "-Wno-attributes=c1::attr,c1::attr,c1::__attr__" } */ > > +/* { dg-additional-options "-Wno-attributes=c2::,c2::attr" } */ > > +/* { dg-additional-options "-Wno-attributes=c3::attr,c3::" } */ > > +/* { dg-additional-options "-Wno-attributes=x::" } */ > > +/* { dg-additional-options "-Wno-attributes=yoyodyne::attr_new" } */ > > +/* { dg-additional-options "-Wno-attributes=c4::__attr__" } */ > > +/* { dg-additional-options "-Wno-attributes=c5::attr" } */ > > +/* { dg-additional-options "-Wno-attributes=__c6__::attr" } */ > > + > > +[[company::attr]] void f1(); > > +[[company::attr2]] void f2(); > > + > > +[[yoyodyne::attr]] void f3(); > > +[[yoyodyne::__attr__]] void f3__(); > > +[[yoyodyne::attrx]] void f4(); /* { dg-warning "ignored" } */ > > +[[yoyodyne::__attrx__]] void f4__(); /* { dg-warning "ignored" } */ > > + > > +[[c1::attr]] void f5(); > > + > > +[[c2::attr]] void f6(); > > +[[c2::attrx]] void f7(); > > +[[c2::__attr__]] void f6__(); > > +[[c2::__attrx__]] void f7__(); > > + > > +[[c3::attr]] void f8(); > > +[[c3::attrx]] void f9(); > > + > > +[[x::x]] void f10(); > > + > > +[[yoyodyne::attr_new]] void f11(); > > +[[yoyodyne::__attr_new__]] void f11__(); > > +[[yoyodyne::attr_mew]] void f12(); /* { dg-warning "ignored" } */ > > +[[yoyodyne::__attr_mew__]] void f12__(); /* { dg-warning "ignored" } */ > > + > > +[[c4::attr]] void f13(); > > +[[c4::__attr__]] void f13__(); > > +[[c4::attrx]] void f14(); /* { dg-warning "ignored" } */ > > + > > +[[c5::attr]] void f15(); > > +[[c5::__attr__]] void f15__(); > > +[[__c5__::attr]] void __f15(); > > +[[__c5__::__attr__]] void __f15__(); > > +[[c5::attrx]] void f15x(); /* { dg-warning "ignored" } */ > > +[[__c5__::attrx]] void f15x(); /* { dg-warning "ignored" } */ > > + > > +[[c6::attr]] void f16(); > > +[[c6::__attr__]] void f16__(); > > +[[__c6__::attr]] void __f16(); > > +[[__c6__::__attr__]] void __f16__(); > > +[[c6::attrx]] void f16x(); /* { dg-warning "ignored" } */ > > +[[__c6__::attrx]] void f16x(); /* { dg-warning "ignored" } */ > > diff --git a/gcc/testsuite/c-c++-common/Wno-attributes-2.c > > b/gcc/testsuite/c-c++-common/Wno-attributes-2.c > > new file mode 100644 > > index 00000000000..4307c74b048 > > --- /dev/null > > +++ b/gcc/testsuite/c-c++-common/Wno-attributes-2.c > > @@ -0,0 +1,56 @@ > > +/* PR c++/101940 */ > > +/* { dg-do compile } */ > > +/* { dg-additional-options "-std=c++11" { target c++ } } */ > > + > > +#pragma GCC diagnostic ignored_attributes "company::,yoyodyne::attr" > > +#pragma GCC diagnostic ignored_attributes "c1::attr,c1::attr,c1::__attr__" > > +#pragma GCC diagnostic ignored_attributes "c2::,c2::attr" > > +#pragma GCC diagnostic ignored_attributes "c3::attr,c3::" > > +#pragma GCC diagnostic ignored_attributes "x::" > > +#pragma GCC diagnostic ignored_attributes "yoyodyne::attr_new" > > +#pragma GCC diagnostic ignored_attributes "c4::__attr__" > > +#pragma GCC diagnostic ignored_attributes "c5::attr" > > +#pragma GCC diagnostic ignored_attributes "__c6__::attr" > > + > > +[[company::attr]] void f1(); > > +[[company::attr2]] void f2(); > > + > > +[[yoyodyne::attr]] void f3(); > > +[[yoyodyne::__attr__]] void f3__(); > > +[[yoyodyne::attrx]] void f4(); /* { dg-warning "ignored" } */ > > +[[yoyodyne::__attrx__]] void f4__(); /* { dg-warning "ignored" } */ > > + > > +[[c1::attr]] void f5(); > > + > > +[[c2::attr]] void f6(); > > +[[c2::attrx]] void f7(); > > +[[c2::__attr__]] void f6__(); > > +[[c2::__attrx__]] void f7__(); > > + > > +[[c3::attr]] void f8(); > > +[[c3::attrx]] void f9(); > > + > > +[[x::x]] void f10(); > > + > > +[[yoyodyne::attr_new]] void f11(); > > +[[yoyodyne::__attr_new__]] void f11__(); > > +[[yoyodyne::attr_mew]] void f12(); /* { dg-warning "ignored" } */ > > +[[yoyodyne::__attr_mew__]] void f12__(); /* { dg-warning "ignored" } */ > > + > > +[[c4::attr]] void f13(); > > +[[c4::__attr__]] void f13__(); > > +[[c4::attrx]] void f14(); /* { dg-warning "ignored" } */ > > + > > +[[c5::attr]] void f15(); > > +[[c5::__attr__]] void f15__(); > > +[[__c5__::attr]] void __f15(); > > +[[__c5__::__attr__]] void __f15__(); > > +[[c5::attrx]] void f15x(); /* { dg-warning "ignored" } */ > > +[[__c5__::attrx]] void f15x(); /* { dg-warning "ignored" } */ > > + > > +[[c6::attr]] void f16(); > > +[[c6::__attr__]] void f16__(); > > +[[__c6__::attr]] void __f16(); > > +[[__c6__::__attr__]] void __f16__(); > > +[[c6::attrx]] void f16x(); /* { dg-warning "ignored" } */ > > +[[__c6__::attrx]] void f16x(); /* { dg-warning "ignored" } */ > > diff --git a/gcc/toplev.c b/gcc/toplev.c > > index e1688aae724..f5ccaf8f799 100644 > > --- a/gcc/toplev.c > > +++ b/gcc/toplev.c > > @@ -463,6 +463,8 @@ compile_file (void) > > if (flag_dump_locations) > > dump_location_info (stderr); > > > > + free_attr_data (); > > + > > /* Compilation is now finished except for writing > > what's left of the symbol table output. */ > > > > > > base-commit: a11052d98db2f2a61841f0c5ee84de4ca1b3e296 > > -- > > 2.31.1 > > > > Marek
Marek