public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
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


  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).