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

commit r16-4403-gbe496fd2aa528b4acc2002c04b7186a1f54b95e2
Author: Pierre Marie de Rodat <[email protected]>
Date:   Tue Oct 14 00:11:37 2025 +0200

    libcpp: decode original directory strings for traditional CPP
    
    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.

Diff:
---
 libcpp/init.cc | 31 +++++++++++++++++++++++++++----
 1 file changed, 27 insertions(+), 4 deletions(-)

diff --git a/libcpp/init.cc b/libcpp/init.cc
index eb495e26effc..567d5e703814 100644
--- a/libcpp/init.cc
+++ b/libcpp/init.cc
@@ -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.  */

Reply via email to