gcc/
authorfroydnj <froydnj@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 7 Dec 2010 13:46:29 +0000 (13:46 +0000)
committerfroydnj <froydnj@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 7 Dec 2010 13:46:29 +0000 (13:46 +0000)
PR c++/45330
* params.def (CXX_MAX_NAMESPACES_FOR_DIAGNOSTIC_HELP): New parameter.
* doc/invoke.texi (cxx-max-namespaces-for-diagnostic-help): Document.

gcc/cp/
PR c++/45330
* cp-tree.h (suggest_alternatives_for, location_of): Declare.
* error.c (dump_expr): Handle TYPE_DECL.
(location_of): Unstaticize.
* name-lookup.c (suggest_alternatives_for): New function.
* lex.c (unqualified_name_lookup_error): Call it.

gcc/testsuite/
PR c++/45330
* g++.dg/pr45330.C: New test.
* g++.dg/ext/builtin3.C: Adjust.
* g++.dg/lookup/error1.C: Adjust.
* g++.dg/lookup/koenig5.C: Adjust.
* g++.dg/overload/koenig1.C: Adjust.
* g++.dg/parse/decl-specifier-1.C: Adjust.
* g++.dg/template/static10.C: Adjust.
* g++.old-deja/g++.mike/ns5.C: Adjust.
* g++.old-deja/g++.mike/ns7.C: Adjust.
* g++.old-deja/g++.ns/koenig5.C: Adjust.
* g++.old-deja/g++.ns/koenig9.C: Adjust.
* g++.old-deja/g++.other/lineno5.C: Adjust.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@167536 138bc75d-0d04-0410-961f-82ee72b054a4

21 files changed:
gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/error.c
gcc/cp/lex.c
gcc/cp/name-lookup.c
gcc/doc/invoke.texi
gcc/params.def
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/builtin3.C
gcc/testsuite/g++.dg/lookup/error1.C
gcc/testsuite/g++.dg/lookup/koenig5.C
gcc/testsuite/g++.dg/overload/koenig1.C
gcc/testsuite/g++.dg/parse/decl-specifier-1.C
gcc/testsuite/g++.dg/pr45330.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/static10.C
gcc/testsuite/g++.old-deja/g++.mike/ns5.C
gcc/testsuite/g++.old-deja/g++.mike/ns7.C
gcc/testsuite/g++.old-deja/g++.ns/koenig5.C
gcc/testsuite/g++.old-deja/g++.ns/koenig9.C
gcc/testsuite/g++.old-deja/g++.other/lineno5.C

index e2dda11..2156529 100644 (file)
@@ -1,3 +1,9 @@
+2010-12-07  Nathan Froyd  <froydnj@codesourcery.com>
+
+       PR c++/45330
+       * params.def (CXX_MAX_NAMESPACES_FOR_DIAGNOSTIC_HELP): New parameter.
+       * doc/invoke.texi (cxx-max-namespaces-for-diagnostic-help): Document.
+
 2010-12-07  Richard Guenther  <rguenther@suse.de>
 
        PR tree-optimization/46832
index ef506d1..2bbd7e4 100644 (file)
@@ -1,3 +1,12 @@
+2010-12-07  Nathan Froyd  <froydnj@codesourcery.com>
+
+       PR c++/45330
+       * cp-tree.h (suggest_alternatives_for, location_of): Declare.
+       * error.c (dump_expr): Handle TYPE_DECL.
+       (location_of): Unstaticize.
+       * name-lookup.c (suggest_alternatives_for): New function.
+       * lex.c (unqualified_name_lookup_error): Call it.
+
 2010-12-06  Nicola Pero  <nicola.pero@meta-innovation.com>
 
        * call.c: Include c-family/c-objc.h.
index 59342e3..aba8dfd 100644 (file)
@@ -4907,6 +4907,7 @@ extern void print_instantiation_context           (void);
 extern void maybe_warn_variadic_templates       (void);
 extern void maybe_warn_cpp0x                   (cpp0x_warn_str str);
 extern bool pedwarn_cxx98                       (location_t, int, const char *, ...) ATTRIBUTE_GCC_DIAG(3,4);
+extern location_t location_of                   (tree);
 
 /* in except.c */
 extern void init_exception_processing          (void);
@@ -5639,6 +5640,9 @@ extern tree cxx_omp_clause_dtor                   (tree, tree);
 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);
+
 /* -- end of C++ */
 
 #endif /* ! GCC_CP_TREE_H */
index ed168c4..4fb47dc 100644 (file)
@@ -98,7 +98,6 @@ static void cp_print_error_function (diagnostic_context *, diagnostic_info *);
 
 static bool cp_printer (pretty_printer *, text_info *, const char *,
                        int, bool, bool, bool);
