From 00956e55dd2fbbee751e953ca2f6b8a87151f85b Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Tue, 14 Oct 2025 17:50:13 -0700 Subject: [PATCH] C/C++: Better notification if misused a function like macro [PR102846] 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 --- 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 4af8f6637cb..36f3f88601f 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 1dc4d1da666..72fe3d74522 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 misused 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 7e94430435c..7dddc23b5e1 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -4671,7 +4671,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 (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 823e28bef76..460c9d30201 100644 --- a/gcc/cp/name-lookup.cc +++ b/gcc/cp/name-lookup.cc @@ -7931,7 +7931,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 (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 + +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.47.3