Skip to content

Commit

Permalink
C++: provide macro used-before-defined hint (PR c++/72786)
Browse files Browse the repository at this point in the history
This patch uses the name_hint/deferred_diagnostic to provide
a message in the C++ frontend if a macro is used before it is defined
e.g.:

test.c:6:24: error: expected ';' at end of member declaration
   virtual void clone() const OVERRIDE { }
                        ^~~~~
                             ;
test.c:6:30: error: 'OVERRIDE' does not name a type
   virtual void clone() const OVERRIDE { }
                              ^~~~~~~~
test.c:6:30: note: the macro 'OVERRIDE' had not yet been defined
test.c:15:0: note: it was later defined here
 #define OVERRIDE override

It's possible to do it from the C++ frontend as tokenization happens
up-front (and hence the macro already exists when the above is parsed);
I attempted to do it from the C frontend, but because the C frontend only
tokenizes on-demand during parsing, the macro isn't known about until
later.

gcc/cp/ChangeLog:
	PR c++/72786
	* name-lookup.c (class macro_use_before_def): New class.
	(lookup_name_fuzzy): Detect macro that were used before being
	defined, and report them as such.

gcc/ChangeLog:
	PR c++/72786
	* spellcheck.h (best_match::blithely_get_best_candidate): New
	accessor.

gcc/testsuite/ChangeLog:
	PR c++/72786
	* g++.dg/spellcheck-macro-ordering-2.C: New test case.
	* g++.dg/spellcheck-macro-ordering.C: Add dg-message directives
	for macro used-before-defined.

libcpp/ChangeLog:
	PR c++/72786
	* include/cpplib.h (cpp_macro_definition_location): New decl.
	* macro.c (cpp_macro_definition): New function.



git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@254978 138bc75d-0d04-0410-961f-82ee72b054a4
  • Loading branch information
dmalcolm committed Nov 21, 2017
1 parent 69eab56 commit dbfb2c4
Show file tree
Hide file tree
Showing 10 changed files with 109 additions and 3 deletions.
6 changes: 6 additions & 0 deletions gcc/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
2017-11-20 David Malcolm <[email protected]>

PR c++/72786
* spellcheck.h (best_match::blithely_get_best_candidate): New
accessor.

2017-11-20 Jakub Jelinek <[email protected]>

* config/i386/i386.c (parse_mtune_ctrl_str): Start diagnostics
Expand Down
7 changes: 7 additions & 0 deletions gcc/cp/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
2017-11-20 David Malcolm <[email protected]>

PR c++/72786
* name-lookup.c (class macro_use_before_def): New class.
(lookup_name_fuzzy): Detect macro that were used before being
defined, and report them as such.

2017-11-20 Jason Merrill <[email protected]>

* decl2.c (constrain_class_visibility): Don't warn about artificial
Expand Down
50 changes: 48 additions & 2 deletions gcc/cp/name-lookup.c
Original file line number Diff line number Diff line change
Expand Up @@ -5636,12 +5636,49 @@ consider_binding_level (tree name, best_match <tree, const char *> &bm,
}
}

/* Subclass of deferred_diagnostic. Notify the user that the
given macro was used before it was defined.
This can be done in the C++ frontend since tokenization happens
upfront. */

class macro_use_before_def : public deferred_diagnostic
{
public:
/* Ctor. LOC is the location of the usage. MACRO is the
macro that was used. */
macro_use_before_def (location_t loc, cpp_hashnode *macro)
: deferred_diagnostic (loc), m_macro (macro)
{
gcc_assert (macro);
}

~macro_use_before_def ()
{
if (is_suppressed_p ())
return;

source_location def_loc = cpp_macro_definition_location (m_macro);
if (def_loc != UNKNOWN_LOCATION)
{
inform (get_location (), "the macro %qs had not yet been defined",
(const char *)m_macro->ident.str);
inform (def_loc, "it was later defined here");
}
}

private:
cpp_hashnode *m_macro;
};


/* 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. */
no reasonable match is found.
Use LOC for any deferred diagnostics. */

name_hint
lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind, location_t)
lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind, location_t loc)
{
gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);

