This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH v2][RFC] Canonize names of attributes.
On 06/28/2017 09:01 PM, Jason Merrill wrote:
> On Wed, Jun 28, 2017 at 12:05 PM, Joseph Myers <joseph@codesourcery.com> wrote:
>> On Wed, 28 Jun 2017, Martin Liška wrote:
>>
>>> On 06/14/2017 07:24 PM, Jason Merrill wrote:
>>>> On Tue, Jun 13, 2017 at 8:32 AM, Martin Liška <mliska@suse.cz> wrote:
>>>>> (canonize_attr_name): New function.
>>>>
>>>> I think this should be "canonicalize"; "canonize" means something else.
>>>>
>>>> Jason
>>>>
>>>
>>> Yes, I hope it's a cosmetic problem. In general, do you welcome the change
>>> to canonicalize attribute names?
>>
>> I think *names* (as opposed to arguments) should be canonicalized, but
>> arguments need separate consideration.
>
> I agree.
>
> Jason
>
Good.
This is v2 of the patch, where just names of attributes are canonicalized.
Patch can bootstrap on ppc64le-redhat-linux and survives regression tests.
Ready to be installed?
Martin
>From 4c604148da4d837b06b166512ae71ddf83e5cf3b Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Thu, 8 Jun 2017 10:23:25 +0200
Subject: [PATCH] Canonicalize names of attributes.
gcc/c-family/ChangeLog:
2017-06-29 Martin Liska <mliska@suse.cz>
* c-format.c (convert_format_name_to_system_name): Add argument
to function call.
(cmp_attribs): Remove the function.
* c-lex.c (c_common_has_attribute): Use canonicalize_attr_name.
* c-pretty-print.c: Include stringpool.h.
gcc/cp/ChangeLog:
2017-06-29 Martin Liska <mliska@suse.cz>
* parser.c (cp_parser_gnu_attribute_list): Use
canonicalize_attr_name.
(cp_parser_std_attribute): Likewise.
* tree.c: Include stringpool.h.
gcc/go/ChangeLog:
2017-06-29 Martin Liska <mliska@suse.cz>
* go-gcc.cc (Gcc_backend::function): Look up for no_split_stack
and not __no_split_stack__.
gcc/c/ChangeLog:
2017-06-29 Martin Liska <mliska@suse.cz>
* c-parser.c (c_parser_attributes): Use canonicalize_attr_name.
gcc/testsuite/ChangeLog:
2017-06-29 Martin Liska <mliska@suse.cz>
* g++.dg/cpp0x/pr65558.C: Update scanned pattern.
* gcc.dg/parm-impl-decl-1.c: Likewise.
* gcc.dg/parm-impl-decl-3.c: Likewise.
gcc/ChangeLog:
2017-06-29 Martin Liska <mliska@suse.cz>
* attribs.h (canonicalize_attr_name): New function.
* tree.c (cmp_attrib_identifiers): Use cmp_attribs.
(attribute_value_equal): Add argument to a call of function.
(private_is_attribute_p): Add checking and use id_equal.
(private_lookup_attribute): Consider attributes do not begin
with '_' character.
(private_lookup_attribute_by_prefix): Likewise.
(remove_attribute): Use string comparison.
* tree.h (cmp_attribs): New functions.
---
gcc/attribs.h | 19 ++++++
gcc/c-family/c-format.c | 27 ++-------
gcc/c-family/c-lex.c | 1 +
gcc/c-family/c-pretty-print.c | 1 +
gcc/c/c-parser.c | 3 +
gcc/cp/parser.c | 6 +-
gcc/cp/tree.c | 1 +
gcc/go/go-gcc.cc | 2 +-
gcc/testsuite/g++.dg/cpp0x/pr65558.C | 2 +-
gcc/testsuite/gcc.dg/parm-impl-decl-1.c | 2 +-
gcc/testsuite/gcc.dg/parm-impl-decl-3.c | 2 +-
gcc/tree.c | 103 +++++++-------------------------
gcc/tree.h | 42 +++++++++++++
13 files changed, 103 insertions(+), 108 deletions(-)
diff --git a/gcc/attribs.h b/gcc/attribs.h
index 7f13332700e..b3b68b2e57e 100644
--- a/gcc/attribs.h
+++ b/gcc/attribs.h
@@ -47,4 +47,23 @@ extern char *make_unique_name (tree, const char *, bool);
extern tree make_dispatcher_decl (const tree);
extern bool is_function_default_version (const tree);
+/* For a given IDENTIFIER_NODE, strip leading and trailing '_' characters
+ so that we have a canonical form of attribute names. */
+
+static inline tree
+canonicalize_attr_name (tree attr_name)
+{
+ const size_t l = IDENTIFIER_LENGTH (attr_name);
+ const char *s = IDENTIFIER_POINTER (attr_name);
+
+ if (l > 4 && s[0] == '_')
+ {
+ gcc_checking_assert (s[l - 2] == '_');
+ return get_identifier_with_length (s + 2, l - 4);
+ }
+
+ return attr_name;
+}
+
+
#endif // GCC_ATTRIBS_H
diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index 732339b9b5e..3aad17522df 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -67,7 +67,6 @@ static bool check_format_string (tree argument,
static bool get_constant (tree expr, unsigned HOST_WIDE_INT *value,
int validated_p);
static const char *convert_format_name_to_system_name (const char *attr_name);
-static bool cmp_attribs (const char *tattr_name, const char *attr_name);
static int first_target_format_type;
static const char *format_name (int format_num);
@@ -3951,10 +3950,10 @@ convert_format_name_to_system_name (const char *attr_name)
for (i = 0; i < TARGET_OVERRIDES_FORMAT_ATTRIBUTES_COUNT; ++i)
{
if (cmp_attribs (TARGET_OVERRIDES_FORMAT_ATTRIBUTES[i].named_attr_src,
- attr_name))
+ attr_name, false))
return attr_name;
if (cmp_attribs (TARGET_OVERRIDES_FORMAT_ATTRIBUTES[i].named_attr_dst,
- attr_name))
+ attr_name, false))
return TARGET_OVERRIDES_FORMAT_ATTRIBUTES[i].named_attr_src;
}
}
@@ -3965,34 +3964,16 @@ convert_format_name_to_system_name (const char *attr_name)
++i)
{
if (cmp_attribs (gnu_target_overrides_format_attributes[i].named_attr_src,
- attr_name))
+ attr_name, false))
return attr_name;
if (cmp_attribs (gnu_target_overrides_format_attributes[i].named_attr_dst,
- attr_name))
+ attr_name, false))
return gnu_target_overrides_format_attributes[i].named_attr_src;
}
return attr_name;
}
-/* Return true if TATTR_NAME and ATTR_NAME are the same format attribute,
- counting "name" and "__name__" as the same, false otherwise. */
-static bool
-cmp_attribs (const char *tattr_name, const char *attr_name)
-{
- int alen = strlen (attr_name);
- int slen = (tattr_name ? strlen (tattr_name) : 0);
- if (alen > 4 && attr_name[0] == '_' && attr_name[1] == '_'
- && attr_name[alen - 1] == '_' && attr_name[alen - 2] == '_')
- {
- attr_name += 2;
- alen -= 4;
- }
- if (alen != slen || strncmp (tattr_name, attr_name, alen) != 0)
- return false;
- return true;
-}
-
/* Handle a "format" attribute; arguments as in
struct attribute_spec.handler. */
tree
diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
index e1c8bdff986..3765a800a57 100644
--- a/gcc/c-family/c-lex.c
+++ b/gcc/c-family/c-lex.c
@@ -316,6 +316,7 @@ c_common_has_attribute (cpp_reader *pfile)
{
attr_name = get_identifier ((const char *)
cpp_token_as_text (pfile, token));
+ attr_name = canonicalize_attr_name (attr_name);
if (c_dialect_cxx ())
{
int idx = 0;
diff --git a/gcc/c-family/c-pretty-print.c b/gcc/c-family/c-pretty-print.c
index fdb7b41f592..b8b8f665ef3 100644
--- a/gcc/c-family/c-pretty-print.c
+++ b/gcc/c-family/c-pretty-print.c
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see
#include "c-pretty-print.h"
#include "diagnostic.h"
#include "stor-layout.h"
+#include "stringpool.h"
#include "attribs.h"
#include "intl.h"
#include "tree-pretty-print.h"
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index f8fbc926172..e358b19a585 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -4170,9 +4170,11 @@ c_parser_attributes (c_parser *parser)
attr_name = c_parser_attribute_any_word (parser);
if (attr_name == NULL)
break;
+ attr_name = canonicalize_attr_name (attr_name);
if (is_cilkplus_vector_p (attr_name))
{
c_token *v_token = c_parser_peek_token (parser);
+ v_token->value = canonicalize_attr_name (v_token->value);
c_parser_cilk_simd_fn_vector_attrs (parser, *v_token);
/* If the next token isn't a comma, we're done. */
if (!c_parser_next_token_is (parser, CPP_COMMA))
@@ -4236,6 +4238,7 @@ c_parser_attributes (c_parser *parser)
release_tree_vector (expr_list);
}
}
+
attr = build_tree_list (attr_name, attr_args);
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
c_parser_consume_token (parser);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index bd99c051340..4f1be517d41 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -24764,7 +24764,8 @@ cp_parser_gnu_attribute_list (cp_parser* parser)
parsed identifier. */
? ridpointers[(int) token->keyword]
: id_token->u.value;
-
+
+ identifier = canonicalize_attr_name (identifier);
attribute = build_tree_list (identifier, NULL_TREE);
/* Peek at the next token. */
@@ -24910,6 +24911,8 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns)
"expected an identifier for the attribute name");
return error_mark_node;
}
+
+ attr_id = canonicalize_attr_name (attr_id);
attribute = build_tree_list (build_tree_list (attr_ns, attr_id),
NULL_TREE);
token = cp_lexer_peek_token (parser->lexer);
@@ -24919,6 +24922,7 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns)
NULL_TREE);
else
{
+ attr_id = canonicalize_attr_name (attr_id);
attribute = build_tree_list (build_tree_list (NULL_TREE, attr_id),
NULL_TREE);
/* C++11 noreturn attribute is equivalent to GNU's. */
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 4535af64dc6..d8dddfd2324 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see
#include "debug.h"
#include "convert.h"
#include "gimplify.h"
+#include "stringpool.h"
#include "attribs.h"
#include "flags.h"
diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc
index a7977fe03c1..04912f0ed01 100644
--- a/gcc/go/go-gcc.cc
+++ b/gcc/go/go-gcc.cc
@@ -3046,7 +3046,7 @@ Gcc_backend::function(Btype* fntype, const std::string& name,
DECL_UNINLINABLE(decl) = 1;
if (disable_split_stack)
{
- tree attr = get_identifier("__no_split_stack__");
+ tree attr = get_identifier ("no_split_stack");
DECL_ATTRIBUTES(decl) = tree_cons(attr, NULL_TREE, NULL_TREE);
}
if (in_unique_section)
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr65558.C b/gcc/testsuite/g++.dg/cpp0x/pr65558.C
index d294c95a657..12946b35eda 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr65558.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr65558.C
@@ -2,6 +2,6 @@
// { dg-do compile { target c++11 } }
inline namespace
-__attribute__((__abi_tag__)) // { dg-warning "ignoring .__abi_tag__. attribute on anonymous namespace" }
+__attribute__((__abi_tag__)) // { dg-warning "ignoring .abi_tag. attribute on anonymous namespace" }
{
}
diff --git a/gcc/testsuite/gcc.dg/parm-impl-decl-1.c b/gcc/testsuite/gcc.dg/parm-impl-decl-1.c
index 5c7ddb0a259..c1219273c75 100644
--- a/gcc/testsuite/gcc.dg/parm-impl-decl-1.c
+++ b/gcc/testsuite/gcc.dg/parm-impl-decl-1.c
@@ -7,7 +7,7 @@
/* Implicit function declaration in attribute in definition (testcase
from bug). */
int
-foo (int __attribute__ ((__mode__ (vector_size(8)))) i) /* { dg-warning "'__mode__' attribute ignored" } */
+foo (int __attribute__ ((__mode__ (vector_size(8)))) i) /* { dg-warning "'mode' attribute ignored" } */
{
return (long long) i;
}
diff --git a/gcc/testsuite/gcc.dg/parm-impl-decl-3.c b/gcc/testsuite/gcc.dg/parm-impl-decl-3.c
index 904295258d7..20197b52402 100644
--- a/gcc/testsuite/gcc.dg/parm-impl-decl-3.c
+++ b/gcc/testsuite/gcc.dg/parm-impl-decl-3.c
@@ -4,7 +4,7 @@
/* { dg-options "-g -std=gnu89" } */
int
-foo (int __attribute__ ((__mode__ (vector_size(8)))) i) /* { dg-warning "'__mode__' attribute ignored" } */
+foo (int __attribute__ ((__mode__ (vector_size(8)))) i) /* { dg-warning "'mode' attribute ignored" } */
{
return (long long) i;
}
diff --git a/gcc/tree.c b/gcc/tree.c
index ca28afad0f2..662752459bb 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -4928,12 +4928,13 @@ simple_cst_list_equal (const_tree l1, const_tree l2)
return l1 == l2;
}
-/* Compare two identifier nodes representing attributes. Either one may
- be in wrapped __ATTR__ form. Return true if they are the same, false
- otherwise. */
+/* Compare two identifier nodes representing attributes.
+ Return true if they are the same, false otherwise. If STRICT is not set,
+ __ATTR__ and ATTR names are considered as equal. */
static bool
-cmp_attrib_identifiers (const_tree attr1, const_tree attr2)
+cmp_attrib_identifiers (const_tree attr1, const_tree attr2,
+ bool strict = true)
{
/* Make sure we're dealing with IDENTIFIER_NODEs. */
gcc_checking_assert (TREE_CODE (attr1) == IDENTIFIER_NODE
@@ -4943,34 +4944,9 @@ cmp_attrib_identifiers (const_tree attr1, const_tree attr2)
if (attr1 == attr2)
return true;
- /* If they are not equal, they may still be one in the form
- 'text' while the other one is in the form '__text__'. TODO:
- If we were storing attributes in normalized 'text' form, then
- this could all go away and we could take full advantage of
- the fact that we're comparing identifiers. :-) */
- const size_t attr1_len = IDENTIFIER_LENGTH (attr1);
- const size_t attr2_len = IDENTIFIER_LENGTH (attr2);
-
- if (attr2_len == attr1_len + 4)
- {
- const char *p = IDENTIFIER_POINTER (attr2);
- const char *q = IDENTIFIER_POINTER (attr1);
- if (p[0] == '_' && p[1] == '_'
- && p[attr2_len - 2] == '_' && p[attr2_len - 1] == '_'
- && strncmp (q, p + 2, attr1_len) == 0)
- return true;;
- }
- else if (attr2_len + 4 == attr1_len)
- {
- const char *p = IDENTIFIER_POINTER (attr2);
- const char *q = IDENTIFIER_POINTER (attr1);
- if (q[0] == '_' && q[1] == '_'
- && q[attr1_len - 2] == '_' && q[attr1_len - 1] == '_'
- && strncmp (q + 2, p, attr2_len) == 0)
- return true;
- }
-
- return false;
+ return cmp_attribs (IDENTIFIER_POINTER (attr1), IDENTIFIER_LENGTH (attr1),
+ IDENTIFIER_POINTER (attr2), IDENTIFIER_LENGTH (attr2),
+ strict);
}
/* Compare two attributes for their value identity. Return true if the
@@ -4994,7 +4970,7 @@ attribute_value_equal (const_tree attr1, const_tree attr2)
attr2 = TREE_VALUE (attr2);
/* Compare the archetypes (printf/scanf/strftime/...). */
if (!cmp_attrib_identifiers (TREE_VALUE (attr1),
- TREE_VALUE (attr2)))
+ TREE_VALUE (attr2), false))
return false;
/* Archetypes are the same. Compare the rest. */
return (simple_cst_list_equal (TREE_CHAIN (attr1),
@@ -6049,24 +6025,9 @@ bool
private_is_attribute_p (const char *attr_name, size_t attr_len, const_tree ident)
{
size_t ident_len = IDENTIFIER_LENGTH (ident);
+ gcc_checking_assert (ident_len == 0 || IDENTIFIER_POINTER (ident)[0] != '_');
- if (ident_len == attr_len)
- {
- if (id_equal (ident, attr_name))
- return true;
- }
- else if (ident_len == attr_len + 4)
- {
- /* There is the possibility that ATTR is 'text' and IDENT is
- '__text__'. */
- const char *p = IDENTIFIER_POINTER (ident);
- if (p[0] == '_' && p[1] == '_'
- && p[ident_len - 2] == '_' && p[ident_len - 1] == '_'
- && strncmp (attr_name, p + 2, attr_len) == 0)
- return true;
- }
-
- return false;
+ return ident_len == attr_len && id_equal (ident, attr_name);
}
/* The backbone of lookup_attribute(). ATTR_LEN is the string length
@@ -6076,25 +6037,13 @@ private_lookup_attribute (const char *attr_name, size_t attr_len, tree list)
{
while (list)
{
- size_t ident_len = IDENTIFIER_LENGTH (get_attribute_name (list));
-
- if (ident_len == attr_len)
- {
- if (!strcmp (attr_name,
- IDENTIFIER_POINTER (get_attribute_name (list))))
- break;
- }
- /* TODO: If we made sure that attributes were stored in the
- canonical form without '__...__' (ie, as in 'text' as opposed
- to '__text__') then we could avoid the following case. */
- else if (ident_len == attr_len + 4)
- {
- const char *p = IDENTIFIER_POINTER (get_attribute_name (list));
- if (p[0] == '_' && p[1] == '_'
- && p[ident_len - 2] == '_' && p[ident_len - 1] == '_'
- && strncmp (attr_name, p + 2, attr_len) == 0)
+ tree attr = get_attribute_name (list);
+ size_t ident_len = IDENTIFIER_LENGTH (attr);
+ gcc_checking_assert (ident_len == 0
+ || IDENTIFIER_POINTER (attr)[0] != '_');
+ if (ident_len == attr_len
+ && strcmp (attr_name, IDENTIFIER_POINTER (attr)) == 0)
break;
- }
list = TREE_CHAIN (list);
}
@@ -6121,17 +6070,11 @@ private_lookup_attribute_by_prefix (const char *attr_name, size_t attr_len,
}
const char *p = IDENTIFIER_POINTER (get_attribute_name (list));
+ gcc_checking_assert (attr_len == 0 || p[0] != '_');
if (strncmp (attr_name, p, attr_len) == 0)
break;
- /* TODO: If we made sure that attributes were stored in the
- canonical form without '__...__' (ie, as in 'text' as opposed
- to '__text__') then we could avoid the following case. */
- if (p[0] == '_' && p[1] == '_' &&
- strncmp (attr_name, p + 2, attr_len) == 0)
- break;
-
list = TREE_CHAIN (list);
}
@@ -6177,16 +6120,16 @@ tree
remove_attribute (const char *attr_name, tree list)
{
tree *p;
- size_t attr_len = strlen (attr_name);
-
gcc_checking_assert (attr_name[0] != '_');
for (p = &list; *p; )
{
tree l = *p;
- /* TODO: If we were storing attributes in normalized form, here
- we could use a simple strcmp(). */
- if (private_is_attribute_p (attr_name, attr_len, get_attribute_name (l)))
+
+ tree attr = get_attribute_name (l);
+ gcc_checking_assert (IDENTIFIER_LENGTH (attr) == 0
+ || IDENTIFIER_POINTER (attr)[0] != '_');
+ if (strcmp (attr_name, IDENTIFIER_POINTER (attr)) == 0)
*p = TREE_CHAIN (l);
else
p = &TREE_CHAIN (l);
diff --git a/gcc/tree.h b/gcc/tree.h
index 91cf253dee5..d16ab3a7d59 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -5493,6 +5493,48 @@ type_with_alias_set_p (const_tree t)
return false;
}
+/* Compare attribute identifiers ATTR1 and ATTR2 with length ATTR1_LEN and
+ ATTR2_LEN. If strict is false, consider __ATTR__ and ATTR as same
+ attribute names. */
+
+static inline bool
+cmp_attribs (const char *attr1, size_t attr1_len,
+ const char *attr2, size_t attr2_len,
+ bool strict = true)
+{
+ if (!strict)
+ {
+ if (attr1_len > 4 && attr1[0] == '_')
+ {
+ attr1 += 2;
+ attr1_len -= 4;
+ }
+
+ if (attr2_len > 4 && attr2[0] == '_')
+ {
+ attr2 += 2;
+ attr2_len -= 4;
+ }
+ }
+ else
+ {
+ gcc_checking_assert (attr1_len == 0 || attr1[0] != '_');
+ gcc_checking_assert (attr2_len == 0 || attr2[0] != '_');
+ }
+
+ return attr1_len == attr2_len && strncmp (attr1, attr2, attr1_len) == 0;
+}
+
+
+/* Compare attribute identifiers ATTR1 and ATTR2.
+ If strict is false, consider __ATTR__ and ATTR as same attribute names. */
+
+static inline bool
+cmp_attribs (const char *attr1, const char *attr2, bool strict = true)
+{
+ return cmp_attribs (attr1, strlen (attr1), attr2, strlen (attr2), strict);
+}
+
extern location_t set_block (location_t loc, tree block);
extern void gt_ggc_mx (tree &);
--
2.13.1