aboutsummaryrefslogtreecommitdiff
path: root/gcc/c/c-parser.cc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2025-03-18 18:48:14 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2025-03-18 18:51:10 +0100
commit1d7f57da583782ae5d56655a3ac413bdf259838a (patch)
tree0772ef5df896af45145a02f2bc39a9a481193602 /gcc/c/c-parser.cc
parent05e20b78416230f6e6d5939d5920a7d21f18fdb8 (diff)
downloadgcc-1d7f57da583782ae5d56655a3ac413bdf259838a.zip
gcc-1d7f57da583782ae5d56655a3ac413bdf259838a.tar.gz
gcc-1d7f57da583782ae5d56655a3ac413bdf259838a.tar.bz2
c, c++: Support musttail attribute even using __attribute__ form [PR116545]
Apparently some programs in the wild use #if __has_attribute(musttail) __attribute__((musttail)) return foo (); #else return foo (); #endif clang supports musttail both as a standard attribute ([[clang::musttail]] which we also support for compatibility) and the above worked just fine with GCC 14 which had __has_attribute(musttail) 0. Now that it is 0, this doesn't compile anymore. So, either we need to ensure that __has_attribute(musttail) is 0 and just __has_c{,pp}_attribute({gnu,clang}::musttail) are non-zero, or IMHO better we just make it work in the attribute form, especially for C < C23 I can see why some projects would prefer that form. While [[gnu::musttail]] is rejected as an error in C11 etc. before GCC 15, rather than just handled as an unknown attribute. I view this as both a regression and compatibility issue. The patch handles it in similar spots to fallthrough/assume attributes inside of __attribute__ for C, and for C++ enables mixing of standard [[]] and GNU __attribute__(()) attributes at the start of statements in any order. While working on it, I've noticed we weren't diagnosing arguments to the clang::musttail attribute (fixed by the c-attribs.cc hunk) and newly on the __attribute__ form attribute (in that case the arguments aren't just skipped, they are always parsed and because we don't call decl_attributes etc., it wouldn't be diagnosed without a manual check). 2025-03-18 Jakub Jelinek <jakub@redhat.com> PR c/116545 gcc/ * doc/extend.texi (musttail statement attribute): Document that musttail GNU attribute can be used as well. gcc/c-family/ * c-attribs.cc (c_common_clang_attributes): Add musttail. gcc/c/ * c-parser.cc (c_parser_declaration_or_fndef): Parse __attribute__((musttail)) return. (c_parser_handle_musttail): Diagnose attribute arguments. (c_parser_statement_after_labels): Parse __attribute__((musttail)) return. gcc/cp/ * parser.cc (cp_parser_statement): Call cp_parser_attributes_opt rather than cp_parser_std_attribute_spec_seq. (cp_parser_jump_statement): Diagnose gnu::musttail attributes with no arguments. gcc/testsuite/ * c-c++-common/attr-fallthrough-2.c: Adjust expected diagnostics for C++. * c-c++-common/musttail15.c: New test. * c-c++-common/musttail16.c: New test. * c-c++-common/musttail17.c: New test. * c-c++-common/musttail18.c: New test. * c-c++-common/musttail19.c: New test. * c-c++-common/musttail20.c: New test. * c-c++-common/musttail21.c: New test. * c-c++-common/musttail22.c: New test. * c-c++-common/musttail23.c: New test. * c-c++-common/musttail24.c: New test. * g++.dg/musttail7.C: New test. * g++.dg/musttail8.C: New test. * g++.dg/musttail12.C: New test. * g++.dg/musttail13.C: New test. * g++.dg/musttail14.C: New test. * g++.dg/ext/pr116545.C: New test.
Diffstat (limited to 'gcc/c/c-parser.cc')
-rw-r--r--gcc/c/c-parser.cc50
1 files changed, 48 insertions, 2 deletions
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 911e7ed..93233a87 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -1820,6 +1820,7 @@ static void c_parser_objc_at_dynamic_declaration (c_parser *);
static bool c_parser_objc_diagnose_bad_element_prefix
(c_parser *, struct c_declspecs *);
static location_t c_parser_parse_rtl_body (c_parser *, char *);
+static tree c_parser_handle_musttail (c_parser *, tree, attr_state &);
#if ENABLE_ANALYZER
@@ -2519,6 +2520,32 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
c_finish_oacc_routine (oacc_routine_data, NULL_TREE, false);
return result;
}
+ else if (specs->typespec_kind == ctsk_none
+ && nested
+ /* Only parse __attribute__((musttail)) when called from
+ c_parser_compound_statement_nostart. This certainly isn't
+ a declaration in that case, but we don't do tentative parsing
+ of GNU attributes right now. */
+ && fallthru_attr_p
+ && c_parser_next_token_is_keyword (parser, RID_RETURN))
+ {
+ attr_state astate = {};
+ specs->attrs = c_parser_handle_musttail (parser, specs->attrs, astate);
+ if (astate.musttail_p)
+ {
+ if (specs->attrs)
+ {
+ auto_urlify_attributes sentinel;
+ warning_at (c_parser_peek_token (parser)->location,
+ OPT_Wattributes,
+ "attribute %<musttail%> mixed with other attributes "
+ "on %<return%> statement");
+ }
+ c_parser_statement_after_labels (parser, NULL, NULL_TREE, NULL,
+ astate);
+ return result;
+ }
+ }
/* Provide better error recovery. Note that a type name here is usually
better diagnosed as a redeclaration. */
@@ -7373,8 +7400,12 @@ c_parser_handle_musttail (c_parser *parser, tree std_attrs, attr_state &attr)
{
if (c_parser_next_token_is_keyword (parser, RID_RETURN))
{
- if (lookup_attribute ("gnu", "musttail", std_attrs))
+ if (tree a = lookup_attribute ("gnu", "musttail", std_attrs))
{
+ for (; a; a = lookup_attribute ("gnu", "musttail", TREE_CHAIN (a)))
+ if (TREE_VALUE (a))
+ error ("%qs attribute does not take any arguments",
+ "musttail");
std_attrs = remove_attribute ("gnu", "musttail", std_attrs);
attr.musttail_p = true;
}
@@ -8237,7 +8268,8 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p,
case RID_ATTRIBUTE:
{
/* Allow '__attribute__((fallthrough));' or
- '__attribute__((assume(cond)));'. */
+ '__attribute__((assume(cond)));' or
+ '__attribute__((musttail))) return'. */
tree attrs = c_parser_gnu_attributes (parser);
bool has_assume = lookup_attribute ("assume", attrs);
if (has_assume)
@@ -8252,6 +8284,20 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p,
has_assume = false;
}
}
+ gcc_assert (!astate.musttail_p);
+ attrs = c_parser_handle_musttail (parser, attrs, astate);
+ if (astate.musttail_p)
+ {
+ if (attrs)
+ {
+ auto_urlify_attributes sentinel;
+ warning_at (c_parser_peek_token (parser)->location,
+ OPT_Wattributes,
+ "attribute %<musttail%> mixed with other "
+ "attributes on %<return%> statement");
+ }
+ goto restart;
+ }
if (attribute_fallthrough_p (attrs))
{
if (c_parser_next_token_is (parser, CPP_SEMICOLON))