xbolva00 created this revision. xbolva00 added reviewers: aaron.ballman, efriedma, haberman. Herald added a project: All. xbolva00 requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
As noted in https://github.com/llvm/llvm-project/issues/54964 , musttail provide assurances that the tail call can be optimized on all targets. But some users could care only one specific target and if they use musttail attribute, they may see an Clang error about signatures mismatch. This mismatch is often a not a real problem in practice and LLVM can still emit tail call. So... Introduce [[clang::nonportable_musttail]] which is a less strict version of [[clang::musttail]] (no checking if signatures fully match). Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D147714 Files: clang/include/clang/Basic/Attr.td clang/include/clang/Sema/Sema.h clang/lib/Sema/SemaStmt.cpp clang/test/SemaCXX/attr-musttail.cpp
Index: clang/test/SemaCXX/attr-musttail.cpp =================================================================== --- clang/test/SemaCXX/attr-musttail.cpp +++ clang/test/SemaCXX/attr-musttail.cpp @@ -6,6 +6,7 @@ [[clang::musttail(1, 2)]] return ReturnsInt1(); // expected-error {{'musttail' attribute takes no arguments}} [[clang::musttail]] return 5; // expected-error {{'musttail' attribute requires that the return value is the result of a function call}} [[clang::musttail]] return ReturnsInt1(); + [[clang::nonportable_musttail]] return ReturnsInt1(); } void NoFunctionCall() { @@ -20,6 +21,11 @@ return NoParams(); // expected-error {{cannot perform a tail call to function 'NoParams' because its signature is incompatible with the calling function}} } +void TestParamArityMismatchNonPortable(int x) { + [[clang::nonportable_musttail]] + return NoParams(); +} + void LongParam(long x); // expected-note {{target function has type mismatch at 1st parameter (expected 'long' but has 'int')}} void TestParamTypeMismatch(int x) { [[clang::musttail]] // expected-note {{tail call required by 'musttail' attribute here}} @@ -267,3 +273,17 @@ void TestCallNonValue() { [[clang::musttail]] return ns; // expected-error {{unexpected namespace name 'ns': expected expression}} } + +struct Foo { + int foo(int) { return 0; } +}; + +struct Bar { + Foo foo; + int bar(int); +}; + +int Bar::bar(int x) { + [[clang::nonportable_musttail]] + return foo.foo(x); +} Index: clang/lib/Sema/SemaStmt.cpp =================================================================== --- clang/lib/Sema/SemaStmt.cpp +++ clang/lib/Sema/SemaStmt.cpp @@ -586,7 +586,7 @@ // attributes lands. for (const auto *A : Attrs) { if (A->getKind() == attr::MustTail) { - if (!checkAndRewriteMustTailAttr(SubStmt, *A)) { + if (!checkAndRewriteMustTailAttr(SubStmt, *cast<MustTailAttr>(A))) { return SubStmt; } setFunctionHasMustTail(); @@ -608,7 +608,7 @@ return SubStmt; } -bool Sema::checkAndRewriteMustTailAttr(Stmt *St, const Attr &MTA) { +bool Sema::checkAndRewriteMustTailAttr(Stmt *St, const MustTailAttr &MTA) { ReturnStmt *R = cast<ReturnStmt>(St); Expr *E = R->getRetValue(); @@ -633,7 +633,7 @@ return true; } -bool Sema::checkMustTailAttr(const Stmt *St, const Attr &MTA) { +bool Sema::checkMustTailAttr(const Stmt *St, const MustTailAttr &MTA) { assert(!CurContext->isDependentContext() && "musttail cannot be checked from a dependent context"); @@ -846,6 +846,9 @@ return true; }; + if (MTA.isNonPortableMustTail()) + return true; + PartialDiagnostic PD = PDiag(diag::note_musttail_mismatch); if (!CheckTypesMatch(CallerType, CalleeType, PD)) { if (const auto *ND = dyn_cast_or_null<NamedDecl>(CE->getCalleeDecl())) Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -12351,12 +12351,12 @@ /// issuing a diagnostic and returning false if not. In the success case, /// the statement is rewritten to remove implicit nodes from the return /// value. - bool checkAndRewriteMustTailAttr(Stmt *St, const Attr &MTA); + bool checkAndRewriteMustTailAttr(Stmt *St, const MustTailAttr &MTA); private: /// Check whether the given statement can have musttail applied to it, /// issuing a diagnostic and returning false if not. - bool checkMustTailAttr(const Stmt *St, const Attr &MTA); + bool checkMustTailAttr(const Stmt *St, const MustTailAttr &MTA); public: /// Check to see if a given expression could have '.c_str()' called on it. Index: clang/include/clang/Basic/Attr.td =================================================================== --- clang/include/clang/Basic/Attr.td +++ clang/include/clang/Basic/Attr.td @@ -1470,8 +1470,9 @@ } def MustTail : StmtAttr { - let Spellings = [Clang<"musttail">]; + let Spellings = [Clang<"musttail">, Clang<"nonportable_musttail">]; let Documentation = [MustTailDocs]; + let Accessors = [Accessor<"isNonPortableMustTail", [Clang<"nonportable_musttail">]>]; let Subjects = SubjectList<[ReturnStmt], ErrorDiag, "return statements">; }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits