diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/attribs.cc | 27 | ||||
-rw-r--r-- | gcc/attribs.h | 19 | ||||
-rw-r--r-- | gcc/c-family/c-common.cc | 7 | ||||
-rw-r--r-- | gcc/cp/cp-gimplify.cc | 32 | ||||
-rw-r--r-- | gcc/cp/parser.cc | 3 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1z/fallthrough2.C | 24 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/attr-likely7.C | 38 |
7 files changed, 123 insertions, 27 deletions
diff --git a/gcc/attribs.cc b/gcc/attribs.cc index 38f3e926..27dea74 100644 --- a/gcc/attribs.cc +++ b/gcc/attribs.cc @@ -1645,7 +1645,8 @@ remove_attribute (const char *attr_name, tree list) return list; } -/* Similarly but also match namespace on the removed attributes. */ +/* Similarly but also match namespace on the removed attributes. + ATTR_NS "" stands for NULL or "gnu" namespace. */ tree remove_attribute (const char *attr_ns, const char *attr_name, tree list) @@ -1659,15 +1660,11 @@ remove_attribute (const char *attr_ns, const char *attr_name, tree list) tree l = *p; tree attr = get_attribute_name (l); - if (is_attribute_p (attr_name, attr)) + if (is_attribute_p (attr_name, attr) + && is_attribute_namespace_p (attr_ns, l)) { - tree ns = get_attribute_namespace (l); - if ((ns == NULL_TREE && attr_ns == NULL) - || (ns && attr_ns && is_attribute_p (attr_ns, ns))) - { - *p = TREE_CHAIN (l); - continue; - } + *p = TREE_CHAIN (l); + continue; } p = &TREE_CHAIN (l); } @@ -2088,14 +2085,20 @@ private_lookup_attribute (const char *attr_ns, const char *attr_name, tree ns = get_attribute_namespace (list); if (ns == NULL_TREE) { - if (attr_ns == NULL) + if (attr_ns_len == 0) break; } else if (attr_ns) { ident_len = IDENTIFIER_LENGTH (ns); - if (cmp_attribs (attr_ns, attr_ns_len, IDENTIFIER_POINTER (ns), - ident_len)) + if (attr_ns_len == 0) + { + if (cmp_attribs ("gnu", strlen ("gnu"), + IDENTIFIER_POINTER (ns), ident_len)) + break; + } + else if (cmp_attribs (attr_ns, attr_ns_len, + IDENTIFIER_POINTER (ns), ident_len)) break; } } diff --git a/gcc/attribs.h b/gcc/attribs.h index 121b9eb..1dc16e4 100644 --- a/gcc/attribs.h +++ b/gcc/attribs.h @@ -188,6 +188,22 @@ is_attribute_p (const char *attr_name, const_tree ident) IDENTIFIER_POINTER (ident), IDENTIFIER_LENGTH (ident)); } +/* Given an attribute ATTR and a string ATTR_NS, return true + if the attribute namespace is valid for the string. ATTR_NS "" stands + for standard attribute (NULL get_attribute_namespace) or "gnu" + namespace. */ + +static inline bool +is_attribute_namespace_p (const char *attr_ns, const_tree attr) +{ + tree ident = get_attribute_namespace (attr); + if (attr_ns == NULL) + return ident == NULL_TREE; + if (attr_ns[0]) + return ident && is_attribute_p (attr_ns, ident); + return ident == NULL_TREE || is_attribute_p ("gnu", ident); +} + /* Given an attribute name ATTR_NAME and a list of attributes LIST, return a pointer to the attribute's list element if the attribute is part of the list, or NULL_TREE if not found. If the attribute @@ -217,7 +233,8 @@ lookup_attribute (const char *attr_name, tree list) } } -/* Similar to lookup_attribute, but also match the attribute namespace. */ +/* Similar to lookup_attribute, but also match the attribute namespace. + ATTR_NS "" stands for either standard attribute or "gnu" namespace. */ static inline tree lookup_attribute (const char *attr_ns, const char *attr_name, tree list) diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc index ffe17ea..9ec9100 100644 --- a/gcc/c-family/c-common.cc +++ b/gcc/c-family/c-common.cc @@ -6008,12 +6008,12 @@ attribute_fallthrough_p (tree attr) { if (attr == error_mark_node) return false; - tree t = lookup_attribute ("fallthrough", attr); + tree t = lookup_attribute ("", "fallthrough", attr); if (t == NULL_TREE) return false; /* It is no longer true that "this attribute shall appear at most once in each attribute-list", but we still give a warning. */ - if (lookup_attribute ("fallthrough", TREE_CHAIN (t))) + if (lookup_attribute ("", "fallthrough", TREE_CHAIN (t))) warning (OPT_Wattributes, "attribute %<fallthrough%> specified multiple " "times"); /* No attribute-argument-clause shall be present. */ @@ -6024,7 +6024,8 @@ attribute_fallthrough_p (tree attr) for (t = attr; t != NULL_TREE; t = TREE_CHAIN (t)) { tree name = get_attribute_name (t); - if (!is_attribute_p ("fallthrough", name)) + if (!is_attribute_p ("fallthrough", name) + || !is_attribute_namespace_p ("", t)) { if (!c_dialect_cxx () && get_attribute_namespace (t) == NULL_TREE) /* The specifications of standard attributes in C mean diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc index 5d26e59..cb8bbd8 100644 --- a/gcc/cp/cp-gimplify.cc +++ b/gcc/cp/cp-gimplify.cc @@ -3028,7 +3028,7 @@ cp_fold (tree x) return x; } -/* Look up either "hot" or "cold" in attribute list LIST. */ +/* Look up "hot", "cold", "likely" or "unlikely" in attribute list LIST. */ tree lookup_hotness_attribute (tree list) @@ -3036,24 +3036,36 @@ lookup_hotness_attribute (tree list) for (; list; list = TREE_CHAIN (list)) { tree name = get_attribute_name (list); - if (is_attribute_p ("hot", name) - || is_attribute_p ("cold", name) - || is_attribute_p ("likely", name) - || is_attribute_p ("unlikely", name)) + if ((is_attribute_p ("hot", name) + || is_attribute_p ("cold", name) + || is_attribute_p ("likely", name) + || is_attribute_p ("unlikely", name)) + && is_attribute_namespace_p ("", list)) break; } return list; } -/* Remove both "hot" and "cold" attributes from LIST. */ +/* Remove "hot", "cold", "likely" and "unlikely" attributes from LIST. */ static tree remove_hotness_attribute (tree list) { - list = remove_attribute ("hot", list); - list = remove_attribute ("cold", list); - list = remove_attribute ("likely", list); - list = remove_attribute ("unlikely", list); + for (tree *p = &list; *p; ) + { + tree l = *p; + tree name = get_attribute_name (l); + if ((is_attribute_p ("hot", name) + || is_attribute_p ("cold", name) + || is_attribute_p ("likely", name) + || is_attribute_p ("unlikely", name)) + && is_attribute_namespace_p ("", l)) + { + *p = TREE_CHAIN (l); + continue; + } + p = &TREE_CHAIN (l); + } return list; } diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 90e06f9..555476e 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -29265,7 +29265,8 @@ cp_parser_check_std_attribute (location_t loc, tree attributes, tree attribute) if (attributes) for (const auto &a : alist) if (is_attribute_p (a, get_attribute_name (attribute)) - && lookup_attribute (a, attributes)) + && is_attribute_namespace_p ("", attribute) + && lookup_attribute ("", a, attributes)) { if (!from_macro_expansion_at (loc)) warning_at (loc, OPT_Wattributes, "attribute %qs specified " diff --git a/gcc/testsuite/g++.dg/cpp1z/fallthrough2.C b/gcc/testsuite/g++.dg/cpp1z/fallthrough2.C new file mode 100644 index 0000000..b74323f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/fallthrough2.C @@ -0,0 +1,24 @@ +// { dg-do compile { target c++17 } } +// { dg-options "-Wextra -Wall -Wpedantic" } + +int +foo (int i) +{ + switch (i) + { + case 2: + ++i; + [[fallthrough, whatever::fallthrough]]; // { dg-bogus "attribute 'fallthrough' specified multiple times" } + case 3: // { dg-warning "'fallthrough' attribute ignored" "" { target *-*-* } .-1 } + ++i; + [[fallthrough, whatever2::fallthrough(1, 2, 3)]]; // { dg-bogus "attribute 'fallthrough' specified multiple times" } + case 4: // { dg-warning "'fallthrough' attribute ignored" "" { target *-*-* } .-1 } + [[whatever3::fallthrough("abcd")]]; // { dg-warning "attributes at the beginning of statement are ignored" } + case 5: + [[whatever4::fallthrough]]; // { dg-bogus "attribute 'fallthrough' not preceding a case label or default label" } + ++i; // { dg-warning "attributes at the beginning of statement are ignored" "" { target *-*-* } .-1 } + default: + break; + } + return i; +} diff --git a/gcc/testsuite/g++.dg/cpp2a/attr-likely7.C b/gcc/testsuite/g++.dg/cpp2a/attr-likely7.C new file mode 100644 index 0000000..638a6d9 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/attr-likely7.C @@ -0,0 +1,38 @@ +// { dg-do compile { target c++20 } } +// { dg-additional-options -fdump-tree-gimple } +// { dg-final { scan-tree-dump-times "hot label" 5 "gimple" } } +// { dg-final { scan-tree-dump-times "cold label" 3 "gimple" } } + +bool b; + +template <class T> int f() +{ + if (b) + [[likely, whatever::unlikely ("abcd")]] return 0; // { dg-bogus "ignoring attribute 'unlikely' after earlier 'likely'" } + else // { dg-warning "attributes at the beginning of statement are ignored" "" { target *-*-* } .-1 } + [[unlikely, whatever2::hot]] flabel: return 1; // { dg-warning "'whatever2::hot' scoped attribute directive ignored" } + switch (b) + { + [[likely, whatever3::cold (1, 2, 3)]] case true: break; // { dg-warning "'whatever3::cold' scoped attribute directive ignored" } + }; + return 1; +} + +int main() +{ + if (b) + [[whatever4::unlikely (1), likely]] return 0; // { dg-bogus "ignoring attribute 'likely' after earlier 'unlikely'" } + else if (b) // { dg-warning "attributes at the beginning of statement are ignored" "" { target *-*-* } .-1 } + [[whatever5::hot, unlikely]] elabel: // { dg-warning "'whatever5::hot' scoped attribute directive ignored" } + return 1; + else + [[whatever6::cold, likely]] b = false; // { dg-bogus "ignoring attribute 'likely' after earlier 'cold'" } + // { dg-warning "attributes at the beginning of statement are ignored" "" { target *-*-* } .-1 } + f<int>(); + + switch (b) + { + [[whatever7::unlikely (1), likely]] case true: break; // { dg-warning "'whatever7::unlikely' scoped attribute directive ignored" } + [[whatever8::unlikely, unlikely]] case false: break; // { dg-bogus "attribute 'unlikely' specified multiple times" } + }; // { dg-warning "'whatever8::unlikely' scoped attribute directive ignored" "" { target *-*-* } .-1 } +} |