From patchwork Wed Nov 10 20:12:57 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Tobias Burnus X-Patchwork-Id: 47429 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 7DB7C3858002 for ; Wed, 10 Nov 2021 20:13:24 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from esa1.mentor.iphmx.com (esa1.mentor.iphmx.com [68.232.129.153]) by sourceware.org (Postfix) with ESMTPS id 2FE603858D35 for ; Wed, 10 Nov 2021 20:13:07 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 2FE603858D35 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=codesourcery.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=mentor.com IronPort-SDR: BXrp1ineMoXG9BxEuNAbCujBoWcR+hrlS6EvC07vEPXRUFLkUR0UazdQyYG8vzVwTV/Z3b/Pls Tl7aKERKGLoI0qHZefyiSBD7lfYZsCHA0cTpdPd3RjkM1vichVGuL4Nr4KnvGRJpWsfwi5G/ji iQdLAAB2eIVMIerCWyW/Z98tvAw7aBqhZBAMWk/Nvpz+q0oYn3JkehNmerQkpKanbwkDqVzWVp iBr1LpDz/xPTzAytXce/LvYQz6Z6bELCFHHPepCHf+fUmokkMMT4xI2MOLcx2+BahnfIrMjFYK PueWtD00ymZDakvsqgaT3TLd X-IronPort-AV: E=Sophos;i="5.87,224,1631606400"; d="diff'?scan'208";a="70789659" Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa1.mentor.iphmx.com with ESMTP; 10 Nov 2021 12:13:07 -0800 IronPort-SDR: snaCBxWQ6Th3Bbv6s2gdNVVEzU84ENgb75JQxLM/NESsGKMU0MV00C402ui8a5MqyriLtXMrqD rxY97mn/Tk2vc0fa6rCT14YjMW/yISp6ShAla/E4tiAG4nWaQxKrAVX0ksFuBcd9ggSzCK+IvE UWRiMVOuSo0iISCTptYg+iZQiy4JFRzaA2fyEUus+nRsGISNKhJdiZPP/G6KsIrCxcC+vdnyNA +p7Jh+JdCfdgJZW0Hc6Hk36Z73WPCPRR7OxjSyYmb5hpRNnuRz0ij3//wdNP785yEGvRHb8+QA 96U= Message-ID: <5e77a918-1943-03dc-5bb7-20eebfc61226@codesourcery.com> Date: Wed, 10 Nov 2021 21:12:57 +0100 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.3.0 Content-Language: en-US To: gcc-patches , Jakub Jelinek From: Tobias Burnus Subject: [Patch] libcpp: Fix _Pragma in #__VA_ARGS__ [PR103165] X-Originating-IP: [137.202.0.90] X-ClientProxiedBy: svr-ies-mbx-02.mgc.mentorg.com (139.181.222.2) To svr-ies-mbx-01.mgc.mentorg.com (139.181.222.1) X-Spam-Status: No, score=-11.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, KAM_DMARC_STATUS, KAM_SHORT, SPF_HELO_PASS, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" This patch fixes a pseudo regression of my previous _Pragma patch. The issue was that a tokenized '_Pragma' (-> CPP_PRAGMA) could end up as to-be quoted argument ('#__VA_ARG__') and that wasn't never handled and gave an ICE for a GCC after my previous patch and before this patch. The expected 'gcc -E' output is in the '#if 0' block in the testcase. Before my previous patch, "gcc -E" yielded the following, which is obviously wrong: const char *str = #pragma omp error severity(warning) message ("Test") at(compilation) "\"1,2\" ;" ; #pragma omp error severity(warning) message ("Test") at(compilation) ; Build on x86-64-gnu-linux, the "make -k check" is running. OK when it passes? * * * Disclaimer: While this patch does a step into the right direction, it probably does help with any of the other _Pragma issues. Neither with 'gcc -E' when the pragma wasn't registered (still expanded too early) nor with the 'GCC diagnostic' issues in general as there the input_location is used to decide when to pop - and depending on the column numbers, this may or may not work. See https://gcc.gnu.org/pipermail/gcc-patches/2021-October/582927.html for some more details and links to PRs. Tobias ----------------- Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955 libcpp: Fix _Pragma in #__VA_ARGS__ [PR103165] Using '#define inner(...) #__VA_ARGS__ _Pragma("...")' yields a string plus the _Pragma, passing this to another '#__VA_ARGS__' lead to having a CPP_PRAGMA inside stringify_arg, which wasn't handled before this commit and gave an ICE. In GCC versions before r12-4797-g0078a058 (cf. PR102409), instead of giving an ICE, the _Pragma wasn't stringified but output as a #pragma before the actual macro expansion. PR preprocessor/103165 libcpp/ChangeLog: * directives.c (_cpp_get_pragma_by_id): New. * internal.h (_cpp_get_pragma_by_id): New prototype. * macro.c (stringify_arg): Use it; hande stringification of _Pragma. gcc/testsuite/ChangeLog: * c-c++-common/gomp/pragma-3.c: New test. * c-c++-common/gomp/pragma-4.c: New test. gcc/testsuite/c-c++-common/gomp/pragma-3.c | 20 ++++++++++++++++++++ gcc/testsuite/c-c++-common/gomp/pragma-4.c | 20 ++++++++++++++++++++ libcpp/directives.c | 23 +++++++++++++++++++++++ libcpp/internal.h | 3 +++ libcpp/macro.c | 29 +++++++++++++++++++++++++++-- 5 files changed, 93 insertions(+), 2 deletions(-) diff --git a/gcc/testsuite/c-c++-common/gomp/pragma-3.c b/gcc/testsuite/c-c++-common/gomp/pragma-3.c new file mode 100644 index 00000000000..f8b741138e7 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/pragma-3.c @@ -0,0 +1,20 @@ +/* { dg-additional-options "-fdump-tree-original" } */ +/* PR preprocessor/103165 */ + +#define inner(...) #__VA_ARGS__ ; _Pragma("omp error severity(warning) message (\"Test\") at(compilation)") +#define outer(...) inner(__VA_ARGS__) + +void +f (void) +{ + const char *str = outer(inner(1,2)); /* { dg-warning "'pragma omp error' encountered: Test" } */ +} + +#if 0 +After preprocessing, the expected result are the following three lines: + const char *str = "\"1,2\" ; _Pragma(\"omp error severity(warning) message (\"Test\") at(compilation)\")" ; +#pragma omp error severity(warning) message ("Test") at(compilation) + ; +#endif + +/* { dg-final { scan-tree-dump "const char \\* str = \\(const char \\*\\) \"\\\\\"1,2\\\\\" ; _Pragma\\(\\\\\"omp error severity\\(warning\\) message \\(\\\\\"Test\\\\\"\\) at\\(compilation\\)\\\\\"\\)\";" "original" } } */ diff --git a/gcc/testsuite/c-c++-common/gomp/pragma-4.c b/gcc/testsuite/c-c++-common/gomp/pragma-4.c new file mode 100644 index 00000000000..608dddc7e6a --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/pragma-4.c @@ -0,0 +1,20 @@ +/* { dg-additional-options "-fdump-tree-original -save-temps" } */ +/* PR preprocessor/103165 */ + +#define inner(...) #__VA_ARGS__ ; _Pragma("omp error severity(warning) message (\"Test\") at(compilation)") +#define outer(...) inner(__VA_ARGS__) + +void +f (void) +{ + const char *str = outer(inner(1,2)); /* { dg-warning "'pragma omp error' encountered: Test" } */ +} + +#if 0 +After preprocessing, the expected result are the following three lines: + const char *str = "\"1,2\" ; _Pragma(\"omp error severity(warning) message (\"Test\") at(compilation)\")" ; +#pragma omp error severity(warning) message ("Test") at(compilation) + ; +#endif + +/* { dg-final { scan-tree-dump "const char \\* str = \\(const char \\*\\) \"\\\\\"1,2\\\\\" ; _Pragma\\(\\\\\"omp error severity\\(warning\\) message \\(\\\\\"Test\\\\\"\\) at\\(compilation\\)\\\\\"\\)\";" "original" } } */ diff --git a/libcpp/directives.c b/libcpp/directives.c index 34f7677f718..9eefb20d4d4 100644 --- a/libcpp/directives.c +++ b/libcpp/directives.c @@ -1236,6 +1236,29 @@ do_ident (cpp_reader *pfile) check_eol (pfile, false); } +/* Convert a pragma id back to the space + name. Currently used by + stringify_arg for _Pragma. The assumption is that it is only very rarely + called such that O(num-pragmas + num-pragma-spaces) checks is acceptable. */ +void +_cpp_get_pragma_by_id (cpp_reader *pfile, const cpp_token *token, + cpp_hashnode const **space, cpp_hashnode const **name) +{ + struct pragma_entry *s, *n = NULL; + for (s = pfile->pragmas; s; s = s->next) + { + if (!s->is_nspace) + continue; + for (n = s->u.space; n; n = n->next) + if (token->val.pragma == n->u.ident) + break; + if (n) + break; + } + gcc_assert (s && n); + *space = s->pragma; + *name = n->pragma; +} + /* Lookup a PRAGMA name in a singly-linked CHAIN. Returns the matching entry, or NULL if none is found. The returned entry could be the start of a namespace chain, or a pragma. */ diff --git a/libcpp/internal.h b/libcpp/internal.h index 8577cab6c83..9e31564cf23 100644 --- a/libcpp/internal.h +++ b/libcpp/internal.h @@ -762,6 +762,9 @@ extern void _cpp_define_builtin (cpp_reader *, const char *); extern char ** _cpp_save_pragma_names (cpp_reader *); extern void _cpp_restore_pragma_names (cpp_reader *, char **); extern int _cpp_do__Pragma (cpp_reader *, location_t); +extern void _cpp_get_pragma_by_id (cpp_reader *, const cpp_token*, + cpp_hashnode const **, + cpp_hashnode const **); extern void _cpp_init_directives (cpp_reader *); extern void _cpp_init_internal_pragmas (cpp_reader *); extern void _cpp_do_file_change (cpp_reader *, enum lc_reason, const char *, diff --git a/libcpp/macro.c b/libcpp/macro.c index b2f797cae35..1642b96e835 100644 --- a/libcpp/macro.c +++ b/libcpp/macro.c @@ -839,6 +839,7 @@ stringify_arg (cpp_reader *pfile, const cpp_token **first, unsigned int count, unsigned int i, escape_it, backslash_count = 0; const cpp_token *source = NULL; size_t len; + cpp_hashnode const *pragma_space = NULL, *pragma_name = NULL; if (BUFF_ROOM (pfile->u_buff) < 3) _cpp_extend_buff (pfile, &pfile->u_buff, 3); @@ -887,7 +888,15 @@ stringify_arg (cpp_reader *pfile, const cpp_token **first, unsigned int count, /* Room for each char being written in octal, initial space and final quote and NUL. */ - len = cpp_token_len (token); + if (token->type == CPP_PRAGMA) + { + gcc_assert (token->flags & PRAGMA_OP); + _cpp_get_pragma_by_id (pfile, token, &pragma_space, &pragma_name); + len = (strlen ("_Pragma(\"") + pragma_space->ident.len + + 1 + pragma_name->ident.len); + } + else + len = cpp_token_len (token); if (escape_it) len *= 4; len += 3; @@ -909,7 +918,23 @@ stringify_arg (cpp_reader *pfile, const cpp_token **first, unsigned int count, } source = NULL; - if (escape_it) + if (token->type == CPP_PRAGMA) + { + memcpy (dest, "_Pragma(\\\"", strlen("_Pragma(\\\"")); + dest += strlen("_Pragma(\\\""); + memcpy (dest, pragma_space->ident.str, pragma_space->ident.len); + dest += pragma_space->ident.len; + *dest = ' '; + dest++; + memcpy (dest, pragma_name->ident.str, pragma_name->ident.len); + dest += pragma_name->ident.len; + } + else if (token->type == CPP_PRAGMA_EOL) + { + memcpy (dest, "\\\")", 3); + dest += 3; + } + else if (escape_it) { _cpp_buff *buff = _cpp_get_buff (pfile, len); unsigned char *buf = BUFF_FRONT (buff);