C++ FE: handle misspelled identifiers and typenames
gcc/cp/ChangeLog: PR c/70339 PR c/71858 * name-lookup.c: Include gcc-rich-location.h, spellcheck-tree.h, and parser.h. (suggest_alternatives_for): If no candidates are found, try lookup_name_fuzzy and report if if finds a suggestion. (consider_binding_level): New function. (lookup_name_fuzzy) New function. * parser.c: Include gcc-rich-location.h. (cp_lexer_next_token_is_decl_specifier_keyword): Move most of logic into... (cp_keyword_starts_decl_specifier_p): ...this new function. (cp_parser_diagnose_invalid_type_name): When issuing "does not name a type" errors, attempt to make a suggestion using lookup_name_fuzzy. * parser.h (cp_keyword_starts_decl_specifier_p): New prototype. * search.c (lookup_field_fuzzy_info::fuzzy_lookup_field): Reject types that are not CLASS_TYPE_P, rather than rejecting individual tree codes. gcc/testsuite/ChangeLog: PR c/70339 PR c/71858 * g++.dg/spellcheck-identifiers.C: New test case, based on gcc.dg/spellcheck-identifiers.c. * g++.dg/spellcheck-identifiers-2.C: New test case, based on gcc.dg/spellcheck-identifiers-2.c. * g++.dg/spellcheck-typenames.C: New test case, based on gcc.dg/spellcheck-typenames.c From-SVN: r238538
This commit is contained in:
parent
1397e16301
commit
52ed68f71a
|
@ -1,3 +1,25 @@
|
||||||
|
2016-07-20 David Malcolm <dmalcolm@redhat.com>
|
||||||
|
|
||||||
|
PR c/70339
|
||||||
|
PR c/71858
|
||||||
|
* name-lookup.c: Include gcc-rich-location.h, spellcheck-tree.h,
|
||||||
|
and parser.h.
|
||||||
|
(suggest_alternatives_for): If no candidates are found, try
|
||||||
|
lookup_name_fuzzy and report if if finds a suggestion.
|
||||||
|
(consider_binding_level): New function.
|
||||||
|
(lookup_name_fuzzy) New function.
|
||||||
|
* parser.c: Include gcc-rich-location.h.
|
||||||
|
(cp_lexer_next_token_is_decl_specifier_keyword): Move most of
|
||||||
|
logic into...
|
||||||
|
(cp_keyword_starts_decl_specifier_p): ...this new function.
|
||||||
|
(cp_parser_diagnose_invalid_type_name): When issuing
|
||||||
|
"does not name a type" errors, attempt to make a suggestion using
|
||||||
|
lookup_name_fuzzy.
|
||||||
|
* parser.h (cp_keyword_starts_decl_specifier_p): New prototype.
|
||||||
|
* search.c (lookup_field_fuzzy_info::fuzzy_lookup_field): Reject
|
||||||
|
types that are not CLASS_TYPE_P, rather than rejecting individual
|
||||||
|
tree codes.
|
||||||
|
|
||||||
2016-07-20 Jakub Jelinek <jakub@redhat.com>
|
2016-07-20 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
PR c++/71909
|
PR c++/71909
|
||||||
|
|
|
@ -29,6 +29,9 @@ along with GCC; see the file COPYING3. If not see
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "c-family/c-pragma.h"
|
#include "c-family/c-pragma.h"
|
||||||
#include "params.h"
|
#include "params.h"
|
||||||
|
#include "gcc-rich-location.h"
|
||||||
|
#include "spellcheck-tree.h"
|
||||||
|
#include "parser.h"
|
||||||
|
|
||||||
/* The bindings for a particular name in a particular scope. */
|
/* The bindings for a particular name in a particular scope. */
|
||||||
|
|
||||||
|
@ -4435,9 +4438,20 @@ suggest_alternatives_for (location_t location, tree name)
|
||||||
|
|
||||||
namespaces_to_search.release ();
|
namespaces_to_search.release ();
|
||||||
|
|
||||||
/* Nothing useful to report. */
|
/* Nothing useful to report for NAME. Report on likely misspellings,
|
||||||
|
or do nothing. */
|
||||||
if (candidates.is_empty ())
|
if (candidates.is_empty ())
|
||||||
|
{
|
||||||
|
const char *fuzzy_name = lookup_name_fuzzy (name, FUZZY_LOOKUP_NAME);
|
||||||
|
if (fuzzy_name)
|
||||||
|
{
|
||||||
|
gcc_rich_location richloc (location);
|
||||||
|
richloc.add_fixit_misspelled_id (location, fuzzy_name);
|
||||||
|
inform_at_rich_loc (&richloc, "suggested alternative: %qs",
|
||||||
|
fuzzy_name);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
inform_n (location, candidates.length (),
|
inform_n (location, candidates.length (),
|
||||||
"suggested alternative:",
|
"suggested alternative:",
|
||||||
|
@ -4672,6 +4686,104 @@ qualified_lookup_using_namespace (tree name, tree scope,
|
||||||
return result->value != error_mark_node;
|
return result->value != error_mark_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Helper function for lookup_name_fuzzy.
|
||||||
|
Traverse binding level LVL, looking for good name matches for NAME
|
||||||
|
(and BM). */
|
||||||
|
static void
|
||||||
|
consider_binding_level (tree name, best_match <tree, tree> &bm,
|
||||||
|
cp_binding_level *lvl, bool look_within_fields,
|
||||||
|
enum lookup_name_fuzzy_kind kind)
|
||||||
|
{
|
||||||
|
if (look_within_fields)
|
||||||
|
if (lvl->this_entity && TREE_CODE (lvl->this_entity) == RECORD_TYPE)
|
||||||
|
{
|
||||||
|
tree type = lvl->this_entity;
|
||||||
|
bool want_type_p = (kind == FUZZY_LOOKUP_TYPENAME);
|
||||||
|
tree best_matching_field
|
||||||
|
= lookup_member_fuzzy (type, name, want_type_p);
|
||||||
|
if (best_matching_field)
|
||||||
|
bm.consider (best_matching_field);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (tree t = lvl->names; t; t = TREE_CHAIN (t))
|
||||||
|
{
|
||||||
|
/* Don't use bindings from implicitly declared functions,
|
||||||
|
as they were likely misspellings themselves. */
|
||||||
|
if (TREE_TYPE (t) == error_mark_node)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Skip anticipated decls of builtin functions. */
|
||||||
|
if (TREE_CODE (t) == FUNCTION_DECL
|
||||||
|
&& DECL_BUILT_IN (t)
|
||||||
|
&& DECL_ANTICIPATED (t))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (DECL_NAME (t))
|
||||||
|
bm.consider (DECL_NAME (t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Search for near-matches for NAME within the current bindings, and within
|
||||||
|
macro names, returning the best match as a const char *, or NULL if
|
||||||
|
no reasonable match is found. */
|
||||||
|
|
||||||
|
const char *
|
||||||
|
lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind)
|
||||||
|
{
|
||||||
|
gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
|
||||||
|
|
||||||
|
best_match <tree, tree> bm (name);
|
||||||
|
|
||||||
|
cp_binding_level *lvl;
|
||||||
|
for (lvl = scope_chain->class_bindings; lvl; lvl = lvl->level_chain)
|
||||||
|
consider_binding_level (name, bm, lvl, true, kind);
|
||||||
|
|
||||||
|
for (lvl = current_binding_level; lvl; lvl = lvl->level_chain)
|
||||||
|
consider_binding_level (name, bm, lvl, false, kind);
|
||||||
|
|
||||||
|
/* Consider macros: if the user misspelled a macro name e.g. "SOME_MACRO"
|
||||||
|
as:
|
||||||
|
x = SOME_OTHER_MACRO (y);
|
||||||
|
then "SOME_OTHER_MACRO" will survive to the frontend and show up
|
||||||
|
as a misspelled identifier.
|
||||||
|
|
||||||
|
Use the best distance so far so that a candidate is only set if
|
||||||
|
a macro is better than anything so far. This allows early rejection
|
||||||
|
(without calculating the edit distance) of macro names that must have
|
||||||
|
distance >= bm.get_best_distance (), and means that we only get a
|
||||||
|
non-NULL result for best_macro_match if it's better than any of
|
||||||
|
the identifiers already checked. */
|
||||||
|
best_macro_match bmm (name, bm.get_best_distance (), parse_in);
|
||||||
|
cpp_hashnode *best_macro = bmm.get_best_meaningful_candidate ();
|
||||||
|
/* If a macro is the closest so far to NAME, suggest it. */
|
||||||
|
if (best_macro)
|
||||||
|
return (const char *)best_macro->ident.str;
|
||||||
|
|
||||||
|
/* Try the "starts_decl_specifier_p" keywords to detect
|
||||||
|
"singed" vs "signed" typos. */
|
||||||
|
for (unsigned i = 0; i < num_c_common_reswords; i++)
|
||||||
|
{
|
||||||
|
const c_common_resword *resword = &c_common_reswords[i];
|
||||||
|
|
||||||
|
if (!cp_keyword_starts_decl_specifier_p (resword->rid))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
tree resword_identifier = ridpointers [resword->rid];
|
||||||
|
if (!resword_identifier)
|
||||||
|
continue;
|
||||||
|
gcc_assert (TREE_CODE (resword_identifier) == IDENTIFIER_NODE);
|
||||||
|
bm.consider (resword_identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See if we have a good suggesion for the user. */
|
||||||
|
tree best_id = bm.get_best_meaningful_candidate ();
|
||||||
|
if (best_id)
|
||||||
|
return IDENTIFIER_POINTER (best_id);
|
||||||
|
|
||||||
|
/* No meaningful suggestion available. */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Subroutine of outer_binding.
|
/* Subroutine of outer_binding.
|
||||||
|
|
||||||
Returns TRUE if BINDING is a binding to a template parameter of
|
Returns TRUE if BINDING is a binding to a template parameter of
|
||||||
|
|
|
@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see
|
||||||
#include "c-family/c-indentation.h"
|
#include "c-family/c-indentation.h"
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
#include "cp-cilkplus.h"
|
#include "cp-cilkplus.h"
|
||||||
|
#include "gcc-rich-location.h"
|
||||||
|
|
||||||
|
|
||||||
/* The lexer. */
|
/* The lexer. */
|
||||||
|
@ -937,15 +938,12 @@ cp_lexer_next_token_is_not_keyword (cp_lexer* lexer, enum rid keyword)
|
||||||
return cp_lexer_peek_token (lexer)->keyword != keyword;
|
return cp_lexer_peek_token (lexer)->keyword != keyword;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return true if the next token is a keyword for a decl-specifier. */
|
/* Return true if KEYWORD can start a decl-specifier. */
|
||||||
|
|
||||||
static bool
|
bool
|
||||||
cp_lexer_next_token_is_decl_specifier_keyword (cp_lexer *lexer)
|
cp_keyword_starts_decl_specifier_p (enum rid keyword)
|
||||||
{
|
{
|
||||||
cp_token *token;
|
switch (keyword)
|
||||||
|
|
||||||
token = cp_lexer_peek_token (lexer);
|
|
||||||
switch (token->keyword)
|
|
||||||
{
|
{
|
||||||
/* auto specifier: storage-class-specifier in C++,
|
/* auto specifier: storage-class-specifier in C++,
|
||||||
simple-type-specifier in C++0x. */
|
simple-type-specifier in C++0x. */
|
||||||
|
@ -985,14 +983,25 @@ cp_lexer_next_token_is_decl_specifier_keyword (cp_lexer *lexer)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (token->keyword >= RID_FIRST_INT_N
|
if (keyword >= RID_FIRST_INT_N
|
||||||
&& token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
|
&& keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
|
||||||
&& int_n_enabled_p[token->keyword - RID_FIRST_INT_N])
|
&& int_n_enabled_p[keyword - RID_FIRST_INT_N])
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return true if the next token is a keyword for a decl-specifier. */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
cp_lexer_next_token_is_decl_specifier_keyword (cp_lexer *lexer)
|
||||||
|
{
|
||||||
|
cp_token *token;
|
||||||
|
|
||||||
|
token = cp_lexer_peek_token (lexer);
|
||||||
|
return cp_keyword_starts_decl_specifier_p (token->keyword);
|
||||||
|
}
|
||||||
|
|
||||||
/* Returns TRUE iff the token T begins a decltype type. */
|
/* Returns TRUE iff the token T begins a decltype type. */
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -3154,6 +3163,18 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
|
||||||
else if (!parser->scope)
|
else if (!parser->scope)
|
||||||
{
|
{
|
||||||
/* Issue an error message. */
|
/* Issue an error message. */
|
||||||
|
const char *suggestion = NULL;
|
||||||
|
if (TREE_CODE (id) == IDENTIFIER_NODE)
|
||||||
|
suggestion = lookup_name_fuzzy (id, FUZZY_LOOKUP_TYPENAME);
|
||||||
|
if (suggestion)
|
||||||
|
{
|
||||||
|
gcc_rich_location richloc (location);
|
||||||
|
richloc.add_fixit_misspelled_id (location, suggestion);
|
||||||
|
error_at_rich_loc (&richloc,
|
||||||
|
"%qE does not name a type; did you mean %qs?",
|
||||||
|
id, suggestion);
|
||||||
|
}
|
||||||
|
else
|
||||||
error_at (location, "%qE does not name a type", id);
|
error_at (location, "%qE does not name a type", id);
|
||||||
/* If we're in a template class, it's possible that the user was
|
/* If we're in a template class, it's possible that the user was
|
||||||
referring to a type from a base class. For example:
|
referring to a type from a base class. For example:
|
||||||
|
|
|
@ -420,5 +420,6 @@ extern void debug (vec<cp_token, va_gc> *ptr);
|
||||||
extern void cp_debug_parser (FILE *, cp_parser *);
|
extern void cp_debug_parser (FILE *, cp_parser *);
|
||||||
extern void debug (cp_parser &ref);
|
extern void debug (cp_parser &ref);
|
||||||
extern void debug (cp_parser *ptr);
|
extern void debug (cp_parser *ptr);
|
||||||
|
extern bool cp_keyword_starts_decl_specifier_p (enum rid keyword);
|
||||||
|
|
||||||
#endif /* GCC_CP_PARSER_H */
|
#endif /* GCC_CP_PARSER_H */
|
||||||
|
|
|
@ -1398,13 +1398,7 @@ lookup_field_fuzzy_info::fuzzy_lookup_fnfields (tree type)
|
||||||
void
|
void
|
||||||
lookup_field_fuzzy_info::fuzzy_lookup_field (tree type)
|
lookup_field_fuzzy_info::fuzzy_lookup_field (tree type)
|
||||||
{
|
{
|
||||||
if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
|
if (!CLASS_TYPE_P (type))
|
||||||
|| TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM
|
|
||||||
|| TREE_CODE (type) == TYPENAME_TYPE)
|
|
||||||
/* The TYPE_FIELDS of a TEMPLATE_TYPE_PARM and
|
|
||||||
BOUND_TEMPLATE_TEMPLATE_PARM are not fields at all;
|
|
||||||
instead TYPE_FIELDS is the TEMPLATE_PARM_INDEX.
|
|
||||||
The TYPE_FIELDS of TYPENAME_TYPE is its TYPENAME_TYPE_FULLNAME. */
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
|
for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
|
||||||
|
|
|
@ -1,3 +1,14 @@
|
||||||
|
2016-07-20 David Malcolm <dmalcolm@redhat.com>
|
||||||
|
|
||||||
|
PR c/70339
|
||||||
|
PR c/71858
|
||||||
|
* g++.dg/spellcheck-identifiers.C: New test case, based on
|
||||||
|
gcc.dg/spellcheck-identifiers.c.
|
||||||
|
* g++.dg/spellcheck-identifiers-2.C: New test case, based on
|
||||||
|
gcc.dg/spellcheck-identifiers-2.c.
|
||||||
|
* g++.dg/spellcheck-typenames.C: New test case, based on
|
||||||
|
gcc.dg/spellcheck-typenames.c
|
||||||
|
|
||||||
2016-07-20 Jonathan Wakely <jwakely@redhat.com>
|
2016-07-20 Jonathan Wakely <jwakely@redhat.com>
|
||||||
|
|
||||||
* g++.dg/cpp0x/nullptr35.C: Change expected result for catching as
|
* g++.dg/cpp0x/nullptr35.C: Change expected result for catching as
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/* PR c/71858 */
|
||||||
|
/* Make sure anticipated builtins are not considered before they are declared. */
|
||||||
|
/* { dg-do compile } */
|
||||||
|
/* { dg-options "-fdiagnostics-show-caret" } */
|
||||||
|
|
||||||
|
int sscafn (const char *, const char *, ...);
|
||||||
|
|
||||||
|
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 }
|
||||||
|
/* { dg-begin-multiline-output "" }
|
||||||
|
return ssacnf (p, "%d", &i);
|
||||||
|
^~~~~~
|
||||||
|
sscafn
|
||||||
|
{ dg-end-multiline-output "" } */
|
||||||
|
}
|
||||||
|
|
||||||
|
int scafn (const char *, ...);
|
||||||
|
int scanf (const char *, ...);
|
||||||
|
|
||||||
|
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 }
|
||||||
|
/* { dg-begin-multiline-output "" }
|
||||||
|
return sacnf ("%d", &i);
|
||||||
|
^~~~~
|
||||||
|
scanf
|
||||||
|
{ dg-end-multiline-output "" } */
|
||||||
|
}
|
|
@ -0,0 +1,255 @@
|
||||||
|
/* { dg-do compile } */
|
||||||
|
/* { dg-options "-fdiagnostics-show-caret" } */
|
||||||
|
|
||||||
|
typedef struct GtkWidget { int dummy; } GtkWidget;
|
||||||
|
|
||||||
|
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 }
|
||||||
|
/* { dg-begin-multiline-output "" }
|
||||||
|
gtk_widget_showall (w);
|
||||||
|
^~~~~~~~~~~~~~~~~~
|
||||||
|
gtk_widget_show_all
|
||||||
|
{ dg-end-multiline-output "" } */
|
||||||
|
|
||||||
|
/* 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 }
|
||||||
|
/* { 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 }
|
||||||
|
/* { dg-begin-multiline-output "" }
|
||||||
|
GtkWidgetShowAll (w);
|
||||||
|
^~~~~~~~~~~~~~~~
|
||||||
|
gtk_widget_show_all
|
||||||
|
{ dg-end-multiline-output "" } */
|
||||||
|
}
|
||||||
|
|
||||||
|
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 }
|
||||||
|
/* { dg-begin-multiline-output "" }
|
||||||
|
return parma * parma;
|
||||||
|
^~~~~
|
||||||
|
param
|
||||||
|
{ dg-end-multiline-output "" } */
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MACRO(X) ((X))
|
||||||
|
|
||||||
|
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 }
|
||||||
|
/* { dg-begin-multiline-output "" }
|
||||||
|
return MACRAME (i);
|
||||||
|
^~~~~~~
|
||||||
|
MACRO
|
||||||
|
{ dg-end-multiline-output "" } */
|
||||||
|
}
|
||||||
|
|
||||||
|
#define IDENTIFIER_POINTER(X) ((X))
|
||||||
|
|
||||||
|
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 }
|
||||||
|
/* { dg-begin-multiline-output "" }
|
||||||
|
return IDENTIFIER_PTR (node);
|
||||||
|
^~~~~~~~~~~~~~
|
||||||
|
IDENTIFIER_POINTER
|
||||||
|
{ dg-end-multiline-output "" } */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 }
|
||||||
|
/* { dg-begin-multiline-output "" }
|
||||||
|
return __LINE_;
|
||||||
|
^~~~~~~
|
||||||
|
__LINE__
|
||||||
|
{ dg-end-multiline-output "" } */
|
||||||
|
}
|
||||||
|
|
||||||
|
#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 }
|
||||||
|
/* { dg-begin-multiline-output "" }
|
||||||
|
int array[MAX_ITEM];
|
||||||
|
^~~~~~~~
|
||||||
|
MAX_ITEMS
|
||||||
|
{ dg-end-multiline-output "" } */
|
||||||
|
|
||||||
|
|
||||||
|
enum foo {
|
||||||
|
FOO_FIRST,
|
||||||
|
FOO_SECOND
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
test_6 (enum foo f)
|
||||||
|
{
|
||||||
|
switch (f)
|
||||||
|
{
|
||||||
|
case FOO_FURST: // { dg-error "10: 'FOO_FURST' was not declared in this scope" }
|
||||||
|
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" }
|
||||||
|
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:
|
||||||
|
^~~~~~~~~~~
|
||||||
|
FOO_SECOND
|
||||||
|
{ dg-end-multiline-output "" } */
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int snprintf (char *, __SIZE_TYPE__, const char *, ...);
|
||||||
|
|
||||||
|
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 }
|
||||||
|
/* { dg-begin-multiline-output "" }
|
||||||
|
snprint (buffer, 100, "%i of %i", i, j);
|
||||||
|
^~~~~~~
|
||||||
|
snprintf
|
||||||
|
{ dg-end-multiline-output "" } */
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
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 }
|
||||||
|
/* { dg-begin-multiline-output "" }
|
||||||
|
return locale;
|
||||||
|
^~~~~~
|
||||||
|
local
|
||||||
|
{ dg-end-multiline-output "" } */
|
||||||
|
}
|
||||||
|
|
||||||
|
class base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int test_method_1 ();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int m_foo;
|
||||||
|
};
|
||||||
|
|
||||||
|
class sub : public base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int test_method_2 ();
|
||||||
|
};
|
||||||
|
|
||||||
|
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 }
|
||||||
|
/* { dg-begin-multiline-output "" }
|
||||||
|
return m_food;
|
||||||
|
^~~~~~
|
||||||
|
m_foo
|
||||||
|
{ dg-end-multiline-output "" } */
|
||||||
|
}
|
||||||
|
|
||||||
|
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 }
|
||||||
|
/* { dg-begin-multiline-output "" }
|
||||||
|
return m_food;
|
||||||
|
^~~~~~
|
||||||
|
m_foo
|
||||||
|
{ dg-end-multiline-output "" } */
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
/* { dg-do compile } */
|
||||||
|
/* { dg-options "-fdiagnostics-show-caret" } */
|
||||||
|
|
||||||
|
void test_1 (signed char e);
|
||||||
|
|
||||||
|
/* PR c/70339. */
|
||||||
|
void test_2 (singed char e); // { dg-error "21: variable or field 'test_2' declared void" }
|
||||||
|
/* { dg-begin-multiline-output "" }
|
||||||
|
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-begin-multiline-output "" }
|
||||||
|
void test_2 (singed char e);
|
||||||
|
^~~~~~
|
||||||
|
signed
|
||||||
|
{ dg-end-multiline-output "" } */
|
||||||
|
|
||||||
|
void test_3 (car e); // { dg-error "14: variable or field 'test_3' declared void" }
|
||||||
|
/* { dg-begin-multiline-output "" }
|
||||||
|
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-begin-multiline-output "" }
|
||||||
|
void test_3 (car e);
|
||||||
|
^~~
|
||||||
|
char
|
||||||
|
{ dg-end-multiline-output "" } */
|
||||||
|
|
||||||
|
/* TODO: this one could be handled better. */
|
||||||
|
void test_4 (signed car e); // { dg-error "25: expected ',' or '...' before 'e'" }
|
||||||
|
/* { dg-begin-multiline-output "" }
|
||||||
|
void test_4 (signed car e);
|
||||||
|
^
|
||||||
|
{ dg-end-multiline-output "" } */
|
||||||
|
|
||||||
|
/* Verify that we handle misspelled typedef names. */
|
||||||
|
|
||||||
|
typedef struct something {} something_t;
|
||||||
|
|
||||||
|
some_thing_t test_5; // { dg-error "1: 'some_thing_t' does not name a type; did you mean 'something_t'?" }
|
||||||
|
/* { dg-begin-multiline-output "" }
|
||||||
|
some_thing_t test_5;
|
||||||
|
^~~~~~~~~~~~
|
||||||
|
something_t
|
||||||
|
{ dg-end-multiline-output "" } */
|
||||||
|
|
||||||
|
/* TODO: we don't yet handle misspelled struct names. */
|
||||||
|
struct some_thing test_6; // { dg-error "aggregate 'some_thing test_6' has incomplete type and cannot be defined" }
|
||||||
|
/* { dg-begin-multiline-output "" }
|
||||||
|
struct some_thing test_6;
|
||||||
|
^~~~~~
|
||||||
|
{ dg-end-multiline-output "" } */
|
||||||
|
|
||||||
|
typedef long int64_t;
|
||||||
|
int64 i; // { dg-error "1: 'int64' does not name a type; did you mean 'int64_t'?" }
|
||||||
|
/* { dg-begin-multiline-output "" }
|
||||||
|
int64 i;
|
||||||
|
^~~~~
|
||||||
|
int64_t
|
||||||
|
{ dg-end-multiline-output "" } */
|
||||||
|
|
||||||
|
/* Verify that gcc doesn't offer nonsensical suggestions. */
|
||||||
|
|
||||||
|
nonsensical_suggestion_t var; /* { dg-bogus "did you mean" } */
|
||||||
|
/* { dg-error "'nonsensical_suggestion_t' does not name a type" "" { target { *-*-* } } 72 } */
|
||||||
|
/* { dg-begin-multiline-output "" }
|
||||||
|
nonsensical_suggestion_t var;
|
||||||
|
^~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
{ dg-end-multiline-output "" } */
|
||||||
|
|
||||||
|
singed char ch; // { dg-error "1: 'singed' does not name a type; did you mean 'signed'?" }
|
||||||
|
/* { dg-begin-multiline-output "" }
|
||||||
|
singed char ch;
|
||||||
|
^~~~~~
|
||||||
|
signed
|
||||||
|
{ dg-end-multiline-output "" } */
|
Loading…
Reference in New Issue