re PR c++/45330 (Suggest likely nested-name-specifiers for undeclared identifiers.)

gcc/
	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.

From-SVN: r167536
This commit is contained in:
Nathan Froyd 2010-12-07 13:46:29 +00:00 committed by Nathan Froyd
parent 85a47bed93
commit 501c95ff05
21 changed files with 189 additions and 21 deletions

View 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

View 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.

View 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 */

View 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))

View 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)

View 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. */

View 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

View 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

View 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

View 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 }
}

View 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; }

View 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 }
}

View 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);
}

View 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 }
}

View File

@ -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 }
}

View 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 }
}

View 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 }

View 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 }
}

View 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 }
}

View 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" }
}

View File

@ -10,10 +10,11 @@
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 }
};