https://github.com/StarOne01 updated https://github.com/llvm/llvm-project/pull/123495
>From 6f2ce4c05c0e03b1c18c694ddea97dac184e2218 Mon Sep 17 00:00:00 2001 From: Prashanth <thestaron...@proton.me> Date: Sun, 19 Jan 2025 07:28:24 +0530 Subject: [PATCH 1/7] [clang][Sema] Add diagnostic note for function-like macros requiring parentheses --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 ++ clang/lib/Sema/SemaExpr.cpp | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index db54312ad965e89..9d98cd2d8bbc881 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5936,6 +5936,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' exists, but as a function-like macro; perhaps, did you forget the parentheses?">; def err_unexpected_typedef : Error< "unexpected type name %0: expected expression">; def err_unexpected_namespace : Error< diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index ae40895980d90a9..f9dd731d59a2dd7 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2509,6 +2509,19 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, DC = DC->getLookupParent(); } + // Check whether a similar function-like macro exists and suggest it + if (IdentifierInfo *II = Name.getAsIdentifierInfo()) { + if (II->hasMacroDefinition()) { + MacroInfo *MI = PP.getMacroInfo(II); + if (MI && MI->isFunctionLike()) { + Diag( R.getNameLoc() ,diag::err_undeclared_var_use) << II->getName(); + Diag(MI->getDefinitionLoc(), diag::note_function_like_macro_requires_parens) + << II->getName(); + return true; + } + } + } + // We didn't find anything, so try to correct for a typo. TypoCorrection Corrected; if (S && Out) { @@ -2619,7 +2632,7 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, << SS.getRange(); return true; } - + // Give up, we can't recover. Diag(R.getNameLoc(), diagnostic) << Name; return true; >From 8e90d9a0a227442d1220f1d6f521f81b6397e146 Mon Sep 17 00:00:00 2001 From: Prashanth <thestaron...@proton.me> Date: Sun, 19 Jan 2025 08:30:39 +0530 Subject: [PATCH 2/7] [clang][Tests] Modify tests for function-like macros according to the new behavior and Format the changes --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 5 +++-- clang/lib/Sema/SemaExpr.cpp | 7 ++++--- clang/test/Preprocessor/macro_with_initializer_list.cpp | 6 ++++-- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 9d98cd2d8bbc881..37a9a67ac1efba8 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5936,8 +5936,9 @@ 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' exists, but as a function-like macro; perhaps, did you forget the parentheses?">; +def note_function_like_macro_requires_parens + : Note<"'%0' exists, but as a function-like macro; perhaps, did you forget " + "the parentheses?">; def err_unexpected_typedef : Error< "unexpected type name %0: expected expression">; def err_unexpected_namespace : Error< diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index f9dd731d59a2dd7..44bab3e47233cb0 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2514,8 +2514,9 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, if (II->hasMacroDefinition()) { MacroInfo *MI = PP.getMacroInfo(II); if (MI && MI->isFunctionLike()) { - Diag( R.getNameLoc() ,diag::err_undeclared_var_use) << II->getName(); - Diag(MI->getDefinitionLoc(), diag::note_function_like_macro_requires_parens) + Diag(R.getNameLoc(), diag::err_undeclared_var_use) << II->getName(); + Diag(MI->getDefinitionLoc(), + diag::note_function_like_macro_requires_parens) << II->getName(); return true; } @@ -2632,7 +2633,7 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, << SS.getRange(); return true; } - + // Give up, we can't recover. Diag(R.getNameLoc(), diagnostic) << Name; return true; diff --git a/clang/test/Preprocessor/macro_with_initializer_list.cpp b/clang/test/Preprocessor/macro_with_initializer_list.cpp index 40f53164b263d91..cc7dae0b5a3e00c 100644 --- a/clang/test/Preprocessor/macro_with_initializer_list.cpp +++ b/clang/test/Preprocessor/macro_with_initializer_list.cpp @@ -134,6 +134,7 @@ void test_NE() { // CHECK: fix-it:"{{.*}}macro_with_initializer_list.cpp":{110:32-110:32}:")" #define INIT(var, init) Foo var = init; // expected-note 3{{defined here}} +// expected-note@-1 2{{'INIT' exists, but as a function-like macro; perhaps, did you forget the parentheses?}} // Can't use an initializer list as a macro argument. The commas in the list // will be interpretted as argument separaters and adding parenthesis will // make it no longer an initializer list. @@ -159,12 +160,13 @@ void test() { // expected-note@-3 {{cannot use initializer list at the beginning of a macro argument}} } -// CHECK: fix-it:"{{.*}}macro_with_initializer_list.cpp":{145:11-145:11}:"(" -// CHECK: fix-it:"{{.*}}macro_with_initializer_list.cpp":{145:23-145:23}:")" +// CHECK: fix-it:"{{.*}}macro_with_initializer_list.cpp":{146:11-146:11}:"(" +// CHECK: fix-it:"{{.*}}macro_with_initializer_list.cpp":{146:23-146:23}:")" #define M(name,a,b,c,d,e,f,g,h,i,j,k,l) \ Foo name = a + b + c + d + e + f + g + h + i + j + k + l; // expected-note@-2 2{{defined here}} +// expected-note@-3 {{'M' exists, but as a function-like macro; perhaps, did you forget the parentheses?}} void test2() { M(F1, Foo(), Foo(), Foo(), Foo(), Foo(), Foo(), Foo(), Foo(), Foo(), Foo(), Foo(), Foo()); >From 230b171ccfad348ed318d5ef8cf42f67acd2ddad Mon Sep 17 00:00:00 2001 From: Prashanth <thestaron...@proton.me> Date: Mon, 20 Jan 2025 13:34:48 +0530 Subject: [PATCH 3/7] Change the note for reference of function-like macros requiring without parentheses Co-authored-by: Sirraide <aeternalm...@gmail.com> --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 37a9a67ac1efba8..ecabb6220806140 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5937,8 +5937,7 @@ def err_fold_expression_limit_exceeded: Error< "limit of %1">, DefaultFatal, NoSFINAE; def note_function_like_macro_requires_parens - : Note<"'%0' exists, but as a function-like macro; perhaps, did you forget " - "the parentheses?">; + : Note<"'%0' is defined here as a function-like macro; did you mean to write '%0(...)'">; def err_unexpected_typedef : Error< "unexpected type name %0: expected expression">; def err_unexpected_namespace : Error< >From 839299abd35e1690e2f9d65aeea84d246a956460 Mon Sep 17 00:00:00 2001 From: Prashanth <thestaron...@proton.me> Date: Tue, 21 Jan 2025 16:20:10 +0530 Subject: [PATCH 4/7] [clang][Tests] Update diagnostic tests for function-like macros to clarify usage and improve error messages --- .../Preprocessor/macro_with_initializer_list.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/clang/test/Preprocessor/macro_with_initializer_list.cpp b/clang/test/Preprocessor/macro_with_initializer_list.cpp index cc7dae0b5a3e00c..f7f645cce1180fc 100644 --- a/clang/test/Preprocessor/macro_with_initializer_list.cpp +++ b/clang/test/Preprocessor/macro_with_initializer_list.cpp @@ -133,8 +133,8 @@ void test_NE() { // CHECK: fix-it:"{{.*}}macro_with_initializer_list.cpp":{110:9-110:9}:"(" // CHECK: fix-it:"{{.*}}macro_with_initializer_list.cpp":{110:32-110:32}:")" -#define INIT(var, init) Foo var = init; // expected-note 3{{defined here}} -// expected-note@-1 2{{'INIT' exists, but as a function-like macro; perhaps, did you forget the parentheses?}} +#define INIT(var, init) Foo var = init; // expected-note 3{{macro 'INIT' defined here}} +// expected-note@-1 2{{'INIT' is defined here as a function-like macro; did you mean to write 'INIT(...)'}} // Can't use an initializer list as a macro argument. The commas in the list // will be interpretted as argument separaters and adding parenthesis will // make it no longer an initializer list. @@ -166,7 +166,7 @@ void test() { #define M(name,a,b,c,d,e,f,g,h,i,j,k,l) \ Foo name = a + b + c + d + e + f + g + h + i + j + k + l; // expected-note@-2 2{{defined here}} -// expected-note@-3 {{'M' exists, but as a function-like macro; perhaps, did you forget the parentheses?}} +// expected-note@-3 {{'M' is defined here as a function-like macro; did you mean to write 'M(...)'}} void test2() { M(F1, Foo(), Foo(), Foo(), Foo(), Foo(), Foo(), Foo(), Foo(), Foo(), Foo(), Foo(), Foo()); @@ -182,3 +182,11 @@ void test2() { // expected-error@-3 {{use of undeclared identifier}} // expected-note@-4 {{cannot use initializer list at the beginning of a macro argument}} } + +#define LIM() 10 +// expected-note@-1 {{'LIM' is defined here as a function-like macro; did you mean to write 'LIM(...)'}} + +void test3() { + int iter = LIM; + // expected-error@-1 {{use of undeclared identifier LIM}} +} \ No newline at end of file >From 0d62be75f684589e8c9e26bb1ed3f3c71791d587 Mon Sep 17 00:00:00 2001 From: Prashanth <thestaron...@proton.me> Date: Tue, 21 Jan 2025 16:22:39 +0530 Subject: [PATCH 5/7] Change the note for reference of function-like macros requiring without parentheses Co-authored-by: Mariya Podchishchaeva <mariya.podchishcha...@intel.com> --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index ecabb6220806140..fe7aa9d446b70af 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5937,7 +5937,7 @@ def err_fold_expression_limit_exceeded: Error< "limit of %1">, DefaultFatal, NoSFINAE; def note_function_like_macro_requires_parens - : Note<"'%0' is defined here as a function-like macro; did you mean to write '%0(...)'">; + : Note<"'%0' is defined here as a function-like macro; did you mean '%0(...)'">; def err_unexpected_typedef : Error< "unexpected type name %0: expected expression">; def err_unexpected_namespace : Error< >From b41ee208b023ff779ba64226313cb4bd3995275f Mon Sep 17 00:00:00 2001 From: Prashanth <thestaron...@proton.me> Date: Tue, 21 Jan 2025 17:03:21 +0530 Subject: [PATCH 6/7] [clang][Tests] Update diagnostic tests for function-like macros for the updated note --- clang/test/Preprocessor/macro_with_initializer_list.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/test/Preprocessor/macro_with_initializer_list.cpp b/clang/test/Preprocessor/macro_with_initializer_list.cpp index f7f645cce1180fc..cf1d137eadcbe2f 100644 --- a/clang/test/Preprocessor/macro_with_initializer_list.cpp +++ b/clang/test/Preprocessor/macro_with_initializer_list.cpp @@ -134,7 +134,7 @@ void test_NE() { // CHECK: fix-it:"{{.*}}macro_with_initializer_list.cpp":{110:32-110:32}:")" #define INIT(var, init) Foo var = init; // expected-note 3{{macro 'INIT' defined here}} -// expected-note@-1 2{{'INIT' is defined here as a function-like macro; did you mean to write 'INIT(...)'}} +// expected-note@-1 2{{'INIT' is defined here as a function-like macro; did you mean 'INIT(...)'}} // Can't use an initializer list as a macro argument. The commas in the list // will be interpretted as argument separaters and adding parenthesis will // make it no longer an initializer list. @@ -166,7 +166,7 @@ void test() { #define M(name,a,b,c,d,e,f,g,h,i,j,k,l) \ Foo name = a + b + c + d + e + f + g + h + i + j + k + l; // expected-note@-2 2{{defined here}} -// expected-note@-3 {{'M' is defined here as a function-like macro; did you mean to write 'M(...)'}} +// expected-note@-3 {{'M' is defined here as a function-like macro; did you mean 'M(...)'}} void test2() { M(F1, Foo(), Foo(), Foo(), Foo(), Foo(), Foo(), Foo(), Foo(), Foo(), Foo(), Foo(), Foo()); @@ -184,7 +184,7 @@ void test2() { } #define LIM() 10 -// expected-note@-1 {{'LIM' is defined here as a function-like macro; did you mean to write 'LIM(...)'}} +// expected-note@-1 {{'LIM' is defined here as a function-like macro; did you mean 'LIM(...)'}} void test3() { int iter = LIM; >From b0cb34d7fe034d0ca28b174af1d070809a627bf6 Mon Sep 17 00:00:00 2001 From: Prashanth <thestaron...@proton.me> Date: Sun, 9 Feb 2025 14:20:36 +0530 Subject: [PATCH 7/7] [clang][Sema] Improve diagnostics for undeclared function-like macros --- .../clang/Basic/DiagnosticSemaKinds.td | 4 +- clang/lib/Sema/SemaExpr.cpp | 43 ++++++++++++------- .../macro_with_initializer_list.cpp | 14 +----- clang/test/Sema/typo-correction.c | 22 ++++++++++ 4 files changed, 55 insertions(+), 28 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index fe7aa9d446b70af..e1814c25ed17469 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5937,7 +5937,7 @@ def err_fold_expression_limit_exceeded: Error< "limit of %1">, DefaultFatal, NoSFINAE; def note_function_like_macro_requires_parens - : Note<"'%0' is defined here as a function-like macro; did you mean '%0(...)'">; + : 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< @@ -10821,6 +10821,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<"use of undeclared identifier %0; 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 44bab3e47233cb0..85bf180d0c890e1 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2334,6 +2334,27 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, return E; } +// Check whether a similar function-like macro exists and suggest it +static bool isFunctionLikeMacro(const DeclarationName &Name, Sema &SemaRef, + const SourceLocation &TypoLoc) { + + if (IdentifierInfo *II = Name.getAsIdentifierInfo()) { + if (II->hasMacroDefinition()) { + MacroInfo *MI = SemaRef.PP.getMacroInfo(II); + if (MI && MI->isFunctionLike()) { + 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, @@ -2369,8 +2390,11 @@ static void emitEmptyLookupTypoDiagnostic( if (Ctx) SemaRef.Diag(TypoLoc, diag::err_no_member) << Typo << Ctx << SS.getRange(); - else + else { + if (isFunctionLikeMacro(Typo, SemaRef, TypoLoc)) + return; SemaRef.Diag(TypoLoc, DiagnosticID) << Typo; + } return; } @@ -2509,20 +2533,6 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, DC = DC->getLookupParent(); } - // Check whether a similar function-like macro exists and suggest it - if (IdentifierInfo *II = Name.getAsIdentifierInfo()) { - if (II->hasMacroDefinition()) { - MacroInfo *MI = PP.getMacroInfo(II); - if (MI && MI->isFunctionLike()) { - Diag(R.getNameLoc(), diag::err_undeclared_var_use) << II->getName(); - Diag(MI->getDefinitionLoc(), - diag::note_function_like_macro_requires_parens) - << II->getName(); - return true; - } - } - } - // We didn't find anything, so try to correct for a typo. TypoCorrection Corrected; if (S && Out) { @@ -2625,6 +2635,9 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, } R.clear(); + if (isFunctionLikeMacro(Name, SemaRef, 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/Preprocessor/macro_with_initializer_list.cpp b/clang/test/Preprocessor/macro_with_initializer_list.cpp index cf1d137eadcbe2f..5f66971622ce728 100644 --- a/clang/test/Preprocessor/macro_with_initializer_list.cpp +++ b/clang/test/Preprocessor/macro_with_initializer_list.cpp @@ -134,7 +134,6 @@ void test_NE() { // CHECK: fix-it:"{{.*}}macro_with_initializer_list.cpp":{110:32-110:32}:")" #define INIT(var, init) Foo var = init; // expected-note 3{{macro 'INIT' defined here}} -// expected-note@-1 2{{'INIT' is defined here as a function-like macro; did you mean 'INIT(...)'}} // Can't use an initializer list as a macro argument. The commas in the list // will be interpretted as argument separaters and adding parenthesis will // make it no longer an initializer list. @@ -160,13 +159,12 @@ void test() { // expected-note@-3 {{cannot use initializer list at the beginning of a macro argument}} } -// CHECK: fix-it:"{{.*}}macro_with_initializer_list.cpp":{146:11-146:11}:"(" -// CHECK: fix-it:"{{.*}}macro_with_initializer_list.cpp":{146:23-146:23}:")" +// CHECK: fix-it:"{{.*}}macro_with_initializer_list.cpp":{145:11-145:11}:"(" +// CHECK: fix-it:"{{.*}}macro_with_initializer_list.cpp":{145:23-145:23}:")" #define M(name,a,b,c,d,e,f,g,h,i,j,k,l) \ Foo name = a + b + c + d + e + f + g + h + i + j + k + l; // expected-note@-2 2{{defined here}} -// expected-note@-3 {{'M' is defined here as a function-like macro; did you mean 'M(...)'}} void test2() { M(F1, Foo(), Foo(), Foo(), Foo(), Foo(), Foo(), Foo(), Foo(), Foo(), Foo(), Foo(), Foo()); @@ -181,12 +179,4 @@ void test2() { // expected-error@-2 {{too many arguments provided}} // expected-error@-3 {{use of undeclared identifier}} // expected-note@-4 {{cannot use initializer list at the beginning of a macro argument}} -} - -#define LIM() 10 -// expected-note@-1 {{'LIM' is defined here as a function-like macro; did you mean 'LIM(...)'}} - -void test3() { - int iter = LIM; - // expected-error@-1 {{use of undeclared identifier LIM}} } \ No newline at end of file diff --git a/clang/test/Sema/typo-correction.c b/clang/test/Sema/typo-correction.c index 4157207a9ac4279..3efd35538dd585b 100644 --- a/clang/test/Sema/typo-correction.c +++ b/clang/test/Sema/typo-correction.c @@ -114,3 +114,25 @@ void PR40286_3(int the_value) { 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 {{use of undeclared identifier FOO1; did you mean FOO1(...)?}} + +void test3() { + int iter = FOO1; + // expected-error@-1 {{use of undeclared identifier FOO1; 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 {{use of undeclared identifier FOO1; did you mean FOO1(...)?}} + bar(FOO1); // expected-error {{use of undeclared identifier FOO1; did you mean FOO1(...)?}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits