-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[Clang] Skip past code generation for unevaluated lambdas #124572
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
As suggested by Corentin, this is taken from llvm#122423 (comment)
@llvm/pr-subscribers-clang Author: Younan Zhang (zyn0217) ChangesThis is taken from #122423 (comment) as suggested by Corentin. Fixes #82926 Full diff: https://github.com/llvm/llvm-project/pull/124572.diff 3 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f75c726e2751cf..7bb33d6b44d4ee 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -966,6 +966,7 @@ Bug Fixes to C++ Support
constraints are applied. (#GH122134)
- Fixed canonicalization of pack indexing types - Clang did not always recognized identical pack indexing. (#GH123033)
- Fixed a nested lambda substitution issue for constraint evaluation. (#GH123441)
+- Fixed some crashes involving unevaluated lambdas during code generation. (#GH82926)
Bug Fixes to AST Handling
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 6a2331e59477a2..6a55dbd98b0b4d 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -5297,8 +5297,24 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
savedContext.pop();
}
- DeclGroupRef DG(Function);
- Consumer.HandleTopLevelDecl(DG);
+ // We never need to emit the code for a lambda in unevaluated context.
+ // We also can't mangle a lambda in the require clause of a function template
+ // during constraint checking as the MSI ABI would need to mangle the (not yet
+ // specialized) enclosing declaration
+ // FIXME: Should we try to skip this for non-lambda functions too?
+ bool ShouldSkipCG = [&] {
+ auto *RD = dyn_cast<CXXRecordDecl>(Function->getParent());
+ if (!RD || !RD->isLambda())
+ return false;
+
+ return llvm::any_of(ExprEvalContexts, [](auto &Context) {
+ return Context.isUnevaluated() || Context.isImmediateFunctionContext();
+ });
+ }();
+ if (!ShouldSkipCG) {
+ DeclGroupRef DG(Function);
+ Consumer.HandleTopLevelDecl(DG);
+ }
// This class may have local implicit instantiations that need to be
// instantiation within this scope.
diff --git a/clang/test/CodeGenCXX/unevaluated-lambdas.cpp b/clang/test/CodeGenCXX/unevaluated-lambdas.cpp
new file mode 100644
index 00000000000000..5bdf8294dc1fc3
--- /dev/null
+++ b/clang/test/CodeGenCXX/unevaluated-lambdas.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -std=c++2b -emit-llvm %s -o - | FileCheck %s -dump-input=always
+
+namespace GH82926 {
+
+template<class Tp>
+using simd_vector = Tp;
+
+template<class VecT>
+using simd_vector_underlying_type_t
+ = decltype([]<class Tp>(simd_vector<Tp>) {}(VecT {}), 1);
+
+template<class VecT>
+void temp() {
+ // CHECK: call void @_ZZN7GH829264tempIcEEvvENKUliE_clEi
+ [](simd_vector_underlying_type_t<VecT>) {}(42);
+}
+
+void call() {
+ temp<simd_vector<char>>();
+}
+
+} // namespace GH82926
+
+namespace GH111058 {
+
+// FIXME: This still crashes because the unevaluated lambda as an argument
+// is also supposed to skipping codegen in Sema::InstantiateFunctionDefinition().
+// auto eat(auto) {}
+
+void foo() {
+ // [] -> decltype(eat([] {})) {};
+
+ // CHECK: call void @"_ZZN8GH1110583fooEvENK3$_0clEv"
+ [] -> decltype([](auto){}(1)) {}();
+}
+
+} // namespace GH111058
|
Fundamentally the issue is that we emit codegen decl for all function instantiations (and presumably that gets ignored for decls that are not ODR-used). I'm not sure this is the best fix but neither @zyn0217 nor myself can come up with a better idea. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would expect that we should instead be marking this function not isUsed
(or isReferenced
? ) to determine whether this should be emitted, and I would expect that to get caught in our existing infrastructure for that.
And we do. But mangling happens before we make that decision |
Which call in EmitGlobal is the one that calls it? I would expect that either of the two (not hte annotations one for obvious reasons) should be able to filter it THERE instead. Do we perhaps just mangle 'too early'? |
We use the mangle name as key to decide whether something was already used haha
But really i don't think we should even get there from an unevaluated context |
Yeah, I agree that we shouldn't get to that point on the decision. That said, I THINK the decision should be made in CodeGen, not Sema? Perhaps @efriedma-quic has comments? |
See also discussion on #117845. I think it makes some sense to add a way for CodeGen to query whether a given declaration is impossible to emit. I suggested in that discussion that it could be a kind of linkage. I'd prefer not to mess with the way DeferredDecls works for decls that aren't impossible to emit, if possible. I don't think "odr-used" is a useful concept here; I think it's possible for an decl to be odr-used even if there isn't a mangling. Alternatively, we could just invent a mangling here, like we did for #117845. |
@efriedma-quic So we would track that a function that was declared in an unevaluated context has "unevaluated linkage" (or really, a bit that said it was declared in unevaluated context), and skip them in Seems reasonable (and I prefer that to inventing mangling, in think) |
Looking a bit more, I'm not sure I buy the premise that we don't need to mangle lambdas written in unevaluated contexts. Consider the following related example:
Both gcc and MSVC seem perfectly happy with this. |
Some of these details need to end up in the summary before this is landed. |
This is taken from #122423 (comment) as suggested by Corentin.
Fixes #82926