Index: gcc/tree-diagnostic.c
===================================================================
--- gcc/tree-diagnostic.c	(revision 192379)
+++ gcc/tree-diagnostic.c	(working copy)
@@ -100,11 +100,11 @@ DEF_VEC_ALLOC_O (loc_map_pair, heap);
    unwound macro expansion trace.  That's the part generated by this
    function.  */
 
 static void
 maybe_unwind_expanded_macro_loc (diagnostic_context *context,
-                                 diagnostic_info *diagnostic,
+                                 const diagnostic_info *diagnostic,
                                  source_location where)
 {
   const struct line_map *map;
   VEC(loc_map_pair,heap) *loc_vec = NULL;
   unsigned ix;
@@ -142,18 +142,16 @@ maybe_unwind_expanded_macro_loc (diagnos
      first triggered the macro expansion.  This must be an ordinary map.  */
 
   /* Walk LOC_VEC and print the macro expansion trace, unless the
      first macro which expansion triggered this trace was expanded
      inside a system header.  */
+  int saved_location_line =
+    expand_location_to_spelling_point (diagnostic->location).line;
+
   if (!LINEMAP_SYSP (map))
     FOR_EACH_VEC_ELT (loc_map_pair, loc_vec, ix, iter)
       {
-        source_location resolved_def_loc = 0, resolved_exp_loc = 0,
-	  saved_location = 0;
-	int resolved_def_loc_line = 0, saved_location_line = 0;
-        diagnostic_t saved_kind;
-        const char *saved_prefix;
 	/* Sometimes, in the unwound macro expansion trace, we want to
 	   print a part of the context that shows where, in the
 	   definition of the relevant macro, is the token (we are
 	   looking at) used.  That is the case in the introductory
 	   comment of this function, where we print:
@@ -172,92 +170,59 @@ maybe_unwind_expanded_macro_loc (diagnos
 	   macro definition context to the user somehow.
 
 	   A contrario, when the first interesting diagnostic line
 	   points into the definition of the macro, we don't need to
 	   display any line for that macro definition in the trace
-	   anymore, otherwise it'd be redundant.
-
-	   This flag is true when we need to display the context of
-	   the macro definition.  */
-	bool print_definition_context_p = false;
+	   anymore, otherwise it'd be redundant.  */
 
         /* Okay, now here is what we want.  For each token resulting
            from macro expansion we want to show: 1/ where in the
            definition of the macro the token comes from; 2/ where the
            macro got expanded.  */
 
         /* Resolve the location iter->where into the locus 1/ of the
            comment above.  */
-        resolved_def_loc =
+        source_location resolved_def_loc =
           linemap_resolve_location (line_table, iter->where,
                                     LRK_MACRO_DEFINITION_LOCATION, NULL);
 
 	/* Don't print trace for locations that are reserved or from
 	   within a system header.  */
-	{
-	  const struct line_map *m = NULL;
-	  source_location l = linemap_resolve_location (line_table, resolved_def_loc,
-							LRK_SPELLING_LOCATION,
-							&m);
-	  if (l < RESERVED_LOCATION_COUNT
-	      || LINEMAP_SYSP (m))
-	    continue;
-
-	  resolved_def_loc_line = SOURCE_LINE (m, l);
-	}
+        const struct line_map *m = NULL;
+        source_location l = 
+          linemap_resolve_location (line_table, resolved_def_loc,
+                                    LRK_SPELLING_LOCATION,  &m);
+        if (l < RESERVED_LOCATION_COUNT || LINEMAP_SYSP (m))
+          continue;
+        
+	/* We need to print the context of the macro definition only
+	   when the locus of the first displayed diagnostic (displayed
+	   before this trace) was inside the definition of the
+	   macro.  */
+        int resolved_def_loc_line = SOURCE_LINE (m, l);
+        if (ix == 0 && saved_location_line != resolved_def_loc_line)
+          {
+            diagnostic_attach_note (context, resolved_def_loc, 
+                                    "in definition of macro %qs",
+                                    linemap_map_get_macro_name (iter->map));
+            /* At this step, as we've printed the context of the macro
+               definition, we don't want to print the context of its
+               expansion, otherwise, it'd be redundant.  */
+            continue;
+          }
 
         /* Resolve the location of the expansion point of the macro
            which expansion gave the token represented by def_loc.
            This is the locus 2/ of the earlier comment.  */
-        resolved_exp_loc =
+        source_location resolved_exp_loc =
           linemap_resolve_location (line_table,
                                     MACRO_MAP_EXPANSION_POINT_LOCATION (iter->map),
                                     LRK_MACRO_DEFINITION_LOCATION, NULL);
 
-        saved_kind = diagnostic->kind;
-        saved_prefix = pp_get_prefix (context->printer);
-        saved_location = diagnostic->location;
-	saved_location_line =
-	  expand_location_to_spelling_point (saved_location).line;
-
-        diagnostic->kind = DK_NOTE;
-
-	/* We need to print the context of the macro definition only
-	   when the locus of the first displayed diagnostic (displayed
-	   before this trace) was inside the definition of the
-	   macro.  */
-	print_definition_context_p =
-	  (ix == 0 && (saved_location_line != resolved_def_loc_line));
-
-	if (print_definition_context_p)
-	  {
-	    diagnostic->location = resolved_def_loc;
-	    pp_set_prefix (context->printer,
-			   diagnostic_build_prefix (context, diagnostic));
-	    pp_newline (context->printer);
-	    pp_printf (context->printer, "in definition of macro '%s'",
-		       linemap_map_get_macro_name (iter->map));
-	    pp_destroy_prefix (context->printer);
-	    diagnostic_show_locus (context, diagnostic);
-	    /* At this step, as we've printed the context of the macro
-	       definition, we don't want to print the context of its
-	       expansion, otherwise, it'd be redundant.  */
-	    continue;
-	  }
-
-	diagnostic->location = resolved_exp_loc;
-	pp_set_prefix (context->printer,
-                       diagnostic_build_prefix (context, diagnostic));
-	pp_newline (context->printer);
-	pp_printf (context->printer, "in expansion of macro '%s'",
-		   linemap_map_get_macro_name (iter->map));
-        pp_destroy_prefix (context->printer);
-        diagnostic_show_locus (context, diagnostic);
-
-        diagnostic->kind = saved_kind;
-        diagnostic->location = saved_location;
-        pp_set_prefix (context->printer, saved_prefix);
+        diagnostic_attach_note (context, resolved_exp_loc, 
+                                "in expansion of macro %qs",
+                                linemap_map_get_macro_name (iter->map));
       }
 
   VEC_free (loc_map_pair, heap, loc_vec);
 }
 
Index: gcc/diagnostic.c
===================================================================
--- gcc/diagnostic.c	(revision 192379)
+++ gcc/diagnostic.c	(working copy)
@@ -206,11 +206,11 @@ diagnostic_set_info (diagnostic_info *di
 
 /* Return a malloc'd string describing a location.  The caller is
    responsible for freeing the memory.  */
 char *
 diagnostic_build_prefix (diagnostic_context *context,
-			 diagnostic_info *diagnostic)
+			 const diagnostic_info *diagnostic)
 {
   static const char *const diagnostic_kind_text[] = {
 #define DEFINE_DIAGNOSTIC_KIND(K, T) (T),
 #include "diagnostic.def"
 #undef DEFINE_DIAGNOSTIC_KIND
@@ -517,14 +517,13 @@ default_diagnostic_starter (diagnostic_c
   pp_set_prefix (context->printer, diagnostic_build_prefix (context,
 							    diagnostic));
 }
 
 void
-default_diagnostic_finalizer (diagnostic_context *context,
+default_diagnostic_finalizer (diagnostic_context *context ATTRIBUTE_UNUSED,
 			      diagnostic_info *diagnostic ATTRIBUTE_UNUSED)
 {
-  pp_destroy_prefix (context->printer);
 }
 
 /* Interface to specify diagnostic kind overrides.  Returns the
    previous setting, or DK_UNSPECIFIED if the parameters are out of
    range.  */
@@ -757,10 +756,11 @@ diagnostic_report_diagnostic (diagnostic
   pp_format (context->printer, &diagnostic->message);
   (*diagnostic_starter (context)) (context, diagnostic);
   pp_output_formatted_text (context->printer);
   diagnostic_show_locus (context, diagnostic);
   (*diagnostic_finalizer (context)) (context, diagnostic);
+  pp_destroy_prefix (context->printer);
   pp_newline_and_flush (context->printer);
   diagnostic_action_after_output (context, diagnostic);
   diagnostic->message.format_spec = saved_format_spec;
   diagnostic->x_data = NULL;
 
@@ -819,10 +819,32 @@ verbatim (const char *gmsgid, ...)
   pp_format_verbatim (global_dc->printer, &text);
   pp_newline_and_flush (global_dc->printer);
   va_end (ap);
 }
 
+void
+diagnostic_attach_note (diagnostic_context *context,
+                        location_t location,
+                        const char * gmsgid, ...)
+{
+  diagnostic_info diagnostic;
+  va_list ap;
+
+  va_start (ap, gmsgid);
+  diagnostic_set_info (&diagnostic, gmsgid, &ap, location, DK_NOTE);
+  if (context->inhibit_notes_p)
+    return;
+  pp_set_prefix (context->printer,
+                 diagnostic_build_prefix (context, &diagnostic));
+  pp_newline (context->printer);
+  pp_format (context->printer, &diagnostic.message);
+  pp_output_formatted_text (context->printer);
+  pp_destroy_prefix (context->printer);
+  diagnostic_show_locus (context, &diagnostic);
+  va_end(ap);
+}
+
 bool
 emit_diagnostic (diagnostic_t kind, location_t location, int opt,
 		 const char *gmsgid, ...)
 {
   diagnostic_info diagnostic;
Index: gcc/diagnostic.h
===================================================================
--- gcc/diagnostic.h	(revision 192379)
+++ gcc/diagnostic.h	(working copy)
@@ -280,12 +280,14 @@ extern void diagnostic_set_info (diagnos
 				 location_t, diagnostic_t) ATTRIBUTE_GCC_DIAG(2,0);
 extern void diagnostic_set_info_translated (diagnostic_info *, const char *,
 					    va_list *, location_t,
 					    diagnostic_t)
      ATTRIBUTE_GCC_DIAG(2,0);
+extern void diagnostic_attach_note (diagnostic_context *, location_t,
+                                    const char *, ...) ATTRIBUTE_GCC_DIAG(3,4);
 #endif
-extern char *diagnostic_build_prefix (diagnostic_context *, diagnostic_info *);
+extern char *diagnostic_build_prefix (diagnostic_context *, const diagnostic_info *);
 void default_diagnostic_starter (diagnostic_context *, diagnostic_info *);
 void default_diagnostic_finalizer (diagnostic_context *, diagnostic_info *);
 void diagnostic_set_caret_max_width (diagnostic_context *context, int value);
 
 
