Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
3 changes: 3 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,9 @@ Improvements to Clang's diagnostics
- Now correctly diagnose a tentative definition of an array with static
storage duration in pedantic mode in C. (#GH50661)

- An error is now emitted when a ``musttail`` call is made to a function marked with the ``not_tail_called`` attribute. (#GH133509).


Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should only be a single -new-line at the end of this list.

Improvements to Clang's time-trace
----------------------------------

Expand Down
6 changes: 6 additions & 0 deletions clang/lib/Sema/SemaStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,12 @@ bool Sema::checkMustTailAttr(const Stmt *St, const Attr &MTA) {
return false;
}

if (const FunctionDecl *CalleeDecl = CE->getDirectCallee();
CalleeDecl && CalleeDecl->hasAttr<NotTailCalledAttr>()) {
Diag(St->getBeginLoc(), diag::err_musttail_mismatch) << true << CalleeDecl;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Diag(St->getBeginLoc(), diag::err_musttail_mismatch) << true << CalleeDecl;
Diag(St->getBeginLoc(), diag::err_musttail_mismatch) << /*show-function-callee=*/true << CalleeDecl;

Not exactly our policy, but makes it way easier to understand what is going on here.

return false;
}

if (const auto *EWC = dyn_cast<ExprWithCleanups>(E)) {
if (EWC->cleanupsHaveSideEffects()) {
Diag(St->getBeginLoc(), diag::err_musttail_needs_trivial_args) << &MTA;
Expand Down
17 changes: 17 additions & 0 deletions clang/test/Sema/attr-musttail.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// RUN: %clang_cc1 -verify -fsyntax-only %s

int __attribute__((not_tail_called)) foo1(int a) {
return a + 1;
}


int foo2(int a) {
[[clang::musttail]]
return foo1(a); // expected-error {{cannot perform a tail call to function 'foo1' because its signature is incompatible with the calling function}}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooof... I know @AaronBallman suggested reusing the diagnostic... can we do at least a note (perhaps pointing to the attribute not_tail_called) to show WHY we are emitting this error?

Something like: `note: 'not_tail_called' attribute here prevents being called as a tail call'?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@erichkeane Where do you want this note to be added?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, a 'note' diagnostic. See a bunch of our diagnostics starting with note. Then you just do a second Diag call afterwards. I would think the source-location for it cna be the attribute on the callee.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@erichkeane I still don't understand what you mean. Do I need to report cannot perform a tail call to function 'foo1' because its signature is incompatible with the calling function note: 'not_tail_called' attribute here prevents being called as a tail call' after the function is run?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In SemaStmt.cpp right after the line:
Diag(St->getBeginLoc(), diag::err_musttail_mismatch) << true << CalleeDecl;

You can do:
Diag(<get location of not_tail_called_attribute>, diag::note_<your new diag>);

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea Erich! I don't think we need a new diagnostic though, we can reuse note_conflicting_attribute, so I think this will suffice:

Diag(CalleeDecl->getAttr<NotTailCalledAttr>()->getLoc(), diag::note_conflicting_attribute);

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that attribute is imperfect (and requires reading tea leaves a bit), but probably good enough. I think that's a good suggestion.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, it'd help if the note mentioned the other attribute that was in conflict with, but I think it probably suffices. It at least gets folks' eyeballs closer to the conflict.

}

int main() {
int result = foo2(10);
return 0;
}