jit: fix string escaping
This patch fixes a bug in recording::string::make_debug_string in which '\t' and '\n' were "escaped" by simply prepending a '\', thus emitting '\' then '\n', rather than '\' then 'n'. It also removes a hack that determined if a string is to be escaped by checking for a leading '"', by instead adding a flag. gcc/jit/ChangeLog: * jit-recording.c (recording::context::new_string): Add "escaped" param and use it when creating the new recording::string instance. (recording::string::string): Add "escaped" param and use it to initialize m_escaped. (recording::string::make_debug_string): Replace check that first char is double-quote with use of m_escaped. Fix escaping of '\t' and '\n'. Set "escaped" on the result. * jit-recording.h (recording::context::new_string): Add "escaped" param. (recording::string::string): Add "escaped" param. (recording::string::m_escaped): New field. gcc/testsuite/ChangeLog: * jit.dg/test-debug-strings.c (create_code): Add tests of string literal escaping.
This commit is contained in:
parent
8948a5715b
commit
fec5734083
|
@ -724,12 +724,12 @@ recording::context::disassociate_from_playback ()
|
|||
This creates a fresh copy of the given 0-terminated buffer. */
|
||||
|
||||
recording::string *
|
||||
recording::context::new_string (const char *text)
|
||||
recording::context::new_string (const char *text, bool escaped)
|
||||
{
|
||||
if (!text)
|
||||
return NULL;
|
||||
|
||||
recording::string *result = new string (this, text);
|
||||
recording::string *result = new string (this, text, escaped);
|
||||
record (result);
|
||||
return result;
|
||||
}
|
||||
|
@ -1954,8 +1954,9 @@ recording::memento::write_to_dump (dump &d)
|
|||
/* Constructor for gcc::jit::recording::string::string, allocating a
|
||||
copy of the given text using new char[]. */
|
||||
|
||||
recording::string::string (context *ctxt, const char *text)
|
||||
: memento (ctxt)
|
||||
recording::string::string (context *ctxt, const char *text, bool escaped)
|
||||
: memento (ctxt),
|
||||
m_escaped (escaped)
|
||||
{
|
||||
m_len = strlen (text);
|
||||
m_buffer = new char[m_len + 1];
|
||||
|
@ -2005,9 +2006,9 @@ recording::string::from_printf (context *ctxt, const char *fmt, ...)
|
|||
recording::string *
|
||||
recording::string::make_debug_string ()
|
||||
{
|
||||
/* Hack to avoid infinite recursion into strings when logging all
|
||||
mementos: don't re-escape strings: */
|
||||
if (m_buffer[0] == '"')
|
||||
/* Avoid infinite recursion into strings when logging all mementos:
|
||||
don't re-escape strings: */
|
||||
if (m_escaped)
|
||||
return this;
|
||||
|
||||
/* Wrap in quotes and do escaping etc */
|
||||
|
@ -2024,15 +2025,31 @@ recording::string::make_debug_string ()
|
|||
for (size_t i = 0; i < m_len ; i++)
|
||||
{
|
||||
char ch = m_buffer[i];
|
||||
if (ch == '\t' || ch == '\n' || ch == '\\' || ch == '"')
|
||||
APPEND('\\');
|
||||
APPEND(ch);
|
||||
switch (ch)
|
||||
{
|
||||
default:
|
||||
APPEND(ch);
|
||||
break;
|
||||
case '\t':
|
||||
APPEND('\\');
|
||||
APPEND('t');
|
||||
break;
|
||||
case '\n':
|
||||
APPEND('\\');
|
||||
APPEND('n');
|
||||
break;
|
||||
case '\\':
|
||||
case '"':
|
||||
APPEND('\\');
|
||||
APPEND(ch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
APPEND('"'); /* closing quote */
|
||||
#undef APPEND
|
||||
tmp[len] = '\0'; /* nil termintator */
|
||||
|
||||
string *result = m_ctxt->new_string (tmp);
|
||||
string *result = m_ctxt->new_string (tmp, true);
|
||||
|
||||
delete[] tmp;
|
||||
return result;
|
||||
|
|
|
@ -74,7 +74,7 @@ public:
|
|||
void disassociate_from_playback ();
|
||||
|
||||
string *
|
||||
new_string (const char *text);
|
||||
new_string (const char *text, bool escaped = false);
|
||||
|
||||
location *
|
||||
new_location (const char *filename,
|
||||
|
@ -414,7 +414,7 @@ private:
|
|||
class string : public memento
|
||||
{
|
||||
public:
|
||||
string (context *ctxt, const char *text);
|
||||
string (context *ctxt, const char *text, bool escaped);
|
||||
~string ();
|
||||
|
||||
const char *c_str () { return m_buffer; }
|
||||
|
@ -431,6 +431,11 @@ private:
|
|||
private:
|
||||
size_t m_len;
|
||||
char *m_buffer;
|
||||
|
||||
/* Flag to track if this string is the result of string::make_debug_string,
|
||||
to avoid infinite recursion when logging all mementos: don't re-escape
|
||||
such strings. */
|
||||
bool m_escaped;
|
||||
};
|
||||
|
||||
class location : public memento
|
||||
|
|
|
@ -178,6 +178,26 @@ create_code (gcc_jit_context *ctxt, void *user_data)
|
|||
"((struct node *)ptr->next)->next");
|
||||
}
|
||||
|
||||
/* Check string literal escaping. */
|
||||
{
|
||||
CHECK_RVALUE_DEBUG_STRING
|
||||
(gcc_jit_context_new_string_literal (ctxt, ""),
|
||||
"\"\"");
|
||||
CHECK_RVALUE_DEBUG_STRING
|
||||
(gcc_jit_context_new_string_literal (ctxt, "foo"),
|
||||
"\"foo\"");
|
||||
CHECK_RVALUE_DEBUG_STRING
|
||||
(gcc_jit_context_new_string_literal (ctxt, "\""),
|
||||
"\"\\\"\"");
|
||||
CHECK_RVALUE_DEBUG_STRING
|
||||
(gcc_jit_context_new_string_literal (ctxt, "line 1\nline 2\n"),
|
||||
"\"line 1\\nline 2\\n\"");
|
||||
CHECK_RVALUE_DEBUG_STRING
|
||||
(gcc_jit_context_new_string_literal (ctxt, "foo\tbar"),
|
||||
"\"foo\\tbar\"");
|
||||
}
|
||||
|
||||
#undef CHECK_RVALUE_DEBUG_STRING
|
||||
#undef CHECK_LVALUE_DEBUG_STRING
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue