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 <[email protected]> Co-authored-by: Mariya Podchishchaeva <[email protected]> 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@-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@-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(...)'?}} +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