-static location_t location_of (tree);
 
 void
 init_error (void)
@@ -1700,6 +1699,7 @@ dump_expr (tree t, int flags)
     case NAMESPACE_DECL:
     case LABEL_DECL:
     case OVERLOAD:
+    case TYPE_DECL:
     case IDENTIFIER_NODE:
       dump_decl (t, (flags & ~TFF_DECL_SPECIFIERS) | TFF_NO_FUNCTION_ARGUMENTS);
       break;
@@ -2487,7 +2487,7 @@ lang_decl_name (tree decl, int v, bool translate)
 
 /* Return the location of a tree passed to %+ formats.  */
 
-static location_t
+location_t
 location_of (tree t)
 {
   if (TREE_CODE (t) == PARM_DECL && DECL_CONTEXT (t))
index 684803f..5a2ae41 100644 (file)
@@ -450,7 +450,10 @@ unqualified_name_lookup_error (tree name)
   else
     {
       if (!objc_diagnose_private_ivar (name))
-        error ("%qD was not declared in this scope", name);
+       {
+         error ("%qD was not declared in this scope", name);
+         suggest_alternatives_for (name);
+       }
       /* Prevent repeated error messages by creating a VAR_DECL with
         this NAME in the innermost block scope.  */
       if (current_function_decl)
index 3d19c08..4cf1380 100644 (file)
@@ -29,8 +29,10 @@ along with GCC; see the file COPYING3.  If not see
 #include "name-lookup.h"
 #include "timevar.h"
 #include "diagnostic-core.h"
+#include "intl.h"
 #include "debug.h"
 #include "c-family/c-pragma.h"
+#include "params.h"
 
 /* The bindings for a particular name in a particular scope.  */
 
@@ -3916,6 +3918,71 @@ remove_hidden_names (tree fns)
   return fns;
 }
 
+/* Suggest alternatives for NAME, an IDENTIFIER_NODE for which name
+   lookup failed.  Search through all available namespaces and print out
+   possible candidates.  */
+
+void
+suggest_alternatives_for (tree name)
+{
+  VEC(tree,heap) *candidates = NULL;
+  VEC(tree,heap) *namespaces_to_search = NULL;
+  int max_to_search = PARAM_VALUE (CXX_MAX_NAMESPACES_FOR_DIAGNOSTIC_HELP);
+  int n_searched = 0;
+  tree t;
+  unsigned ix;
+  location_t name_location;
+
+  VEC_safe_push (tree, heap, namespaces_to_search, global_namespace);
+
+  while (!VEC_empty (tree, namespaces_to_search)
+        && n_searched < max_to_search)
+    {
+      tree scope = VEC_pop (tree, namespaces_to_search);
+      struct scope_binding binding = EMPTY_SCOPE_BINDING;
+      struct cp_binding_level *level = NAMESPACE_LEVEL (scope);
+
+      /* Look in this namespace.  */
+      qualified_lookup_using_namespace (name, scope, &binding, 0);
+
+      n_searched++;
+
+      if (binding.value)
+       VEC_safe_push (tree, heap, candidates, binding.value);
+
+      /* Add child namespaces.  */
+      for (t = level->namespaces; t; t = DECL_CHAIN (t))
+       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,
+           "maximum limit of %d namespaces searched for %qE",
+           max_to_search, name);
+
+  VEC_free (tree, heap, namespaces_to_search);
+
+  /* Nothing useful to report.  */
+  if (VEC_empty (tree, candidates))
+    return;
+
+  inform_n (name_location, VEC_length (tree, candidates),
+           "suggested alternative:",
+           "suggested alternatives:");
+
+  FOR_EACH_VEC_ELT (tree, candidates, ix, t)
+    inform (location_of (t), "  %qE", t);
+
+  VEC_free (tree, heap, candidates);
+}
+
 /* Unscoped lookup of a global: iterate over current namespaces,
    considering using-directives.  */
 
index 2813532..4e3d002 100644 (file)
@@ -8821,6 +8821,10 @@ Size of minimal paritition for WHOPR (in estimated instructions).
 This prevents expenses of splitting very small programs into too many
 partitions.
 
+@item cxx-max-namespaces-for-diagnostic-help
+The maximum number of namespaces to consult for suggestions when C++
+name lookup fails for an identifier.  The default is 1000.
+
 @end table
 @end table
 
index 6b6e055..2ea0013 100644 (file)
@@ -855,6 +855,15 @@ DEFPARAM (MIN_PARTITION_SIZE,
          "lto-min-partition",
          "Size of minimal paritition for WHOPR (in estimated instructions)",
          1000, 0, 0)
+
+/* Diagnostic parameters.  */
+
+DEFPARAM (CXX_MAX_NAMESPACES_FOR_DIAGNOSTIC_HELP,
+         "cxx-max-namespaces-for-diagnostic-help",
+         "Maximum number of namespaces to search for alternatives when "
+         "name lookup fails",
+         1000, 0, 0)
+
 /*
 Local variables:
 mode:c
index 3ff9cd8..318477e 100644 (file)
@@ -1,3 +1,19 @@
+2010-12-07  Nathan Froyd  <froydnj@codesourcery.com>
+
+       PR c++/45330
+       * g++.dg/pr45330.C: New test.
+       * g++.dg/ext/builtin3.C: Adjust.
+       * g++.dg/lookup/error1.C: Adjust.
+       * g++.dg/lookup/koenig5.C: Adjust.
+       * g++.dg/overload/koenig1.C: Adjust.
+       * g++.dg/parse/decl-specifier-1.C: Adjust.
+       * g++.dg/template/static10.C: Adjust.
+       * g++.old-deja/g++.mike/ns5.C: Adjust.
+       * g++.old-deja/g++.mike/ns7.C: Adjust.
+       * g++.old-deja/g++.ns/koenig5.C: Adjust.
+       * g++.old-deja/g++.ns/koenig9.C: Adjust.
+       * g++.old-deja/g++.other/lineno5.C: Adjust.
+
 2010-12-07  Richard Guenther  <rguenther@suse.de>
 
        PR tree-optimization/46832
index 3d06dd7..001d5f7 100644 (file)
@@ -5,9 +5,10 @@
 // { dg-options "" }
 
 namespace std {
-extern "C" int printf(char*, ...);
+extern "C" int printf(char*, ...); // { dg-message "std::printf" }
 }
 
 void foo() {
   printf("abc");               // { dg-error "not declared" }
+  // { dg-message "suggested alternative" "suggested alternative" { target *-*-* } 12 }
 }
index 2264b23..3eb4b97 100644 (file)
@@ -2,8 +2,9 @@
 // Origin: <papadopo@shfj.cea.fr>
 // { dg-do compile }
 
-namespace N { int i; }
+namespace N { int i; }         // { dg-message "N::i" }
 void foo() { i; }   // { dg-error "not declared" }
+  // { dg-message "suggested alternative" "suggested alternative" { target *-*-* } 6 }
 
 using namespace N;
 void bar() { i; }
index 6ecc25d..c44543b 100644 (file)
@@ -8,23 +8,23 @@
 namespace N
 {
   struct A {};
-  void One (...);
-  void (*Two) (...);
-  namespace Three {}
+  void One (...);              // { dg-message "N::One" }
+  void (*Two) (...);           // { dg-message "N::Two" }
+  namespace Three {}           // { dg-message "N::Three" }
 }
 
 namespace M
 {
   struct B {};
-  struct One {};
-  void (*Two) (...);
-  void Three (...);
+  struct One {};               // { dg-message "M::One" }
+  void (*Two) (...);           // { dg-message "M::Two" }
+  void Three (...);            // { dg-message "M::Three" }
 }
 
 namespace O 
 {
   struct C {};
-  void Two (...);
+  void Two (...);              // { dg-message "O::Two" }
 }
   
 void g (N::A *a, M::B *b, O::C *c)
@@ -32,10 +32,12 @@ void g (N::A *a, M::B *b, O::C *c)
   One (a); // ok
   One (a, b); // ok
   One (b); // { dg-error "not declared" }
+  // { dg-message "suggested alternatives" "suggested alternative for One" { target *-*-* } 34 }
 
   Two (c); // ok
   Two (a, c); // ok
   Two (a); // { dg-error "not declared" }
+  // { dg-message "suggested alternatives" "suggested alternative for Two" { target *-*-* } 39 }
   Two (a, a); // error masked by earlier error
   Two (b); // error masked by earlier error
   Two (a, b); // error masked by earlier error
@@ -43,4 +45,5 @@ void g (N::A *a, M::B *b, O::C *c)
   Three (b); // ok
   Three (a, b); // ok
   Three (a); // { dg-error "not declared" }
+  // { dg-message "suggested alternatives" "suggested alternative for Three" { target *-*-* } 47 }
 }
index 1ed7bce..a461259 100644 (file)
@@ -3,7 +3,7 @@
 // valid call.
 
 namespace N {
-  template <class T> void f (T);
+  template <class T> void f (T); // { dg-message "N::f" }
   struct A;
 }
 
@@ -14,5 +14,6 @@ void g ()
   B *bp;
   N::A *ap;
   f (bp);                      // { dg-error "not declared" }
+  // { dg-message "suggested alternative" "suggested alternative" { target *-*-* } 16 }
   f (ap);
 }
index e81fbab..baf0fe7 100644 (file)
@@ -5,7 +5,7 @@
 namespace N
 {
     template<typename> 
-    struct X { };
+    struct X { };              // { dg-message "N::X" }
 }
 
 N::X X;                           // { dg-error "" "" }
@@ -13,4 +13,5 @@ N::X X;                           // { dg-error "" "" }
 int main()
 {
     return sizeof(X);             // { dg-error "" "" }
+    // { dg-message "suggested alternative" "suggested alternative" { target *-*-* } 15 }
 }
diff --git a/gcc/testsuite/g++.dg/pr45330.C b/gcc/testsuite/g++.dg/pr45330.C
new file mode 100644 (file)
index 0000000..02d9b3f
--- /dev/null
@@ -0,0 +1,37 @@
+// { dg-do compile }
+// Search std, __cxxabiv1, and global namespaces, plus one more.
+// { dg-options "--param cxx-max-namespaces-for-diagnostic-help=4" }
+
+#define NSPACE(NAME) namespace NAME { int foo; }
+
+namespace A
+{
+  int foo;                     // { dg-message "A::foo" "suggested alternative" }
+}
+
+namespace B
+{
+  int foo;
+}
+
+namespace C
+{
+  int foo;
+}
+
+namespace D
+{
+  int foo;
+}
+
+namespace E
+{
+  int foo;
+}
+
+int bar()
+{
+  return foo;                  // { dg-error "was not declared" }
+  // { dg-message "maximum limit of 4 namespaces" "maximum limit" { target *-*-* } 34 }
+  // { dg-message "suggested alternative" "suggested alternative" { target *-*-* } 34 }
+}
index ab857bd..881db08 100644 (file)
@@ -4,7 +4,7 @@ namespace __gnu_debug_def { }
 namespace std
 {
   using namespace __gnu_debug_def;
-  template<typename _Tp> class allocator {};
+  template<typename _Tp> class allocator {}; // { dg-message "std::allocator" }
 }
 namespace __gnu_debug_def
 {
@@ -20,4 +20,5 @@ namespace std
 {
   template<> void
   vector<int, allocator<int> >::swap(vector<int, allocator<int> >&) { } // { dg-error "" }
+  // { dg-message "suggested alternative" "suggested alternative" { target *-*-* } 22 }
 }
index 9d806ca..fd1fbff 100644 (file)
@@ -1,6 +1,7 @@
 // { dg-do assemble  }
 namespace A {
-  int i = 1;
+  int i = 1;                   // { dg-message "A::i" }
 }
 
 int j = i;             // { dg-error "" } 
+  // { dg-message "suggested alternative" "suggested alternative" { target *-*-* } 6 }
index 57008db..67d9e77 100644 (file)
@@ -1,9 +1,10 @@
 // { dg-do assemble  }
 
 namespace A {
-  int i = 1;
+  int i = 1;                   // { dg-message "A::i" }
 }
 
 namespace B {
   int j = i;   // { dg-error "" } 
+  // { dg-message "suggested alternative" "suggested alternative" { target *-*-* } 8 }
 }
index 33061ad..7c56d5c 100644 (file)
@@ -3,7 +3,7 @@
 namespace A{
   void foo();             
   struct X{};
-  void (*bar)(X*)=0;
+  void (*bar)(X*)=0;           // { dg-message "A::bar" }
 }
 using A::X;
 
@@ -15,4 +15,5 @@ void g()
                         // foo variable first, and therefore do not
                         // perform argument-dependent lookup.
   bar(new X);            // { dg-error "not declared" }
+  // { dg-message "suggested alternative" "suggested alternative" { target *-*-* } 17 }
 }
index 78b0e8b..46efcb7 100644 (file)
@@ -3,11 +3,12 @@
 // Copyright (C) 2000 Free Software Foundation, Inc.
 // Contributed by Theodore.Papadopoulo 23 Jun 2000 <Theodore.Papadopoulo@sophia.inria.fr>
 
-#include <algorithm>
+int count (int);
+void *count (char *, char);
 
 void foo(const char*,...);
 
 inline void
 bar() {
-  foo("",count);    //  { dg-error "" } multiple overloaded count functions
+  foo("",count);    //  { dg-error "overloaded function" "multiple overloaded functions" }
 }
index d14bd90..d227339 100644 (file)
 
 namespace tmp {
   typedef int B;
-  B b;
+  B b;                         // { dg-message "tmp::b" }
 }
 
 class A {
   public:
   int kaka(tmp::B = b);                // { dg-error "" } no b in scope
+  // { dg-message "suggested alternative" "suggested alternative" { target *-*-* } 18 }
 };