[gcc(refs/vendors/ibm/heads/perf)] c++: Partially implement P1042R1: __VA_OPT__ wording clarifications [PR92319]

Jiu Fu Guo guojiufu@gcc.gnu.org
Thu Mar 19 05:33:49 GMT 2020


https://gcc.gnu.org/g:e235031d490e8ed2aa0bc229694975493fd58977

commit e235031d490e8ed2aa0bc229694975493fd58977
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Fri Feb 14 09:04:14 2020 +0100

    c++: Partially implement P1042R1: __VA_OPT__ wording clarifications [PR92319]
    
    I've noticed we claim in cxx-status.html that we implement P1042R1,
    but it seems we don't implement any of the changes from there.
    The following patch implements just the change that __VA_OPT__ determines
    whether to expand to nothing or the enclosed tokens no longer based on
    whether there were any tokens passed to __VA_ARGS__, but whether __VA_ARGS__
    expands to any tokens (from testing apparently it has to be non-CPP_PADDING
    tokens).
    
    I'm afraid I'm completely lost about the padding preservation/removal
    changes that are also in the paper, so haven't touched that part.
    
    2020-02-14  Jakub Jelinek  <jakub@redhat.com>
    
            Partially implement P1042R1: __VA_OPT__ wording clarifications
            PR preprocessor/92319
            * macro.c (expand_arg): Move declarations before vaopt_state
            definition.
            (class vaopt_state): Move enum update_type definition earlier.  Remove
            m_allowed member, add m_arg and m_update members.
            (vaopt_state::vaopt_state): Change last argument from bool any_args
            to macro_arg *arg, initialize m_arg and m_update instead of m_allowed.
            (vaopt_state::update): When bumping m_state from 1 to 2 and m_update
            is ERROR, determine if __VA_ARGS__ expansion has any non-CPP_PADDING
            tokens and set m_update to INCLUDE if it has any, DROP otherwise.
            Return m_update instead of m_allowed ? INCLUDE : DROP in m_state >= 2.
            (replace_args, create_iso_definition): Adjust last argument to
            vaopt_state ctor.
    
            * c-c++-common/cpp/va-opt-4.c: New test.

Diff:
---
 gcc/testsuite/ChangeLog                   |  6 +++
 gcc/testsuite/c-c++-common/cpp/va-opt-4.c | 20 ++++++++++
 libcpp/ChangeLog                          | 17 +++++++++
 libcpp/macro.c                            | 61 +++++++++++++++++++++----------
 4 files changed, 85 insertions(+), 19 deletions(-)

diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a262bdde886..e42751e5658 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2020-02-14  Jakub Jelinek  <jakub@redhat.com>
+
+	Partially implement P1042R1: __VA_OPT__ wording clarifications
+	PR preprocessor/92319
+	* c-c++-common/cpp/va-opt-4.c: New test.
+
 2020-02-13  Jakub Jelinek  <jakub@redhat.com>
 
 	PR c/93576
diff --git a/gcc/testsuite/c-c++-common/cpp/va-opt-4.c b/gcc/testsuite/c-c++-common/cpp/va-opt-4.c
new file mode 100644
index 00000000000..57241bc80fa
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cpp/va-opt-4.c
@@ -0,0 +1,20 @@
+/* PR preprocessor/92319 */
+/* { dg-do preprocess } */
+/* { dg-options "-std=gnu99" { target c } } */
+/* { dg-options "-std=c++2a" { target c++ } } */
+
+#define f1(...) b##__VA_OPT__(c)
+#define e
+#define e2 e
+#define e3 1
+#define e5 e3
+t1 f1 (e);
+/* { dg-final { scan-file va-opt-4.i "t1 b;" } } */
+t2 f1 (e2);
+/* { dg-final { scan-file va-opt-4.i "t2 b;" } } */
+t3 f1 (e3);
+/* { dg-final { scan-file va-opt-4.i "t3 bc;" } } */
+t4 f1 (e4);
+/* { dg-final { scan-file va-opt-4.i "t4 bc;" } } */
+t5 f1 (e5);
+/* { dg-final { scan-file va-opt-4.i "t5 bc;" } } */
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index 65e8f400679..307cf3add94 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,20 @@
+2020-02-14  Jakub Jelinek  <jakub@redhat.com>
+
+	Partially implement P1042R1: __VA_OPT__ wording clarifications
+	PR preprocessor/92319
+	* macro.c (expand_arg): Move declarations before vaopt_state
+	definition.
+	(class vaopt_state): Move enum update_type definition earlier.  Remove
+	m_allowed member, add m_arg and m_update members.
+	(vaopt_state::vaopt_state): Change last argument from bool any_args
+	to macro_arg *arg, initialize m_arg and m_update instead of m_allowed.
+	(vaopt_state::update): When bumping m_state from 1 to 2 and m_update
+	is ERROR, determine if __VA_ARGS__ expansion has any non-CPP_PADDING
+	tokens and set m_update to INCLUDE if it has any, DROP otherwise.
+	Return m_update instead of m_allowed ? INCLUDE : DROP in m_state >= 2.
+	(replace_args, create_iso_definition): Adjust last argument to
+	vaopt_state ctor.
+
 2020-02-05  Martin Sebor  <msebor@redhat.com>
 
 	* include/cpplib.h (cpp_builtin_type): Remove trailing comma to
