From patchwork Wed Jul 15 13:08:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 1329479 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=acm.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=sdpH0P8g; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4B6HlM2MTmz9sTN for ; Wed, 15 Jul 2020 23:09:03 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id F2BD73870868; Wed, 15 Jul 2020 13:09:00 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-qt1-x82a.google.com (mail-qt1-x82a.google.com [IPv6:2607:f8b0:4864:20::82a]) by sourceware.org (Postfix) with ESMTPS id 2BECF385ED4D for ; Wed, 15 Jul 2020 13:08:58 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 2BECF385ED4D Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=acm.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=nathanmsidwell@gmail.com Received: by mail-qt1-x82a.google.com with SMTP id u12so1533830qth.12 for ; Wed, 15 Jul 2020 06:08:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:to:from:subject:message-id:date:user-agent:mime-version :content-language; bh=t7BnD3vMG47S0DCzw/43BGZCke+JpgN4S5MFdmmEXBE=; b=sdpH0P8gXIRXjV9qPNEuDOAO8wrgrmNTJ1ch3Nk+m+iTcciT+Wb9ikVXcY8BL8fCOe rRY/QIls5wITRc263/NUVckqn/jA4YrJeVyEg5zr7UA0JH2KCC95QJGGnC0otEDMMQRD kVhrKG1Mmnxl6OEO7ZfZzkFwCFQC8I7W1wtP9kB9j5TNtpmihKSzifZeqvEiI/HvqM7l VZ2Ob9ihumIQpKMljX6G2d5qI/HMs7+ApwKMyXaUDpbFe2UtPPQ3m5hcnI4Yh5HFeNFV BoXA4w3H4zZGY8CEsg7Yd0kWmG/CQNMj7UxrKzy0bQoOtjSFe/CxPSkQ8kJSD3fnBfpP cHcg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:to:from:subject:message-id:date :user-agent:mime-version:content-language; bh=t7BnD3vMG47S0DCzw/43BGZCke+JpgN4S5MFdmmEXBE=; b=ICEoRsA9aB840Ac/TyXJuCuJ2mqpS+0XtikjwHnwUO9ZRJkcQIgti0xqqzC152P9wt 6NOTjjJ1t/K0fnVIpqnhD9WYUczm+LRHZsU4N3VVux0F+pnfK9ZBlzG9AzMIJXMWv6fL Gy17iwttFgBQW1b6E8rlY1oy4fZrefsu8MsZoGKHFL/yIN3VfG/hcOdf3+V41EKLQ6lc 6GeAU+fyNVbIkysAUmPfU/sZMuRLTqAvbdvMVPQVOpOb+BWslKlYvVVO96k4z+k+6h/g Y8UhZ61mqyXX31QhpPoshizxxsP0byqEmYenS62SilIli/uesDSziqU9oD/BfBo1UoyF RVJQ== X-Gm-Message-State: AOAM5322fG8C5VSpGU+hUZcI7XQzRzsFNo6KR+8tRn5qDkBncipiCDlN NqC/lQdgP2gJpqrtjhwHbts= X-Google-Smtp-Source: ABdhPJxwD0/u8/byYnyv14D2/HAFt+/wYyZTn3Nnfu8MjvEvv/qGENx9bg7+DFdZ2/HN1+lmuo+7sw== X-Received: by 2002:ac8:ac3:: with SMTP id g3mr10259234qti.178.1594818537216; Wed, 15 Jul 2020 06:08:57 -0700 (PDT) Received: from ?IPv6:2620:10d:c0a8:1102:a175:4a66:2ef2:dc82? ([2620:10d:c091:480::1:ddcf]) by smtp.googlemail.com with ESMTPSA id g145sm2294485qke.17.2020.07.15.06.08.55 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 15 Jul 2020 06:08:56 -0700 (PDT) To: GCC Patches From: Nathan Sidwell Subject: c++: error recovery & pragmas Message-ID: <7b9cf161-6bd1-d6b6-767b-898f7d467156@acm.org> Date: Wed, 15 Jul 2020 09:08:54 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.5.0 MIME-Version: 1.0 Content-Language: en-US X-Spam-Status: No, score=-10.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_EF, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" Parser error recovery can get confused by the tokens within a deferred pragma, as treats those as regular tokens. This adjusts the recovery so that the pragma is treated as a unit. Also, the preprocessor now ensures that we never have an EOF token inside a pragma -- the pragma is always closed first. In case you're wondering, C++ modules has some preprocessor-recognized constructs that are naturally passed through as deferred pragmas, but with neither '#' nor 'pragma' being in the source. gcc/cp/ * parser.c (cp_parser_skip_to_closing_parenthesis_1): Deal with meeting a deferred pragma. (cp_parser_skip_to_end_of_statement): Likewise. (cp_parser_skip_to_end_of_block_or_statement): Likewise. (cp_parser_skip_to_pragma_eol): We should never meet EOF. (cp_parser_omp_declare_simd): Likewise. (cp_parser_omp_declare_reduction, cp_parser_oacc_routine) (pragma_lex): Likewise. gcc/testsuite/ * g++.dg/parse/pragma-recovery.C: New. pushed diff --git c/gcc/cp/parser.c w/gcc/cp/parser.c index 08cfd23d8c4..1532431378e 100644 --- c/gcc/cp/parser.c +++ w/gcc/cp/parser.c @@ -3689,6 +3689,11 @@ cp_parser_skip_to_closing_parenthesis_1 (cp_parser *parser, condop_depth--; break; + case CPP_PRAGMA: + /* We fell into a pragma. Skip it, and continue. */ + cp_parser_skip_to_pragma_eol (parser, token); + continue; + default: break; } @@ -3780,6 +3785,13 @@ cp_parser_skip_to_end_of_statement (cp_parser* parser) ++nesting_depth; break; + case CPP_PRAGMA: + /* We fell into a pragma. Skip it, and continue or return. */ + cp_parser_skip_to_pragma_eol (parser, token); + if (!nesting_depth) + return; + continue; + default: break; } @@ -3855,6 +3867,13 @@ cp_parser_skip_to_end_of_block_or_statement (cp_parser* parser) nesting_depth++; break; + case CPP_PRAGMA: + /* Skip it, and continue or return. */ + cp_parser_skip_to_pragma_eol (parser, token); + if (!nesting_depth) + return; + continue; + default: break; } @@ -3921,8 +3940,15 @@ cp_parser_skip_to_pragma_eol (cp_parser* parser, cp_token *pragma_tok) parser->lexer->in_pragma = false; do - token = cp_lexer_consume_token (parser->lexer); - while (token->type != CPP_PRAGMA_EOL && token->type != CPP_EOF); + { + /* The preprocessor makes sure that a PRAGMA_EOL token appears + before an EOF token, even when the EOF is on the pragma line. + We should never get here without being inside a deferred + pragma. */ + gcc_checking_assert (cp_lexer_next_token_is_not (parser->lexer, CPP_EOF)); + token = cp_lexer_consume_token (parser->lexer); + } + while (token->type != CPP_PRAGMA_EOL); /* Ensure that the pragma is not parsed again. */ cp_lexer_purge_tokens_after (parser->lexer, pragma_tok); @@ -41470,11 +41496,8 @@ cp_parser_omp_declare_simd (cp_parser *parser, cp_token *pragma_tok, } /* Store away all pragma tokens. */ - while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL) - && cp_lexer_next_token_is_not (parser->lexer, CPP_EOF)) + while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)) cp_lexer_consume_token (parser->lexer); - if (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)) - parser->omp_declare_simd->error_seen = true; cp_parser_require_pragma_eol (parser, pragma_tok); struct cp_token_cache *cp = cp_token_cache_new (pragma_tok, cp_lexer_peek_token (parser->lexer)); @@ -42534,11 +42557,8 @@ cp_parser_omp_declare_reduction (cp_parser *parser, cp_token *pragma_tok, { if (cp == NULL) { - while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL) - && cp_lexer_next_token_is_not (parser->lexer, CPP_EOF)) + while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)) cp_lexer_consume_token (parser->lexer); - if (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)) - goto fail; cp = cp_token_cache_new (first_token, cp_lexer_peek_nth_token (parser->lexer, 2)); @@ -43017,11 +43037,8 @@ cp_parser_oacc_routine (cp_parser *parser, cp_token *pragma_tok, else /* No optional '( name )'. */ { /* Store away all pragma tokens. */ - while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL) - && cp_lexer_next_token_is_not (parser->lexer, CPP_EOF)) + while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)) cp_lexer_consume_token (parser->lexer); - if (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)) - parser->oacc_routine->error_seen = true; cp_parser_require_pragma_eol (parser, pragma_tok); struct cp_token_cache *cp = cp_token_cache_new (pragma_tok, cp_lexer_peek_token (parser->lexer)); @@ -44014,7 +44031,7 @@ pragma_lex (tree *value, location_t *loc) if (loc) *loc = tok->location; - if (ret == CPP_PRAGMA_EOL || ret == CPP_EOF) + if (ret == CPP_PRAGMA_EOL) ret = CPP_EOF; else if (ret == CPP_STRING) *value = cp_parser_string_literal (the_parser, false, false); diff --git c/gcc/testsuite/g++.dg/parse/pragma-recovery.C w/gcc/testsuite/g++.dg/parse/pragma-recovery.C new file mode 100644 index 00000000000..cc9d323ad19 --- /dev/null +++ w/gcc/testsuite/g++.dg/parse/pragma-recovery.C @@ -0,0 +1,32 @@ +/* { dg-additional-options -fopenmp } */ +/* { dg-require-effective-target fopenmp } */ + +// Make sure error recovery doesn't get confused by tokens inside a +// deferred pragma. +// OpenMP is a convenient deferred pragma insertion mechanism. + +void foo () +{ + 1 * "" // { dg-error "invalid" } +#pragma omp atomic { + ; + + } + +void bar () +{ + 1 * "" // { dg-error "invalid" } +#pragma omp atomic } + ; + + } + +void baz () +{ + 1 * "" // { dg-error "invalid" } +#pragma omp atomic ; + 0; + + + } +