From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2153) id C000C3857430; Thu, 12 Aug 2021 07:34:27 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C000C3857430 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Jakub Jelinek To: gcc-cvs@gcc.gnu.org Subject: [gcc r12-2871] c++: Fix up parsing of attributes for using-directive X-Act-Checkin: gcc X-Git-Author: Jakub Jelinek X-Git-Refname: refs/heads/master X-Git-Oldrev: 2bdf17de1d0ad7a75d3474e672a3a2110919862f X-Git-Newrev: 3890c28ac5bd03ba334a20fbf9518a37dcdbfe5d Message-Id: <20210812073427.C000C3857430@sourceware.org> Date: Thu, 12 Aug 2021 07:34:27 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 12 Aug 2021 07:34:27 -0000 https://gcc.gnu.org/g:3890c28ac5bd03ba334a20fbf9518a37dcdbfe5d commit r12-2871-g3890c28ac5bd03ba334a20fbf9518a37dcdbfe5d Author: Jakub Jelinek Date: Thu Aug 12 09:09:39 2021 +0200 c++: Fix up parsing of attributes for using-directive As I've said earlier and added xfails in gen-attrs-76.C test, https://eel.is/c++draft/namespace.udir#nt:using-directive has attribute-specifier-seq[opt] at the start, not at the end before ; as gcc is expecting. IMHO we should continue parsing at the end the GNU attributes because using namespace N __attribute__((strong));, while not supported anymore, used to be supported in the past, but my code searches for using namespace N [[gnu::strong]]; didn't reveal anything at all. 2021-08-12 Jakub Jelinek * parser.c (cp_parser_block_declaration): Call cp_parser_using_directive for C++11 attributes followed by using namespace tokens. (cp_parser_using_directive): Parse C++11 attributes at the start of the directive rather than at the end, only parse GNU attributes at the end. * g++.dg/lookup/strong-using.C: Add test using [[gnu::strong]] as well. * g++.dg/lookup/strong-using2.C: Likewise. * g++.dg/cpp0x/gen-attrs-58.C: Move alignas(int) before using namespace. * g++.dg/cpp0x/gen-attrs-59.C: Move alignas(X) before using namespace, add tests for alignas before semicolon. * g++.dg/cpp0x/gen-attrs-76.C: Remove xfails. Add test for C++11 attributes on using directive before semicolon. Diff: --- gcc/cp/parser.c | 31 ++++++++++++++++++++++++----- gcc/testsuite/g++.dg/cpp0x/gen-attrs-58.C | 2 +- gcc/testsuite/g++.dg/cpp0x/gen-attrs-59.C | 9 ++++++++- gcc/testsuite/g++.dg/cpp0x/gen-attrs-76.C | 7 +++++-- gcc/testsuite/g++.dg/lookup/strong-using.C | 9 +++++++++ gcc/testsuite/g++.dg/lookup/strong-using2.C | 9 +++++++++ 6 files changed, 58 insertions(+), 9 deletions(-) diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index d564e3ba2fa..ec885d774f2 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -14853,6 +14853,7 @@ cp_parser_block_declaration (cp_parser *parser, /* Peek at the next token to figure out which kind of declaration is present. */ cp_token *token1 = cp_lexer_peek_token (parser->lexer); + size_t attr_idx; /* If the next keyword is `asm', we have an asm-definition. */ if (token1->keyword == RID_ASM) @@ -14906,6 +14907,18 @@ cp_parser_block_declaration (cp_parser *parser, /* If the next token is `static_assert' we have a static assertion. */ else if (token1->keyword == RID_STATIC_ASSERT) cp_parser_static_assert (parser, /*member_p=*/false); + /* If the next tokens after attributes is `using namespace', then we have + a using-directive. */ + else if ((attr_idx = cp_parser_skip_std_attribute_spec_seq (parser, 1)) != 1 + && cp_lexer_nth_token_is_keyword (parser->lexer, attr_idx, + RID_USING) + && cp_lexer_nth_token_is_keyword (parser->lexer, attr_idx + 1, + RID_NAMESPACE)) + { + if (statement_p) + cp_parser_commit_to_tentative_parse (parser); + cp_parser_using_directive (parser); + } /* Anything else must be a simple-declaration. */ else cp_parser_simple_declaration (parser, !statement_p, @@ -21609,14 +21622,21 @@ cp_parser_alias_declaration (cp_parser* parser) /* Parse a using-directive. using-directive: - using namespace :: [opt] nested-name-specifier [opt] - namespace-name ; */ + attribute-specifier-seq [opt] using namespace :: [opt] + nested-name-specifier [opt] namespace-name ; */ static void cp_parser_using_directive (cp_parser* parser) { tree namespace_decl; - tree attribs; + tree attribs = cp_parser_std_attribute_spec_seq (parser); + if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)) + { + /* Error during attribute parsing that resulted in skipping + to next semicolon. */ + cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); + return; + } /* Look for the `using' keyword. */ cp_parser_require_keyword (parser, RID_USING, RT_USING); @@ -21633,8 +21653,9 @@ cp_parser_using_directive (cp_parser* parser) /* Get the namespace being used. */ namespace_decl = cp_parser_namespace_name (parser); cp_warn_deprecated_use_scopes (namespace_decl); - /* And any specified attributes. */ - attribs = cp_parser_attributes_opt (parser); + /* And any specified GNU attributes. */ + if (cp_next_tokens_can_be_gnu_attribute_p (parser)) + attribs = chainon (attribs, cp_parser_gnu_attributes_opt (parser)); /* Update the symbol table. */ finish_using_directive (namespace_decl, attribs); diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-58.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-58.C index f760f560828..dc01722062a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-58.C +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-58.C @@ -2,4 +2,4 @@ // { dg-do compile { target c++11 } } namespace N { int i; } -using namespace N alignas(int); // { dg-warning "ignored" } +alignas(int) using namespace N; // { dg-warning "ignored" } diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-59.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-59.C index c7839fefed9..9776dc33745 100644 --- a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-59.C +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-59.C @@ -2,4 +2,11 @@ // { dg-do compile { target c++11 } } namespace N {} -using namespace N alignas(X); // { dg-error "declared" } +alignas(X) using namespace N; // { dg-error "declared" } +namespace O {} +using namespace O alignas(X); // { dg-error "expected" } +// { dg-error "declared" "" { target *-*-* } .-1 } +// { dg-warning "attribute ignored" "" { target *-*-* } .-2 } +namespace P {} +using namespace P alignas(int); // { dg-error "expected" } +// { dg-warning "attribute ignored" "" { target *-*-* } .-1 } diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-76.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-76.C index cbda8de327e..72cd4b33e93 100644 --- a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-76.C +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-76.C @@ -3,6 +3,7 @@ namespace N {} namespace O { typedef int T; }; +namespace P {} void foo () @@ -11,7 +12,8 @@ foo () [[]] __extension__ asm (""); // { dg-error "expected" } __extension__ [[]] asm (""); // { dg-error "expected" } [[]] namespace M = ::N; // { dg-error "expected" } - [[]] using namespace N; // { dg-bogus "expected" "" { xfail *-*-* } } + [[]] using namespace N; // { dg-bogus "expected" } + using namespace P [[]]; // { dg-error "expected" } [[]] using O::T; // { dg-error "expected" } [[]] __label__ foo; // { dg-error "expected" } [[]] static_assert (true, ""); // { dg-error "expected" } @@ -24,7 +26,8 @@ bar () [[gnu::unused]] __extension__ asm (""); // { dg-error "expected" } __extension__ [[gnu::unused]] asm (""); // { dg-error "expected" } [[gnu::unused]] namespace M = ::N; // { dg-error "expected" } - [[gnu::unused]] using namespace N; // { dg-bogus "expected" "" { xfail *-*-* } } + [[gnu::unused]] using namespace N; // { dg-bogus "expected" } + using namespace P [[gnu::unused]]; // { dg-error "expected" } [[gnu::unused]] using O::T; // { dg-error "expected" } [[gnu::unused]] __label__ foo; // { dg-error "expected" } [[gnu::unused]] static_assert (true, ""); // { dg-error "expected" } diff --git a/gcc/testsuite/g++.dg/lookup/strong-using.C b/gcc/testsuite/g++.dg/lookup/strong-using.C index 9d58fddbb8f..2bd821ea219 100644 --- a/gcc/testsuite/g++.dg/lookup/strong-using.C +++ b/gcc/testsuite/g++.dg/lookup/strong-using.C @@ -8,3 +8,12 @@ namespace A using namespace B __attribute__ ((strong)); // { dg-warning "no longer supported" "" } } + +namespace C +{ + namespace D // { dg-message "inline namespace" } + { + } + + [[gnu::strong]] using namespace D; // { dg-warning "no longer supported" "" } +} diff --git a/gcc/testsuite/g++.dg/lookup/strong-using2.C b/gcc/testsuite/g++.dg/lookup/strong-using2.C index 17284949645..989827cacd3 100644 --- a/gcc/testsuite/g++.dg/lookup/strong-using2.C +++ b/gcc/testsuite/g++.dg/lookup/strong-using2.C @@ -9,3 +9,12 @@ namespace A using namespace B __attribute__ ((strong)); // { dg-bogus "no longer supported" } } + +namespace C +{ + namespace D // { dg-bogus "inline namespace" } + { + } + + [[gnu::strong]] using namespace D; // { dg-bogus "no longer supported" } +}