rsmith added a comment. Functionally this looks good to me. I've suggested some minor cleanups and I understand you're doing some wordsmithing on the diagnostics; I think once those are complete this will be ready to land. Thank you!
================ Comment at: clang/lib/CodeGen/CGExpr.cpp:4828 ReturnValueSlot ReturnValue) { + SaveAndRestore<bool> SaveMustTail(InMustTailCallExpr, E == MustTailCall); + ---------------- haberman wrote: > rsmith wrote: > > The more I think about this, the more it makes me nervous: if any of the > > `Emit*CallExpr` functions below incidentally emit a call on the way to > > producing their results via the CGCall machinery, and do so without > > recursing through this function, that incidental call will be emitted as a > > tail call instead of the intended one. Specifically: > > > > -- I could imagine a block call involving multiple function calls, > > depending on the blocks ABI. > > -- I could imagine a member call performing a function call to convert from > > derived to virtual base in some ABIs. > > -- A CUDA kernel call in general involves calling a setup function before > > the actual function call happens (and it doesn't make sense for a CUDA > > kernel call to be a tail call anyway...) > > -- A call to a builtin can result in any number of function calls. > > -- If any expression in the function arguments emits a call without calling > > back into this function, we'll emit that call as a tail call instead of > > this one. Eg, `[[clang::musttail]] return f(dynamic_cast<T*>(p));` might > > emit the call to `__cxa_dynamic_cast` as the tail call instead of emitting > > the call to `f` as the tail call, depending on whether the CGCall machinery > > is used when emitting the `__cxa_dynamic_cast` call. > > > > Is it feasible to sink this check into the `CodeGenFunction::EmitCall` > > overload that takes a `CallExpr`, > > `CodeGenFunction::EmitCXXMemberOrOperatorCall`, and > > `CodeGenFunction::EmitCXXMemberPointerCallExpr`, after we've emitted the > > callee and call args? It looks like we might be able to check this > > immediately before calling the CGCall overload of `EmitCall`, so we could > > pass in the 'musttail' information as a flag or similar instead of using > > global state in the `CodeGenFunction` object; if so, it'd be much easier to > > be confident that we're applying the attribute to the right call. > Done. It's feeling like `IsMustTail`, `callOrInvoke`, and `Loc` might want to > get collapsed into an options struct, especially given the default parameters > on the first two. Maybe could do as a follow up? I agree, that sounds like a nice cleanup. Delaying this to a future change makes sense to me. ================ Comment at: clang/lib/Sema/SemaStmt.cpp:616 + + const auto *R = cast<const ReturnStmt>(St); + const Expr *Ex = R->getRetValue(); ---------------- You shouldn't need the `const` in the argument to `cast`, and we generally omit it; `cast` copies the pointer/referenceness and qualifiers from its argument anyway, and the explicit `const` in the type of `R` seems sufficient for readers. (I'm not even sure if `cast` intends to permit explicit qualfiiers here.) ================ Comment at: clang/lib/Sema/SemaStmt.cpp:664 + // Find caller function signature. + if (!CallerDecl || isa<CapturedDecl>(CurContext)) { + int ContextType; ---------------- I think this `isa<CapturedDecl>` check is redundant, because a `CapturedDecl` is not a `FunctionDecl`, so `CallerDecl` will always be null when `CurContext` is a `CapturedDecl`. ================ Comment at: clang/lib/Sema/SemaStmt.cpp:711 + if (CalleeQualType.isNull()) { + // The function callee is invalid and already triggered an error. + // Avoid compounding errors. ---------------- Even in invalid code we should never see a `CallExpr` whose callee has a null type; if `Sema` can't form an `Expr` that meets the normal expression invariants during error recovery, it doesn't build one at all. I think you can remove this `if`. ================ Comment at: clang/lib/Sema/SemaStmt.cpp:771 + if (!Context.hasSimilarType(A, B)) { + PD << Select << A << B; + return false; ---------------- Given that we don't care about differences in qualifiers, it might be clearer to not include them in the diagnostics. ================ Comment at: clang/test/CodeGenCXX/attr-musttail.cpp:212 +int TestNonCapturingLambda() { + auto lambda = []() { return 12; }; // expected-note {{target function is a member function of class 'const (lambda at /usr/local/google/home/haberman/code/llvm-project/clang/test/SemaCXX/attr-musttail.cpp:142:17)'}} + [[clang::musttail]] return (+lambda)(); ---------------- Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D99517/new/ https://reviews.llvm.org/D99517 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits