Currently if assert is misused, e.g. like passing to a function like a
function pointer, GCC suggests to include assert.h/cassert. But since
it is already included that is just a bogus suggestion. Instead we should
see if a function-like macro is that same name (in the case of assert it will 
be),
and inform the user that it is being mis-used.

        PR c++/102846
        PR c/102846
gcc/c-family/ChangeLog:

        * known-headers.cc 
(macro_like_function_used::macro_like_function_used): New.
        (macro_like_function_used::~macro_like_function_used): New.
        * known-headers.h (class macro_like_function_used): New class.

gcc/c/ChangeLog:

        * c-decl.cc (lookup_name_fuzzy): Lookup function-like macro and
        notify of misuse there.

gcc/cp/ChangeLog:

        * name-lookup.cc (lookup_name_fuzzy): Lookup function-like macro and
        notify of misuse there.

gcc/testsuite/ChangeLog:

        * c-c++-common/function-like-macro-1.c: New test.
        * c-c++-common/function-like-macro-2.c: New test.

Signed-off-by: Andrew Pinski <[email protected]>
---
 gcc/c-family/known-headers.cc                 | 20 +++++++++++++++++++
 gcc/c-family/known-headers.h                  | 13 ++++++++++++
 gcc/c/c-decl.cc                               | 12 ++++++++++-
 gcc/cp/name-lookup.cc                         | 12 ++++++++++-
 .../c-c++-common/function-like-macro-1.c      | 10 ++++++++++
 .../c-c++-common/function-like-macro-2.c      | 11 ++++++++++
 6 files changed, 76 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/function-like-macro-1.c
 create mode 100644 gcc/testsuite/c-c++-common/function-like-macro-2.c

diff --git a/gcc/c-family/known-headers.cc b/gcc/c-family/known-headers.cc
index e3c01130639..65e92d226cd 100644
--- a/gcc/c-family/known-headers.cc
+++ b/gcc/c-family/known-headers.cc
@@ -352,3 +352,23 @@ suggest_missing_option::~suggest_missing_option ()
          " this is probably fixable by adding %qs to the command-line options",
          m_name_str, option_name, option_name);
 }
+
+/* macro_like_function_used's ctor.  */
+
+macro_like_function_used::macro_like_function_used (location_t loc, const char 
*name)
+: deferred_diagnostic (loc), m_name_str (name)
+{
+  gcc_assert (name);
+}
+
+/* macro_like_function_used's dtor.  */
+
+macro_like_function_used::~macro_like_function_used ()
+{
+  if (is_suppressed_p ())
+    return;
+
+  inform (get_location (),
+         "%qs is a function-like macro and might be used incorrectly",
+         m_name_str);
+}
diff --git a/gcc/c-family/known-headers.h b/gcc/c-family/known-headers.h
index 3ffe5f364ce..1f2feacb975 100644
--- a/gcc/c-family/known-headers.h
+++ b/gcc/c-family/known-headers.h
@@ -56,4 +56,17 @@ class suggest_missing_option : public deferred_diagnostic
   diagnostics::option_id m_option_id;
 };
 
+/* Subclass of deferred_diagnostic for suggesting to the user
+   that they have miss-used a function like macro.  */
+class macro_like_function_used : public deferred_diagnostic
+{
+ public:
+  macro_like_function_used (location_t loc, const char *name);
+
+  ~macro_like_function_used ();
+
+ private:
+  const char *m_name_str;
+};
+
 #endif /* GCC_KNOWN_HEADERS_H */
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 4a940d5eec3..73535cbafab 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -4637,7 +4637,17 @@ lookup_name_fuzzy (tree name, enum 
lookup_name_fuzzy_kind kind, location_t loc)
 {
   gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
 
-  /* First, try some well-known names in the C standard library, in case
+  /* Look up function-like macros first; maybe misusing them. */
+  auto cpp_node = cpp_lookup (parse_in,
+                             (const unsigned char*)IDENTIFIER_POINTER (name),
+                             IDENTIFIER_LENGTH (name));
+  if (cpp_node && cpp_fun_like_macro_p (cpp_node))
+    return name_hint
+      (nullptr,
+       std::make_unique<macro_like_function_used> (loc,
+                                                  IDENTIFIER_POINTER (name)));
+
+  /* Next, try some well-known names in the C standard library, in case
      the user forgot a #include.  */
   const char *header_hint
     = get_c_stdlib_header_for_name (IDENTIFIER_POINTER (name));
diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc
index b7530616ef0..41c1548ca33 100644
--- a/gcc/cp/name-lookup.cc
+++ b/gcc/cp/name-lookup.cc
@@ -7858,7 +7858,17 @@ lookup_name_fuzzy (tree name, enum 
lookup_name_fuzzy_kind kind, location_t loc)
 {
   gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
 
-  /* First, try some well-known names in the C++ standard library, in case
+  /* Look up function-like macros first; maybe misusing them. */
+  auto cpp_node = cpp_lookup (parse_in,
+                             (const unsigned char*)IDENTIFIER_POINTER (name),
+                             IDENTIFIER_LENGTH (name));
+  if (cpp_node && cpp_fun_like_macro_p (cpp_node))
+    return name_hint
+      (nullptr,
+       std::make_unique<macro_like_function_used> (loc,
+                                                  IDENTIFIER_POINTER (name)));
+
+  /* Then, try some well-known names in the C++ standard library, in case
      the user forgot a #include.  */
   const char *header_hint
     = get_cp_stdlib_header_for_name (IDENTIFIER_POINTER (name));
diff --git a/gcc/testsuite/c-c++-common/function-like-macro-1.c 
b/gcc/testsuite/c-c++-common/function-like-macro-1.c
new file mode 100644
index 00000000000..8f108887985
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/function-like-macro-1.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* PR c/102846 */
+
+#define f(a) ((void)0)
+
+void g(int a)
+{
+  (f)(a); /* { dg-error "was not declared|undeclared" "undeclared" } */
+  /* { dg-message "is a function-like macro and might be used incorrectly" "" 
{ target *-*-* } .-1 } */
+}
diff --git a/gcc/testsuite/c-c++-common/function-like-macro-2.c 
b/gcc/testsuite/c-c++-common/function-like-macro-2.c
new file mode 100644
index 00000000000..340e83932a0
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/function-like-macro-2.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* PR c/102846 */
+
+#include <assert.h>
+
+void g(int a)
+{
+  (assert)(a); /* { dg-error "was not declared|undeclared" "undeclared" } */
+  /* { dg-message "is a function-like macro and might be used incorrectly" 
"macro" { target *-*-* } .-1 } */
+  /* { dg-bogus "is defined in header" "header" { target *-*-* } .-2  }*/
+}
-- 
2.43.0

Reply via email to