Some builtin macros are only defined when certain command-line options
are provided.  Update the error messages for them so that we suggest
the pertinent option ('-fopenacc' for '_OPENACC', and '-fopenmp' for
'_OPENMP')

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to trunk as r15-5739-g5341eb669658c7.

gcc/c-family/ChangeLog:
        PR c/82892
        * c-common.h (get_option_for_builtin_define): New decl.
        * c-cppbuiltin.cc (get_option_for_builtin_define): New.
        * known-headers.cc: Include "opts.h".
        (suggest_missing_option::suggest_missing_option): New.
        (suggest_missing_option::~suggest_missing_option): New.
        * known-headers.h (class suggest_missing_option): New.

gcc/c/ChangeLog:
        PR c/82892
        * c-decl.cc (lookup_name_fuzzy): Provide hints for missing
        command-line options.

gcc/cp/ChangeLog:
        PR c/82892
        * name-lookup.cc (suggest_alternatives_for_1): Provide hints for
        missing command-line options.

gcc/testsuite/ChangeLog:
        PR c/82892
        * c-c++-common/spellcheck-missing-option.c: New test.

Signed-off-by: David Malcolm <dmalc...@redhat.com>
---
 gcc/c-family/c-common.h                       |  1 +
 gcc/c-family/c-cppbuiltin.cc                  | 13 +++++++++
 gcc/c-family/known-headers.cc                 | 28 +++++++++++++++++++
 gcc/c-family/known-headers.h                  | 15 ++++++++++
 gcc/c/c-decl.cc                               | 11 ++++++++
 gcc/cp/name-lookup.cc                         | 11 ++++++++
 .../c-c++-common/spellcheck-missing-option.c  | 15 ++++++++++
 7 files changed, 94 insertions(+)
 create mode 100644 gcc/testsuite/c-c++-common/spellcheck-missing-option.c

diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index a323982ae26b..7834e0d19590 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1260,6 +1260,7 @@ extern void c_stddef_cpp_builtins (void);
 extern void fe_file_change (const line_map_ordinary *);
 extern void c_parse_error (const char *, enum cpp_ttype, tree, unsigned char,
                           rich_location *richloc);
+extern diagnostic_option_id get_option_for_builtin_define (const char 
*macro_name);
 
 /* In c-ppoutput.cc  */
 extern void init_pp_output (FILE *);
diff --git a/gcc/c-family/c-cppbuiltin.cc b/gcc/c-family/c-cppbuiltin.cc
index 8fbfef561e8a..c354c794b55e 100644
--- a/gcc/c-family/c-cppbuiltin.cc
+++ b/gcc/c-family/c-cppbuiltin.cc
@@ -1673,6 +1673,19 @@ c_cpp_builtins (cpp_reader *pfile)
     cpp_define (pfile, "__DECIMAL_BID_FORMAT__");
 }
 
+/* Given NAME, return the command-line option that would make it be
+   a builtin define, or 0 if unrecognized.  */
+
+diagnostic_option_id
+get_option_for_builtin_define (const char *name)
+{
+  if (!strcmp (name, "_OPENACC"))
+    return OPT_fopenacc;
+  if (!strcmp (name, "_OPENMP"))
+    return OPT_fopenmp;
+  return 0;
+}
+
 /* Pass an object-like macro.  If it doesn't lie in the user's
    namespace, defines it unconditionally.  Otherwise define a version
    with two leading underscores, and another version with two leading
diff --git a/gcc/c-family/known-headers.cc b/gcc/c-family/known-headers.cc
index 58a7259e8c49..2077cab6c098 100644
--- a/gcc/c-family/known-headers.cc
+++ b/gcc/c-family/known-headers.cc
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "c-family/name-hint.h"
 #include "c-family/known-headers.h"
 #include "gcc-rich-location.h"
+#include "opts.h"
 
 /* An enum for distinguishing between the C and C++ stdlibs.  */
 
@@ -323,3 +324,30 @@ suggest_missing_header::~suggest_missing_header ()
          " this is probably fixable by adding %<#include %s%>",
          m_name_str, m_header_hint, m_header_hint);
 }
+
+/* Implementation of class suggest_missing_option.  */
+
+/* suggest_missing_option's ctor.  */
+
+suggest_missing_option::suggest_missing_option (location_t loc,
+                                               const char *macro_name,
+                                               diagnostic_option_id option_id)
+: deferred_diagnostic (loc), m_name_str (macro_name), m_option_id (option_id)
+{
+  gcc_assert (macro_name);
+  gcc_assert (option_id.m_idx > 0);
+}
+
+/* suggest_missing_option's dtor.  */
+
+suggest_missing_option::~suggest_missing_option ()
+{
+  if (is_suppressed_p ())
+    return;
+
+  const char *option_name = cl_options[m_option_id.m_idx].opt_text;
+  inform (get_location (),
+         "%qs is defined when using option %qs;"
+         " this is probably fixable by adding %qs to the command-line options",
+         m_name_str, option_name, option_name);
+}
diff --git a/gcc/c-family/known-headers.h b/gcc/c-family/known-headers.h
index 7c7ee781e739..a6cbbd2d86b2 100644
--- a/gcc/c-family/known-headers.h
+++ b/gcc/c-family/known-headers.h
@@ -41,4 +41,19 @@ class suggest_missing_header : public deferred_diagnostic
   const char *m_header_hint;
 };
 
+/* Subclass of deferred_diagnostic for suggesting to the user
+   that they have missed a command-line option.  */
+
+class suggest_missing_option : public deferred_diagnostic
+{
+ public:
+  suggest_missing_option (location_t loc, const char *name,
+                         diagnostic_option_id option_id);
+  ~suggest_missing_option ();
+
+ private:
+  const char *m_name_str;
+  diagnostic_option_id m_option_id;
+};
+
 #endif /* GCC_KNOWN_HEADERS_H */
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index b9c688eb2093..1c11c216bd6c 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -4547,6 +4547,17 @@ lookup_name_fuzzy (tree name, enum 
lookup_name_fuzzy_kind kind, location_t loc)
                                                  IDENTIFIER_POINTER (name),
                                                  header_hint));
 
+  /* Next, look for exact matches for builtin defines that would have been
+     defined if the user had passed a command-line option (e.g. -fopenmp
+     for "_OPENMP").  */
+  diagnostic_option_id option_id
+    = get_option_for_builtin_define (IDENTIFIER_POINTER (name));
+  if (option_id.m_idx > 0)
+    return name_hint (nullptr,
+                     new suggest_missing_option (loc,
+                                                 IDENTIFIER_POINTER (name),
+                                                 option_id));
+
   /* Only suggest names reserved for the implementation if NAME begins
      with an underscore.  */
   bool consider_implementation_names = (IDENTIFIER_POINTER (name)[0] == '_');
diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc
index 30dfbfe2e48d..73d2662a7ead 100644
--- a/gcc/cp/name-lookup.cc
+++ b/gcc/cp/name-lookup.cc
@@ -7179,6 +7179,17 @@ suggest_alternatives_for_1 (location_t location, tree 
name,
        return hint;
     }
 
+  /* Look for exact matches for builtin defines that would have been
+     defined if the user had passed a command-line option (e.g. -fopenmp
+     for "_OPENMP").  */
+  diagnostic_option_id option_id
+    = get_option_for_builtin_define (IDENTIFIER_POINTER (name));
+  if (option_id.m_idx > 0)
+    return name_hint (nullptr,
+                     new suggest_missing_option (location,
+                                                 IDENTIFIER_POINTER (name),
+                                                 option_id));
+
   /* Otherwise, consider misspellings.  */
   if (!suggest_misspellings)
     return name_hint ();
diff --git a/gcc/testsuite/c-c++-common/spellcheck-missing-option.c 
b/gcc/testsuite/c-c++-common/spellcheck-missing-option.c
new file mode 100644
index 000000000000..d7dbb2e4a7b9
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/spellcheck-missing-option.c
@@ -0,0 +1,15 @@
+void
+test_fopenacc ()
+{
+  __builtin_printf ("_OPENACC = %d\n", _OPENACC); /* { dg-error "'_OPENACC' 
undeclared" "" { target c } } */
+  /* { dg-error "'_OPENACC' was not declared in this scope" "" { target c++ } 
.-1 } */
+  /* { dg-message "'_OPENACC' is defined when using option '-fopenacc'" "" { 
target *-*-* } .-2 } */
+}
+
+void
+test_fopenmp ()
+{
+  __builtin_printf ("_OPENMP = %d\n", _OPENMP); /* { dg-error "'_OPENMP' 
undeclared" "" { target c } } */
+  /* { dg-error "'_OPENMP' was not declared in this scope" "" { target c++ } 
.-1 } */
+  /* { dg-message "'_OPENMP' is defined when using option '-fopenmp'" "" { 
target *-*-* } .-2 } */
+}
-- 
2.26.3

Reply via email to