From: Jakub Jelinek <jakub@redhat.com>
To: Jason Merrill <jason@redhat.com>, Nathan Sidwell <nathan@acm.org>,
Lewis Hyatt <lhyatt@gmail.com>
Cc: gcc-patches@gcc.gnu.org
Subject: Re: Ping^3: [PATCH] libcpp: Handle extended characters in user-defined literal suffix [PR103902]
Date: Fri, 10 Feb 2023 17:30:31 +0100 [thread overview]
Message-ID: <Y+ZxJ/w2ffHc/lES@tucnak> (raw)
In-Reply-To: <20220926222725.GA19652@ldh-imac.local>
On Mon, Sep 26, 2022 at 06:27:25PM -0400, Lewis Hyatt via Gcc-patches wrote:
> May I please ping this patch again? Joseph suggested that it would be best if
> a C++ maintainer has a look at it. This is one of just a few places left where
> we don't handle UTF-8 properly in libcpp, it would be really nice to get them
> fixed up if there is time to review this patch. Thanks!
CCing them.
Just some nits from me, but I agree C++ maintainers are the best reviewers
for this.
> libcpp/ChangeLog:
>
> PR preprocessor/103902
> * lex.cc (identifier_diagnostics_on_lex): New function refactors
> common code from...
> (lex_identifier_intern): ...here, and...
> (lex_identifier): ...here.
> (struct scan_id_result): New struct to hold the result of...
I'd just write
(struct scan_id_result): New type.
or similar, no need to explain what it will be used for.
> (scan_cur_identifier): ...new function.
So just New function here too.
> (create_literal2): New function.
> (is_macro): Removed function that is now handled directly in
> lex_string() and lex_raw_string().
> (is_macro_not_literal_suffix): Likewise.
> (lit_accum::create_literal2): New function.
> (lex_raw_string): Make use of new function scan_cur_identifier().
> (lex_string): Likewise.
> +/* Helper function to perform diagnostics that are needed (rarely)
> + when an identifier is lexed. */
> +static void identifier_diagnostics_on_lex (cpp_reader *pfile,
> + cpp_hashnode *node)
Formatting, function name should be at the start of line, so
static void
identifier_diagnostics_on_lex (cpp_reader *pfile, cpp_hashnode *node)
> +{
> + if (__builtin_expect (!(node->flags & NODE_DIAGNOSTIC)
> + || pfile->state.skipping, 1))
> + return;
> +
> + /* It is allowed to poison the same identifier twice. */
> + if ((node->flags & NODE_POISONED) && !pfile->state.poisoned_ok)
> + cpp_error (pfile, CPP_DL_ERROR, "attempt to use poisoned \"%s\"",
> + NODE_NAME (node));
> +
> + /* Constraint 6.10.3.5: __VA_ARGS__; should only appear in the
> + replacement list of a variadic macro. */
> + if (node == pfile->spec_nodes.n__VA_ARGS__
> + && !pfile->state.va_args_ok)
> + {
> + if (CPP_OPTION (pfile, cplusplus))
> + cpp_error (pfile, CPP_DL_PEDWARN,
> + "__VA_ARGS__ can only appear in the expansion"
> + " of a C++11 variadic macro");
> + else
> + cpp_error (pfile, CPP_DL_PEDWARN,
> + "__VA_ARGS__ can only appear in the expansion"
> + " of a C99 variadic macro");
> + }
> +
Perhaps add here the:
+ /* __VA_OPT__ should only appear in the replacement list of a
+ variadic macro. */
comment that used to be present only in the second occurrence of
all this.
> + if (node == pfile->spec_nodes.n__VA_OPT__)
> + maybe_va_opt_error (pfile);
> +
> + /* For -Wc++-compat, warn about use of C++ named operators. */
> + if (node->flags & NODE_WARN_OPERATOR)
> + cpp_warning (pfile, CPP_W_CXX_OPERATOR_NAMES,
> + "identifier \"%s\" is a special operator name in C++",
> + NODE_NAME (node));
> +}
> +
> +/* Helper function to scan an entire identifier beginning at
> + pfile->buffer->cur, and possibly containing extended characters (UCNs
> + and/or UTF-8). Returns the cpp_hashnode for the identifier on success, or
> + else nullptr, as well as a normalize_state so that normalization warnings
> + may be issued once the token lexing is complete. */
This looks like a function comment that should be immediately above
scan_cur_identifier, there might be another comment above struct
scan_id_result which would just explain the purpose of the class.
> +
> +struct scan_id_result
> +{
> + cpp_hashnode *node;
> + normalize_state nst;
> +
> + scan_id_result ()
> + : node (nullptr)
> + {
> + nst = INITIAL_NORMALIZE_STATE;
> + }
> +
> + explicit operator bool () const { return node; }
> +};
> +
> +static scan_id_result
> +scan_cur_identifier (cpp_reader *pfile)
> +{
> @@ -2741,26 +2800,53 @@ lex_raw_string (cpp_reader *pfile, cpp_token *token, const uchar *base)
>
> if (CPP_OPTION (pfile, user_literals))
> {
> - /* If a string format macro, say from inttypes.h, is placed touching
> - a string literal it could be parsed as a C++11 user-defined string
> - literal thus breaking the program. */
> - if (is_macro_not_literal_suffix (pfile, pos))
> - {
> - /* Raise a warning, but do not consume subsequent tokens. */
> - if (CPP_OPTION (pfile, warn_literal_suffix) && !pfile->state.skipping)
> - cpp_warning_with_line (pfile, CPP_W_LITERAL_SUFFIX,
> - token->src_loc, 0,
> - "invalid suffix on literal; C++11 requires "
> - "a space between literal and string macro");
> - }
> - /* Grab user defined literal suffix. */
> - else if (ISIDST (*pos))
> - {
> - type = cpp_userdef_string_add_type (type);
> - ++pos;
> + const uchar *const suffix_begin = pos;
> + pfile->buffer->cur = pos;
>
> - while (ISIDNUM (*pos))
> - ++pos;
> + if (const auto sr = scan_cur_identifier (pfile))
> + {
> + /* If a string format macro, say from inttypes.h, is placed touching
> + a string literal it could be parsed as a C++11 user-defined
> + string literal thus breaking the program. User-defined literals
> + outside of namespace std must start with a single underscore, so
> + assume anything of that form really is a UDL suffix. We don't
> + need to worry about UDLs defined inside namespace std because
> + their names are reserved, so cannot be used as macro names in
> + valid programs. */
> + if ((suffix_begin[0] != '_' || suffix_begin[1] == '_')
> + && cpp_macro_p (sr.node))
What is the advantage of dropping is_macro_not_literal_suffix and
hand-inlining it in two different spots?
Couldn't even the actual warning be moved into an inline function?
> + {
> + /* Maybe raise a warning, but do not consume the tokens. */
> + pfile->buffer->cur = suffix_begin;
> + if (CPP_OPTION (pfile, warn_literal_suffix)
> + && !pfile->state.skipping)
> + cpp_warning_with_line
> + (pfile, CPP_W_LITERAL_SUFFIX,
> + token->src_loc, 0,
> + "invalid suffix on literal; C++11 requires "
> + "a space between literal and string macro");
The ( on a call on a different line is quite ugly, so if it can be avoided,
it should.
cpp_warning_with_line (pfile, CPP_W_LITERAL_SUFFIX,
token->src_loc, 0,
"invalid suffix on literal; C++11 "
"requires a space between literal "
"and string macro");
is more readable and same number of lines.
Otherwise it looks reasonable to me, but I'd still prefer Jason or Nathan
to review this.
Jakub
next prev parent reply other threads:[~2023-02-10 16:30 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-06-14 21:26 Lewis Hyatt
2022-06-15 19:06 ` Lewis Hyatt
2022-09-26 22:27 ` Ping^3: " Lewis Hyatt
2023-02-10 16:30 ` Jakub Jelinek [this message]
2023-02-10 16:58 ` Lewis Hyatt
2023-02-10 17:10 ` Jakub Jelinek
2023-02-15 18:39 ` Jason Merrill
2023-02-15 23:18 ` Lewis Hyatt
2023-03-02 23:07 ` [PATCH v2] " Lewis Hyatt
2023-07-18 20:33 ` Jason Merrill
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Y+ZxJ/w2ffHc/lES@tucnak \
--to=jakub@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=jason@redhat.com \
--cc=lhyatt@gmail.com \
--cc=nathan@acm.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).