From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 28326 invoked by alias); 16 Feb 2018 12:43:53 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 28312 invoked by uid 89); 16 Feb 2018 12:43:52 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.9 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_LOW,T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy= X-Spam-User: qpsmtpd, 2 recipients X-HELO: mx1.redhat.com Received: from mx3-rdu2.redhat.com (HELO mx1.redhat.com) (66.187.233.73) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 16 Feb 2018 12:43:51 +0000 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id EB2EE4084FF2; Fri, 16 Feb 2018 12:43:44 +0000 (UTC) Received: from [10.36.117.10] (ovpn-117-10.ams2.redhat.com [10.36.117.10]) by smtp.corp.redhat.com (Postfix) with ESMTPS id CE741213AEE2; Fri, 16 Feb 2018 12:43:43 +0000 (UTC) Subject: Re: RFA: Sanitize deprecation messages (PR 84195) To: David Malcolm , Martin Sebor , msebor@gcc.gnu.org Cc: dodji@redhat.com, gcc-patches@gcc.gnu.org References: <87h8qv9xhb.fsf@redhat.com> <79784243-bf45-167f-a546-55c892ea02e9@gmail.com> <93d668b3-30d1-e898-544f-19a153325e03@redhat.com> <1518031052.26503.90.camel@redhat.com> <0d7e6077-0d67-0c7b-5058-fc66e7c18d87@gmail.com> <1518728685.2913.14.camel@redhat.com> From: Nick Clifton Message-ID: Date: Fri, 16 Feb 2018 12:43:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.5.2 MIME-Version: 1.0 In-Reply-To: <1518728685.2913.14.camel@redhat.com> Content-Type: multipart/mixed; boundary="------------1A9E2D804D2830BFBEFA6D0A" X-IsSubscribed: yes X-SW-Source: 2018-02/txt/msg00977.txt.bz2 This is a multi-part message in MIME format. --------------1A9E2D804D2830BFBEFA6D0A Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit Content-length: 1070 Hi David, Attached is a revised version of the patch which I hope addresses all of your (very helpful) comments on the v3 patch. OK to apply once the sources are back on stage 1 ? Cheers Nick gcc/ChangeLog 2018-02-09 Nick Clifton PR 84195 * tree.c (escaped_string): New class. Converts an unescaped string into its escaped equivalent. (warn_deprecated_use): Use the new class to convert the deprecation message, if present. (test_escaped_strings): New self test. (test_c_tests): Add test_escaped_strings. * doc/extend.texi (deprecated): Add a note that the deprecation message is affected by the -fmessage-length option, and that control characters will be escaped. (#pragma GCC error): Document this pragma. (#pragma GCC warning): Likewise. * doc/invoke.texi (-fmessage-length): Document this option's effect on the #warning and #error preprocessor directives and the deprecated attribute. gcc/testsuite/ChangeLog 2018-02-09 Nick Clifton PR 84195 * gcc.c-torture/compile/pr84195.c: New test. --------------1A9E2D804D2830BFBEFA6D0A Content-Type: application/x-troff-man; name="pr84195.patch.4" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="pr84195.patch.4" Content-length: 11551 gcc/ChangeLog 2018-02-09 Nick Clifton PR 84195 * tree.c (escaped_string): New class. Converts an unescaped string into its escaped equivalent. (warn_deprecated_use): Use the new class to convert the deprecation message, if present. (test_escaped_strings): New self test. (test_c_tests): Add test_escaped_strings. * doc/extend.texi (deprecated): Add a note that the deprecation message is affected by the -fmessage-length option, and that control characters will be escaped. (#pragma GCC error): Document this pragma. (#pragma GCC warning): Likewise. * doc/invoke.texi (-fmessage-length): Document this option's effect on the #warning and #error preprocessor directives and the deprecated attribute. gcc/testsuite/ChangeLog 2018-02-09 Nick Clifton PR 84195 * gcc.c-torture/compile/pr84195.c: New test. Index: gcc/doc/extend.texi =================================================================== --- gcc/doc/extend.texi (revision 257653) +++ gcc/doc/extend.texi (working copy) @@ -2563,6 +2563,9 @@ The @code{deprecated} attribute can also be used for variables and types (@pxref{Variable Attributes}, @pxref{Type Attributes}.) +The message attached to the attribute is affected by the setting of +the @option{-fmessage-length} option. + @item error ("@var{message}") @itemx warning ("@var{message}") @cindex @code{error} function attribute @@ -6077,6 +6080,9 @@ types (@pxref{Common Function Attributes}, @pxref{Common Type Attributes}). +The message attached to the attribute is affected by the setting of +the @option{-fmessage-length} option. + @item nonstring @cindex @code{nonstring} variable attribute The @code{nonstring} variable attribute specifies that an object or member @@ -7035,11 +7041,16 @@ deprecated. Line 5 has no warning because T3 is explicitly deprecated. Similarly for line 6. The optional @var{msg} argument, which must be a string, is printed in the warning if -present. +present. Control characters in the string will be replaced with +spaces, and if the @option{-fmessage-length} option is set to 0 (its +default value) then any newline characters will also be replaced. The @code{deprecated} attribute can also be used for functions and variables (@pxref{Function Attributes}, @pxref{Variable Attributes}.) +The message attached to the attribute is affected by the setting of +the @option{-fmessage-length} option. + @item designated_init @cindex @code{designated_init} type attribute This attribute may only be applied to structure types. It indicates @@ -22372,7 +22383,9 @@ @cindex pragma, diagnostic Prints @var{string} as a compiler message on compilation. The message -is informational only, and is neither a compilation warning nor an error. +is informational only, and is neither a compilation warning nor an +error. Newlines can be included in the string by using the @samp{\n} +escape sequence. @smallexample #pragma message "Compiling " __FILE__ "..." @@ -22392,6 +22405,37 @@ prints @samp{/tmp/file.c:4: note: #pragma message: TODO - Remember to fix this}. +@item #pragma GCC error @var{message} +@cindex pragma, diagnostic +Generates an error message. This pragma @emph{is} considered to +indicate an error in the compilation, and it will be treated as such. + +Newlines can be included in the string by using the @samp{\n} +escape sequence. They will be displayed as newlines even if the +@option{-fmessage-length} option is set to zero. + +The error is only generated if the pragma is present in the code after +pre-processing has been completed. It does not matter however if the +code containing the pragma is unreachable: + +@smallexample +#if 0 +#pragma GCC error "this error is not seen" +#endif +void foo (void) +@{ + return; +#pragma GCC error "this error is seen" +@} +@end smallexample + +@item #pragma GCC warning @var{message} +@cindex pragma, diagnostic +This is just like @samp{pragma GCC error} except that a warning +message is issued instead of an error message. Unless +@option{-Werror} is in effect, in which case this pragma will generate +an error as well. + @end table @node Visibility Pragmas Index: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (revision 257653) +++ gcc/doc/invoke.texi (working copy) @@ -3500,6 +3500,11 @@ done; each error message appears on a single line. This is the default for all front ends. +Note - this option also affects the display of the @samp{#error} and +@samp{#warning} pre-processor directives, and the @samp{deprecated} +function/type/variable attribute. It does not however affect the +@samp{pragma GCC warning} and @samp{pragma GCC error} pragmas. + @item -fdiagnostics-show-location=once @opindex fdiagnostics-show-location Only meaningful in line-wrapping mode. Instructs the diagnostic messages Index: gcc/tree.c =================================================================== --- gcc/tree.c (revision 257653) +++ gcc/tree.c (working copy) @@ -12416,11 +12416,101 @@ return is_typedef_decl (TYPE_NAME (type)); } +/* A class to handle converting a string that might contain + control characters, (eg newline, form-feed, etc), into one + in which contains escape sequences instead. */ + +class escaped_string +{ + public: + escaped_string () { m_owned = false; m_str = NULL; }; + ~escaped_string () { if (m_owned) free (m_str); } + operator const char *() const { return (const char *) m_str; } + void escape (const char *); + private: + char *m_str; + bool m_owned; +}; + +/* PR 84195: Replace control characters in "unescaped" with their + escaped equivalents. Allow newlines if -fmessage-length has + been set to a non-zero value. This is done here, rather than + where the attribute is recorded as the message length can + change between these two locations. */ + +void +escaped_string::escape (const char * unescaped) +{ + char *escaped; + size_t i, new_i, len; + + if (m_owned) + free (m_str); + + m_str = (char *) unescaped; + m_owned = false; + + if (unescaped == NULL || *unescaped == 0) + return; + + len = strlen (unescaped); + escaped = NULL; + new_i = 0; + + for (i = 0; i < len; i++) + { + char c = unescaped[i]; + + if (!ISCNTRL (c)) + { + if (escaped) + escaped[new_i++] = c; + continue; + } + + if (c != '\n' || !pp_is_wrapping_line (global_dc->printer)) + { + if (escaped == NULL) + { + /* We only allocate space for a new string if we + actually encounter a control character that + needs replacing. */ + escaped = (char *) xmalloc (len * 2 + 1); + strncpy (escaped, unescaped, i); + new_i = i; + } + + escaped[new_i++] = '\\'; + + switch (c) + { + case '\a': escaped[new_i++] = 'a'; break; + case '\b': escaped[new_i++] = 'b'; break; + case '\f': escaped[new_i++] = 'f'; break; + case '\n': escaped[new_i++] = 'n'; break; + case '\r': escaped[new_i++] = 'r'; break; + case '\t': escaped[new_i++] = 't'; break; + case '\v': escaped[new_i++] = 'v'; break; + default: escaped[new_i++] = '?'; break; + } + } + else if (escaped) + escaped[new_i++] = c; + } + + if (escaped) + { + escaped[new_i] = 0; + m_str = escaped; + m_owned = true; + } +} + /* Warn about a use of an identifier which was marked deprecated. */ void warn_deprecated_use (tree node, tree attr) { - const char *msg; + escaped_string msg; if (node == 0 || !warn_deprecated_decl) return; @@ -12442,9 +12532,7 @@ attr = lookup_attribute ("deprecated", attr); if (attr) - msg = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))); - else - msg = NULL; + msg.escape (TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr)))); bool w; if (DECL_P (node)) @@ -12451,7 +12539,7 @@ { if (msg) w = warning (OPT_Wdeprecated_declarations, - "%qD is deprecated: %s", node, msg); + "%qD is deprecated: %s", node, (const char *) msg); else w = warning (OPT_Wdeprecated_declarations, "%qD is deprecated", node); @@ -12478,7 +12566,7 @@ { if (msg) w = warning (OPT_Wdeprecated_declarations, - "%qE is deprecated: %s", what, msg); + "%qE is deprecated: %s", what, (const char *) msg); else w = warning (OPT_Wdeprecated_declarations, "%qE is deprecated", what); @@ -12487,7 +12575,7 @@ { if (msg) w = warning (OPT_Wdeprecated_declarations, - "type is deprecated: %s", msg); + "type is deprecated: %s", (const char *) msg); else w = warning (OPT_Wdeprecated_declarations, "type is deprecated"); @@ -12501,7 +12589,7 @@ { if (msg) warning (OPT_Wdeprecated_declarations, "%qE is deprecated: %s", - what, msg); + what, (const char *) msg); else warning (OPT_Wdeprecated_declarations, "%qE is deprecated", what); } @@ -12509,7 +12597,7 @@ { if (msg) warning (OPT_Wdeprecated_declarations, "type is deprecated: %s", - msg); + (const char *) msg); else warning (OPT_Wdeprecated_declarations, "type is deprecated"); } @@ -14548,6 +14636,49 @@ check_strip_nops (wrapped_int_var, int_var); } +/* Check that string escaping works correctly. */ + +static void +test_escaped_strings (void) +{ + int saved_cutoff; + escaped_string msg; + + msg.escape (NULL); + /* ASSERT_STREQ does not accept NULL as a valid test + result, so we have to use ASSERT_EQ instead. */ + ASSERT_EQ (NULL, (const char *) msg); + + msg.escape (""); + ASSERT_STREQ ("", (const char *) msg); + + msg.escape ("foobar"); + ASSERT_STREQ ("foobar", (const char *) msg); + + /* Ensure that we have -fmessage-length set to 0. */ + saved_cutoff = pp_line_cutoff (global_dc->printer); + pp_line_cutoff (global_dc->printer) = 0; + + msg.escape ("foo\nbar"); + ASSERT_STREQ ("foo\\nbar", (const char *) msg); + + msg.escape ("\a\b\f\n\r\t\v"); + ASSERT_STREQ ("\\a\\b\\f\\n\\r\\t\\v", (const char *) msg); + + /* Now repeat the tests with -fmessage-length set to 5. */ + pp_line_cutoff (global_dc->printer) = 5; + + /* Note that the newline is not translated into an escape. */ + msg.escape ("foo\nbar"); + ASSERT_STREQ ("foo\nbar", (const char *) msg); + + msg.escape ("\a\b\f\n\r\t\v"); + ASSERT_STREQ ("\\a\\b\\f\n\\r\\t\\v", (const char *) msg); + + /* Restore the original message length setting. */ + pp_line_cutoff (global_dc->printer) = saved_cutoff; +} + /* Run all of the selftests within this file. */ void @@ -14558,6 +14689,7 @@ test_labels (); test_vector_cst_patterns (); test_location_wrappers (); + test_escaped_strings (); } } // namespace selftest --- /dev/null 2018-02-08 08:21:34.475648704 +0000 +++ gcc/testsuite/gcc.c-torture/compile/pr84195.c 2018-02-07 17:20:13.494587052 +0000 @@ -0,0 +1,17 @@ +/* { dg-options "-Wdeprecated-declarations" } */ + +/* Check that MSG is printed without the escape characters being interpreted. + Especially the newlines. + + Note - gcc's behaviour is inconsistent in this regard as #error and + #warning will also display control characters as escape sequences, + whereas #pragma GCC error and #pragma GCC warning will perform the + control operations of the control characters. */ + +#define MSG "foo\n\t\rbar" + +int f (int i __attribute__ ((deprecated (MSG)))) +{ + return 0 ? i : 0; /* { dg-warning "'i' is deprecated: foo.n.t.rbar" } */ +} + --------------1A9E2D804D2830BFBEFA6D0A--