[clang] [clang][Sema] Add diagnostic note for reference of function-like macros requiring without parentheses (PR #123495)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Feb 9 01:46:24 PST 2025
https://github.com/StarOne01 updated https://github.com/llvm/llvm-project/pull/123495
>From 6f2ce4c05c0e03b1c18c694ddea97dac184e2218 Mon Sep 17 00:00:00 2001
From: Prashanth <TheStarOne01 at proton.me>
Date: Sun, 19 Jan 2025 07:28:24 +0530
Subject: [PATCH 01/17] [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 <TheStarOne01 at proton.me>
Date: Sun, 19 Jan 2025 08:30:39 +0530
Subject: [PATCH 02/17] [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 at -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 at -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 at -2 2{{defined here}}
+// expected-note at -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 <TheStarOne01 at proton.me>
Date: Mon, 20 Jan 2025 13:34:48 +0530
Subject: [PATCH 03/17] Change the note for reference of function-like macros
requiring without parentheses
Co-authored-by: Sirraide <aeternalmail at 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 <TheStarOne01 at proton.me>
Date: Tue, 21 Jan 2025 16:20:10 +0530
Subject: [PATCH 04/17] [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 at -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 at -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 at -2 2{{defined here}}
-// expected-note at -3 {{'M' exists, but as a function-like macro; perhaps, did you forget the parentheses?}}
+// expected-note at -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 at -3 {{use of undeclared identifier}}
// expected-note at -4 {{cannot use initializer list at the beginning of a macro argument}}
}
+
+#define LIM() 10
+// expected-note at -1 {{'LIM' is defined here as a function-like macro; did you mean to write 'LIM(...)'}}
+
+void test3() {
+ int iter = LIM;
+ // expected-error at -1 {{use of undeclared identifier LIM}}
+}
\ No newline at end of file
>From 0d62be75f684589e8c9e26bb1ed3f3c71791d587 Mon Sep 17 00:00:00 2001
From: Prashanth <TheStarOne01 at proton.me>
Date: Tue, 21 Jan 2025 16:22:39 +0530
Subject: [PATCH 05/17] Change the note for reference of function-like macros
requiring without parentheses
Co-authored-by: Mariya Podchishchaeva <mariya.podchishchaeva at 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 <TheStarOne01 at proton.me>
Date: Tue, 21 Jan 2025 17:03:21 +0530
Subject: [PATCH 06/17] [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 at -1 2{{'INIT' is defined here as a function-like macro; did you mean to write 'INIT(...)'}}
+// expected-note at -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 at -2 2{{defined here}}
-// expected-note at -3 {{'M' is defined here as a function-like macro; did you mean to write 'M(...)'}}
+// expected-note at -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 at -1 {{'LIM' is defined here as a function-like macro; did you mean to write 'LIM(...)'}}
+// expected-note at -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 <TheStarOne01 at proton.me>
Date: Sun, 9 Feb 2025 14:20:36 +0530
Subject: [PATCH 07/17] [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 at -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 at -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 at -2 2{{defined here}}
-// expected-note at -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 at -2 {{too many arguments provided}}
// expected-error at -3 {{use of undeclared identifier}}
// expected-note at -4 {{cannot use initializer list at the beginning of a macro argument}}
-}
-
-#define LIM() 10
-// expected-note at -1 {{'LIM' is defined here as a function-like macro; did you mean 'LIM(...)'}}
-
-void test3() {
- int iter = LIM;
- // expected-error at -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 at -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 at -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(...)?}}
+}
>From f4798f2b1cb11c7ef4a31c41aeb55cb9f283bc0c Mon Sep 17 00:00:00 2001
From: Prashanth <TheStarOne01 at proton.me>
Date: Sun, 9 Feb 2025 14:50:49 +0530
Subject: [PATCH 08/17] [clang][Tests] Enhance diagnostic notes for
function-like macros in initializer list tests
---
clang/test/Preprocessor/macro_with_initializer_list.cpp | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/clang/test/Preprocessor/macro_with_initializer_list.cpp b/clang/test/Preprocessor/macro_with_initializer_list.cpp
index 5f66971622ce728..dab60e60b14a186 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{{macro 'INIT' defined here}}
+// expected-note at -1 2{{'INIT' defined here as a function-like macro}}
// 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 at -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 at -2 2{{defined here}}
+// expected-note at -3 {{'M' defined here as a function-like macro}}
void test2() {
M(F1, Foo(), Foo(), Foo(), Foo(), Foo(), Foo(),
Foo(), Foo(), Foo(), Foo(), Foo(), Foo());
@@ -179,4 +181,4 @@ void test2() {
// expected-error at -2 {{too many arguments provided}}
// expected-error at -3 {{use of undeclared identifier}}
// expected-note at -4 {{cannot use initializer list at the beginning of a macro argument}}
-}
\ No newline at end of file
+}
>From ea6c9ca9cffbf4327fc7bab85e37e2a3c2c0f0cd Mon Sep 17 00:00:00 2001
From: Prashanth <TheStarOne01 at proton.me>
Date: Sun, 19 Jan 2025 07:28:24 +0530
Subject: [PATCH 09/17] [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 bcae9e9f3009387..d9c8fcc66acf280 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5961,6 +5961,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 3cd4010740d1944..dff03ac31ef2aa6 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -2522,6 +2522,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) {
@@ -2632,7 +2645,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 c274178a0ce3a510eaaa9390b277b860bcc5a2a9 Mon Sep 17 00:00:00 2001
From: Prashanth <TheStarOne01 at proton.me>
Date: Sun, 19 Jan 2025 08:30:39 +0530
Subject: [PATCH 10/17] [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 d9c8fcc66acf280..697b92d32524007 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5961,8 +5961,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 dff03ac31ef2aa6..da894dd3a6d6a6c 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -2527,8 +2527,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;
}
@@ -2645,7 +2646,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 at -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 at -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 at -2 2{{defined here}}
+// expected-note at -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 33e001ee6e852f630fd1b69bea424c6e7166078b Mon Sep 17 00:00:00 2001
From: Prashanth <TheStarOne01 at proton.me>
Date: Mon, 20 Jan 2025 13:34:48 +0530
Subject: [PATCH 11/17] Change the note for reference of function-like macros
requiring without parentheses
Co-authored-by: Sirraide <aeternalmail at 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 697b92d32524007..6d3a065077d4bcf 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5962,8 +5962,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 5aa4654ffe3f7499faf6f8abc7dbdf3468a8dcb9 Mon Sep 17 00:00:00 2001
From: Prashanth <TheStarOne01 at proton.me>
Date: Tue, 21 Jan 2025 16:20:10 +0530
Subject: [PATCH 12/17] [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 at -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 at -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 at -2 2{{defined here}}
-// expected-note at -3 {{'M' exists, but as a function-like macro; perhaps, did you forget the parentheses?}}
+// expected-note at -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 at -3 {{use of undeclared identifier}}
// expected-note at -4 {{cannot use initializer list at the beginning of a macro argument}}
}
+
+#define LIM() 10
+// expected-note at -1 {{'LIM' is defined here as a function-like macro; did you mean to write 'LIM(...)'}}
+
+void test3() {
+ int iter = LIM;
+ // expected-error at -1 {{use of undeclared identifier LIM}}
+}
\ No newline at end of file
>From bd0848786ffb70e6f06b2b93b1b2fae46478484c Mon Sep 17 00:00:00 2001
From: Prashanth <TheStarOne01 at proton.me>
Date: Tue, 21 Jan 2025 16:22:39 +0530
Subject: [PATCH 13/17] Change the note for reference of function-like macros
requiring without parentheses
Co-authored-by: Mariya Podchishchaeva <mariya.podchishchaeva at 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 6d3a065077d4bcf..34ed18e518773e4 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5962,7 +5962,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 6ef338ab4c2dd123397327fb3de7f1057643fa49 Mon Sep 17 00:00:00 2001
From: Prashanth <TheStarOne01 at proton.me>
Date: Tue, 21 Jan 2025 17:03:21 +0530
Subject: [PATCH 14/17] [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 at -1 2{{'INIT' is defined here as a function-like macro; did you mean to write 'INIT(...)'}}
+// expected-note at -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 at -2 2{{defined here}}
-// expected-note at -3 {{'M' is defined here as a function-like macro; did you mean to write 'M(...)'}}
+// expected-note at -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 at -1 {{'LIM' is defined here as a function-like macro; did you mean to write 'LIM(...)'}}
+// expected-note at -1 {{'LIM' is defined here as a function-like macro; did you mean 'LIM(...)'}}
void test3() {
int iter = LIM;
>From 094887dbe3a521ad4733cd37cbfb5313bbb0dc4e Mon Sep 17 00:00:00 2001
From: Prashanth <TheStarOne01 at proton.me>
Date: Sun, 9 Feb 2025 14:20:36 +0530
Subject: [PATCH 15/17] [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 34ed18e518773e4..33a3bfe4ff6468d 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5962,7 +5962,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<
@@ -10857,6 +10857,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 da894dd3a6d6a6c..27c2cf65762e3de 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -2347,6 +2347,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,
@@ -2382,8 +2403,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;
}
@@ -2522,20 +2546,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) {
@@ -2638,6 +2648,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 at -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 at -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 at -2 2{{defined here}}
-// expected-note at -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 at -2 {{too many arguments provided}}
// expected-error at -3 {{use of undeclared identifier}}
// expected-note at -4 {{cannot use initializer list at the beginning of a macro argument}}
-}
-
-#define LIM() 10
-// expected-note at -1 {{'LIM' is defined here as a function-like macro; did you mean 'LIM(...)'}}
-
-void test3() {
- int iter = LIM;
- // expected-error at -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 at -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 at -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(...)?}}
+}
>From eac145ae3c3de06573cc7cbef40fe5436606e089 Mon Sep 17 00:00:00 2001
From: Prashanth <TheStarOne01 at proton.me>
Date: Sun, 9 Feb 2025 14:50:49 +0530
Subject: [PATCH 16/17] [clang][Tests] Enhance diagnostic notes for
function-like macros in initializer list tests
---
clang/test/Preprocessor/macro_with_initializer_list.cpp | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/clang/test/Preprocessor/macro_with_initializer_list.cpp b/clang/test/Preprocessor/macro_with_initializer_list.cpp
index 5f66971622ce728..dab60e60b14a186 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{{macro 'INIT' defined here}}
+// expected-note at -1 2{{'INIT' defined here as a function-like macro}}
// 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 at -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 at -2 2{{defined here}}
+// expected-note at -3 {{'M' defined here as a function-like macro}}
void test2() {
M(F1, Foo(), Foo(), Foo(), Foo(), Foo(), Foo(),
Foo(), Foo(), Foo(), Foo(), Foo(), Foo());
@@ -179,4 +181,4 @@ void test2() {
// expected-error at -2 {{too many arguments provided}}
// expected-error at -3 {{use of undeclared identifier}}
// expected-note at -4 {{cannot use initializer list at the beginning of a macro argument}}
-}
\ No newline at end of file
+}
>From 424da7c94ca2ded676d71acf495f0d549e402689 Mon Sep 17 00:00:00 2001
From: Prashanth <TheStarOne01 at proton.me>
Date: Sun, 9 Feb 2025 15:15:53 +0530
Subject: [PATCH 17/17] [clang][Sema] Add release notes for function-like
macros
---
clang/docs/ReleaseNotes.rst | 1 +
1 file changed, 1 insertion(+)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 50d3bbbc97e9192..a469e5a97a4acf2 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -128,6 +128,7 @@ Improvements to Clang's diagnostics
which are supposed to only exist once per program, but may get duplicated when
built into a shared library.
- Fixed a bug where Clang's Analysis did not correctly model the destructor behavior of ``union`` members (#GH119415).
+- Clang now provides a diagnostic note for ``function-like macros`` that are missing the required parentheses.
Improvements to Clang's time-trace
----------------------------------
More information about the cfe-commits
mailing list