diff mbox series

c-family: add name_hint/deferred_diagnostic (v3)

Message ID 1509668482-38959-1-git-send-email-dmalcolm@redhat.com
State New
Headers show
Series c-family: add name_hint/deferred_diagnostic (v3) | expand

Commit Message

David Malcolm Nov. 3, 2017, 12:21 a.m. UTC
Jeff: You previously had concerns about the refcounting used in v1
of this patch; this avoids that in favor of using gnu::unique_ptr.
Joseph already approved the C frontend parts of v2 of this
patch.  

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
OK for trunk?

Changed in v3:
- We can't directly include "unique-ptr.h" due to the fix for
  PR bootstrap/82610; see:
    https://gcc.gnu.org/ml/gcc-patches/2017-10/msg01289.html
  The fix is to define INCLUDE_UNIQUE_PTR before including system.h.
  This version of the patch moves the usage of gnu::unique_ptr from
  c-common.h to a new name-hint.h header, to avoid having to define
  INCLUDE_UNIQUE_PTR everywhere that uses c-common.h.
- Updated for *_at_rich_loc renaming

Changed in v2:
- dropped refcounting in favor of using gnu::unique_ptr.  One
  wart with this is that the handling of suppressed diagnostics
  has to happen in every deferred_diagnostic subclass, rather
  than in the name_hint class.  It would be possible to fix this
  by introducing another dynamically-allocated object to manage
  this concern, but adding another dynamic allocation seemed like
  overkill.

Blurb from v1:

In various places we use lookup_name_fuzzy to provide a hint,
and can report messages of the form:
  error: unknown foo named 'bar'
or:
  error: unknown foo named 'bar'; did you mean 'SUGGESTION?

This patch provides a way for lookup_name_fuzzy to provide
both the suggestion above, and (optionally) additional hints
that can be printed e.g.

  note: did you forget to include <SOME_HEADER.h>?

This patch provides the mechanism and ports existing users
of lookup_name_fuzzy to the new return type.
There are no uses of such hints in this patch, but followup
patches provide various front-end specific uses of this.

gcc/c-family/ChangeLog:
	* c-common.h (enum lookup_name_fuzzy_kind): Move to name-hint.h.
	(lookup_name_fuzzy): Likewise.  Convert return type from
	const char * to name_hint.  Add location_t param.
	* name-hint.h: New header.

gcc/c/ChangeLog:
	* c-decl.c: Define INCLUDE_UNIQUE_PTR before including system.h.
	Include "c-family/name-hint.h"
	(implicit_decl_warning): Convert "hint" from
	const char * to name_hint.  Pass location to
	lookup_name_fuzzy.  Suppress any deferred diagnostic if the
	warning was not printed.
	(undeclared_variable): Likewise for "guessed_id".
	(lookup_name_fuzzy): Convert return type from const char *
	to name_hint.  Add location_t param.
	* c-parser.c: Define INCLUDE_UNIQUE_PTR before including system.h.
	Include "c-family/name-hint.h"
	(c_parser_declaration_or_fndef): Convert "hint" from
	const char * to name_hint.  Pass location to lookup_name_fuzzy.
	(c_parser_parameter_declaration): Likewise.

gcc/cp/ChangeLog:
	* name-lookup.c: Define INCLUDE_UNIQUE_PTR before including system.h.
	Include "c-family/name-hint.h"
	(suggest_alternatives_for): Convert "fuzzy_name" from const char *
	to name_hint, and rename to "hint".  Pass location to
	lookup_name_fuzzy.
	(lookup_name_fuzzy): Convert return type from const char *
	to name_hint.  Add location_t param.
	* parser.c: Define INCLUDE_UNIQUE_PTR before including system.h.
	Include "c-family/name-hint.h"
	(cp_parser_diagnose_invalid_type_name): Convert
	"suggestion" from const char * to name_hint, and rename to "hint".
	Pass location to lookup_name_fuzzy.
---
 gcc/c-family/c-common.h  |  12 -----
 gcc/c-family/name-hint.h | 121 +++++++++++++++++++++++++++++++++++++++++++++++
 gcc/c/c-decl.c           |  37 ++++++++-------
 gcc/c/c-parser.c         |  18 ++++---
 gcc/cp/name-lookup.c     |  15 +++---
 gcc/cp/parser.c          |  12 +++--
 6 files changed, 169 insertions(+), 46 deletions(-)
 create mode 100644 gcc/c-family/name-hint.h

Comments

Jeff Law Nov. 16, 2017, 6:29 p.m. UTC | #1
On 11/02/2017 06:21 PM, David Malcolm wrote:
> Jeff: You previously had concerns about the refcounting used in v1
> of this patch; this avoids that in favor of using gnu::unique_ptr.
> Joseph already approved the C frontend parts of v2 of this
> patch.  
I had to go back and find my original message to remember what I was
concerned about.  It was the "delete this" that caught my eye in
conjunction with reference counting which brought up issues of ensuring
the object was always heap allocated and such.

Otherwise the patch was reasonable.  Given you've changed the concerning
code to use the blessed gnu::unique_ptr those concerns should be fully
addressed now.


> 
> Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
> OK for trunk?
> 
> Changed in v3:
> - We can't directly include "unique-ptr.h" due to the fix for
>   PR bootstrap/82610; see:
>     https://gcc.gnu.org/ml/gcc-patches/2017-10/msg01289.html
>   The fix is to define INCLUDE_UNIQUE_PTR before including system.h.
>   This version of the patch moves the usage of gnu::unique_ptr from
>   c-common.h to a new name-hint.h header, to avoid having to define
>   INCLUDE_UNIQUE_PTR everywhere that uses c-common.h.
> - Updated for *_at_rich_loc renaming
> 
> Changed in v2:
> - dropped refcounting in favor of using gnu::unique_ptr.  One
>   wart with this is that the handling of suppressed diagnostics
>   has to happen in every deferred_diagnostic subclass, rather
>   than in the name_hint class.  It would be possible to fix this
>   by introducing another dynamically-allocated object to manage
>   this concern, but adding another dynamic allocation seemed like
>   overkill.
> 
> Blurb from v1:
> 
> In various places we use lookup_name_fuzzy to provide a hint,
> and can report messages of the form:
>   error: unknown foo named 'bar'
> or:
>   error: unknown foo named 'bar'; did you mean 'SUGGESTION?
> 
> This patch provides a way for lookup_name_fuzzy to provide
> both the suggestion above, and (optionally) additional hints
> that can be printed e.g.
> 
>   note: did you forget to include <SOME_HEADER.h>?
> 
> This patch provides the mechanism and ports existing users
> of lookup_name_fuzzy to the new return type.
> There are no uses of such hints in this patch, but followup
> patches provide various front-end specific uses of this.
> 
> gcc/c-family/ChangeLog:
> 	* c-common.h (enum lookup_name_fuzzy_kind): Move to name-hint.h.
> 	(lookup_name_fuzzy): Likewise.  Convert return type from
> 	const char * to name_hint.  Add location_t param.
> 	* name-hint.h: New header.
> 
> gcc/c/ChangeLog:
> 	* c-decl.c: Define INCLUDE_UNIQUE_PTR before including system.h.
> 	Include "c-family/name-hint.h"
> 	(implicit_decl_warning): Convert "hint" from
> 	const char * to name_hint.  Pass location to
> 	lookup_name_fuzzy.  Suppress any deferred diagnostic if the
> 	warning was not printed.
> 	(undeclared_variable): Likewise for "guessed_id".
> 	(lookup_name_fuzzy): Convert return type from const char *
> 	to name_hint.  Add location_t param.
> 	* c-parser.c: Define INCLUDE_UNIQUE_PTR before including system.h.
> 	Include "c-family/name-hint.h"
> 	(c_parser_declaration_or_fndef): Convert "hint" from
> 	const char * to name_hint.  Pass location to lookup_name_fuzzy.
> 	(c_parser_parameter_declaration): Likewise.
> 
> gcc/cp/ChangeLog:
> 	* name-lookup.c: Define INCLUDE_UNIQUE_PTR before including system.h.
> 	Include "c-family/name-hint.h"
> 	(suggest_alternatives_for): Convert "fuzzy_name" from const char *
> 	to name_hint, and rename to "hint".  Pass location to
> 	lookup_name_fuzzy.
> 	(lookup_name_fuzzy): Convert return type from const char *
> 	to name_hint.  Add location_t param.
> 	* parser.c: Define INCLUDE_UNIQUE_PTR before including system.h.
> 	Include "c-family/name-hint.h"
> 	(cp_parser_diagnose_invalid_type_name): Convert
> 	"suggestion" from const char * to name_hint, and rename to "hint".
> 	Pass location to lookup_name_fuzzy.
OK.

