preprocessor stringizing raw strings

Message ID 73e05bed-c871-7e3c-dc01-dbf1f2b2b9d8@acm.org
State New
Headers show
Series
  • preprocessor stringizing raw strings
Related show

Commit Message

Nathan Sidwell Oct. 10, 2017, 6:54 p.m.
This patch fixes PR 82506, where we fail to properly stringize a raw 
string literal, which can contain a raw LF character.

When we're not just preprocessing, there isn't a problem.  The string 
literal gets correctly escaped into the assembly file.  This is just a 
problem with preprocessing.

Applying to trunk.

nathan

Comments

Christophe Lyon Oct. 11, 2017, 6:51 a.m. | #1
Hi Nathan,


On 10 October 2017 at 20:54, Nathan Sidwell <nathan@acm.org> wrote:
> This patch fixes PR 82506, where we fail to properly stringize a raw string
> literal, which can contain a raw LF character.
>
> When we're not just preprocessing, there isn't a problem.  The string
> literal gets correctly escaped into the assembly file.  This is just a
> problem with preprocessing.
>
> Applying to trunk.
>

Didn't you forget to add -save-temps in the testcase?
I'm seeing it failing because:
g++.dg/cpp/string-3.C  -std=c++11 : output file does not exist
UNRESOLVED: g++.dg/cpp/string-3.C  -std=c++11  scan-file BEGIN
"R\\"(\\n)\\""\n END

Christophe

> nathan
> --
> Nathan Sidwell
Nathan Sidwell Oct. 11, 2017, 11:59 a.m. | #2
Christophe,
> Didn't you forget to add -save-temps in the testcase?
> I'm seeing it failing because:
> g++.dg/cpp/string-3.C  -std=c++11 : output file does not exist
> UNRESOLVED: g++.dg/cpp/string-3.C  -std=c++11  scan-file BEGIN
> "R\\"(\\n)\\""\n END

Surprisingly we emit a .i file, but I'd also flubbed the regexp with 
insufficient escaping.

Fixed thusly.

nathan
Andreas Schwab Oct. 11, 2017, 12:21 p.m. | #3
On Okt 11 2017, Nathan Sidwell <nathan@acm.org> wrote:

> Index: g++.dg/cpp/string-3.C
> ===================================================================
> --- g++.dg/cpp/string-3.C	(revision 253622)
> +++ g++.dg/cpp/string-3.C	(working copy)
> @@ -6,4 +6,4 @@
>  BEGIN STRINGIZE(R"(
>  )") END
>  
> -// { dg-final { scan-file string-3.ii "BEGIN \"R\\\"(\\n)\\\"\"\n END" } }
> +// { dg-final { scan-file string-3.i "BEGIN \"R\\\\\"\\(\\\\n\\)\\\\\"\"\n    END" } }

You can avoid the inflation by using braces.

Andreas.

Patch

2017-10-10  Nathan Sidwell  <nathan@acm.org>

	libcpp/
	PR preprocessor/82506
	* macro.c (cpp_quote_string): Escape raw LFs.

	gcc/testsuite/
	PR preprocessor/82506
	* g++.dg/cpp/string-3.C: New.

Index: gcc/testsuite/g++.dg/cpp/string-3.C
===================================================================
--- gcc/testsuite/g++.dg/cpp/string-3.C	(revision 0)
+++ gcc/testsuite/g++.dg/cpp/string-3.C	(working copy)
@@ -0,0 +1,9 @@ 
+// PR c++/82506
+// { dg-do preprocess { target c++11 } }
+
+#define STRINGIZE(A) #A
+
+BEGIN STRINGIZE(R"(
+)") END
+
+// { dg-final { scan-file string-3.ii "BEGIN \"R\\\"(\\n)\\\"\"\n END" } }
Index: libcpp/macro.c
===================================================================
--- libcpp/macro.c	(revision 253587)
+++ libcpp/macro.c	(working copy)
@@ -502,13 +502,21 @@  cpp_quote_string (uchar *dest, const uch
     {
       uchar c = *src++;
 
-      if (c == '\\' || c == '"')
+      switch (c)
 	{
+	case '\n':
+	  /* Naked LF can appear in raw string literals  */
+	  c = 'n';
+	  /* FALLTHROUGH */
+
+	case '\\':
+	case '"':
 	  *dest++ = '\\';
+	  /* FALLTHROUGH */
+
+	default:
 	  *dest++ = c;
 	}
-      else
-	  *dest++ = c;
     }
 
   return dest;