aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2017-11-21 00:40:53 +0000
committerDavid Malcolm <dmalcolm@gcc.gnu.org>2017-11-21 00:40:53 +0000
commit01ada12136c64ad9ff305f456637d43b9f6d4356 (patch)
tree2fd6c86557307e928d7444794521945cbde6d559 /gcc/cp
parent874b8068f6c4cab53b14b7d2db117abd71f7da95 (diff)
downloadgcc-01ada12136c64ad9ff305f456637d43b9f6d4356.zip
gcc-01ada12136c64ad9ff305f456637d43b9f6d4356.tar.gz
gcc-01ada12136c64ad9ff305f456637d43b9f6d4356.tar.bz2
C++: provide macro used-before-defined hint (PR c++/72786)
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. From-SVN: r254978
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/name-lookup.c50
2 files changed, 55 insertions, 2 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 5de732f..908b48e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2017-11-20 David Malcolm <dmalcolm@redhat.com>
+
+ 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 <jason@redhat.com>
* decl2.c (constrain_class_visibility): Don't warn about artificial
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 9d97da3..fc317b1 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -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);
@@ -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. */