]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libcpp: decode original directory strings for traditional CPP
authorPierre Marie de Rodat <derodat@adacore.com>
Mon, 13 Oct 2025 22:11:37 +0000 (00:11 +0200)
committerEric Botcazou <ebotcazou@adacore.com>
Mon, 13 Oct 2025 22:24:19 +0000 (00:24 +0200)
In traditional CPP mode (-save-temps, -no-integrated-cpp, etc.), the
compilation directory is conveyed to cc1 using a line such as:

 # <line> "/path/name//"

This string literal can contain escape sequences, for instance, if the
original source file was compiled in "/tmp/a\b", then this line will be:

 # <line> "/tmp/a\\b//"

So reading the compilation directory must decode escape sequences. This
last part is currently missing and this patch implements it.

libcpp/
* init.cc (read_original_directory): Attempt to decode escape
sequences with cpp_interpret_string_notranslate.

libcpp/init.cc

index eb495e26effc3bc397a444565eb3d947529d4828..567d5e7038142a582773b5a3b4470b9036dd9910 100644 (file)
@@ -893,11 +893,34 @@ read_original_directory (cpp_reader *pfile)
 
       if (pfile->cb.dir_change)
        {
-         /* Smash the string directly, it's dead at this point  */
-         char *smashy = (char *)text;
-         smashy[len - 3] = 0;
+         cpp_string s = { 0, 0 };
+         const char *dir_slashslash;
+         unsigned int dir_slashslash_len;
+
+         /* If we fail to decode escape sequences in the string literal, fall
+            back onto the literal itself, manually removing the opening and
+            closing quotes (").  */
+         if (cpp_interpret_string_notranslate (pfile, &string->val.str, 1, &s,
+                                               CPP_STRING))
+           {
+             /* At this point, the trailing NUL byte in S is included in its
+                length, so take it out.  */
+             dir_slashslash = (const char *) s.text;
+             dir_slashslash_len = s.len - 1;
+           }
+         else
+           {
+             dir_slashslash = (const char *) string->val.str.text + 1;
+             dir_slashslash_len = string->val.str.len - 2;
+           }
+
+         /* Strip the trailing double slash.  */
+         const unsigned dir_len = dir_slashslash_len - 2;
+         char *dir = (char *) alloca (dir_len + 1);
+         memcpy (dir, dir_slashslash, dir_len);
+         dir[dir_len] = '\0';
 
-         pfile->cb.dir_change (pfile, smashy + 1);
+         pfile->cb.dir_change (pfile, dir);
        }
 
       /* We should be at EOL.  */