This is an archive of the discontinued LLVM Phabricator instance.

Fix crash with lambda and variadic template
ClosedPublic

Authored by rtrieu on Dec 15 2022, 6:43 PM.

Details

Summary

Inside Sema::tryCaptureVariable, there is an unconditional cast from a FunctionScopeInfo to a CapturingScopeInfo. With a mixture of lambdas and variadic template, we can arrive at this point with a FunctionScopeInfo that is not a CapturingScopeInfo. This is the simple fix of bailing out early with a default return value.

This fixes https://github.com/llvm/llvm-project/issues/56071 plus another test case reduction I found.

Diff Detail

Event Timeline

rtrieu created this revision.Dec 15 2022, 6:43 PM
Herald added a project: Restricted Project. · View Herald TranscriptDec 15 2022, 6:43 PM
rtrieu requested review of this revision.Dec 15 2022, 6:43 PM
rtrieu edited the summary of this revision. (Show Details)Dec 15 2022, 6:56 PM
rtrieu added a reviewer: aaron.ballman.
asbirlea accepted this revision.Jan 3 2023, 10:34 AM
This revision is now accepted and ready to land.Jan 3 2023, 10:34 AM

Adding additional reviewers for some additional perspective (perhaps my concerns are unfounded).

The changes should also have a release note about the fix.

clang/lib/Sema/SemaExpr.cpp
18875–18876

I'm not certain whether this is indicative of a deeper issue where we expect to get a capturing scope and we're not, but the early return seems surprising. I would have guessed that we'd want to continue so that we loop around again and continue to try to capture the variable.

cor3ntin added inline comments.Jan 3 2023, 12:18 PM
clang/lib/Sema/SemaExpr.cpp
18875–18876

Yes, i think there is something fishy here, and I am uncertain this is the right fix.

Either we are not currently in a lambda and if (VarDC == DC) return true; would prevent us from continuing, or there should only ever be lambda scopes between us and the variable declaration point.

Note that in either tests, the lambda don't capture anything.

My guess is that either:

  • We are trying to capture something when we should not - unevaluated lambdas can't have captures. In which case bailing early in unevaluated scope may be a cleaner fix
  • We are trying to capture in the the wrong context (ie we should do sdomethink like ActOnReenterFunctionContext but that would also be suspicious)

I think continuing would be wrong too. captures cannot skip a capturing scope.

Gentle ping. Can you propose an alternate patch to fix this crash? The github issue is 6 months old and similar crashes are reported due to this.

rtrieu added inline comments.Jan 13 2023, 6:20 PM
clang/lib/Sema/SemaExpr.cpp
18875–18876

I've been trying look into this more. From my understanding, FunctionScopeInfo FSI should correspond to DeclContext DC. When the crash happens, DC->dumpAsDecl() shows that the DeclContext is for a lambda (specifically, inner_lambda), but FSI->Kind evaluates to FunctionScopeInfo::SK_Function. I think this means that a function scope was never popped off FunctionScopes and replaced with a lambda scope.

shafik added a subscriber: shafik.Jan 19 2023, 4:00 PM

It looks like this bug may also be related: https://github.com/llvm/llvm-project/issues/60155

Re-ping to current reviewers. Any thoughts on the above @cor3ntin? Is there someone who you recommend look into this issue?

ayzhao added a subscriber: ayzhao.Jan 30 2023, 2:59 PM
ayzhao added inline comments.Feb 2 2023, 5:04 PM
clang/lib/Sema/SemaExpr.cpp
18875–18876

I took a look at this and it appears that in test2, in the following lines from inner_function():

char c;
[](auto param) -> decltype(c) { return param; }(0);

we try to capture char c because of the decltype.

I'm not entirely sure what the behavior is here - if we remove the template parameter from inner_function(), this function still tries to capture char c, and yet it FSI is always a CapturingScopeInfo.

It looks like we might have another similar bug: https://github.com/llvm/llvm-project/issues/61589

@cor3ntin is this still relevant? It looks like the test cases don't crash: https://godbolt.org/z/o3Y9req17

Nope, the "deeper issue" seemed to have been fixed in the 17 cycle. But maybe we could keep the tests anyway?

Keeping the tests seems reasonable, please do so!

@cor3ntin can you do a new PR on github w/ just the tests or alternatively land the tests w/o the rest of the patch?

cor3ntin closed this revision.Sep 28 2023, 8:59 AM

I've added the tests to clang.
Thanks a lot of finding these tests cases and the work you did on this PR!