diff --git a/libcpp/macro.c b/libcpp/macro.c
index ec0030742c0..2573f316bf5 100644
--- a/libcpp/macro.c
+++ b/libcpp/macro.c
@@ -93,6 +93,8 @@ struct macro_arg_saved_data {
 static const char *vaopt_paste_error =
   N_("'##' cannot appear at either end of __VA_OPT__");
 
+static void expand_arg (cpp_reader *, macro_arg *);
+
 /* A class for tracking __VA_OPT__ state while iterating over a
    sequence of tokens.  This is used during both macro definition and
    expansion.  */
@@ -100,28 +102,29 @@ class vaopt_state {
 
  public:
 
+  enum update_type
+  {
+    ERROR,
+    DROP,
+    INCLUDE,
+    BEGIN,
+    END
+  };
+
   /* Initialize the state tracker.  ANY_ARGS is true if variable
      arguments were provided to the macro invocation.  */
-  vaopt_state (cpp_reader *pfile, bool is_variadic, bool any_args)
+  vaopt_state (cpp_reader *pfile, bool is_variadic, macro_arg *arg)
     : m_pfile (pfile),
-    m_allowed (any_args),
+    m_arg (arg),
     m_variadic (is_variadic),
     m_last_was_paste (false),
     m_state (0),
     m_paste_location (0),
-    m_location (0)
+    m_location (0),
+    m_update (ERROR)
   {
   }
 
-  enum update_type
-  {
-    ERROR,
-    DROP,
-    INCLUDE,
-    BEGIN,
-    END
-  };
-
   /* Given a token, update the state of this tracker and return a
      boolean indicating whether the token should be be included in the
      expansion.  */
@@ -154,6 +157,23 @@ class vaopt_state {
 	    return ERROR;
 	  }
 	++m_state;
+	if (m_update == ERROR)
+	  {
+	    if (m_arg == NULL)
+	      m_update = INCLUDE;
+	    else
+	      {
+		m_update = DROP;
+		if (!m_arg->expanded)
+		  expand_arg (m_pfile, m_arg);
+		for (unsigned idx = 0; idx < m_arg->expanded_count; ++idx)
+		  if (m_arg->expanded[idx]->type != CPP_PADDING)
+		    {
+		      m_update = INCLUDE;
+		      break;
+		    }
+	      }
+	  }
 	return DROP;
       }
     else if (m_state >= 2)
@@ -197,7 +217,7 @@ class vaopt_state {
 		return END;
 	      }
 	  }
-	return m_allowed ? INCLUDE : DROP;
+	return m_update;
       }
 
     /* Nothing to do with __VA_OPT__.  */
@@ -219,8 +239,9 @@ class vaopt_state {
   /* The cpp_reader.  */
   cpp_reader *m_pfile;
 
-  /* True if there were varargs.  */
-  bool m_allowed;
+  /* The __VA_ARGS__ argument.  */
+  macro_arg *m_arg;
+
   /* True if the macro is variadic.  */
   bool m_variadic;
   /* If true, the previous token was ##.  This is used to detect when
@@ -239,6 +260,10 @@ class vaopt_state {
 
   /* Location of the __VA_OPT__ token.  */
   location_t m_location;
+
+  /* If __VA_ARGS__ substitutes to no preprocessing tokens,
+     INCLUDE, otherwise DROP.  ERROR when unknown yet.  */
+  update_type m_update;
 };
 
 /* Macro expansion.  */
@@ -256,7 +281,6 @@ static _cpp_buff *collect_args (cpp_reader *, const cpp_hashnode *,
 				_cpp_buff **, unsigned *);
 static cpp_context *next_context (cpp_reader *);
 static const cpp_token *padding_token (cpp_reader *, const cpp_token *);
-static void expand_arg (cpp_reader *, macro_arg *);
 static const cpp_token *new_string_token (cpp_reader *, uchar *, unsigned int);
 static const cpp_token *stringify_arg (cpp_reader *, macro_arg *);
 static void paste_all_tokens (cpp_reader *, const cpp_token *);
@@ -1924,8 +1948,7 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro,
 				 num_macro_tokens);
     }
   i = 0;
-  vaopt_state vaopt_tracker (pfile, macro->variadic,
-			     args[macro->paramc - 1].count > 0);
+  vaopt_state vaopt_tracker (pfile, macro->variadic, &args[macro->paramc - 1]);
   const cpp_token **vaopt_start = NULL;
   for (src = macro->exp.tokens; src < limit; src++)
     {
@@ -3424,7 +3447,7 @@ create_iso_definition (cpp_reader *pfile)
       macro->count = 1;
     }
 
-  for (vaopt_state vaopt_tracker (pfile, macro->variadic, true);; token = NULL)
+  for (vaopt_state vaopt_tracker (pfile, macro->variadic, NULL);; token = NULL)
     {
       if (!token)
 	{


More information about the Gcc-cvs mailing list