jeff
diff mbox series

Patch

diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 7e1877e..0f84de9 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -990,18 +990,6 @@  extern tree lookup_label (tree);
 extern tree lookup_name (tree);
 extern bool lvalue_p (const_tree);
 
-enum lookup_name_fuzzy_kind {
-  /* Names of types.  */
-  FUZZY_LOOKUP_TYPENAME,
-
-  /* Names of function decls.  */
-  FUZZY_LOOKUP_FUNCTION_NAME,
-
-  /* Any name.  */
-  FUZZY_LOOKUP_NAME
-};
-extern const char *lookup_name_fuzzy (tree, enum lookup_name_fuzzy_kind);
-
 extern bool vector_targets_convertible_p (const_tree t1, const_tree t2);
 extern bool vector_types_convertible_p (const_tree t1, const_tree t2, bool emit_lax_note);
 extern tree c_build_vec_perm_expr (location_t, tree, tree, tree, bool = true);
diff --git a/gcc/c-family/name-hint.h b/gcc/c-family/name-hint.h
new file mode 100644
index 0000000..9f342c8
--- /dev/null
+++ b/gcc/c-family/name-hint.h
@@ -0,0 +1,121 @@ 
+/* Support for offering suggestions for handling unrecognized names.
+   Copyright (C) 2016-2017 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_NAME_HINT_H
+#define GCC_NAME_HINT_H
+
+/* This header uses gnu::unique_ptr, but unique-ptr.h can't be directly
+   included due to issues with macros.  Hence it must be included from
+   system.h by defining INCLUDE_UNIQUE_PTR in any source file using it.  */
+
+#ifndef GNU_UNIQUE_PTR_H
+# error "You must define INCLUDE_UNIQUE_PTR before including system.h to use name-hint.h"
+#endif
+
+enum lookup_name_fuzzy_kind {
+  /* Names of types.  */
+  FUZZY_LOOKUP_TYPENAME,
+
+  /* Names of function decls.  */
+  FUZZY_LOOKUP_FUNCTION_NAME,
+
+  /* Any name.  */
+  FUZZY_LOOKUP_NAME
+};
+
+/* A deferred_diagnostic is a wrapper around optional extra diagnostics
+   that we may want to bundle into a name_hint.
+
+   The diagnostic is emitted by the subclass destructor, which should
+   check that is_suppressed_p () is not true.  */
+
+class deferred_diagnostic
+{
+ public:
+  virtual ~deferred_diagnostic () {}
+
+  location_t get_location () const { return m_loc; }
+
+  /* Call this if the corresponding warning was not emitted,
+     in which case we should also not emit the deferred_diagnostic.  */
+  void suppress ()
+  {
+    m_suppress = true;
+  }
+
+  bool is_suppressed_p () const { return m_suppress; }
+
+ protected:
+  deferred_diagnostic (location_t loc)
+  : m_loc (loc), m_suppress (false) {}
+
+ private:
+  location_t m_loc;
+  bool m_suppress;
+};
+
+/* A name_hint is an optional string suggestion, along with an
+   optional deferred_diagnostic.
+   For example:
+
+       error: unknown foo named 'bar'
+
+   if the SUGGESTION is "baz", then one might print:
+
+       error: unknown foo named 'bar'; did you mean 'baz'?
+
+   and the deferred_diagnostic allows for additional (optional)
+   diagnostics e.g.:
+
+       note: did you check behind the couch?
+
+   The deferred_diagnostic is emitted by its destructor, when the
+   name_hint goes out of scope.  */
+
+class name_hint
+{
+public:
+  name_hint () : m_suggestion (NULL), m_deferred () {}
+
+  name_hint (const char *suggestion, deferred_diagnostic *deferred)
+  : m_suggestion (suggestion), m_deferred (deferred)
+  {
+  }
+
+  const char *suggestion () const { return m_suggestion; }
+  operator bool () const { return m_suggestion != NULL; }
+
+  /* Call this on a name_hint if the corresponding warning was not emitted,
+     in which case we should also not emit the deferred_diagnostic.  */
+
+  void suppress ()
+  {
+    if (m_deferred)
+      m_deferred->suppress ();
+  }
+
+private:
+  const char *m_suggestion;
+  gnu::unique_ptr<deferred_diagnostic> m_deferred;
+};
+
+extern name_hint lookup_name_fuzzy (tree, enum lookup_name_fuzzy_kind,
+				    location_t);
+
+#endif /* ! GCC_NAME_HINT_H */
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index d95a2b6..7726476 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -25,6 +25,7 @@  along with GCC; see the file COPYING3.  If not see
    line numbers.  For example, the CONST_DECLs for enum values.  */
 
 #include "config.h"
+#define INCLUDE_UNIQUE_PTR
 #include "system.h"
 #include "coretypes.h"
 #include "target.h"
@@ -54,6 +55,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "spellcheck-tree.h"
 #include "gcc-rich-location.h"
 #include "asan.h"
+#include "c-family/name-hint.h"
 
 /* In grokdeclarator, distinguish syntactic contexts of declarators.  */
 enum decl_context
@@ -3109,20 +3111,20 @@  implicit_decl_warning (location_t loc, tree id, tree olddecl)
     return;
 
   bool warned;
-  const char *hint = NULL;
+  name_hint hint;
   if (!olddecl)
-    hint = lookup_name_fuzzy (id, FUZZY_LOOKUP_FUNCTION_NAME);
+    hint = lookup_name_fuzzy (id, FUZZY_LOOKUP_FUNCTION_NAME, loc);
 
   if (flag_isoc99)
     {
       if (hint)
 	{
 	  gcc_rich_location richloc (loc);
-	  richloc.add_fixit_replace (hint);
+	  richloc.add_fixit_replace (hint.suggestion ());
 	  warned = pedwarn (&richloc, OPT_Wimplicit_function_declaration,
 			    "implicit declaration of function %qE;"
 			    " did you mean %qs?",
-			    id, hint);
+			    id, hint.suggestion ());
 	}
       else
 	warned = pedwarn (loc, OPT_Wimplicit_function_declaration,
@@ -3131,11 +3133,11 @@  implicit_decl_warning (location_t loc, tree id, tree olddecl)
   else if (hint)
     {
       gcc_rich_location richloc (loc);
-      richloc.add_fixit_replace (hint);
+      richloc.add_fixit_replace (hint.suggestion ());
       warned = warning_at
 	(&richloc, OPT_Wimplicit_function_declaration,
 	 G_("implicit declaration of function %qE; did you mean %qs?"),
-	 id, hint);
+	 id, hint.suggestion ());
     }
   else
     warned = warning_at (loc, OPT_Wimplicit_function_declaration,
@@ -3143,6 +3145,9 @@  implicit_decl_warning (location_t loc, tree id, tree olddecl)
 
   if (olddecl && warned)
     locate_old_decl (olddecl);
+
+  if (!warned)
+    hint.suppress ();
 }
 
 /* This function represents mapping of a function code FCODE
@@ -3466,15 +3471,15 @@  undeclared_variable (location_t loc, tree id)
 
   if (current_function_decl == NULL_TREE)
     {
-      const char *guessed_id = lookup_name_fuzzy (id, FUZZY_LOOKUP_NAME);
+      name_hint guessed_id = lookup_name_fuzzy (id, FUZZY_LOOKUP_NAME, loc);
       if (guessed_id)
 	{
 	  gcc_rich_location richloc (loc);
-	  richloc.add_fixit_replace (guessed_id);
+	  richloc.add_fixit_replace (guessed_id.suggestion ());
 	  error_at (&richloc,
 		    "%qE undeclared here (not in a function);"
 		    " did you mean %qs?",
-		    id, guessed_id);
+		    id, guessed_id.suggestion ());
 	}
       else
 	error_at (loc, "%qE undeclared here (not in a function)", id);
@@ -3484,15 +3489,15 @@  undeclared_variable (location_t loc, tree id)
     {
       if (!objc_diagnose_private_ivar (id))
 	{
-	  const char *guessed_id = lookup_name_fuzzy (id, FUZZY_LOOKUP_NAME);
+	  name_hint guessed_id = lookup_name_fuzzy (id, FUZZY_LOOKUP_NAME, loc);
 	  if (guessed_id)
 	    {
 	      gcc_rich_location richloc (loc);
-	      richloc.add_fixit_replace (guessed_id);
+	      richloc.add_fixit_replace (guessed_id.suggestion ());
 	      error_at (&richloc,
 			"%qE undeclared (first use in this function);"
 			" did you mean %qs?",
-			id, guessed_id);
+			id, guessed_id.suggestion ());
 	    }
 	  else
 	    error_at (loc, "%qE undeclared (first use in this function)", id);
@@ -4003,8 +4008,8 @@  lookup_name_in_scope (tree name, struct c_scope *scope)
    It also looks for start_typename keywords, to detect "singed" vs "signed"
    typos.  */
 
-const char *
-lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind)
+name_hint
+lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind, location_t)
 {
   gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
 
@@ -4094,9 +4099,9 @@  lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind)
 
   tree best = bm.get_best_meaningful_candidate ();
   if (best)
-    return IDENTIFIER_POINTER (best);
+    return name_hint (IDENTIFIER_POINTER (best), NULL);
   else
-    return NULL;
+    return name_hint (NULL, NULL);
 }
 
 
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 7bca5f1..dae8297 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -36,6 +36,7 @@  along with GCC; see the file COPYING3.  If not see
    location rather than implicitly using input_location.  */
 
 #include "config.h"
+#define INCLUDE_UNIQUE_PTR
 #include "system.h"
 #include "coretypes.h"
 #include "target.h"
@@ -65,6 +66,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "read-rtl-function.h"
 #include "run-rtl-passes.h"
 #include "intl.h"
+#include "c-family/name-hint.h"
 
 /* We need to walk over decls with incomplete struct/union/enum types
    after parsing the whole translation unit.
@@ -1808,13 +1810,14 @@  c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 	}
       else
 	{
-	  const char *hint = lookup_name_fuzzy (name, FUZZY_LOOKUP_TYPENAME);
+	  name_hint hint = lookup_name_fuzzy (name, FUZZY_LOOKUP_TYPENAME,
+					      here);
 	  if (hint)
 	    {
-	      richloc.add_fixit_replace (hint);
+	      richloc.add_fixit_replace (hint.suggestion ());
 	      error_at (&richloc,
 			"unknown type name %qE; did you mean %qs?",
-			name, hint);
+			name, hint.suggestion ());
 	    }
 	  else
 	    error_at (here, "unknown type name %qE", name);
@@ -4066,15 +4069,16 @@  c_parser_parameter_declaration (c_parser *parser, tree attrs)
       c_parser_set_source_position_from_token (token);
       if (c_parser_next_tokens_start_typename (parser, cla_prefer_type))
 	{
-	  const char *hint = lookup_name_fuzzy (token->value,
-						FUZZY_LOOKUP_TYPENAME);
+	  name_hint hint = lookup_name_fuzzy (token->value,
+					      FUZZY_LOOKUP_TYPENAME,
+					      token->location);
 	  if (hint)
 	    {
 	      gcc_rich_location richloc (token->location);
-	      richloc.add_fixit_replace (hint);
+	      richloc.add_fixit_replace (hint.suggestion ());
 	      error_at (&richloc,
 			"unknown type name %qE; did you mean %qs?",
-			token->value, hint);
+			token->value, hint.suggestion ());
 	    }
 	  else
 	    error_at (token->location, "unknown type name %qE", token->value);
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index b4976d8..8c7fb97 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -19,6 +19,7 @@  along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
+#define INCLUDE_UNIQUE_PTR
 #include "system.h"
 #include "coretypes.h"
 #include "cp-tree.h"
@@ -32,6 +33,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "gcc-rich-location.h"
 #include "spellcheck-tree.h"
 #include "parser.h"
+#include "c-family/name-hint.h"
 
 static cxx_binding *cxx_binding_make (tree value, tree type);
 static cp_binding_level *innermost_nonclass_level (void);
@@ -5371,13 +5373,14 @@  suggest_alternatives_for (location_t location, tree name,
     }
   else if (!suggest_misspellings)
     ;
-  else if (const char *fuzzy = lookup_name_fuzzy (name, FUZZY_LOOKUP_NAME))
+  else if (name_hint hint = lookup_name_fuzzy (name, FUZZY_LOOKUP_NAME,
+					       location))
     {
       /* Show a spelling correction.  */
       gcc_rich_location richloc (location);
 
-      richloc.add_fixit_replace (fuzzy);
-      inform (&richloc, "suggested alternative: %qs", fuzzy);
+      richloc.add_fixit_replace (hint.suggestion ());
+      inform (&richloc, "suggested alternative: %qs", hint.suggestion ());
     }
 }
 
@@ -5628,8 +5631,8 @@  consider_binding_level (tree name, best_match <tree, const char *> &bm,
    macro names, returning the best match as a const char *, or NULL if
    no reasonable match is found.  */
 
-const char *
-lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind)
+name_hint
+lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind, location_t)
 {
   gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
 
@@ -5683,7 +5686,7 @@  lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind)
       bm.consider (IDENTIFIER_POINTER (resword_identifier));
     }
 
-  return bm.get_best_meaningful_candidate ();
+  return name_hint (bm.get_best_meaningful_candidate (), NULL);
 }
 
 /* Subroutine of outer_binding.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 77b9637..8775eeb 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -19,6 +19,7 @@  along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
+#define INCLUDE_UNIQUE_PTR
 #include "system.h"
 #include "coretypes.h"
 #include "cp-tree.h"
@@ -43,6 +44,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "cp-cilkplus.h"
 #include "gcc-rich-location.h"
 #include "tree-iterator.h"
+#include "c-family/name-hint.h"
 
 
 /* The lexer.  */
@@ -3287,16 +3289,16 @@  cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
   else if (!parser->scope)
     {
       /* Issue an error message.  */
-      const char *suggestion = NULL;
+      name_hint hint;
       if (TREE_CODE (id) == IDENTIFIER_NODE)
-        suggestion = lookup_name_fuzzy (id, FUZZY_LOOKUP_TYPENAME);
-      if (suggestion)
+	hint = lookup_name_fuzzy (id, FUZZY_LOOKUP_TYPENAME, location);
+      if (hint)
 	{
 	  gcc_rich_location richloc (location);
-	  richloc.add_fixit_replace (suggestion);
+	  richloc.add_fixit_replace (hint.suggestion ());
 	  error_at (&richloc,
 		    "%qE does not name a type; did you mean %qs?",
-		    id, suggestion);
+		    id, hint.suggestion ());
 	}
       else
 	error_at (location, "%qE does not name a type", id);