Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(revision 257451)
+++ gcc/tree.c	(working copy)
@@ -12431,8 +12431,66 @@
   if (attr)
     attr = lookup_attribute ("deprecated", attr);
 
+  char * new_msg = NULL;
+  unsigned int new_i = 0;
+
   if (attr)
-    msg = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr)));
+    {
+      msg = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr)));
+
+      if (msg)
+	{
+	  /* PR 84195: Replace control characters in the message with their
+	     escaped equivalents.  Allow newlines if -fmessage-length has
+	     been set to a non-zero value.  This is done here, rather than
+	     where the attribute is recorded as the message length can
+	     change between these two locations.  */
+
+	  /* FIXME: Do we need to check to see if msg is longer than 2^32 ?  */
+	  unsigned int i;
+
+	  for (i = 0; i < strlen (msg); i++)
+	    {
+	      char c = msg[i];
+
+	      if (! ISCNTRL (c))
+		{
+		  if (new_msg)
+		    new_msg[new_i++] = c;
+		  continue;
+		}
+
+	      if (c != '\n' || ! pp_is_wrapping_line (global_dc->printer))
+		{
+		  if (new_msg == NULL)
+		    {
+		      new_msg = (char *) xmalloc (strlen (msg) * 2);
+		      strncpy (new_msg, msg, i);
+		      new_i = i;
+		    }
+		  new_msg [new_i++] = '\\';
+		  switch (c)
+		    {
+		    case  7: new_msg[new_i++] = 'a'; break;
+		    case  8: new_msg[new_i++] = 'b'; break;
+		    case 27: new_msg[new_i++] = 'e'; break;
+		    case 12: new_msg[new_i++] = 'f'; break;
+		    case 10: new_msg[new_i++] = 'n'; break;
+		    case 13: new_msg[new_i++] = 'r'; break;
+		    case  9: new_msg[new_i++] = 't'; break;
+		    case 11: new_msg[new_i++] = 'v'; break;
+		    default: new_msg[new_i++] = '?'; break;
+		    }
+		}
+	    }
+
+	  if (new_msg)
+	    {
+	      new_msg[new_i] = 0;
+	      msg = new_msg;
+	    }
+	}
+    }
   else
     msg = NULL;
 
@@ -12505,6 +12563,8 @@
 	    }
 	}
     }
+
+  free (new_msg);
 }
 
 /* Return true if REF has a COMPONENT_REF with a bit-field field declaration
--- /dev/null	2018-02-07 09:26:20.608663241 +0000
+++ gcc/testsuite/gcc.c-torture/compile/pr84195.c	2018-02-07 17:20:13.494587052 +0000
@@ -0,0 +1,17 @@
+/* { dg-options "-Wdeprecated-declarations" } */
+
+/* Check that MSG is printed without the escape characters being interpreted.
+   Especially the newlines.
+
+   Note - gcc's behaviour is inconsistent in this regard as #error and
+   #warning will also display control characters as escape sequences,
+   whereas #pragma GCC error and #pragma GCC warning will perform the
+   control operations of the control characters.  */
+   
+#define MSG "foo\n\t\rbar"
+
+int f (int i __attribute__ ((deprecated (MSG))))
+{
+  return 0 ? i : 0; /* { dg-warning "'i' is deprecated: foo.n.t.rbar" } */
+}
+
