Hi!

Another easy part from the paper.

Part of the CWG2579 has been already done in an earlier paper (with
test commits by Marek) and the remaining part is implemented correctly,
we diagnose as error when token pasting doesn't form a valid token.

Except that message
pasting """" and """" does not give a valid preprocessing token
looked weird and so I've updated the message to use %< and %> instead
of \" quoting.

Ok for trunk?

2025-08-04  Jakub Jelinek  <ja...@redhat.com>

        PR preprocessor/120778
        * macro.cc (paste_tokens): Use %< and %> instead of \" in
        diagnostics around %.*s.

        * g++.dg/DRs/dr2579.C: New test.
        * c-c++-common/cpp/va-opt-6.c: Expect ' rather than \" around
        tokens in incorrect pasting diagnostics.
        * gcc.dg/c23-attr-syntax-6.c: Likewise.
        * gcc.dg/cpp/paste12.c: Likewise.
        * gcc.dg/cpp/paste12-2.c: Likewise.
        * gcc.dg/cpp/paste14.c: Likewise.
        * gcc.dg/cpp/paste14-2.c: Likewise.

--- libcpp/macro.cc.jj  2025-08-01 19:51:38.156038976 +0200
+++ libcpp/macro.cc     2025-08-04 16:49:57.489046833 +0200
@@ -1071,7 +1071,7 @@ paste_tokens (cpp_reader *pfile, locatio
       /* Mandatory error for all apart from assembler.  */
       if (CPP_OPTION (pfile, lang) != CLK_ASM)
        cpp_error_with_line (pfile, CPP_DL_ERROR, location, 0,
-                            "pasting \"%.*s\" and \"%.*s\" does not give "
+                            "pasting %<%.*s%> and %<%.*s%> does not give "
                             "a valid preprocessing token",
                             (int) (lhsend - buf), buf,
                             (int) (end - rhsstart), rhsstart);
--- gcc/testsuite/g++.dg/DRs/dr2579.C.jj        2025-08-04 16:54:38.488305465 
+0200
+++ gcc/testsuite/g++.dg/DRs/dr2579.C   2025-08-04 17:00:20.338756103 +0200
@@ -0,0 +1,9 @@
+// DR 2579 - Undefined behavior when token pasting does not create a 
preprocessing token
+// { dg-do preprocess }
+// { dg-options "-pedantic-errors" }
+
+#define A(a, b) a ## b
+A(5,6)
+A(-,32)                        // { dg-error "pasting '-' and '32' does not 
give a valid preprocessing token" }
+A("","")               // { dg-error "pasting '\"\"' and '\"\"' does not give 
a valid preprocessing token" }
+A(\,u0393)
--- gcc/testsuite/c-c++-common/cpp/va-opt-6.c.jj        2021-08-17 
19:06:14.638793462 +0200
+++ gcc/testsuite/c-c++-common/cpp/va-opt-6.c   2025-08-04 16:51:20.749937055 
+0200
@@ -3,15 +3,15 @@
 /* { dg-options "-std=c++20" { target c++ } } */
 
 #define a ""
-#define b(...) a ## #__VA_OPT__(1)     /* { dg-error "pasting \"a\" and 
\"\"\"\" does not give a valid preprocessing token" } */
-#define c(...) a ## #__VA_OPT__(1)     /* { dg-error "pasting \"a\" and 
\"\"1\"\" does not give a valid preprocessing token" } */
+#define b(...) a ## #__VA_OPT__(1)     /* { dg-error "pasting 'a' and '\"\"' 
does not give a valid preprocessing token" } */
+#define c(...) a ## #__VA_OPT__(1)     /* { dg-error "pasting 'a' and '\"1\"' 
does not give a valid preprocessing token" } */
 #define d(...) #__VA_OPT__(1) ## !
 #define e(...) #__VA_OPT__(1) ## !
 #define f(...) #__VA_OPT__(. ## !)
 #define g(...) #__VA_OPT__(. ## !)
 b()
 c(1)
-d(   )         /* { dg-error "pasting \"\"\"\" and \"!\" does not give a valid 
preprocessing token" } */
-e(  1 )                /* { dg-error "pasting \"\"1\"\" and \"!\" does not 
give a valid preprocessing token" } */
+d(   )         /* { dg-error "pasting '\"\"' and '!' does not give a valid 
preprocessing token" } */
+e(  1 )                /* { dg-error "pasting '\"1\"' and '!' does not give a 
valid preprocessing token" } */
 f()
-g(0)           /* { dg-error "pasting \".\" and \"!\" does not give a valid 
preprocessing token" } */
+g(0)           /* { dg-error "pasting '.' and '!' does not give a valid 
preprocessing token" } */
--- gcc/testsuite/gcc.dg/c23-attr-syntax-6.c.jj 2024-02-22 22:34:18.838230561 
+0100
+++ gcc/testsuite/gcc.dg/c23-attr-syntax-6.c    2025-08-04 16:52:14.086227176 
+0200
@@ -45,7 +45,7 @@ typedef int [[__extension__ __extension_
 typedef int [[__extension__ unknown_attribute]] b3; /* { dg-error 
{'unknown_attribute' attribute ignored} } */
 typedef int [[__extension__ gnu:vector_size(4)]] b4; /* { dg-error {expected 
'\]' before ':'} } */
 /* { dg-error {'gnu' attribute ignored} "" { target *-*-* } .-1 } */
-typedef int [[__extension__ gnu JOIN2(:,:) vector_size (4)]] b5; /* { dg-error 
{pasting ":" and ":" does not give a valid preprocessing token} } */
+typedef int [[__extension__ gnu JOIN2(:,:) vector_size (4)]] b5; /* { dg-error 
{pasting ':' and ':' does not give a valid preprocessing token} } */
 /* { dg-error {expected '\]' before ':'} "" { target *-*-* } .-1 } */
 /* { dg-error {'gnu' attribute ignored} "" { target *-*-* } .-2 } */
 typedef int [[__extension__ gnu : : vector_size (4)]] b6; /* { dg-error 
{expected '\]' before ':'} } */
@@ -81,7 +81,7 @@ typedef int [[gnu :: vector_size (4)]] b
 typedef int [[gnu FOO vector_size (4)]] b19; /* { dg-error {attributes before 
C23} } */
 typedef int [[gnu :: vector_size (sizeof (void (*)(...)))]] b20; /* { dg-error 
{attributes before C23} } */
 /* { dg-error {requires a named argument before} "" { target *-*-* } .-1 } */
-typedef int [[gnu JOIN2(:,:) vector_size (4)]] b21; /* { dg-error {pasting ":" 
and ":" does not give a valid preprocessing token} } */
+typedef int [[gnu JOIN2(:,:) vector_size (4)]] b21; /* { dg-error {pasting ':' 
and ':' does not give a valid preprocessing token} } */
 /* { dg-error {expected '\]' before ':'} "" { target *-*-* } .-1 } */
 /* { dg-error {'gnu' attribute ignored} "" { target *-*-* } .-2 } */
 /* { dg-error {attributes before C23} "" { target *-*-* } .-3 } */
--- gcc/testsuite/gcc.dg/cpp/paste12.c.jj       2020-01-14 20:02:47.258602719 
+0100
+++ gcc/testsuite/gcc.dg/cpp/paste12.c  2025-08-04 16:53:34.867152142 +0200
@@ -8,4 +8,4 @@
 
 #define inc2(a,b) <##a.b>
 #define INC(X) inc2(X,h)
-#include INC(stdio) /* { dg-error "pasting \"<\" and \"stdio\" does not" } */
+#include INC(stdio) /* { dg-error "pasting '<' and 'stdio' does not" } */
--- gcc/testsuite/gcc.dg/cpp/paste12-2.c.jj     2020-01-14 20:02:47.258602719 
+0100
+++ gcc/testsuite/gcc.dg/cpp/paste12-2.c        2025-08-04 16:53:12.255453058 
+0200
@@ -6,6 +6,6 @@
 /* Test correct diagnostics when pasting in #include.
    Source: PR preprocessor/6780.  */
 
-#define inc2(a,b) <##a.b>  /* { dg-error "pasting \"<\" and \"stdio\" does 
not" } */
+#define inc2(a,b) <##a.b>  /* { dg-error "pasting '<' and 'stdio' does not" } 
*/
 #define INC(X) inc2(X,h)
 #include INC(stdio)
--- gcc/testsuite/gcc.dg/cpp/paste14.c.jj       2020-01-14 20:02:47.258602719 
+0100
+++ gcc/testsuite/gcc.dg/cpp/paste14.c  2025-08-04 16:58:46.013011393 +0200
@@ -5,6 +5,6 @@
 */
 
 #define foo - ## >>
-foo            /* { dg-error "pasting \"-\" and \">>\"" } */
+foo            /* { dg-error "pasting '-' and '>>'" } */
 #define bar = ## ==
-bar            /* { dg-error "pasting \"=\" and \"==\"" } */
+bar            /* { dg-error "pasting '=' and '=='" } */
--- gcc/testsuite/gcc.dg/cpp/paste14-2.c.jj     2020-01-14 20:02:47.258602719 
+0100
+++ gcc/testsuite/gcc.dg/cpp/paste14-2.c        2025-08-04 16:54:08.091709985 
+0200
@@ -4,8 +4,8 @@
    { dg-do preprocess }
 */
 
-#define foo - ## >> /* { dg-error "pasting \"-\" and \">>\"" } */
+#define foo - ## >> /* { dg-error "pasting '-' and '>>'" } */
 foo
-#define bar = ## == /* { dg-error "pasting \"=\" and \"==\"" } */
+#define bar = ## == /* { dg-error "pasting '=' and '=='" } */
 bar
 


        Jakub

Reply via email to