Expand Down Expand Up @@ -5671,6 +5708,15 @@ lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind, location_t)
/* If a macro is the closest so far to NAME, consider it. */
if (best_macro)
bm.consider ((const char *)best_macro->ident.str);
else if (bmm.get_best_distance () == 0)
{
/* If we have an exact match for a macro name, then the
macro has been used before it was defined. */
cpp_hashnode *macro = bmm.blithely_get_best_candidate ();
if (macro)
return name_hint (NULL,
new macro_use_before_def (loc, macro));
}

/* Try the "starts_decl_specifier_p" keywords to detect
"singed" vs "signed" typos. */
Expand Down
7 changes: 7 additions & 0 deletions gcc/spellcheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,13 @@ class best_match
return m_best_candidate;
}

/* Get the closest candidate so far, without applying any filtering. */

candidate_t blithely_get_best_candidate () const
{
return m_best_candidate;
}

edit_distance_t get_best_distance () const { return m_best_distance; }
size_t get_best_candidate_length () const { return m_best_candidate_len; }

Expand Down
7 changes: 7 additions & 0 deletions gcc/testsuite/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
2017-11-20 David Malcolm <[email protected]>

PR c++/72786
* g++.dg/spellcheck-macro-ordering-2.C: New test case.
* g++.dg/spellcheck-macro-ordering.C: Add dg-message directives
for macro used-before-defined.

2017-11-20 Steve Ellcey <[email protected]>

PR target/81356
Expand Down
17 changes: 17 additions & 0 deletions gcc/testsuite/g++.dg/spellcheck-macro-ordering-2.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// PR c++/72786

/* Example of undeffed macro. */

#define OVERRIDE override

#undef OVERRIDE

class DocTargetDriver {
virtual void clone() const OVERRIDE { } // { dg-line usage }
/* Offering "OVERRIDE" as a spelling suggestion for "OVERRIDE" would be
nonsensical. */
// { dg-bogus "did you mean" "" { target *-*-* } usage }
// { dg-error "expected .;. at end of member declaration" "" { target *-*-* } usage }
// { dg-error ".OVERRIDE. does not name a type" "" { target *-*-* } usage }
// { dg-bogus "macro" "" { target *-*-* } usage }
};
3 changes: 2 additions & 1 deletion gcc/testsuite/g++.dg/spellcheck-macro-ordering.C
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ class DocTargetDriver {
// { dg-bogus "did you mean" "" { target *-*-* } .-3 }
// { dg-error "expected .;. at end of member declaration" "" { target *-*-* } .-4 }
// { dg-error ".OVERRIDE. does not name a type" "" { target *-*-* } .-5 }
// { dg-message "the macro 'OVERRIDE' had not yet been defined" "" { target *-*-* } .-6 }
};

#define OVERRIDE override

// { dg-message "-:it was later defined here" "" { target *-*-* } .-1 }
6 changes: 6 additions & 0 deletions libcpp/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
2017-11-20 David Malcolm <[email protected]>

PR c++/72786
* include/cpplib.h (cpp_macro_definition_location): New decl.
* macro.c (cpp_macro_definition): New function.

2017-11-13 Tom Tromey <[email protected]>

* pch.c (cpp_read_state): Set n__VA_OPT__.
Expand Down
1 change: 1 addition & 0 deletions libcpp/include/cpplib.h
Original file line number Diff line number Diff line change
Expand Up @@ -889,6 +889,7 @@ extern const cpp_token *cpp_get_token_with_location (cpp_reader *,
extern bool cpp_fun_like_macro_p (cpp_hashnode *);
extern const unsigned char *cpp_macro_definition (cpp_reader *,
cpp_hashnode *);
extern source_location cpp_macro_definition_location (cpp_hashnode *);
extern void _cpp_backup_tokens (cpp_reader *, unsigned int);
extern const cpp_token *cpp_peek_token (cpp_reader *, int);

Expand Down
8 changes: 8 additions & 0 deletions libcpp/macro.c
Original file line number Diff line number Diff line change
Expand Up @@ -3646,3 +3646,11 @@ cpp_macro_definition (cpp_reader *pfile, cpp_hashnode *node)
*buffer = '\0';
return pfile->macro_buffer;
}

/* Get the line at which the macro was defined. */

source_location
cpp_macro_definition_location (cpp_hashnode *node)
{
return node->value.macro->line;
}

0 comments on commit dbfb2c4

Please sign in to comment.