[clang] 21ef0ad - [clang][Sema] Add diagnostic note for reference of function-like macros requiring without parentheses (#123495)

via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 11 05:53:13 PDT 2026


Author: Prashanth
Date: 2026-09-11T08:53:08-04:00
New Revision: 21ef0ade496fcaf20cfcb32f4a7e46f4f38abafd

URL: https://github.com/llvm/llvm-project/commit/21ef0ade496fcaf20cfcb32f4a7e46f4f38abafd
DIFF: https://github.com/llvm/llvm-project/commit/21ef0ade496fcaf20cfcb32f4a7e46f4f38abafd.diff

LOG: [clang][Sema]  Add diagnostic note for reference of function-like macros requiring without parentheses (#123495)

This PR enhances the Clang diagnostics to provide better guidance when
function-like macros are used without parentheses. Additionally, it
updates the relevant test cases to reflect these changes (#123038 ).

---------

Co-authored-by: Sirraide <aeternalmail at gmail.com>
Co-authored-by: Mariya Podchishchaeva <mariya.podchishchaeva at intel.com>

Added: 
    

Modified: 
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Sema/SemaExpr.cpp
    clang/test/Sema/typo-correction.c

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index a7b40a7b64c2d..72b7f9116c3f9 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6345,6 +6345,8 @@ def err_fold_expression_limit_exceeded: Error<
   "instantiating fold expression with %0 arguments exceeded expression nesting "
   "limit of %1">, DefaultFatal, NoSFINAE;
 
+def note_function_like_macro_requires_parens
+    : Note<"'%0' defined here as a function-like macro">;
 def err_unexpected_typedef : Error<
   "unexpected type name %0: expected expression">;
 def err_unexpected_namespace : Error<
@@ -11689,6 +11691,8 @@ def err_undeclared_use_suggest : Error<
   "use of undeclared %0; did you mean %1?">;
 def err_undeclared_var_use_suggest : Error<
   "use of undeclared identifier %0; did you mean %1?">;
+def err_undeclared_var_use_suggest_func_like_macro : Error<
+  "'%0' is defined as a function-like macro; did you mean '%0(...)'?">;
 def err_no_template : Error<"no template named %0">;
 def err_no_template_suggest : Error<"no template named %0; did you mean %1?">;
 def err_no_member_template : Error<"no template named %0 in %1">;

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 9fa8e517d9098..bec58da8efa00 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -2548,6 +2548,39 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
   return E;
 }
 
+// Diagnose when a macro cannot be expanded because it's a function-like macro
+// being used as a function-like macro. Returns true if a diagnostic is emitted.
+static bool diagnoseFunctionLikeMacro(Sema &SemaRef, DeclarationName Name,
+                                      SourceLocation TypoLoc) {
+
+  if (IdentifierInfo *II = Name.getAsIdentifierInfo()) {
+    if (II->hasMacroDefinition()) {
+      MacroInfo *MI = SemaRef.PP.getMacroInfo(II);
+      if (MI && MI->isFunctionLike()) {
+        // If the identifier is immediately followed by '(', the user did
+        // attempt to invoke it as a function-like macro; the failure is
+        // for some other reason (e.g. wrong argument count), which the
+        // preprocessor already diagnosed separately. Don't suggest adding
+        // parens in that case, since they're already there.
+        SourceManager &SM = SemaRef.getSourceManager();
+        const LangOptions &LangOpts = SemaRef.getLangOpts();
+        std::optional<Token> NextTok =
+            Lexer::findNextToken(TypoLoc, SM, LangOpts);
+        if (NextTok && NextTok->is(tok::l_paren))
+          return false;
+        SemaRef.Diag(TypoLoc,
+                     diag::err_undeclared_var_use_suggest_func_like_macro)
+            << II->getName();
+        SemaRef.Diag(MI->getDefinitionLoc(),
+                     diag::note_function_like_macro_requires_parens)
+            << II->getName();
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
 void
 Sema::DecomposeUnqualifiedId(const UnqualifiedId &Id,
                              TemplateArgumentListInfo &Buffer,
@@ -2784,6 +2817,9 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
   }
   R.clear();
 
+  if (diagnoseFunctionLikeMacro(SemaRef, Name, R.getNameLoc()))
+    return true;
+
   // Emit a special diagnostic for failed member lookups.
   // FIXME: computing the declaration context might fail here (?)
   if (!SS.isEmpty()) {

diff  --git a/clang/test/Sema/typo-correction.c b/clang/test/Sema/typo-correction.c
index 510a67e725f9c..1f6bcd0485a02 100644
--- a/clang/test/Sema/typo-correction.c
+++ b/clang/test/Sema/typo-correction.c
@@ -118,3 +118,25 @@ void PR40286_3(int the_value) { // expected-note {{'the_value' declared here}}
 void PR40286_4(int the_value) { // expected-note {{'the_value' declared here}}
   PR40286_h(the_value, the_value, the_walue); // expected-error {{use of undeclared identifier 'the_walue'; did you mean 'the_value'?}}
 }
+
+#define FOO1() 10
+// expected-note at -1 4 {{'FOO1' defined here as a function-like macro}}
+
+int x = FOO1; // expected-error {{'FOO1' is defined as a function-like macro; did you mean 'FOO1(...)'?}}
+
+void test3() {
+  int iter = FOO1;
+  // expected-error at -1 {{'FOO1' is defined as a function-like macro; did you mean 'FOO1(...)'?}}
+}
+
+void bar(int);
+
+void test4() {
+    int FOO; // expected-note {{'FOO' declared here}}
+    int x = FOO1; // expected-error {{use of undeclared identifier 'FOO1'; did you mean 'FOO'?}}
+}
+
+void test5() {
+    FOO1 + 1; // expected-error {{'FOO1' is defined as a function-like macro; did you mean 'FOO1(...)'?}}
+    bar(FOO1); // expected-error {{'FOO1' is defined as a function-like macro; did you mean 'FOO1(...)'?}}
+}


        


More information about the cfe-commits mailing list