Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.
StarOne01 marked this conversation as resolved.
Show resolved Hide resolved

Improvements to Clang's time-trace
----------------------------------
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -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' defined here as a function-like macro">;
def err_unexpected_typedef : Error<
"unexpected type name %0: expected expression">;
def err_unexpected_namespace : Error<
Expand Down Expand Up @@ -10855,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(...)?">;
StarOne01 marked this conversation as resolved.
Show resolved Hide resolved
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">;
Expand Down
29 changes: 28 additions & 1 deletion clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
StarOne01 marked this conversation as resolved.
Show resolved Hide resolved
static bool isFunctionLikeMacro(const DeclarationName &Name, Sema &SemaRef,
const SourceLocation &TypoLoc) {
StarOne01 marked this conversation as resolved.
Show resolved Hide resolved

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();
AaronBallman marked this conversation as resolved.
Show resolved Hide resolved
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,
Expand Down Expand Up @@ -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;
StarOne01 marked this conversation as resolved.
Show resolved Hide resolved
SemaRef.Diag(TypoLoc, DiagnosticID) << Typo;
}
return;
}

Expand Down Expand Up @@ -2624,6 +2648,9 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
}
R.clear();

if (isFunctionLikeMacro(Name, SemaRef, R.getNameLoc()))
StarOne01 marked this conversation as resolved.
Show resolved Hide resolved
return true;

// Emit a special diagnostic for failed member lookups.
// FIXME: computing the declaration context might fail here (?)
if (!SS.isEmpty()) {
Expand Down
8 changes: 5 additions & 3 deletions clang/test/Preprocessor/macro_with_initializer_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +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}}
#define INIT(var, init) Foo var = init; // expected-note 3{{macro 'INIT' defined here}}
// expected-note@-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.
Expand All @@ -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' defined here as a function-like macro}}
void test2() {
M(F1, Foo(), Foo(), Foo(), Foo(), Foo(), Foo(),
Foo(), Foo(), Foo(), Foo(), Foo(), Foo());
Expand Down
22 changes: 22 additions & 0 deletions clang/test/Sema/typo-correction.c
Original file line number Diff line number Diff line change
Expand Up @@ -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(...)?}}
}