diff mbox

[c++] provide suggestions when qualified name lookups fail

Message ID 20101213164535.GT25904@nightcrawler
State New
Headers show

Commit Message

Nathan Froyd Dec. 13, 2010, 4:45 p.m. UTC
The patch below piggybacks on the bits provided by:

http://gcc.gnu.org/ml/gcc-patches/2010-12/msg00507.html

to also provide suggestions when qualified name lookup fails.  The only
unusual part of the patch is to tweak the interface to
suggest_alternatives_for, as qualified_name_lookup_error has a
location_t argument and we'd like to use that for our note, rather than
the location of the name.

Tested on x86_64-unknown-linux-gnu.  OK to commit?

-Nathan

gcc/cp/
	PR c++/45330
	* cp-tree.h (suggest_alternatives_for): Add location_t parameter.
	* name-lookup.c (suggest_alternatives_for): Likewise.  Adjust.
	* lex.c (unqualified_name_lookup_error): Adjust call to it.
	* semantics.c (qualified_name_lookup_error): Call
	suggest_alternatives_for.

gcc/testsuite/
	PR c++/45330
	* g++.dg/parse/suggestions1.C: New test.

Comments

Gabriel Dos Reis Dec. 14, 2010, 7:09 a.m. UTC | #1
On Mon, Dec 13, 2010 at 10:45 AM, Nathan Froyd <froydnj@codesourcery.com> wrote:
> The patch below piggybacks on the bits provided by:
>
> http://gcc.gnu.org/ml/gcc-patches/2010-12/msg00507.html
>
> to also provide suggestions when qualified name lookup fails.  The only
> unusual part of the patch is to tweak the interface to
> suggest_alternatives_for, as qualified_name_lookup_error has a
> location_t argument and we'd like to use that for our note, rather than
> the location of the name.
>
> Tested on x86_64-unknown-linux-gnu.  OK to commit?

OK with one request: qualified_name_lookup_error
does seem to use anything that is defined only in cp/semantics.c.
I would suggest to move it to cp/error.c.  Patch approved with
that change.

Thanks,

-- Gaby
diff mbox

Patch

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 79f9f24..fe6540d 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5631,7 +5631,7 @@  extern void cxx_omp_finish_clause		(tree);
 extern bool cxx_omp_privatize_by_reference	(const_tree);
 
 /* in name-lookup.c */
-extern void suggest_alternatives_for (tree);
+extern void suggest_alternatives_for (location_t, tree);
 
 /* -- end of C++ */
 
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index 5a2ae41..b04c89f 100644
--- a/gcc/cp/lex.c
+++ b/gcc/cp/lex.c
@@ -452,7 +452,7 @@  unqualified_name_lookup_error (tree name)
       if (!objc_diagnose_private_ivar (name))
 	{
 	  error ("%qD was not declared in this scope", name);
-	  suggest_alternatives_for (name);
+	  suggest_alternatives_for (location_of (name), name);
 	}
       /* Prevent repeated error messages by creating a VAR_DECL with
 	 this NAME in the innermost block scope.  */
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 4cf1380..e2e5450 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -3923,7 +3923,7 @@  remove_hidden_names (tree fns)
    possible candidates.  */
 
 void
-suggest_alternatives_for (tree name)
+suggest_alternatives_for (location_t location, tree name)
 {
   VEC(tree,heap) *candidates = NULL;
   VEC(tree,heap) *namespaces_to_search = NULL;
@@ -3931,7 +3931,6 @@  suggest_alternatives_for (tree name)
   int n_searched = 0;
   tree t;
   unsigned ix;
-  location_t name_location;
 
   VEC_safe_push (tree, heap, namespaces_to_search, global_namespace);
 
@@ -3955,15 +3954,13 @@  suggest_alternatives_for (tree name)
 	VEC_safe_push (tree, heap, namespaces_to_search, t);
     }
 
-  name_location = location_of (name);
-
   /* If we stopped before we could examine all namespaces, inform the
      user.  Do this even if we don't have any candidates, since there
      might be more candidates further down that we weren't able to
      find.  */
   if (n_searched >= max_to_search
       && !VEC_empty (tree, namespaces_to_search))
-    inform (name_location,
+    inform (location,
 	    "maximum limit of %d namespaces searched for %qE",
 	    max_to_search, name);
 
@@ -3973,7 +3970,7 @@  suggest_alternatives_for (tree name)
   if (VEC_empty (tree, candidates))
     return;
 
-  inform_n (name_location, VEC_length (tree, candidates),
+  inform_n (location, VEC_length (tree, candidates),
 	    "suggested alternative:",
 	    "suggested alternatives:");
 
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 7e42553..c4c38bb 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2672,9 +2672,15 @@  qualified_name_lookup_error (tree scope, tree name,
 	error_at (location, "%qD is not a member of %qT", name, scope);
     }
   else if (scope != global_namespace)
-    error_at (location, "%qD is not a member of %qD", name, scope);
+    {
+      error_at (location, "%qD is not a member of %qD", name, scope);
+      suggest_alternatives_for (location, name);
+    }
   else
-    error_at (location, "%<::%D%> has not been declared", name);
+    {
+      error_at (location, "%<::%D%> has not been declared", name);
+      suggest_alternatives_for (location, name);
+    }
 }
 
 /* If FNS is a member function, a set of member functions, or a
diff --git a/gcc/testsuite/g++.dg/lookup/suggestions1.C b/gcc/testsuite/g++.dg/lookup/suggestions1.C
new file mode 100644
index 0000000..1185d58
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/suggestions1.C
@@ -0,0 +1,8 @@ 
+// { dg-do compile }
+
+namespace N { namespace M { int foo; } } // { dg-message "N::M::foo" }
+int f (void) { return N::foo; }		 // { dg-error "not a member" }
+// { dg-message "suggested alternative" "missing namespace" { target *-*-* } 4 }
+
+int g (void) { return ::foo; }	// { dg-error "not been declared" }
+// { dg-message "suggested alternative" "omitted namespace" { target *-*-* } 7 }