C++: simplify output from suggest_alternatives_for
In the C++ FE, after emitting various errors about unrecognized names, the parser can call suggest_alternatives_for and/or suggest_alternative_in_explicit_scope. These can issue zero or more suggestions for the unrecognized name, or various other "note" diagnostics suggesting how to fix the problem. For example, currently g++ emits: t.cc:12:3: error: 'gtk_widget_showall' was not declared in this scope 12 | gtk_widget_showall (w); | ^~~~~~~~~~~~~~~~~~ t.cc:12:3: note: suggested alternative: 'gtk_widget_show_all' 12 | gtk_widget_showall (w); | ^~~~~~~~~~~~~~~~~~ | gtk_widget_show_all This patch consolidates the common case when there is a single candidate, so that the error can issue a fix-it hint directly. This simplifies the above to: t.cc:12:3: error: 'gtk_widget_showall' was not declared in this scope; did you mean 'gtk_widget_show_all'? 12 | gtk_widget_showall (w); | ^~~~~~~~~~~~~~~~~~ | gtk_widget_show_all omitting the second "note" diagnostic. Doing so requires changing the above "suggest_" functions so that rather than being called after "error" and emitting a note directly, they are called before the "error", and return a name_hint, which can contain a suggestion and/or a deferred diagnostic. The "single candidate" case is handled via a suggestion, and the "multiple candidates" case via a new subclass of deferred_diagnostic. There was some complication due to the fact that we don't always have enough location information to issue a fix-it hint. Specifically, for the case in qualified_name_lookup_error, the location is that of the name, but the location of the qualifier prefix isn't reliably available. For some hints, e.g. spell-corrections, the replacement is of the name, and for others, e.g. parent namespaces, it's for the qualified name. The patch addresses this by splitting this case out into a new "suggest_alternatives_in_other_namespaces" function, for which fix-it hints aren't issued. Another complication is that of emitting a note when --param cxx-max-namespaces-for-diagnostic-help is reached. The patch emulates the existing behavior by emitting the note from a deferred_diagnostic. This potentially needs to co-exist with another deferred_diagnostic, so it works as a decorator around any other such deferred_diagnostic. Doing so requires slightly extending class name_hint. On adding test coverage for the various cases, I discovered that after emitting a "FOO is not a namespace-name" error, we also emit a "expected namespace-name before" error. The patch removes this second error for the case where it's redundant, simplifying this case from e.g.: spellcheck-ns.C:10:24: error: 'inner_ms' is not a namespace-name 10 | using namespace outer::inner_ms; | ^~~~~~~~ spellcheck-ns.C:10:24: note: suggested alternative: 'inner_ns' 10 | using namespace outer::inner_ms; | ^~~~~~~~ | inner_ns spellcheck-ns.C:10:32: error: expected namespace-name before ';' token 10 | using namespace outer::inner_ms; | ^ to: spellcheck-ns.C:10:24: error: 'inner_ms' is not a namespace-name; did you mean 'inner_ns'? 10 | using namespace outer::inner_ms; | ^~~~~~~~ | inner_ns include/ChangeLog: * unique-ptr.h (gnu::move): Generalize so it applies to all lvalue references, rather than just to unique_ptr values. gcc/c-family/ChangeLog: * name-hint.h (name_hint::take_deferred): New member function. gcc/c/ChangeLog: * c-decl.c (implicit_decl_warning): Update "is there a suggestion" logic for change to name_hint::operator bool. (undeclared_variable): Likewise. * c-parser.c (c_parser_declaration_or_fndef): Likewise. (c_parser_parameter_declaration): Likewise. gcc/cp/ChangeLog: * cp-name-hint.h: New file. * cp-tree.h (expr_to_string): New decl. (suggest_alternatives_for): Move to cp-name-hint.h, changing return type from bool to name_hint. (suggest_alternative_in_explicit_scope): Likewise. * error.c: Define INCLUDE_UNIQUE_PTR. Include "cp-name-hint.h". (expr_to_string): Make non-static. (qualified_name_lookup_error): For the non-"::" case, take responsibity for issuing any suggestion from suggest_alternative_in_explicit_scope, as it changes from returning a bool to returning a name_hint. Replace fallback call to suggest_alternatives_for to a call to suggest_alternatives_in_other_namespaces, capturing the fact that we don't have enough location information to issue a fix-it hint for this case. Update the error to support emitting a fix-it hint where appropriate. For the "::" case, take responsibility for issuing any suggestion from suggest_alternatives_for, supporting emitting a fix-it hint. * lex.c: Define INCLUDE_UNIQUE_PTR. Include "gcc-rich-location.h" and "cp-name-hint.h". (unqualified_name_lookup_error): Take responsibility for issuing any suggestion from suggest_alternatives_for, supporting emitting a fix-it hint. * name-lookup.c (class namespace_limit_reached): New subclass of deferred_diagnostic. (class show_candidate_location): Likewise. (class suggest_alternatives): Likewise. (class namespace_hints): New class. (suggest_alternatives_for): Convert return type from bool to name_hint, replacing all direct diagnostic emission by setting suggestions on the return value, or creating deferred diagnostics. Specifically, split out initial traversal of namespaces into namespace_hints' ctor, and maybe_decorate_with_limit, and move the rest of the implementation to namespace_hints::convert_candidates_to_name_hint and suggest_alternatives_for_1. (namespace_hints::namespace_hints): New ctor, adapted from suggest_alternatives_for's initial namespace traversal, storing location and name, and converting locals "candidates", "limited" and "limit" into members. (namespace_hints::convert_candidates_to_name_hint): New member function. (namespace_hints::maybe_decorate_with_limit): New member function. (suggest_alternatives_for_1): New function, based on second half of old implementation of suggest_alternatives_for, converting from immediate emission of suggestions to using name_hint. (suggest_alternatives_in_other_namespaces): New function. (maybe_suggest_missing_std_header): Convert from immediate emission of suggestions to using name_hint, moving emission implementation to... (class missing_std_header): New subclass of deferred_diagnostic. (maybe_suggest_missing_header): Convert return type from bool to name_hint. (suggest_alternative_in_explicit_scope): Convert from immediate emission of suggestions to using name_hint. * parser.c: Replace include of "c-family/name-hint.h" with "cp-name-hint.h". (cp_parser_diagnose_invalid_type_name): Update "is there a suggestion" logic for change to name_hint::operator bool. Take responsibility for emitting fix-it hints from suggest_alternative_in_explicit_scope. (cp_parser_namespace_name): Take responsibility for emitting fix-it hints from suggest_alternative_in_explicit_scope. Don't emit the "expected namespace-name" error if we've already emitted an "is not a namespace-name" error. gcc/testsuite/ChangeLog: * c-c++-common/spellcheck-reserved.c: Update expected output for C++ for merger of "did you mean" suggestions into the error message. * g++.dg/ext/builtin3.C: Update expected output for merger of "did you mean" suggestion into the error. * g++.dg/lookup/error1.C: Likewise. * g++.dg/lookup/pr77549.C: Likewise. * g++.dg/lookup/pr80913.C: Likewise. * g++.dg/lookup/suggestions1.C: Likewise. * g++.dg/lookup/suggestions2.C: New test. * g++.dg/overload/koenig1.C: Update expected output as above. * g++.dg/spellcheck-identifiers-2.C: Likewise. * g++.dg/spellcheck-identifiers.C: Likewise. * g++.dg/spellcheck-ns.C: New test. * g++.dg/spellcheck-pr77829.C: Update expected output as above. * g++.dg/spellcheck-pr78656.C: Likewise. * g++.dg/spellcheck-pr79298.C: Likewise, adding -fdiagnostics-show-caret to options. * g++.dg/spellcheck-pr80177.C: Likewise. * g++.dg/spellcheck-single-vs-multiple.C: New test. * g++.dg/spellcheck-typenames.C: Update expected output as above. * g++.dg/template/static10.C: Likewise. * g++.old-deja/g++.mike/ns5.C: Likewise. * g++.old-deja/g++.mike/ns7.C: Likewise. * g++.old-deja/g++.ns/koenig5.C: Likewise. * g++.old-deja/g++.other/lineno5.C: Likewise. libstdc++-v3/ChangeLog: * testsuite/17_intro/using_namespace_std_exp_neg.cc: Remove "expected namespace-name before" error. * testsuite/17_intro/using_namespace_std_tr1_neg.cc: Likewise. From-SVN: r265610
This commit is contained in:
parent
b2bf438c02
commit
7e2de6df10
40 changed files with 913 additions and 356 deletions
|
@ -1,3 +1,7 @@
|
|||
2018-10-29 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* name-hint.h (name_hint::take_deferred): New member function.
|
||||
|
||||
2018-10-29 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
PR c++/56856
|
||||
|
|
|
@ -99,7 +99,14 @@ public:
|
|||
}
|
||||
|
||||
const char *suggestion () const { return m_suggestion; }
|
||||
operator bool () const { return m_suggestion != NULL; }
|
||||
|
||||
/* Does this name_hint have a suggestion or a deferred diagnostic? */
|
||||
operator bool () const { return (m_suggestion != NULL
|
||||
|| m_deferred != NULL); }
|
||||
|
||||
/* Take ownership of this name_hint's deferred_diagnostic, for use
|
||||
in chaining up deferred diagnostics. */
|
||||
gnu::unique_ptr<deferred_diagnostic> take_deferred () { return move (m_deferred); }
|
||||
|
||||
/* Call this on a name_hint if the corresponding warning was not emitted,
|
||||
in which case we should also not emit the deferred_diagnostic. */
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
2018-10-29 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* c-decl.c (implicit_decl_warning): Update "is there a suggestion"
|
||||
logic for change to name_hint::operator bool.
|
||||
(undeclared_variable): Likewise.
|
||||
* c-parser.c (c_parser_declaration_or_fndef): Likewise.
|
||||
(c_parser_parameter_declaration): Likewise.
|
||||
|
||||
2018-10-17 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
* c-errors.c (pedwarn_c11): New function.
|
||||
|
|
|
@ -3150,27 +3150,27 @@ implicit_decl_warning (location_t loc, tree id, tree olddecl)
|
|||
|
||||
if (flag_isoc99)
|
||||
{
|
||||
if (hint)
|
||||
if (const char *suggestion = hint.suggestion ())
|
||||
{
|
||||
gcc_rich_location richloc (loc);
|
||||
richloc.add_fixit_replace (hint.suggestion ());
|
||||
richloc.add_fixit_replace (suggestion);
|
||||
warned = pedwarn (&richloc, OPT_Wimplicit_function_declaration,
|
||||
"implicit declaration of function %qE;"
|
||||
" did you mean %qs?",
|
||||
id, hint.suggestion ());
|
||||
id, suggestion);
|
||||
}
|
||||
else
|
||||
warned = pedwarn (loc, OPT_Wimplicit_function_declaration,
|
||||
"implicit declaration of function %qE", id);
|
||||
}
|
||||
else if (hint)
|
||||
else if (const char *suggestion = hint.suggestion ())
|
||||
{
|
||||
gcc_rich_location richloc (loc);
|
||||
richloc.add_fixit_replace (hint.suggestion ());
|
||||
richloc.add_fixit_replace (suggestion);
|
||||
warned = warning_at
|
||||
(&richloc, OPT_Wimplicit_function_declaration,
|
||||
G_("implicit declaration of function %qE; did you mean %qs?"),
|
||||
id, hint.suggestion ());
|
||||
id, suggestion);
|
||||
}
|
||||
else
|
||||
warned = warning_at (loc, OPT_Wimplicit_function_declaration,
|
||||
|
@ -3513,14 +3513,14 @@ undeclared_variable (location_t loc, tree id)
|
|||
if (current_function_decl == NULL_TREE)
|
||||
{
|
||||
name_hint guessed_id = lookup_name_fuzzy (id, FUZZY_LOOKUP_NAME, loc);
|
||||
if (guessed_id)
|
||||
if (const char *suggestion = guessed_id.suggestion ())
|
||||
{
|
||||
gcc_rich_location richloc (loc);
|
||||
richloc.add_fixit_replace (guessed_id.suggestion ());
|
||||
richloc.add_fixit_replace (suggestion);
|
||||
error_at (&richloc,
|
||||
"%qE undeclared here (not in a function);"
|
||||
" did you mean %qs?",
|
||||
id, guessed_id.suggestion ());
|
||||
id, suggestion);
|
||||
}
|
||||
else
|
||||
error_at (loc, "%qE undeclared here (not in a function)", id);
|
||||
|
@ -3531,14 +3531,14 @@ undeclared_variable (location_t loc, tree id)
|
|||
if (!objc_diagnose_private_ivar (id))
|
||||
{
|
||||
name_hint guessed_id = lookup_name_fuzzy (id, FUZZY_LOOKUP_NAME, loc);
|
||||
if (guessed_id)
|
||||
if (const char *suggestion = guessed_id.suggestion ())
|
||||
{
|
||||
gcc_rich_location richloc (loc);
|
||||
richloc.add_fixit_replace (guessed_id.suggestion ());
|
||||
richloc.add_fixit_replace (suggestion);
|
||||
error_at (&richloc,
|
||||
"%qE undeclared (first use in this function);"
|
||||
" did you mean %qs?",
|
||||
id, guessed_id.suggestion ());
|
||||
id, suggestion);
|
||||
}
|
||||
else
|
||||
error_at (loc, "%qE undeclared (first use in this function)", id);
|
||||
|
|
|
@ -1822,12 +1822,12 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
|
|||
auto_diagnostic_group d;
|
||||
name_hint hint = lookup_name_fuzzy (name, FUZZY_LOOKUP_TYPENAME,
|
||||
here);
|
||||
if (hint)
|
||||
if (const char *suggestion = hint.suggestion ())
|
||||
{
|
||||
richloc.add_fixit_replace (hint.suggestion ());
|
||||
richloc.add_fixit_replace (suggestion);
|
||||
error_at (&richloc,
|
||||
"unknown type name %qE; did you mean %qs?",
|
||||
name, hint.suggestion ());
|
||||
name, suggestion);
|
||||
}
|
||||
else
|
||||
error_at (here, "unknown type name %qE", name);
|
||||
|
@ -4074,13 +4074,13 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs)
|
|||
name_hint hint = lookup_name_fuzzy (token->value,
|
||||
FUZZY_LOOKUP_TYPENAME,
|
||||
token->location);
|
||||
if (hint)
|
||||
if (const char *suggestion = hint.suggestion ())
|
||||
{
|
||||
gcc_rich_location richloc (token->location);
|
||||
richloc.add_fixit_replace (hint.suggestion ());
|
||||
richloc.add_fixit_replace (suggestion);
|
||||
error_at (&richloc,
|
||||
"unknown type name %qE; did you mean %qs?",
|
||||
token->value, hint.suggestion ());
|
||||
token->value, suggestion);
|
||||
}
|
||||
else
|
||||
error_at (token->location, "unknown type name %qE", token->value);
|
||||
|
|
|
@ -1,3 +1,71 @@
|
|||
2018-10-29 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* cp-name-hint.h: New file.
|
||||
* cp-tree.h (expr_to_string): New decl.
|
||||
(suggest_alternatives_for): Move to cp-name-hint.h, changing
|
||||
return type from bool to name_hint.
|
||||
(suggest_alternative_in_explicit_scope): Likewise.
|
||||
* error.c: Define INCLUDE_UNIQUE_PTR. Include "cp-name-hint.h".
|
||||
(expr_to_string): Make non-static.
|
||||
(qualified_name_lookup_error): For the non-"::" case, take
|
||||
responsibity for issuing any suggestion from
|
||||
suggest_alternative_in_explicit_scope, as it changes from
|
||||
returning a bool to returning a name_hint. Replace fallback call
|
||||
to suggest_alternatives_for to a call to
|
||||
suggest_alternatives_in_other_namespaces, capturing the fact that
|
||||
we don't have enough location information to issue a fix-it hint
|
||||
for this case. Update the error to support emitting a fix-it hint
|
||||
where appropriate. For the "::" case, take responsibility for
|
||||
issuing any suggestion from suggest_alternatives_for, supporting
|
||||
emitting a fix-it hint.
|
||||
* lex.c: Define INCLUDE_UNIQUE_PTR. Include "gcc-rich-location.h"
|
||||
and "cp-name-hint.h".
|
||||
(unqualified_name_lookup_error): Take responsibility for issuing
|
||||
any suggestion from suggest_alternatives_for, supporting emitting
|
||||
a fix-it hint.
|
||||
* name-lookup.c (class namespace_limit_reached): New subclass of
|
||||
deferred_diagnostic.
|
||||
(class show_candidate_location): Likewise.
|
||||
(class suggest_alternatives): Likewise.
|
||||
(class namespace_hints): New class.
|
||||
(suggest_alternatives_for): Convert return type from bool to
|
||||
name_hint, replacing all direct diagnostic emission by setting
|
||||
suggestions on the return value, or creating deferred diagnostics.
|
||||
Specifically, split out initial traversal of namespaces into
|
||||
namespace_hints' ctor, and maybe_decorate_with_limit, and move the
|
||||
rest of the implementation to
|
||||
namespace_hints::convert_candidates_to_name_hint and
|
||||
suggest_alternatives_for_1.
|
||||
(namespace_hints::namespace_hints): New ctor, adapted from
|
||||
suggest_alternatives_for's initial namespace traversal, storing
|
||||
location and name, and converting locals "candidates", "limited"
|
||||
and "limit" into members.
|
||||
(namespace_hints::convert_candidates_to_name_hint): New member
|
||||
function.
|
||||
(namespace_hints::maybe_decorate_with_limit): New member function.
|
||||
(suggest_alternatives_for_1): New function, based on second half
|
||||
of old implementation of suggest_alternatives_for, converting from
|
||||
immediate emission of suggestions to using name_hint.
|
||||
(suggest_alternatives_in_other_namespaces): New function.
|
||||
(maybe_suggest_missing_std_header): Convert from immediate
|
||||
emission of suggestions to using name_hint, moving emission
|
||||
implementation to...
|
||||
(class missing_std_header): New subclass of deferred_diagnostic.
|
||||
(maybe_suggest_missing_header): Convert return type from bool to
|
||||
name_hint.
|
||||
(suggest_alternative_in_explicit_scope): Convert from immediate
|
||||
emission of suggestions to using name_hint.
|
||||
* parser.c: Replace include of "c-family/name-hint.h" with
|
||||
"cp-name-hint.h".
|
||||
(cp_parser_diagnose_invalid_type_name): Update
|
||||
"is there a suggestion" logic for change to
|
||||
name_hint::operator bool. Take responsibility for emitting
|
||||
fix-it hints from suggest_alternative_in_explicit_scope.
|
||||
(cp_parser_namespace_name): Take responsibility for emitting
|
||||
fix-it hints from suggest_alternative_in_explicit_scope. Don't
|
||||
emit the "expected namespace-name" error if we've already emitted
|
||||
an "is not a namespace-name" error.
|
||||
|
||||
2018-10-29 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
PR c++/56856
|
||||
|
|
37
gcc/cp/cp-name-hint.h
Normal file
37
gcc/cp/cp-name-hint.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
/* Declarations for working with name_hint instances in the C++ frontend.
|
||||
Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
Contributed by David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
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_CP_NAME_HINT_H
|
||||
#define GCC_CP_NAME_HINT_H
|
||||
|
||||
/* class name_hint is declared in c-family/name-hint.h, but due
|
||||
to issues described in that header, we have to jump through some
|
||||
#define hoops to be able to include it.
|
||||
|
||||
This header (cp/cp-name-hint.h) exists to limit the C++ frontend's
|
||||
exposure to the issue. */
|
||||
|
||||
#include "c-family/name-hint.h"
|
||||
|
||||
extern name_hint suggest_alternatives_for (location_t, tree, bool);
|
||||
extern name_hint suggest_alternatives_in_other_namespaces (location_t, tree);
|
||||
extern name_hint suggest_alternative_in_explicit_scope (location_t, tree, tree);
|
||||
|
||||
#endif /* GCC_CP_NAME_HINT_H */
|
|
@ -6445,6 +6445,7 @@ extern const char *decl_as_string (tree, int);
|
|||
extern const char *decl_as_string_translate (tree, int);
|
||||
extern const char *decl_as_dwarf_string (tree, int);
|
||||
extern const char *expr_as_string (tree, int);
|
||||
extern const char *expr_to_string (tree);
|
||||
extern const char *lang_decl_name (tree, int, bool);
|
||||
extern const char *lang_decl_dwarf_name (tree, int, bool);
|
||||
extern const char *language_to_string (enum languages);
|
||||
|
@ -7478,8 +7479,6 @@ extern tree cp_fully_fold (tree);
|
|||
extern void clear_fold_cache (void);
|
||||
|
||||
/* in name-lookup.c */
|
||||
extern void suggest_alternatives_for (location_t, tree, bool);
|
||||
extern bool suggest_alternative_in_explicit_scope (location_t, tree, tree);
|
||||
extern tree strip_using_decl (tree);
|
||||
|
||||
/* Tell the binding oracle what kind of binding we are looking for. */
|
||||
|
|
|
@ -18,6 +18,8 @@ along with GCC; see the file COPYING3. If not see
|
|||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "config.h"
|
||||
/* For use with name_hint. */
|
||||
#define INCLUDE_UNIQUE_PTR
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "cp-tree.h"
|
||||
|
@ -32,6 +34,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "ubsan.h"
|
||||
#include "internal-fn.h"
|
||||
#include "gcc-rich-location.h"
|
||||
#include "cp-name-hint.h"
|
||||
|
||||
#define pp_separate_with_comma(PP) pp_cxx_separate_with (PP, ',')
|
||||
#define pp_separate_with_semicolon(PP) pp_cxx_separate_with (PP, ';')
|
||||
|
@ -54,7 +57,6 @@ static const char *args_to_string (tree, int);
|
|||
static const char *code_to_string (enum tree_code);
|
||||
static const char *cv_to_string (tree, int);
|
||||
static const char *decl_to_string (tree, int);
|
||||
static const char *expr_to_string (tree);
|
||||
static const char *fndecl_to_string (tree, int);
|
||||
static const char *op_to_string (bool, enum tree_code);
|
||||
static const char *parm_to_string (int);
|
||||
|
@ -3059,7 +3061,7 @@ decl_to_string (tree decl, int verbose)
|
|||
return pp_ggc_formatted_text (cxx_pp);
|
||||
}
|
||||
|
||||
static const char *
|
||||
const char *
|
||||
expr_to_string (tree decl)
|
||||
{
|
||||
reinit_cxx_pp ();
|
||||
|
@ -4261,15 +4263,42 @@ qualified_name_lookup_error (tree scope, tree name,
|
|||
else if (scope != global_namespace)
|
||||
{
|
||||
auto_diagnostic_group d;
|
||||
error_at (location, "%qD is not a member of %qD", name, scope);
|
||||
if (!suggest_alternative_in_explicit_scope (location, name, scope))
|
||||
suggest_alternatives_for (location, name, false);
|
||||
bool emit_fixit = true;
|
||||
name_hint hint
|
||||
= suggest_alternative_in_explicit_scope (location, name, scope);
|
||||
if (!hint)
|
||||
{
|
||||
hint = suggest_alternatives_in_other_namespaces (location, name);
|
||||
/* "location" is just the location of the name, not of the explicit
|
||||
scope, and it's not easy to get at the latter, so we can't issue
|
||||
fix-it hints for the suggestion. */
|
||||
emit_fixit = false;
|
||||
}
|
||||
if (const char *suggestion = hint.suggestion ())
|
||||
{
|
||||
gcc_rich_location richloc (location);
|
||||
if (emit_fixit)
|
||||
richloc.add_fixit_replace (suggestion);
|
||||
error_at (&richloc, "%qD is not a member of %qD; did you mean %qs?",
|
||||
name, scope, suggestion);
|
||||
}
|
||||
else
|
||||
error_at (location, "%qD is not a member of %qD", name, scope);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto_diagnostic_group d;
|
||||
error_at (location, "%<::%D%> has not been declared", name);
|
||||
suggest_alternatives_for (location, name, true);
|
||||
name_hint hint = suggest_alternatives_for (location, name, true);
|
||||
if (const char *suggestion = hint.suggestion ())
|
||||
{
|
||||
gcc_rich_location richloc (location);
|
||||
richloc.add_fixit_replace (suggestion);
|
||||
error_at (&richloc,
|
||||
"%<::%D%> has not been declared; did you mean %qs?",
|
||||
name, suggestion);
|
||||
}
|
||||
else
|
||||
error_at (location, "%<::%D%> has not been declared", name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
17
gcc/cp/lex.c
17
gcc/cp/lex.c
|
@ -22,12 +22,16 @@ along with GCC; see the file COPYING3. If not see
|
|||
/* This file is the lexical analyzer for GNU C++. */
|
||||
|
||||
#include "config.h"
|
||||
/* For use with name_hint. */
|
||||
#define INCLUDE_UNIQUE_PTR
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "cp-tree.h"
|
||||
#include "stringpool.h"
|
||||
#include "c-family/c-pragma.h"
|
||||
#include "c-family/c-objc.h"
|
||||
#include "gcc-rich-location.h"
|
||||
#include "cp-name-hint.h"
|
||||
|
||||
static int interface_strcmp (const char *);
|
||||
static void init_cp_pragma (void);
|
||||
|
@ -500,8 +504,17 @@ unqualified_name_lookup_error (tree name, location_t loc)
|
|||
if (!objc_diagnose_private_ivar (name))
|
||||
{
|
||||
auto_diagnostic_group d;
|
||||
error_at (loc, "%qD was not declared in this scope", name);
|
||||
suggest_alternatives_for (loc, name, true);
|
||||
name_hint hint = suggest_alternatives_for (loc, name, true);
|
||||
if (const char *suggestion = hint.suggestion ())
|
||||
{
|
||||
gcc_rich_location richloc (loc);
|
||||
richloc.add_fixit_replace (suggestion);
|
||||
error_at (&richloc,
|
||||
"%qD was not declared in this scope; did you mean %qs?",
|
||||
name, suggestion);
|
||||
}
|
||||
else
|
||||
error_at (loc, "%qD was not declared in this scope", name);
|
||||
}
|
||||
/* Prevent repeated error messages by creating a VAR_DECL with
|
||||
this NAME in the innermost block scope. */
|
||||
|
|
|
@ -41,7 +41,10 @@ static cxx_binding *cxx_binding_make (tree value, tree type);
|
|||
static cp_binding_level *innermost_nonclass_level (void);
|
||||
static void set_identifier_type_value_with_scope (tree id, tree decl,
|
||||
cp_binding_level *b);
|
||||
static bool maybe_suggest_missing_std_header (location_t location, tree name);
|
||||
static name_hint maybe_suggest_missing_std_header (location_t location,
|
||||
tree name);
|
||||
static name_hint suggest_alternatives_for_1 (location_t location, tree name,
|
||||
bool suggest_misspellings);
|
||||
|
||||
/* Create an overload suitable for recording an artificial TYPE_DECL
|
||||
and another decl. We use this machanism to implement the struct
|
||||
|
@ -5299,20 +5302,132 @@ has_using_namespace_std_directive_p ()
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Suggest alternatives for NAME, an IDENTIFIER_NODE for which name
|
||||
lookup failed. Search through all available namespaces and print out
|
||||
possible candidates. If no exact matches are found, and
|
||||
SUGGEST_MISSPELLINGS is true, then also look for near-matches and
|
||||
suggest the best near-match, if there is one. */
|
||||
/* Subclass of deferred_diagnostic, for issuing a note when
|
||||
--param cxx-max-namespaces-for-diagnostic-help is reached.
|
||||
|
||||
void
|
||||
suggest_alternatives_for (location_t location, tree name,
|
||||
bool suggest_misspellings)
|
||||
The note should be issued after the error, but before any other
|
||||
deferred diagnostics. This is handled by decorating a wrapped
|
||||
deferred_diagnostic, and emitting a note before that wrapped note is
|
||||
deleted. */
|
||||
|
||||
class namespace_limit_reached : public deferred_diagnostic
|
||||
{
|
||||
vec<tree> candidates = vNULL;
|
||||
vec<tree> worklist = vNULL;
|
||||
unsigned limit = PARAM_VALUE (CXX_MAX_NAMESPACES_FOR_DIAGNOSTIC_HELP);
|
||||
bool limited = false;
|
||||
public:
|
||||
namespace_limit_reached (location_t loc, unsigned limit, tree name,
|
||||
gnu::unique_ptr<deferred_diagnostic> wrapped)
|
||||
: deferred_diagnostic (loc),
|
||||
m_limit (limit), m_name (name),
|
||||
m_wrapped (move (wrapped))
|
||||
{
|
||||
}
|
||||
|
||||
~namespace_limit_reached ()
|
||||
{
|
||||
/* Unconditionally warn that the search was truncated. */
|
||||
inform (get_location (),
|
||||
"maximum limit of %d namespaces searched for %qE",
|
||||
m_limit, m_name);
|
||||
/* m_wrapped will be implicitly deleted after this, emitting any followup
|
||||
diagnostic after the above note. */
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned m_limit;
|
||||
tree m_name;
|
||||
gnu::unique_ptr<deferred_diagnostic> m_wrapped;
|
||||
};
|
||||
|
||||
/* Subclass of deferred_diagnostic, for use when issuing a single suggestion.
|
||||
Emit a note showing the location of the declaration of the suggestion. */
|
||||
|
||||
class show_candidate_location : public deferred_diagnostic
|
||||
{
|
||||
public:
|
||||
show_candidate_location (location_t loc, tree candidate)
|
||||
: deferred_diagnostic (loc),
|
||||
m_candidate (candidate)
|
||||
{
|
||||
}
|
||||
|
||||
~show_candidate_location ()
|
||||
{
|
||||
inform (location_of (m_candidate), "%qE declared here", m_candidate);
|
||||
}
|
||||
|
||||
private:
|
||||
tree m_candidate;
|
||||
};
|
||||
|
||||
/* Subclass of deferred_diagnostic, for use when there are multiple candidates
|
||||
to be suggested by suggest_alternatives_for.
|
||||
|
||||
Emit a series of notes showing the various suggestions. */
|
||||
|
||||
class suggest_alternatives : public deferred_diagnostic
|
||||
{
|
||||
public:
|
||||
suggest_alternatives (location_t loc, vec<tree> candidates)
|
||||
: deferred_diagnostic (loc),
|
||||
m_candidates (candidates)
|
||||
{
|
||||
}
|
||||
|
||||
~suggest_alternatives ()
|
||||
{
|
||||
if (m_candidates.length ())
|
||||
{
|
||||
inform_n (get_location (), m_candidates.length (),
|
||||
"suggested alternative:",
|
||||
"suggested alternatives:");
|
||||
for (unsigned ix = 0; ix != m_candidates.length (); ix++)
|
||||
{
|
||||
tree val = m_candidates[ix];
|
||||
|
||||
inform (location_of (val), " %qE", val);
|
||||
}
|
||||
}
|
||||
m_candidates.release ();
|
||||
}
|
||||
|
||||
private:
|
||||
vec<tree> m_candidates;
|
||||
};
|
||||
|
||||
/* A class for encapsulating the result of a search across
|
||||
multiple namespaces for an unrecognized name seen at a
|
||||
given source location. */
|
||||
|
||||
class namespace_hints
|
||||
{
|
||||
public:
|
||||
namespace_hints (location_t loc, tree name);
|
||||
|
||||
name_hint convert_candidates_to_name_hint ();
|
||||
name_hint maybe_decorate_with_limit (name_hint);
|
||||
|
||||
private:
|
||||
location_t m_loc;
|
||||
tree m_name;
|
||||
vec<tree> m_candidates;
|
||||
|
||||
/* Value of "--param cxx-max-namespaces-for-diagnostic-help". */
|
||||
unsigned m_limit;
|
||||
|
||||
/* Was the limit reached? */
|
||||
bool m_limited;
|
||||
};
|
||||
|
||||
/* Constructor for namespace_hints. Search namespaces, looking for a match
|
||||
for unrecognized NAME seen at LOC. */
|
||||
|
||||
namespace_hints::namespace_hints (location_t loc, tree name)
|
||||
: m_loc(loc), m_name (name)
|
||||
{
|
||||
auto_vec<tree> worklist;
|
||||
|
||||
m_candidates = vNULL;
|
||||
m_limited = false;
|
||||
m_limit = PARAM_VALUE (CXX_MAX_NAMESPACES_FOR_DIAGNOSTIC_HELP);
|
||||
|
||||
/* Breadth-first search of namespaces. Up to limit namespaces
|
||||
searched (limit zero == unlimited). */
|
||||
|
@ -5323,14 +5438,14 @@ suggest_alternatives_for (location_t location, tree name,
|
|||
name_lookup lookup (name);
|
||||
|
||||
if (lookup.search_qualified (ns, false))
|
||||
candidates.safe_push (lookup.value);
|
||||
m_candidates.safe_push (lookup.value);
|
||||
|
||||
if (!limited)
|
||||
if (!m_limited)
|
||||
{
|
||||
/* Look for child namespaces. We have to do this
|
||||
indirectly because they are chained in reverse order,
|
||||
which is confusing to the user. */
|
||||
vec<tree> children = vNULL;
|
||||
auto_vec<tree> children;
|
||||
|
||||
for (tree decl = NAMESPACE_LEVEL (ns)->names;
|
||||
decl; decl = TREE_CHAIN (decl))
|
||||
|
@ -5339,60 +5454,141 @@ suggest_alternatives_for (location_t location, tree name,
|
|||
&& !DECL_NAMESPACE_INLINE_P (decl))
|
||||
children.safe_push (decl);
|
||||
|
||||
while (!limited && !children.is_empty ())
|
||||
while (!m_limited && !children.is_empty ())
|
||||
{
|
||||
if (worklist.length () == limit)
|
||||
{
|
||||
/* Unconditionally warn that the search was truncated. */
|
||||
inform (location,
|
||||
"maximum limit of %d namespaces searched for %qE",
|
||||
limit, name);
|
||||
limited = true;
|
||||
}
|
||||
if (worklist.length () == m_limit)
|
||||
m_limited = true;
|
||||
else
|
||||
worklist.safe_push (children.pop ());
|
||||
}
|
||||
children.release ();
|
||||
}
|
||||
}
|
||||
worklist.release ();
|
||||
}
|
||||
|
||||
if (candidates.length ())
|
||||
/* Drop ownership of m_candidates, using it to generate a name_hint at m_loc
|
||||
for m_name, an IDENTIFIER_NODE for which name lookup failed.
|
||||
|
||||
If m_candidates is non-empty, use it to generate a suggestion and/or
|
||||
a deferred diagnostic that lists the possible candidate(s).
|
||||
*/
|
||||
|
||||
name_hint
|
||||
namespace_hints::convert_candidates_to_name_hint ()
|
||||
{
|
||||
/* How many candidates do we have? */
|
||||
|
||||
/* If we have just one candidate, issue a name_hint with it as a suggestion
|
||||
(so that consumers are able to suggest it within the error message and emit
|
||||
it as a fix-it hint), and with a note showing the candidate's location. */
|
||||
if (m_candidates.length () == 1)
|
||||
{
|
||||
inform_n (location, candidates.length (),
|
||||
"suggested alternative:",
|
||||
"suggested alternatives:");
|
||||
for (unsigned ix = 0; ix != candidates.length (); ix++)
|
||||
{
|
||||
tree val = candidates[ix];
|
||||
|
||||
inform (location_of (val), " %qE", val);
|
||||
}
|
||||
candidates.release ();
|
||||
return;
|
||||
tree candidate = m_candidates[0];
|
||||
/* Clean up CANDIDATES. */
|
||||
m_candidates.release ();
|
||||
return name_hint (expr_to_string (candidate),
|
||||
new show_candidate_location (m_loc, candidate));
|
||||
}
|
||||
else if (m_candidates.length () > 1)
|
||||
/* If we have more than one candidate, issue a name_hint without a single
|
||||
"suggestion", but with a deferred diagnostic that lists the
|
||||
various candidates. This takes ownership of m_candidates. */
|
||||
return name_hint (NULL, new suggest_alternatives (m_loc, m_candidates));
|
||||
|
||||
/* Otherwise, m_candidates ought to be empty, so no cleanup is necessary. */
|
||||
gcc_assert (m_candidates.length () == 0);
|
||||
gcc_assert (m_candidates == vNULL);
|
||||
|
||||
return name_hint ();
|
||||
}
|
||||
|
||||
/* If --param cxx-max-namespaces-for-diagnostic-help was reached,
|
||||
then we want to emit a note about after the error, but before
|
||||
any other deferred diagnostics.
|
||||
|
||||
Handle this by figuring out what hint is needed, then optionally
|
||||
decorating HINT with a namespace_limit_reached wrapper. */
|
||||
|
||||
name_hint
|
||||
namespace_hints::maybe_decorate_with_limit (name_hint hint)
|
||||
{
|
||||
if (m_limited)
|
||||
return name_hint (hint.suggestion (),
|
||||
new namespace_limit_reached (m_loc, m_limit,
|
||||
m_name,
|
||||
hint.take_deferred ()));
|
||||
else
|
||||
return hint;
|
||||
}
|
||||
|
||||
/* Generate a name_hint at LOCATION for NAME, an IDENTIFIER_NODE for which
|
||||
name lookup failed.
|
||||
|
||||
Search through all available namespaces and generate a suggestion and/or
|
||||
a deferred diagnostic that lists possible candidate(s).
|
||||
|
||||
If no exact matches are found, and SUGGEST_MISSPELLINGS is true, then also
|
||||
look for near-matches and suggest the best near-match, if there is one.
|
||||
|
||||
If nothing is found, then an empty name_hint is returned. */
|
||||
|
||||
name_hint
|
||||
suggest_alternatives_for (location_t location, tree name,
|
||||
bool suggest_misspellings)
|
||||
{
|
||||
/* First, search for exact matches in other namespaces. */
|
||||
namespace_hints ns_hints (location, name);
|
||||
name_hint result = ns_hints.convert_candidates_to_name_hint ();
|
||||
|
||||
/* Otherwise, try other approaches. */
|
||||
if (!result)
|
||||
result = suggest_alternatives_for_1 (location, name, suggest_misspellings);
|
||||
|
||||
return ns_hints.maybe_decorate_with_limit (gnu::move (result));
|
||||
}
|
||||
|
||||
/* The second half of suggest_alternatives_for, for when no exact matches
|
||||
were found in other namespaces. */
|
||||
|
||||
static name_hint
|
||||
suggest_alternatives_for_1 (location_t location, tree name,
|
||||
bool suggest_misspellings)
|
||||
{
|
||||
/* No candidates were found in the available namespaces. */
|
||||
|
||||
/* If there's a "using namespace std;" active, and this
|
||||
is one of the most common "std::" names, then it's probably a
|
||||
missing #include. */
|
||||
if (has_using_namespace_std_directive_p ())
|
||||
if (maybe_suggest_missing_std_header (location, name))
|
||||
return;
|
||||
{
|
||||
name_hint hint = maybe_suggest_missing_std_header (location, name);
|
||||
if (hint)
|
||||
return hint;
|
||||
}
|
||||
|
||||
/* Otherwise, consider misspellings. */
|
||||
if (!suggest_misspellings)
|
||||
return;
|
||||
if (name_hint hint = lookup_name_fuzzy (name, FUZZY_LOOKUP_NAME,
|
||||
location))
|
||||
{
|
||||
/* Show a spelling correction. */
|
||||
gcc_rich_location richloc (location);
|
||||
return name_hint ();
|
||||
|
||||
richloc.add_fixit_replace (hint.suggestion ());
|
||||
inform (&richloc, "suggested alternative: %qs", hint.suggestion ());
|
||||
}
|
||||
return lookup_name_fuzzy (name, FUZZY_LOOKUP_NAME, location);
|
||||
}
|
||||
|
||||
/* Generate a name_hint at LOCATION for NAME, an IDENTIFIER_NODE for which
|
||||
name lookup failed.
|
||||
|
||||
Search through all available namespaces and generate a suggestion and/or
|
||||
a deferred diagnostic that lists possible candidate(s).
|
||||
|
||||
This is similiar to suggest_alternatives_for, but doesn't fallback to
|
||||
the other approaches used by that function. */
|
||||
|
||||
name_hint
|
||||
suggest_alternatives_in_other_namespaces (location_t location, tree name)
|
||||
{
|
||||
namespace_hints ns_hints (location, name);
|
||||
|
||||
name_hint result = ns_hints.convert_candidates_to_name_hint ();
|
||||
|
||||
return ns_hints.maybe_decorate_with_limit (gnu::move (result));
|
||||
}
|
||||
|
||||
/* A well-known name within the C++ standard library, returned by
|
||||
|
@ -5603,11 +5799,51 @@ get_cxx_dialect_name (enum cxx_dialect dialect)
|
|||
}
|
||||
}
|
||||
|
||||
/* Suggest pertinent header files for NAME at LOCATION, for common
|
||||
names within the "std" namespace.
|
||||
Return true iff a suggestion was offered. */
|
||||
/* Subclass of deferred_diagnostic for use for names in the "std" namespace
|
||||
that weren't recognized, but for which we know which header it ought to be
|
||||
in.
|
||||
|
||||
static bool
|
||||
Emit a note either suggesting the header to be included, or noting that
|
||||
the current dialect is too early for the given name. */
|
||||
|
||||
class missing_std_header : public deferred_diagnostic
|
||||
{
|
||||
public:
|
||||
missing_std_header (location_t loc,
|
||||
const char *name_str,
|
||||
const std_name_hint *header_hint)
|
||||
: deferred_diagnostic (loc),
|
||||
m_name_str (name_str),
|
||||
m_header_hint (header_hint)
|
||||
{}
|
||||
~missing_std_header ()
|
||||
{
|
||||
gcc_rich_location richloc (get_location ());
|
||||
if (cxx_dialect >= m_header_hint->min_dialect)
|
||||
{
|
||||
const char *header = m_header_hint->header;
|
||||
maybe_add_include_fixit (&richloc, header, true);
|
||||
inform (&richloc,
|
||||
"%<std::%s%> is defined in header %qs;"
|
||||
" did you forget to %<#include %s%>?",
|
||||
m_name_str, header, header);
|
||||
}
|
||||
else
|
||||
inform (&richloc,
|
||||
"%<std::%s%> is only available from %s onwards",
|
||||
m_name_str, get_cxx_dialect_name (m_header_hint->min_dialect));
|
||||
}
|
||||
|
||||
private:
|
||||
const char *m_name_str;
|
||||
const std_name_hint *m_header_hint;
|
||||
};
|
||||
|
||||
/* Attempt to generate a name_hint that suggests pertinent header files
|
||||
for NAME at LOCATION, for common names within the "std" namespace,
|
||||
or an empty name_hint if this isn't applicable. */
|
||||
|
||||
static name_hint
|
||||
maybe_suggest_missing_std_header (location_t location, tree name)
|
||||
{
|
||||
gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
|
||||
|
@ -5615,62 +5851,49 @@ maybe_suggest_missing_std_header (location_t location, tree name)
|
|||
const char *name_str = IDENTIFIER_POINTER (name);
|
||||
const std_name_hint *header_hint = get_std_name_hint (name_str);
|
||||
if (!header_hint)
|
||||
return false;
|
||||
return name_hint ();
|
||||
|
||||
gcc_rich_location richloc (location);
|
||||
if (cxx_dialect >= header_hint->min_dialect)
|
||||
{
|
||||
const char *header = header_hint->header;
|
||||
maybe_add_include_fixit (&richloc, header, true);
|
||||
inform (&richloc,
|
||||
"%<std::%s%> is defined in header %qs;"
|
||||
" did you forget to %<#include %s%>?",
|
||||
name_str, header, header);
|
||||
}
|
||||
else
|
||||
{
|
||||
inform (&richloc,
|
||||
"%<std::%s%> is only available from %s onwards",
|
||||
name_str, get_cxx_dialect_name (header_hint->min_dialect));
|
||||
}
|
||||
return true;
|
||||
return name_hint (NULL, new missing_std_header (location, name_str,
|
||||
header_hint));
|
||||
}
|
||||
|
||||
/* If SCOPE is the "std" namespace, then suggest pertinent header
|
||||
files for NAME at LOCATION.
|
||||
Return true iff a suggestion was offered. */
|
||||
/* Attempt to generate a name_hint that suggests a missing header file
|
||||
for NAME within SCOPE at LOCATION, or an empty name_hint if this isn't
|
||||
applicable. */
|
||||
|
||||
static bool
|
||||
static name_hint
|
||||
maybe_suggest_missing_header (location_t location, tree name, tree scope)
|
||||
{
|
||||
if (scope == NULL_TREE)
|
||||
return false;
|
||||
return name_hint ();
|
||||
if (TREE_CODE (scope) != NAMESPACE_DECL)
|
||||
return false;
|
||||
return name_hint ();
|
||||
/* We only offer suggestions for the "std" namespace. */
|
||||
if (scope != std_node)
|
||||
return false;
|
||||
return name_hint ();
|
||||
return maybe_suggest_missing_std_header (location, name);
|
||||
}
|
||||
|
||||
/* Look for alternatives for NAME, an IDENTIFIER_NODE for which name
|
||||
lookup failed within the explicitly provided SCOPE. Suggest the
|
||||
the best meaningful candidates (if any) as a fix-it hint.
|
||||
Return true iff a suggestion was provided. */
|
||||
/* Generate a name_hint at LOCATION for NAME, an IDENTIFIER_NODE for which name
|
||||
lookup failed within the explicitly provided SCOPE.
|
||||
|
||||
bool
|
||||
Suggest the the best meaningful candidates (if any), otherwise
|
||||
an empty name_hint is returned. */
|
||||
|
||||
name_hint
|
||||
suggest_alternative_in_explicit_scope (location_t location, tree name,
|
||||
tree scope)
|
||||
{
|
||||
/* Something went very wrong; don't suggest anything. */
|
||||
if (name == error_mark_node)
|
||||
return false;
|
||||
return name_hint ();
|
||||
|
||||
/* Resolve any namespace aliases. */
|
||||
scope = ORIGINAL_NAMESPACE (scope);
|
||||
|
||||
if (maybe_suggest_missing_header (location, name, scope))
|
||||
return true;
|
||||
name_hint hint = maybe_suggest_missing_header (location, name, scope);
|
||||
if (hint)
|
||||
return hint;
|
||||
|
||||
cp_binding_level *level = NAMESPACE_LEVEL (scope);
|
||||
|
||||
|
@ -5680,15 +5903,9 @@ suggest_alternative_in_explicit_scope (location_t location, tree name,
|
|||
/* See if we have a good suggesion for the user. */
|
||||
const char *fuzzy_name = bm.get_best_meaningful_candidate ();
|
||||
if (fuzzy_name)
|
||||
{
|
||||
gcc_rich_location richloc (location);
|
||||
richloc.add_fixit_replace (fuzzy_name);
|
||||
inform (&richloc, "suggested alternative: %qs",
|
||||
fuzzy_name);
|
||||
return true;
|
||||
}
|
||||
return name_hint (fuzzy_name, NULL);
|
||||
|
||||
return false;
|
||||
return name_hint ();
|
||||
}
|
||||
|
||||
/* Look up NAME (an IDENTIFIER_NODE) in SCOPE (either a NAMESPACE_DECL
|
||||
|
|
|
@ -43,7 +43,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "context.h"
|
||||
#include "gcc-rich-location.h"
|
||||
#include "tree-iterator.h"
|
||||
#include "c-family/name-hint.h"
|
||||
#include "cp-name-hint.h"
|
||||
|
||||
|
||||
/* The lexer. */
|
||||
|
@ -3292,13 +3292,13 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
|
|||
name_hint hint;
|
||||
if (TREE_CODE (id) == IDENTIFIER_NODE)
|
||||
hint = lookup_name_fuzzy (id, FUZZY_LOOKUP_TYPENAME, location);
|
||||
if (hint)
|
||||
if (const char *suggestion = hint.suggestion ())
|
||||
{
|
||||
gcc_rich_location richloc (location);
|
||||
richloc.add_fixit_replace (hint.suggestion ());
|
||||
richloc.add_fixit_replace (suggestion);
|
||||
error_at (&richloc,
|
||||
"%qE does not name a type; did you mean %qs?",
|
||||
id, hint.suggestion ());
|
||||
id, suggestion);
|
||||
}
|
||||
else
|
||||
error_at (location, "%qE does not name a type", id);
|
||||
|
@ -3364,23 +3364,53 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
|
|||
if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
|
||||
{
|
||||
auto_diagnostic_group d;
|
||||
name_hint hint;
|
||||
if (decl == error_mark_node)
|
||||
hint = suggest_alternative_in_explicit_scope (location, id,
|
||||
parser->scope);
|
||||
const char *suggestion = hint.suggestion ();
|
||||
gcc_rich_location richloc (location_of (id));
|
||||
if (suggestion)
|
||||
richloc.add_fixit_replace (suggestion);
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))
|
||||
error_at (location_of (id),
|
||||
"%qE in namespace %qE does not name a template type",
|
||||
id, parser->scope);
|
||||
{
|
||||
if (suggestion)
|
||||
error_at (&richloc,
|
||||
"%qE in namespace %qE does not name a template"
|
||||
" type; did you mean %qs?",
|
||||
id, parser->scope, suggestion);
|
||||
else
|
||||
error_at (&richloc,
|
||||
"%qE in namespace %qE does not name a template type",
|
||||
id, parser->scope);
|
||||
}
|
||||
else if (TREE_CODE (id) == TEMPLATE_ID_EXPR)
|
||||
error_at (location_of (id),
|
||||
"%qE in namespace %qE does not name a template type",
|
||||
TREE_OPERAND (id, 0), parser->scope);
|
||||
{
|
||||
if (suggestion)
|
||||
error_at (&richloc,
|
||||
"%qE in namespace %qE does not name a template"
|
||||
" type; did you mean %qs?",
|
||||
TREE_OPERAND (id, 0), parser->scope, suggestion);
|
||||
else
|
||||
error_at (&richloc,
|
||||
"%qE in namespace %qE does not name a template"
|
||||
" type",
|
||||
TREE_OPERAND (id, 0), parser->scope);
|
||||
}
|
||||
else
|
||||
error_at (location_of (id),
|
||||
"%qE in namespace %qE does not name a type",
|
||||
id, parser->scope);
|
||||
{
|
||||
if (suggestion)
|
||||
error_at (&richloc,
|
||||
"%qE in namespace %qE does not name a type"
|
||||
"; did you mean %qs?",
|
||||
id, parser->scope, suggestion);
|
||||
else
|
||||
error_at (&richloc,
|
||||
"%qE in namespace %qE does not name a type",
|
||||
id, parser->scope);
|
||||
}
|
||||
if (DECL_P (decl))
|
||||
inform (DECL_SOURCE_LOCATION (decl), "%qD declared here", decl);
|
||||
else if (decl == error_mark_node)
|
||||
suggest_alternative_in_explicit_scope (location, id,
|
||||
parser->scope);
|
||||
}
|
||||
else if (CLASS_TYPE_P (parser->scope)
|
||||
&& constructor_name_p (id, parser->scope))
|
||||
|
@ -18620,13 +18650,26 @@ cp_parser_namespace_name (cp_parser* parser)
|
|||
if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
|
||||
{
|
||||
auto_diagnostic_group d;
|
||||
error_at (token->location, "%qD is not a namespace-name", identifier);
|
||||
name_hint hint;
|
||||
if (namespace_decl == error_mark_node
|
||||
&& parser->scope && TREE_CODE (parser->scope) == NAMESPACE_DECL)
|
||||
suggest_alternative_in_explicit_scope (token->location, identifier,
|
||||
parser->scope);
|
||||
hint = suggest_alternative_in_explicit_scope (token->location,
|
||||
identifier,
|
||||
parser->scope);
|
||||
if (const char *suggestion = hint.suggestion ())
|
||||
{
|
||||
gcc_rich_location richloc (token->location);
|
||||
richloc.add_fixit_replace (suggestion);
|
||||
error_at (&richloc,
|
||||
"%qD is not a namespace-name; did you mean %qs?",
|
||||
identifier, suggestion);
|
||||
}
|
||||
else
|
||||
error_at (token->location, "%qD is not a namespace-name",
|
||||
identifier);
|
||||
}
|
||||
cp_parser_error (parser, "expected namespace-name");
|
||||
else
|
||||
cp_parser_error (parser, "expected namespace-name");
|
||||
namespace_decl = error_mark_node;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,32 @@
|
|||
2018-10-29 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* c-c++-common/spellcheck-reserved.c: Update expected output for
|
||||
C++ for merger of "did you mean" suggestions into the error
|
||||
message.
|
||||
* g++.dg/ext/builtin3.C: Update expected output for merger of "did
|
||||
you mean" suggestion into the error.
|
||||
* g++.dg/lookup/error1.C: Likewise.
|
||||
* g++.dg/lookup/pr77549.C: Likewise.
|
||||
* g++.dg/lookup/pr80913.C: Likewise.
|
||||
* g++.dg/lookup/suggestions1.C: Likewise.
|
||||
* g++.dg/lookup/suggestions2.C: New test.
|
||||
* g++.dg/overload/koenig1.C: Update expected output as above.
|
||||
* g++.dg/spellcheck-identifiers-2.C: Likewise.
|
||||
* g++.dg/spellcheck-identifiers.C: Likewise.
|
||||
* g++.dg/spellcheck-ns.C: New test.
|
||||
* g++.dg/spellcheck-pr77829.C: Update expected output as above.
|
||||
* g++.dg/spellcheck-pr78656.C: Likewise.
|
||||
* g++.dg/spellcheck-pr79298.C: Likewise, adding
|
||||
-fdiagnostics-show-caret to options.
|
||||
* g++.dg/spellcheck-pr80177.C: Likewise.
|
||||
* g++.dg/spellcheck-single-vs-multiple.C: New test.
|
||||
* g++.dg/spellcheck-typenames.C: Update expected output as above.
|
||||
* g++.dg/template/static10.C: Likewise.
|
||||
* g++.old-deja/g++.mike/ns5.C: Likewise.
|
||||
* g++.old-deja/g++.mike/ns7.C: Likewise.
|
||||
* g++.old-deja/g++.ns/koenig5.C: Likewise.
|
||||
* g++.old-deja/g++.other/lineno5.C: Likewise.
|
||||
|
||||
2018-10-29 Paolo Carlini <paolo.carlini@oracle.com>
|
||||
|
||||
* g++.dg/cpp0x/auto24.C: Test location too.
|
||||
|
|
|
@ -30,8 +30,7 @@ void test (const char *buf, char ch)
|
|||
{
|
||||
__builtin_strtchr (buf, ch); /* { dg-line misspelled_reserved } */
|
||||
/* { dg-warning "did you mean '__builtin_strchr'" "" { target c } misspelled_reserved } */
|
||||
/* { dg-error "not declared" "" { target c++ } misspelled_reserved } */
|
||||
/* { dg-message "'__builtin_strrchr'" "" { target c++ } misspelled_reserved } */
|
||||
/* { dg-error "'__builtin_strtchr' was not declared in this scope; did you mean '__builtin_strrchr'\\?" "" { target c++ } misspelled_reserved } */
|
||||
}
|
||||
|
||||
/* Similarly for a name that begins with a single underscore. */
|
||||
|
@ -40,8 +39,7 @@ void test_2 (const char *buf, char ch)
|
|||
{
|
||||
_builtin_strchr (buf, ch); /* { dg-line misspelled_one_underscore } */
|
||||
/* { dg-warning "did you mean '__builtin_strchr'" "" { target c } misspelled_one_underscore } */
|
||||
/* { dg-error "not declared" "" { target c++ } misspelled_one_underscore } */
|
||||
/* { dg-message "'__builtin_strchr'" "" { target c++ } misspelled_one_underscore } */
|
||||
/* { dg-error "'_builtin_strchr' was not declared in this scope; did you mean '__builtin_strchr'\\?" "" { target c++ } misspelled_one_underscore } */
|
||||
}
|
||||
|
||||
/* Verify that we can correct "__FILE_" to "__FILE__". */
|
||||
|
@ -50,6 +48,5 @@ const char * test_3 (void)
|
|||
{
|
||||
return __FILE_; /* { dg-line misspelled__FILE_ } */
|
||||
/* { dg-error "did you mean '__FILE__'" "" { target c } misspelled__FILE_ } */
|
||||
/* { dg-error "not declared" "" { target c++ } misspelled__FILE_ } */
|
||||
/* { dg-message "'__FILE__'" "" { target c++ } misspelled__FILE_ } */
|
||||
/* { dg-error "'__FILE_' was not declared in this scope; did you mean '__FILE__'\\?" "" { target c++ } misspelled__FILE_ } */
|
||||
}
|
||||
|
|
|
@ -9,6 +9,5 @@ extern "C" int printf(char*, ...); // { dg-message "std::printf" }
|
|||
}
|
||||
|
||||
void foo() {
|
||||
printf("abc"); // { dg-error "3:'printf' was not declared" }
|
||||
// { dg-message "suggested alternative" "suggested alternative" { target *-*-* } .-1 }
|
||||
printf("abc"); // { dg-error "3:'printf' was not declared in this scope; did you mean 'std::printf'\\?" }
|
||||
}
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
// { dg-do compile }
|
||||
|
||||
namespace N { int i; } // { dg-message "N::i" }
|
||||
void foo() { i; } // { dg-error "not declared" }
|
||||
// { dg-message "suggested alternative" "suggested alternative" { target *-*-* } .-1 }
|
||||
void foo() { i; } // { dg-error "'i' was not declared in this scope; did you mean 'N::i'\\?" }
|
||||
|
||||
using namespace N;
|
||||
void bar() { i; }
|
||||
|
|
|
@ -22,8 +22,8 @@ void
|
|||
f2 ()
|
||||
{
|
||||
using N::bar;
|
||||
baz++; // { dg-error "'baz' was not declared in this scope" }
|
||||
} // { dg-message "note: suggested alternative: 'bar'" "" { target *-*-* } .-1 }
|
||||
baz++; // { dg-error "'baz' was not declared in this scope; did you mean 'bar'\\?" }
|
||||
}
|
||||
|
||||
int
|
||||
bar ()
|
||||
|
@ -44,8 +44,8 @@ void
|
|||
f3 ()
|
||||
{
|
||||
using M::bar;
|
||||
baz (); // { dg-error "'baz' was not declared in this scope" }
|
||||
} // { dg-message "note: suggested alternative: 'bar'" "" { target *-*-* } .-1 }
|
||||
baz (); // { dg-error "'baz' was not declared in this scope; did you mean 'bar'\\?" }
|
||||
}
|
||||
|
||||
namespace O
|
||||
{
|
||||
|
@ -70,7 +70,6 @@ f4 ()
|
|||
{
|
||||
using O::foo;
|
||||
using P::bar;
|
||||
fooo (); // { dg-error "'fooo' was not declared in this scope" }
|
||||
// { dg-message "note: suggested alternative: 'foo'" "" { target *-*-* } .-1 }
|
||||
baz (); // { dg-error "'baz' was not declared in this scope" }
|
||||
} // { dg-message "note: suggested alternative: 'bar'" "" { target *-*-* } .-1 }
|
||||
fooo (); // { dg-error "'fooo' was not declared in this scope; did you mean 'foo'\\?" }
|
||||
baz (); // { dg-error "'baz' was not declared in this scope; did you mean 'bar'\\?" }
|
||||
}
|
||||
|
|
|
@ -6,6 +6,5 @@ struct meminfo {};
|
|||
|
||||
void frob ()
|
||||
{
|
||||
meminf (); // { dg-error "not declared" }
|
||||
// { dg-message "suggested alternative" "" { target *-*-* } .-1 }
|
||||
meminf (); // { dg-error "'meminf' was not declared in this scope; did you mean 'meminfo'\\?" }
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
// { 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 *-*-* } .-1 }
|
||||
namespace N { namespace M { int foo; } } // { dg-message "'N::M::foo' declared here" }
|
||||
int f (void) { return N::foo; } // { dg-error "'foo' is not a member of 'N'; did you mean 'N::M::foo'\\?" }
|
||||
|
||||
int g (void) { return ::foo; } // { dg-error "not been declared" }
|
||||
// { dg-message "suggested alternative" "omitted namespace" { target *-*-* } .-1 }
|
||||
int g (void) { return ::foo; } // { dg-error "'::foo' has not been declared; did you mean 'N::M::foo'\\?" }
|
||||
|
|
128
gcc/testsuite/g++.dg/lookup/suggestions2.C
Normal file
128
gcc/testsuite/g++.dg/lookup/suggestions2.C
Normal file
|
@ -0,0 +1,128 @@
|
|||
/* Suggestions involving namespaces.
|
||||
|
||||
The long variable names in this test case are close enough that we offer
|
||||
spellchecking suggestions for them in the given namespace, with fix-it
|
||||
hints.
|
||||
|
||||
The short variable names don't get spellchecking suggestions; instead
|
||||
we offer suggestions about other namespaces. However, as we don't
|
||||
reliably have location information about the namespace part of the name,
|
||||
we shouldn't offer fix-it hints for such cases. */
|
||||
|
||||
// { dg-do compile }
|
||||
// { dg-options "-fdiagnostics-show-caret" }
|
||||
|
||||
namespace outer_ns {
|
||||
int var_in_outer_ns; // { dg-line decl_of_var_in_outer_ns }
|
||||
int o; // { dg-line decl_of_o }
|
||||
|
||||
namespace inner_ns_a {
|
||||
int var_in_inner_ns_a;
|
||||
int a; // { dg-line decl_of_a }
|
||||
}
|
||||
namespace inner_ns_b {
|
||||
int var_in_inner_ns_b;
|
||||
int b; // { dg-line decl_of_b }
|
||||
}
|
||||
}
|
||||
|
||||
/* This one should get spell-corrected within the same namespace,
|
||||
with a fix-it hint. */
|
||||
|
||||
int test_1_long (void) {
|
||||
return outer_ns::var_in_inner_ns_a; // { dg-error "did you mean 'var_in_outer_ns'" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return outer_ns::var_in_inner_ns_a;
|
||||
^~~~~~~~~~~~~~~~~
|
||||
var_in_outer_ns
|
||||
{ dg-end-multiline-output "" } */
|
||||
}
|
||||
|
||||
/* This one should get a namespace suggestion (child namespace),
|
||||
with no fix-it hint. */
|
||||
|
||||
int test_1_short (void) {
|
||||
return outer_ns::a; // { dg-error "did you mean 'outer_ns::inner_ns_a::a'" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return outer_ns::a;
|
||||
^
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "declared here" "" { target *-*-*} decl_of_a }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
int a;
|
||||
^
|
||||
{ dg-end-multiline-output "" } */
|
||||
}
|
||||
|
||||
/* This one should get spell-corrected within the same namespace,
|
||||
with a fix-it hint. */
|
||||
|
||||
int test_2_long (void) {
|
||||
return outer_ns::inner_ns_a::var_in_outer_ns; // { dg-error "did you mean 'var_in_inner_ns_a'" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return outer_ns::inner_ns_a::var_in_outer_ns;
|
||||
^~~~~~~~~~~~~~~
|
||||
var_in_inner_ns_a
|
||||
{ dg-end-multiline-output "" } */
|
||||
}
|
||||
|
||||
/* This one should get a namespace suggestion (parent namespace),
|
||||
with no fix-it hint. */
|
||||
|
||||
int test_2_short (void) {
|
||||
return outer_ns::inner_ns_a::o; // { dg-error "did you mean 'outer_ns::o'" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return outer_ns::inner_ns_a::o;
|
||||
^
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "declared here" "" { target *-*-*} decl_of_o }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
int o;
|
||||
^
|
||||
{ dg-end-multiline-output "" } */
|
||||
}
|
||||
|
||||
/* This one should get spell-corrected within the same namespace,
|
||||
with a fix-it hint. */
|
||||
|
||||
int test_3_long (void) {
|
||||
return outer_ns::inner_ns_a::var_in_inner_ns_b; // { dg-error "did you mean 'var_in_inner_ns_a'" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return outer_ns::inner_ns_a::var_in_inner_ns_b;
|
||||
^~~~~~~~~~~~~~~~~
|
||||
var_in_inner_ns_a
|
||||
{ dg-end-multiline-output "" } */
|
||||
}
|
||||
|
||||
/* This one should get a namespace suggestion (sibling namespace),
|
||||
with no fix-it hint. */
|
||||
|
||||
int test_3_short (void) {
|
||||
return outer_ns::inner_ns_a::b; // { dg-error "did you mean 'outer_ns::inner_ns_b::b'" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return outer_ns::inner_ns_a::b;
|
||||
^
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "declared here" "" { target *-*-*} decl_of_b }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
int b;
|
||||
^
|
||||
{ dg-end-multiline-output "" } */
|
||||
}
|
||||
|
||||
/* This one should get a namespace suggestion, from the global ns to a child ns.
|
||||
It should get a fix-it hint. */
|
||||
|
||||
int test_4_long (void) {
|
||||
return ::var_in_outer_ns; // { dg-error "did you mean 'outer_ns::var_in_outer_ns'" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return ::var_in_outer_ns;
|
||||
^~~~~~~~~~~~~~~
|
||||
outer_ns::var_in_outer_ns
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "declared here" "" { target *-*-*} decl_of_var_in_outer_ns }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
int var_in_outer_ns;
|
||||
^~~~~~~~~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
}
|
|
@ -13,7 +13,6 @@ void g ()
|
|||
{
|
||||
B *bp;
|
||||
N::A *ap;
|
||||
f (bp); // { dg-error "3:'f' was not declared" }
|
||||
// { dg-message "suggested alternative" "suggested alternative" { target *-*-* } .-1 }
|
||||
f (bp); // { dg-error "3:'f' was not declared in this scope; did you mean 'N::f'" }
|
||||
f (ap);
|
||||
}
|
||||
|
|
|
@ -9,12 +9,7 @@ int
|
|||
test_1 (const char *p)
|
||||
{
|
||||
int i;
|
||||
return ssacnf (p, "%d", &i); /* { dg-error "10: .ssacnf. was not declared in this scope" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return ssacnf (p, "%d", &i);
|
||||
^~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "10: suggested alternative: 'sscafn'" "" { target *-*-* } 12 }
|
||||
return ssacnf (p, "%d", &i); /* { dg-error "10: .ssacnf. was not declared in this scope; did you mean 'sscafn'\\?" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return ssacnf (p, "%d", &i);
|
||||
^~~~~~
|
||||
|
@ -29,12 +24,7 @@ int
|
|||
test_2 (void)
|
||||
{
|
||||
int i;
|
||||
return sacnf ("%d", &i); /* { dg-error "10: .sacnf. was not declared in this scope" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return sacnf ("%d", &i);
|
||||
^~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "10: suggested alternative: 'scanf'" "" { target *-*-* } 32 }
|
||||
return sacnf ("%d", &i); /* { dg-error "10: .sacnf. was not declared in this scope; did you mean 'scanf'\\?" } */
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return sacnf ("%d", &i);
|
||||
^~~~~
|
||||
|
|
|
@ -9,12 +9,7 @@ extern void gtk_widget_show_all (GtkWidget *w);
|
|||
void
|
||||
test_1 (GtkWidget *w)
|
||||
{
|
||||
gtk_widget_showall (w); // { dg-error "3: 'gtk_widget_showall' was not declared in this scope" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
gtk_widget_showall (w);
|
||||
^~~~~~~~~~~~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "3: suggested alternative: 'gtk_widget_show_all'" "" { target *-*-* } 12 }
|
||||
gtk_widget_showall (w); // { dg-error "3: 'gtk_widget_showall' was not declared in this scope; did you mean 'gtk_widget_show_all'\\?" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
gtk_widget_showall (w);
|
||||
^~~~~~~~~~~~~~~~~~
|
||||
|
@ -23,24 +18,14 @@ test_1 (GtkWidget *w)
|
|||
|
||||
/* Ensure we don't try to suggest "gtk_widget_showall" for subsequent
|
||||
corrections. */
|
||||
gtk_widget_showall_ (w); // { dg-error "3: 'gtk_widget_showall_' was not declared in this scope" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
gtk_widget_showall_ (w);
|
||||
^~~~~~~~~~~~~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "3: suggested alternative: 'gtk_widget_show_all'" "" { target *-*-* } 26 }
|
||||
gtk_widget_showall_ (w); // { dg-error "3: 'gtk_widget_showall_' was not declared in this scope; did you mean 'gtk_widget_show_all'\\?" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
gtk_widget_showall_ (w);
|
||||
^~~~~~~~~~~~~~~~~~~
|
||||
gtk_widget_show_all
|
||||
{ dg-end-multiline-output "" } */
|
||||
|
||||
GtkWidgetShowAll (w); // { dg-error "3: 'GtkWidgetShowAll' was not declared in this scope" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
GtkWidgetShowAll (w);
|
||||
^~~~~~~~~~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "3: suggested alternative: 'gtk_widget_show_all'" "" { target *-*-* } 38 }
|
||||
GtkWidgetShowAll (w); // { dg-error "3: 'GtkWidgetShowAll' was not declared in this scope; did you mean 'gtk_widget_show_all'\\?" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
GtkWidgetShowAll (w);
|
||||
^~~~~~~~~~~~~~~~
|
||||
|
@ -51,12 +36,7 @@ test_1 (GtkWidget *w)
|
|||
int
|
||||
test_2 (int param)
|
||||
{
|
||||
return parma * parma; // { dg-error "10: 'parma' was not declared in this scope" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return parma * parma;
|
||||
^~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "10: suggested alternative: 'param'" "" { target *-*-* } 54 }
|
||||
return parma * parma; // { dg-error "10: 'parma' was not declared in this scope; did you mean 'param'\\?" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return parma * parma;
|
||||
^~~~~
|
||||
|
@ -69,12 +49,7 @@ test_2 (int param)
|
|||
int
|
||||
test_3 (int i)
|
||||
{
|
||||
return MACRAME (i); // { dg-error "10: 'MACRAME' was not declared in this scope" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return MACRAME (i);
|
||||
^~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "10: suggested alternative: 'MACRO'" "" { target *-*-* } 72 }
|
||||
return MACRAME (i); // { dg-error "10: 'MACRAME' was not declared in this scope; did you mean 'MACRO'\\?" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return MACRAME (i);
|
||||
^~~~~~~
|
||||
|
@ -87,12 +62,7 @@ test_3 (int i)
|
|||
int
|
||||
test_4 (int node)
|
||||
{
|
||||
return IDENTIFIER_PTR (node); // { dg-error "10: 'IDENTIFIER_PTR' was not declared in this scope" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return IDENTIFIER_PTR (node);
|
||||
^~~~~~~~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "10: suggested alternative: 'IDENTIFIER_POINTER'" "" { target *-*-* } 90 }
|
||||
return IDENTIFIER_PTR (node); // { dg-error "10: 'IDENTIFIER_PTR' was not declared in this scope; did you mean 'IDENTIFIER_POINTER'\\?" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return IDENTIFIER_PTR (node);
|
||||
^~~~~~~~~~~~~~
|
||||
|
@ -104,12 +74,7 @@ test_4 (int node)
|
|||
int
|
||||
test_5 (void)
|
||||
{
|
||||
return __LINE_; /* { dg-error "10: '__LINE_' was not declared in this scope" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return __LINE_;
|
||||
^~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "10: suggested alternative: '__LINE__'" "" { target *-*-* } 107 }
|
||||
return __LINE_; /* { dg-error "10: '__LINE_' was not declared in this scope; did you mean '__LINE__'\\?" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return __LINE_;
|
||||
^~~~~~~
|
||||
|
@ -118,12 +83,7 @@ test_5 (void)
|
|||
}
|
||||
|
||||
#define MAX_ITEMS 100
|
||||
int array[MAX_ITEM]; // { dg-error "11: 'MAX_ITEM' was not declared in this scope" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
int array[MAX_ITEM];
|
||||
^~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "11: suggested alternative: 'MAX_ITEMS'" "" { target *-*-* } 121 }
|
||||
int array[MAX_ITEM]; // { dg-error "11: 'MAX_ITEM' was not declared in this scope; did you mean 'MAX_ITEMS'\\?" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
int array[MAX_ITEM];
|
||||
^~~~~~~~
|
||||
|
@ -141,26 +101,16 @@ test_6 (enum foo f)
|
|||
{
|
||||
switch (f)
|
||||
{
|
||||
case FOO_FURST: // { dg-error "10: 'FOO_FURST' was not declared in this scope" }
|
||||
case FOO_FURST: // { dg-error "10: 'FOO_FURST' was not declared in this scope; did you mean 'FOO_FIRST'\\?" }
|
||||
break;
|
||||
/* { dg-begin-multiline-output "" }
|
||||
case FOO_FURST:
|
||||
^~~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "10: suggested alternative: 'FOO_FIRST'" "" { target *-*-* } 144 }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
case FOO_FURST:
|
||||
^~~~~~~~~
|
||||
FOO_FIRST
|
||||
{ dg-end-multiline-output "" } */
|
||||
|
||||
case FOO_SECCOND: // { dg-error "10: 'FOO_SECCOND' was not declared in this scope" }
|
||||
case FOO_SECCOND: // { dg-error "10: 'FOO_SECCOND' was not declared in this scope; did you mean 'FOO_SECOND'\\?" }
|
||||
break;
|
||||
/* { dg-begin-multiline-output "" }
|
||||
case FOO_SECCOND:
|
||||
^~~~~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "10: suggested alternative: 'FOO_SECOND'" "" { target *-*-* } 157 }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
case FOO_SECCOND:
|
||||
^~~~~~~~~~~
|
||||
|
@ -178,12 +128,7 @@ void
|
|||
test_7 (int i, int j)
|
||||
{
|
||||
int buffer[100];
|
||||
snprint (buffer, 100, "%i of %i", i, j); // { dg-error "3: 'snprint' was not declared in this scope" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
snprint (buffer, 100, "%i of %i", i, j);
|
||||
^~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "3: suggested alternative: 'snprintf'" "" { target *-*-* } 181 }
|
||||
snprint (buffer, 100, "%i of %i", i, j); // { dg-error "3: 'snprint' was not declared in this scope; did you mean 'snprintf'\\?" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
snprint (buffer, 100, "%i of %i", i, j);
|
||||
^~~~~~~
|
||||
|
@ -196,12 +141,7 @@ test_8 ()
|
|||
{
|
||||
int local = 42;
|
||||
|
||||
return locale; // { dg-error "10: 'locale' was not declared in this scope" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return locale;
|
||||
^~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "10: suggested alternative: 'local'" "" { target *-*-* } 199 }
|
||||
return locale; // { dg-error "10: 'locale' was not declared in this scope; did you mean 'local'\\?" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return locale;
|
||||
^~~~~~
|
||||
|
@ -226,12 +166,7 @@ public:
|
|||
|
||||
int base::test_method_1 ()
|
||||
{
|
||||
return m_food; // { dg-error "10: 'm_food' was not declared in this scope" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return m_food;
|
||||
^~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "10: suggested alternative: 'm_foo'" "" { target *-*-* } 229 }
|
||||
return m_food; // { dg-error "10: 'm_food' was not declared in this scope; did you mean 'm_foo'\\?" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return m_food;
|
||||
^~~~~~
|
||||
|
@ -241,12 +176,7 @@ int base::test_method_1 ()
|
|||
|
||||
int sub::test_method_2 ()
|
||||
{
|
||||
return m_food; // { dg-error "10: 'm_food' was not declared in this scope" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return m_food;
|
||||
^~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "10: suggested alternative: 'm_foo'" "" { target *-*-* } 244 }
|
||||
return m_food; // { dg-error "10: 'm_food' was not declared in this scope; did you mean 'm_foo'\\?" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return m_food;
|
||||
^~~~~~
|
||||
|
|
22
gcc/testsuite/g++.dg/spellcheck-ns.C
Normal file
22
gcc/testsuite/g++.dg/spellcheck-ns.C
Normal file
|
@ -0,0 +1,22 @@
|
|||
// { dg-options "-fdiagnostics-show-caret" }
|
||||
|
||||
namespace outer {
|
||||
namespace inner_ns {
|
||||
}
|
||||
typedef int some_typedef;
|
||||
}
|
||||
|
||||
using namespace outer;
|
||||
using namespace outer::inner_ms; // { dg-error "'inner_ms' is not a namespace-name; did you mean 'inner_ns'" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
using namespace outer::inner_ms;
|
||||
^~~~~~~~
|
||||
inner_ns
|
||||
{ dg-end-multiline-output "" } */
|
||||
|
||||
outer::some_typedfe var; // { dg-error "'some_typedfe' in namespace 'outer' does not name a type; did you mean 'some_typedef'" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
outer::some_typedfe var;
|
||||
^~~~~~~~~~~~
|
||||
some_typedef
|
||||
{ dg-end-multiline-output "" } */
|
|
@ -18,12 +18,7 @@ namespace detail {
|
|||
|
||||
void fn_1_explicit ()
|
||||
{
|
||||
detail::some_type i; // { dg-error ".some_type. is not a member of .detail." }
|
||||
// { dg-message "suggested alternative: .some_typedef." "" { target *-*-* } .-1 }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
detail::some_type i;
|
||||
^~~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
detail::some_type i; // { dg-error ".some_type. is not a member of .detail.; did you mean 'some_typedef'\\?" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
detail::some_type i;
|
||||
^~~~~~~~~
|
||||
|
@ -35,12 +30,7 @@ namespace detail {
|
|||
|
||||
void fn_1_implicit ()
|
||||
{
|
||||
some_type i; // { dg-error ".some_type. was not declared in this scope" }
|
||||
// { dg-message "suggested alternative: .some_typedef." "" { target *-*-* } .-1 }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
some_type i;
|
||||
^~~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
some_type i; // { dg-error ".some_type. was not declared in this scope; did you mean 'some_typedef'\\?" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
some_type i;
|
||||
^~~~~~~~~
|
||||
|
@ -54,12 +44,7 @@ void fn_1_implicit ()
|
|||
/* Tests of lookup of a function. */
|
||||
|
||||
void fn_2_explicit (int i) {
|
||||
detail::foo(i); // { dg-error ".foo. is not a member of .detail." }
|
||||
// { dg-message "suggested alternative: ._foo." "" { target *-*-* } .-1 }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
detail::foo(i);
|
||||
^~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
detail::foo(i); // { dg-error ".foo. is not a member of .detail.; did you mean '_foo'\\?" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
detail::foo(i);
|
||||
^~~
|
||||
|
@ -70,12 +55,7 @@ void fn_2_explicit (int i) {
|
|||
namespace detail {
|
||||
|
||||
void fn_2_implicit (int i) {
|
||||
foo(i); // { dg-error ".foo. was not declared in this scope" }
|
||||
// { dg-message "suggested alternative: ._foo." "" { target *-*-* } .-1 }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
foo(i);
|
||||
^~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
foo(i); // { dg-error ".foo. was not declared in this scope; did you mean '_foo'\\?" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
foo(i);
|
||||
^~~
|
||||
|
@ -89,13 +69,7 @@ void fn_2_implicit (int i) {
|
|||
/* Examples using a template. */
|
||||
|
||||
void fn_3_explicit (int i) {
|
||||
detail::something_els(i); // { dg-error ".something_els. is not a member of .detail." }
|
||||
// { dg-message "suggested alternative: .something_else." "" { target *-*-* } .-1 }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
detail::something_els(i);
|
||||
^~~~~~~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
|
||||
detail::something_els(i); // { dg-error ".something_els. is not a member of .detail.; did you mean 'something_else'\\?" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
detail::something_els(i);
|
||||
^~~~~~~~~~~~~
|
||||
|
@ -106,13 +80,7 @@ void fn_3_explicit (int i) {
|
|||
namespace detail {
|
||||
|
||||
void fn_3_implicit (int i) {
|
||||
something_els(i); // { dg-error ".something_els. was not declared in this scope" }
|
||||
// { dg-message "suggested alternative: .something_else." "" { target *-*-* } .-1 }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
something_els(i);
|
||||
^~~~~~~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
|
||||
something_els(i); // { dg-error ".something_els. was not declared in this scope; did you mean 'something_else'\\?" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
something_els(i);
|
||||
^~~~~~~~~~~~~
|
||||
|
@ -153,12 +121,7 @@ typedef int another_typedef;
|
|||
|
||||
void fn_5 ()
|
||||
{
|
||||
::another_type i; // { dg-error ".::another_type. has not been declared" }
|
||||
// { dg-message "suggested alternative: .another_typedef." "" { target *-*-* } .-1 }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
::another_type i;
|
||||
^~~~~~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
::another_type i; // { dg-error ".::another_type. has not been declared; did you mean 'another_typedef'\\?" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
::another_type i;
|
||||
^~~~~~~~~~~~
|
||||
|
|
|
@ -4,12 +4,7 @@
|
|||
|
||||
void* allocate(std::size_t n)
|
||||
{
|
||||
return std::allocate<char>().allocate(n); // { dg-error ".allocate. is not a member of .std." }
|
||||
// { dg-message "suggested alternative: .allocator." "" { target *-*-* } .-1 }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return std::allocate<char>().allocate(n);
|
||||
^~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
return std::allocate<char>().allocate(n); // { dg-error ".allocate. is not a member of .std.; did you mean 'allocator'\\?" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return std::allocate<char>().allocate(n);
|
||||
^~~~~~~~
|
||||
|
@ -22,12 +17,7 @@ void* allocate(std::size_t n)
|
|||
|
||||
void* test_2(std::size_t n)
|
||||
{
|
||||
return std::alocator<char>().allocate(n); // { dg-error ".alocator. is not a member of .std." }
|
||||
// { dg-message "suggested alternative: .allocator." "" { target *-*-* } .-1 }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return std::alocator<char>().allocate(n);
|
||||
^~~~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
return std::alocator<char>().allocate(n); // { dg-error ".alocator. is not a member of .std.; did you mean 'allocator'\\?" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return std::alocator<char>().allocate(n);
|
||||
^~~~~~~~
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// Ensure that we can offer suggestions for misspellings via a
|
||||
// namespace alias.
|
||||
// { dg-options "-fdiagnostics-show-caret" }
|
||||
|
||||
namespace N { int x; int color; }
|
||||
namespace M = N;
|
||||
|
@ -8,10 +9,18 @@ namespace O = M;
|
|||
int foo ()
|
||||
{
|
||||
return M::y; // { dg-error ".y. is not a member of .M." }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return M::y;
|
||||
^
|
||||
{ dg-end-multiline-output "" } */
|
||||
}
|
||||
|
||||
int bar ()
|
||||
{
|
||||
return O::colour; // { dg-error ".colour. is not a member of .O." }
|
||||
// { dg-message "suggested alternative: .color." "" { target *-*-* } .-1 }
|
||||
return O::colour; // { dg-error ".colour. is not a member of .O.; did you mean 'color'\\?" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
return O::colour;
|
||||
^~~~~~
|
||||
color
|
||||
{ dg-end-multiline-output "" } */
|
||||
}
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
// { dg-do compile { target c++11 } }
|
||||
// { dg-options "-fdiagnostics-show-caret" }
|
||||
|
||||
void pr80177 ()
|
||||
{
|
||||
static_assertion (1 == 0, "1 == 0"); // { dg-error "3: 'static_assertion' was not declared in this scope" }
|
||||
// { dg-message "3: suggested alternative: 'static_assert'" "" { target *-*-* } .-1 }
|
||||
static_assertion (1 == 0, "1 == 0"); // { dg-error "3: 'static_assertion' was not declared in this scope; did you mean 'static_assert'\\?" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
static_assertion (1 == 0, "1 == 0");
|
||||
^~~~~~~~~~~~~~~~
|
||||
static_assert
|
||||
{ dg-end-multiline-output "" } */
|
||||
}
|
||||
|
|
79
gcc/testsuite/g++.dg/spellcheck-single-vs-multiple.C
Normal file
79
gcc/testsuite/g++.dg/spellcheck-single-vs-multiple.C
Normal file
|
@ -0,0 +1,79 @@
|
|||
/* Example of namespace suggestions, covering the special-case handling
|
||||
of where there's one suggestion, vs multiple suggestions. */
|
||||
|
||||
/* { dg-options "-fdiagnostics-show-caret" } */
|
||||
|
||||
/* Missing a namespace, where there's one candidate.
|
||||
Verify that we issue a fix-it hint. */
|
||||
|
||||
namespace ns1
|
||||
{
|
||||
void foo_1 (); // { dg-line foo_1_decl }
|
||||
}
|
||||
|
||||
void test_1 ()
|
||||
{
|
||||
foo_1 (); // { dg-error "'foo_1' was not declared in this scope; did you mean 'ns1::foo_1'\\?" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
foo_1 ();
|
||||
^~~~~
|
||||
ns1::foo_1
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "'ns1::foo_1' declared here" "" { target *-*-*} foo_1_decl }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
void foo_1 ();
|
||||
^~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
}
|
||||
|
||||
/* Missing a namespace, where there are multiple candidates.
|
||||
We don't issue a fix-it hint. */
|
||||
|
||||
namespace ns2_a
|
||||
{
|
||||
char foo_2 (); // { dg-line ns2_a_foo_2_decl }
|
||||
}
|
||||
|
||||
namespace ns2_b
|
||||
{
|
||||
int foo_2 (); // { dg-line ns2_b_foo_2_decl }
|
||||
}
|
||||
|
||||
void test_2 ()
|
||||
{
|
||||
foo_2 (); // { dg-line foo_2_usage }
|
||||
// { dg-error "'foo_2' was not declared in this scope" "" { target *-*-*} foo_2_usage }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
foo_2 ();
|
||||
^~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "suggested alternatives:" "" { target *-*-*} foo_2_usage }
|
||||
// { dg-message " 'ns2_a::foo_2'" "" { target *-*-*} ns2_a_foo_2_decl }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
char foo_2 ();
|
||||
^~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message " 'ns2_b::foo_2'" "" { target *-*-*} ns2_b_foo_2_decl }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
int foo_2 ();
|
||||
^~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
}
|
||||
|
||||
/* Misspelling within an explicit namespace.
|
||||
Verify that we issue a fix-it hint. */
|
||||
|
||||
namespace ns3
|
||||
{
|
||||
void foo_3 ();
|
||||
}
|
||||
|
||||
void test_3 ()
|
||||
{
|
||||
ns3::goo_3 (); // { dg-error "'goo_3' is not a member of 'ns3'; did you mean 'foo_3'\\?" }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
ns3::goo_3 ();
|
||||
^~~~~
|
||||
foo_3
|
||||
{ dg-end-multiline-output "" } */
|
||||
}
|
|
@ -9,12 +9,7 @@ void test_2 (singed char e); // { dg-error "21: variable or field 'test_2' decla
|
|||
void test_2 (singed char e);
|
||||
^~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "14: 'singed' was not declared in this scope" "" { target *-*-* } 7 }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
void test_2 (singed char e);
|
||||
^~~~~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "14: suggested alternative: 'signed'" "" { target *-*-* } 7 }
|
||||
// { dg-message "14: 'singed' was not declared in this scope; did you mean 'signed'\\?" "" { target *-*-* } 7 }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
void test_2 (singed char e);
|
||||
^~~~~~
|
||||
|
@ -26,8 +21,7 @@ void test_3 (car e); // { dg-error "14: variable or field 'test_3' declared void
|
|||
void test_3 (car e);
|
||||
^~~
|
||||
{ dg-end-multiline-output "" } */
|
||||
// { dg-message "14: 'car' was not declared in this scope" "" { target *-*-* } 24 }
|
||||
// { dg-message "14: suggested alternative: 'char'" "" { target *-*-* } 24 }
|
||||
// { dg-message "14: 'car' was not declared in this scope; did you mean 'char'\\?" "" { target *-*-* } 19 }
|
||||
/* { dg-begin-multiline-output "" }
|
||||
void test_3 (car e);
|
||||
^~~
|
||||
|
|
|
@ -19,6 +19,6 @@ namespace __gnu_debug_def
|
|||
namespace std
|
||||
{
|
||||
template<> void
|
||||
vector<int, allocator<int> >::swap(vector<int, allocator<int> >&) { } // { dg-error "" }
|
||||
// { dg-message "suggested alternative" "suggested alternative" { target *-*-* } .-1 }
|
||||
vector<int, allocator<int> >::swap(vector<int, allocator<int> >&) { } // { dg-error "did you mean 'std::allocator'" }
|
||||
// { dg-error "" "" { target *-*-*} .-1 }
|
||||
}
|
||||
|
|
|
@ -3,5 +3,4 @@ namespace A {
|
|||
int i = 1; // { dg-message "A::i" }
|
||||
}
|
||||
|
||||
int j = i; // { dg-error "" }
|
||||
// { dg-message "suggested alternative" "suggested alternative" { target *-*-* } .-1 }
|
||||
int j = i; // { dg-error "'i' was not declared in this scope; did you mean 'A::i'" }
|
||||
|
|
|
@ -5,6 +5,5 @@ namespace A {
|
|||
}
|
||||
|
||||
namespace B {
|
||||
int j = i; // { dg-error "" }
|
||||
// { dg-message "suggested alternative" "suggested alternative" { target *-*-* } .-1 }
|
||||
int j = i; // { dg-error "'i' was not declared in this scope; did you mean 'A::i'" }
|
||||
}
|
||||
|
|
|
@ -14,6 +14,5 @@ void g()
|
|||
foo(new X); // ok -- DR 218 says that we find the global
|
||||
// foo variable first, and therefore do not
|
||||
// perform argument-dependent lookup.
|
||||
bar(new X); // { dg-error "3:'bar' was not declared" }
|
||||
// { dg-message "suggested alternative" "suggested alternative" { target *-*-* } .-1 }
|
||||
bar(new X); // { dg-error "3:'bar' was not declared in this scope; did you mean 'A::bar'" }
|
||||
}
|
||||
|
|
|
@ -15,6 +15,5 @@ namespace tmp {
|
|||
|
||||
class A {
|
||||
public:
|
||||
int kaka(tmp::B = b); // { dg-error "" } no b in scope
|
||||
// { dg-message "suggested alternative" "suggested alternative" { target *-*-* } .-1 }
|
||||
int kaka(tmp::B = b); // { dg-error "'b' was not declared in this scope; did you mean 'tmp::b'" }
|
||||
};
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2018-10-29 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* unique-ptr.h (gnu::move): Generalize so it applies to all
|
||||
lvalue references, rather than just to unique_ptr values.
|
||||
|
||||
2018-07-26 Martin Liska <mliska@suse.cz>
|
||||
|
||||
PR lto/86548
|
||||
|
|
|
@ -336,13 +336,13 @@ operator>= (const detail::unique_ptr_base<T, D> &x,
|
|||
{ return !(x < y); }
|
||||
|
||||
/* std::move "emulation". This is as simple as it can be -- no
|
||||
attempt is made to emulate rvalue references. Instead relies on
|
||||
the fact that gnu::unique_ptr has move semantics like
|
||||
std::auto_ptr. I.e., copy/assignment actually moves. */
|
||||
attempt is made to emulate rvalue references. This relies on T
|
||||
having move semantics like std::auto_ptr.
|
||||
I.e., copy/assignment actually moves. */
|
||||
|
||||
template<typename T, typename D>
|
||||
unique_ptr<T, D>
|
||||
move (unique_ptr<T, D> v)
|
||||
template<typename T>
|
||||
const T&
|
||||
move (T& v)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2018-10-29 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* testsuite/17_intro/using_namespace_std_exp_neg.cc: Remove
|
||||
"expected namespace-name before" error.
|
||||
* testsuite/17_intro/using_namespace_std_tr1_neg.cc: Likewise.
|
||||
|
||||
2018-10-28 François Dumont <fdumont@gcc.gnu.org>
|
||||
|
||||
* testsuite/23_containers/deque/48101_neg.cc: Remove dg-prune-output
|
||||
|
|
|
@ -61,5 +61,3 @@ namespace gnu
|
|||
{
|
||||
using namespace std::experimental; // { dg-error "is not a namespace-name" }
|
||||
}
|
||||
|
||||
// { dg-error "expected namespace-name before" "" { target *-*-* } 62 }
|
||||
|
|
|
@ -64,5 +64,3 @@ namespace gnu
|
|||
{
|
||||
using namespace std::tr1; // { dg-error "is not a namespace-name" }
|
||||
}
|
||||
|
||||
// { dg-error "expected namespace-name before" "" { target *-*-* } 65 }
|
||||
|
|
Loading…
Add table
Reference in a new issue