haberman added a comment.

I added tests for all the cases you mentioned. PTAL.



================
Comment at: clang/lib/CodeGen/CGCall.cpp:5315-5317
+    // TODO(haberman): insert checks/assertions to verify that this early exit
+    // is safe. We tried to verify this in Sema but we should double-check
+    // here.
----------------
rsmith wrote:
> haberman wrote:
> > aaron.ballman wrote:
> > > Are you planning to handle this TODO in the patch? If not, can you switch 
> > > to a FIXME without a name associated with it?
> > I am interested in feedback on the best way to proceed here.
> > 
> >   - Is my assessment correct that we should have an assertion that 
> > validates this?
> >   - Is such an assertion reasonably feasible to implement?
> >   - Is it ok to defer with FIXME, or should I try to fix it in this patch?
> > 
> > I've changed it to a FIXME for now.
> Yes, I think we should validate this by an assertion if we can. We can check 
> this by walking the cleanup scope stack (walk from `CurrentCleanupScopeDepth` 
> to `EHScopeStack::stable_end()`) and making sure that there is no 
> "problematic" enclosing cleanup scope. Here, "problematic" would mean any 
> scope other than an `EHCleanupScope` containing only `CallLifetimeEnd` 
> cleanups.
> 
> Looking at the kinds of cleanups that we might encounter here, I think there 
> may be a few more things that Sema needs to check in order to not get in the 
> way of exception handling. In particular, I think we should reject if the 
> callee is potentially-throwing and the musttail call is inside a try block or 
> a function that's either noexcept or has a dynamic exception specification.
> 
> Oh, also, we should disallow musttail calls inside statement expressions, in 
> order to defend against cleanups that exist transiently within an expression.
I'm having trouble implementing the check because there doesn't appear to be 
any discriminator in `EHScopeStack::Cleanup` that will let you test if it is a 
`CallLifetimeEnd`. (The actual code just does virtual dispatch through 
`EHScopeStack::Cleanup::Emit()`.

I temporarily implemented this by adding an extra virtual function to act as 
discriminator. The check fires if a VLA is in scope:

```
int Func14(int x) {
  int vla[x];
  [[clang::musttail]] return Bar(x);
}
```

Do we need to forbid VLAs or do I need to refine the check?

It appears that `JumpDiagnostics.cpp` is already diagnosing statement 
expressions and `try`. However I could not get testing to work. I tried adding 
a test with `try`  but even with `-fexceptions` I am getting:

```
cannot use 'try' with exceptions disabled
```


================
Comment at: clang/lib/CodeGen/CGExpr.cpp:4828
                                      ReturnValueSlot ReturnValue) {
+  SaveAndRestore<bool> SaveMustTail(InMustTailCallExpr, E == MustTailCall);
+
----------------
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?


================
Comment at: clang/test/CodeGen/attr-musttail.cpp:72
+
+// CHECK: musttail call void @_Z11ReturnsVoidv()
+
----------------
rsmith wrote:
> For completeness, can we also get a `CHECK-NEXT: ret void` here too?
I turned on LLVM verification via `opt` so I think this should get verified by 
the IR verifier. Is that sufficient?


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

Reply via email to