[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