-
Notifications
You must be signed in to change notification settings - Fork 10.9k
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
Clang v15.0.2: crash #58207
Comments
@llvm/issue-subscribers-clang-frontend |
Reduced to struct channel {
consteval channel(const char* name) noexcept { }
};
consteval const char* make_channel_name(const char* name) { return name;}
channel rsx_log(make_channel_name("rsx_log"));
channel sys_log(make_channel_name("sys_log")); |
Assertion: clang++: /root/llvm-project/clang/lib/Sema/SemaExpr.cpp:17866:
void RemoveNestedImmediateInvocation(clang::Sema&, clang::Sema::ExpressionEvaluationContextRecord&, llvm::SmallVectorTemplateCommon<llvm::PointerIntPair<clang::ConstantExpr*, 1>, void>::reverse_iterator)::ComplexRemove::RemoveImmediateInvocation(clang::ConstantExpr*):
Assertion `It != IISet.rend() && "ConstantExpr marked IsImmediateInvocation should " "be present"' failed. Backtrace: Stack dump:
0. Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/clang++ -gdwarf-4 -g -o /app/output.s -mllvm --x86-asm-syntax=intel -S --gcc-toolchain=/opt/compiler-explorer/gcc-snapshot -fcolor-diagnostics -fno-crash-diagnostics -std=c++2b <source>
1. <eof> parser at end of file
#0 0x000056318d1625cf llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x40d25cf)
#1 0x000056318d16056c llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x40d056c)
#2 0x000056318d0ad248 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
#3 0x00007f3a77ef8420 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x14420)
#4 0x00007f3a779c500b raise (/lib/x86_64-linux-gnu/libc.so.6+0x4300b)
#5 0x00007f3a779a4859 abort (/lib/x86_64-linux-gnu/libc.so.6+0x22859)
#6 0x00007f3a779a4729 (/lib/x86_64-linux-gnu/libc.so.6+0x22729)
#7 0x00007f3a779b5fd6 (/lib/x86_64-linux-gnu/libc.so.6+0x33fd6)
#8 0x000056318fcb4255 (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6c24255)
#9 0x000056318fdd34f2 RemoveNestedImmediateInvocation(clang::Sema&, clang::Sema::ExpressionEvaluationContextRecord&, std::reverse_iterator<llvm::PointerIntPair<clang::ConstantExpr*, 1u, unsigned int, llvm::PointerLikeTypeTraits<clang::ConstantExpr*>, llvm::PointerIntPairInfo<clang::ConstantExpr*, 1u, llvm::PointerLikeTypeTraits<clang::ConstantExpr*>>>*>)::ComplexRemove::TransformInitializer(clang::Expr*, bool) SemaExpr.cpp:0:0
#10 0x000056318fdd375e clang::TreeTransform<RemoveNestedImmediateInvocation(clang::Sema&, clang::Sema::ExpressionEvaluationContextRecord&, std::reverse_iterator<llvm::PointerIntPair<clang::ConstantExpr*, 1u, unsigned int, llvm::PointerLikeTypeTraits<clang::ConstantExpr*>, llvm::PointerIntPairInfo<clang::ConstantExpr*, 1u, llvm::PointerLikeTypeTraits<clang::ConstantExpr*>>>*>)::ComplexRemove>::TransformExprs(clang::Expr* const*, unsigned int, bool, llvm::SmallVectorImpl<clang::Expr*>&, bool*) SemaExpr.cpp:0:0
#11 0x000056318fdd4a9e clang::TreeTransform<RemoveNestedImmediateInvocation(clang::Sema&, clang::Sema::ExpressionEvaluationContextRecord&, std::reverse_iterator<llvm::PointerIntPair<clang::ConstantExpr*, 1u, unsigned int, llvm::PointerLikeTypeTraits<clang::ConstantExpr*>, llvm::PointerIntPairInfo<clang::ConstantExpr*, 1u, llvm::PointerLikeTypeTraits<clang::ConstantExpr*>>>*>)::ComplexRemove>::TransformCXXConstructExpr(clang::CXXConstructExpr*) SemaExpr.cpp:0:0
#12 0x000056318fd45f28 clang::Sema::PopExpressionEvaluationContext() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6cb5f28)
#13 0x000056318f7f2a06 clang::ParseAST(clang::Sema&, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6762a06)
#14 0x000056318e4e66c8 clang::CodeGenAction::ExecuteAction() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x54566c8)
#15 0x000056318dd50db9 clang::FrontendAction::Execute() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4cc0db9)
#16 0x000056318dcd656e clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4c4656e)
#17 0x000056318de38443 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4da8443)
#18 0x000056318a5e05cd cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x15505cd)
#19 0x000056318a5dc6e7 ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&) driver.cpp:0:0
#20 0x000056318db3c4d9 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const::'lambda'()>(long) Job.cpp:0:0
#21 0x000056318d0ad730 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x401d730)
#22 0x000056318db3cd8f clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const (.part.0) Job.cpp:0:0
#23 0x000056318db052ec clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4a752ec)
#24 0x000056318db05d6d clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4a75d6d)
#25 0x000056318db0ef3c clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4a7ef3c)
#26 0x000056318a5ded32 clang_main(int, char**) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x154ed32)
#27 0x00007f3a779a6083 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24083)
#28 0x000056318a5d73ce _start (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x15473ce)
clang-17: error: clang frontend command failed with exit code 134 (use -v to see invocation)
Compiler returned: 134 |
This starts appearing after 1c55f05 ("Properly diagnose constant evaluation issues at TU scope") by @AaronBallman. It looks like this change is pretty minimal, but add a line |
I've been looking into this. Looks like when immediate invocations are handled, it it expected that if there was several immediate invocations they all belong to the same expression evaluation context, so the function call below: llvm-project/clang/lib/Sema/SemaExpr.cpp Line 17982 in 117db47
tries to remove subexpressions and fails to find one. It starts with a call to constructor of The thing is, during parsing of non local variable initializer a new evaluation context is pushed: llvm-project/clang/lib/Sema/SemaDeclCXX.cpp Line 17852 in 117db47
so the call to |
Great work, that makes sense, maybe I missing this but this does not happen if we comment out the What is the difference here? |
The thing is, we start "removing" expressions only if there is more than one of them. See: llvm-project/clang/lib/Sema/SemaExpr.cpp Line 17969 in 117db47
Once you comment |
Ooofda, so in 1c55f05, I added an expression evaluation context for the entire TU, which is why we now get the immediate invocation in different evaluation contexts. Ugh. Notionally, I think that was the correct approach, but I didn't realize I was introducing this issue where we then add declarations to different contexts. |
I wonder if one approach worth exploring is to only do this if the non-local variable is not at global scope; the evaluation context at TU scope should suffice now, shouldn't it? |
Static variables at function scope seems to have the same problem. It seems adding evaluation context at TU scope just revealed the problem that's been there for a while. https://godbolt.org/z/5eh998qdP |
I wonder if should just stop assuming that an immediate expression and its subexpression belong to the same evaluation context and remove the failed assertion. Clearly with non-local variables whose initializers are nested immediate invocations that is not the case. It seems that the "removal" which fails now only prevents double diagnosing for some cases (like checking if address of consteval function is taken outside of another consteval function, or checking that result of immediate invocation produces constexpr result). I actually can't figure out a case that would trigger such a diagnostic from subexpression of consteval initializer of global variable. |
I think that could be worth exploring -- it seems like that assumption is no longer true. However, we do need to be careful not to issue duplicate diagnostics, as well. Please tell me we have existing test coverage that breaks if you remove the assumption? ;-) |
I'm not seeing any tests failing, so we likely don't have tests that actually run into the situation with separate evaluation contexts. Hence the bug report, I guess. |
Oh no. :-( If we can't find any duplicate diagnostics generated by removing that check, it's possible that duplicates are filtered through some other means. CC @usx95, @ilya-biryukov, and @cor3ntin in case this rings any bells for others who've worked in this area recently. |
That is probably not the right way to fix it. I figured the test case which produces duplicate errors. BTW, it gives two errors even now without any changes due to separate evaluation contexts. See https://godbolt.org/z/r41E98nff . |
I posted https://reviews.llvm.org/D146234 as possible solution. |
@Fznamznon we have another case here: #61463 |
Seems to be the same thing. https://reviews.llvm.org/D146234 helps. |
Before this patch it was expected that if there was several immediate invocations they all belong to the same expression evaluation context. During parsing of non local variable initializer a new evaluation context is pushed, so code like this ``` namespace scope { struct channel { consteval channel(const char* name) noexcept { } }; consteval const char* make_channel_name(const char* name) { return name;} channel rsx_log(make_channel_name("rsx_log")); } ``` produced a nested immediate invocation whose subexpressions are attached to different expression evaluation contexts. The constructor call belongs to TU context and `make_channel_name` call to context of variable initializer. This patch removes this assumption and adds tracking of previously failed immediate invocations, so it is possible when handling an immediate invocation th check that its subexpressions from possibly another evaluation context contains errors and not produce duplicate diagnostics. Fixes llvm#58207 Reviewed By: aaron.ballman, shafik Differential Revision: https://reviews.llvm.org/D146234
Merge commit a5e1a93ea10f from llvm-project (by Mariya Podchishchaeva): [clang] Fix crash when handling nested immediate invocations Before this patch it was expected that if there was several immediate invocations they all belong to the same expression evaluation context. During parsing of non local variable initializer a new evaluation context is pushed, so code like this ``` namespace scope { struct channel { consteval channel(const char* name) noexcept { } }; consteval const char* make_channel_name(const char* name) { return name;} channel rsx_log(make_channel_name("rsx_log")); } ``` produced a nested immediate invocation whose subexpressions are attached to different expression evaluation contexts. The constructor call belongs to TU context and `make_channel_name` call to context of variable initializer. This patch removes this assumption and adds tracking of previously failed immediate invocations, so it is possible when handling an immediate invocation th check that its subexpressions from possibly another evaluation context contains errors and not produce duplicate diagnostics. Fixes llvm/llvm-project#58207 Reviewed By: aaron.ballman, shafik Differential Revision: https://reviews.llvm.org/D146234 PR: 269489 MFC after: 3 days
Merge commit a5e1a93ea10f from llvm-project (by Mariya Podchishchaeva): [clang] Fix crash when handling nested immediate invocations Before this patch it was expected that if there was several immediate invocations they all belong to the same expression evaluation context. During parsing of non local variable initializer a new evaluation context is pushed, so code like this ``` namespace scope { struct channel { consteval channel(const char* name) noexcept { } }; consteval const char* make_channel_name(const char* name) { return name;} channel rsx_log(make_channel_name("rsx_log")); } ``` produced a nested immediate invocation whose subexpressions are attached to different expression evaluation contexts. The constructor call belongs to TU context and `make_channel_name` call to context of variable initializer. This patch removes this assumption and adds tracking of previously failed immediate invocations, so it is possible when handling an immediate invocation th check that its subexpressions from possibly another evaluation context contains errors and not produce duplicate diagnostics. Fixes llvm/llvm-project#58207 Reviewed By: aaron.ballman, shafik Differential Revision: https://reviews.llvm.org/D146234 PR: 269489 MFC after: 3 days (cherry picked from commit 56f2446)
Merge commit a5e1a93ea10f from llvm-project (by Mariya Podchishchaeva): [clang] Fix crash when handling nested immediate invocations Before this patch it was expected that if there was several immediate invocations they all belong to the same expression evaluation context. During parsing of non local variable initializer a new evaluation context is pushed, so code like this ``` namespace scope { struct channel { consteval channel(const char* name) noexcept { } }; consteval const char* make_channel_name(const char* name) { return name;} channel rsx_log(make_channel_name("rsx_log")); } ``` produced a nested immediate invocation whose subexpressions are attached to different expression evaluation contexts. The constructor call belongs to TU context and `make_channel_name` call to context of variable initializer. This patch removes this assumption and adds tracking of previously failed immediate invocations, so it is possible when handling an immediate invocation th check that its subexpressions from possibly another evaluation context contains errors and not produce duplicate diagnostics. Fixes llvm/llvm-project#58207 Reviewed By: aaron.ballman, shafik Differential Revision: https://reviews.llvm.org/D146234 PR: 269489 MFC after: 3 days (cherry picked from commit 56f2446)
/cherry-pick a5e1a93 |
Failed to cherry-pick: a5e1a93 https://github.com/llvm/llvm-project/actions/runs/5026430589 Please manually backport the fix and push it to your github fork. Once this is done, please add a comment like this:
|
Before this patch it was expected that if there was several immediate invocations they all belong to the same expression evaluation context. During parsing of non local variable initializer a new evaluation context is pushed, so code like this ``` namespace scope { struct channel { consteval channel(const char* name) noexcept { } }; consteval const char* make_channel_name(const char* name) { return name;} channel rsx_log(make_channel_name("rsx_log")); } ``` produced a nested immediate invocation whose subexpressions are attached to different expression evaluation contexts. The constructor call belongs to TU context and `make_channel_name` call to context of variable initializer. This patch removes this assumption and adds tracking of previously failed immediate invocations, so it is possible when handling an immediate invocation th check that its subexpressions from possibly another evaluation context contains errors and not produce duplicate diagnostics. Fixes llvm#58207 Reviewed By: aaron.ballman, shafik Differential Revision: https://reviews.llvm.org/D146234 (cherry picked from commit a5e1a93)
/branch ormris/llvm-project/release/16.x |
Failed to create pull request for release/16.x https://github.com/llvm/llvm-project/actions/runs/5063148022 |
Before this patch it was expected that if there was several immediate invocations they all belong to the same expression evaluation context. During parsing of non local variable initializer a new evaluation context is pushed, so code like this ``` namespace scope { struct channel { consteval channel(const char* name) noexcept { } }; consteval const char* make_channel_name(const char* name) { return name;} channel rsx_log(make_channel_name("rsx_log")); } ``` produced a nested immediate invocation whose subexpressions are attached to different expression evaluation contexts. The constructor call belongs to TU context and `make_channel_name` call to context of variable initializer. This patch removes this assumption and adds tracking of previously failed immediate invocations, so it is possible when handling an immediate invocation th check that its subexpressions from possibly another evaluation context contains errors and not produce duplicate diagnostics. Fixes llvm#58207 Reviewed By: aaron.ballman, shafik Differential Revision: https://reviews.llvm.org/D146234 (cherry picked from commit a5e1a93)
/branch ormris/llvm-project/pick/release/16.x |
/pull-request llvm/llvm-project-release-prs#456 |
@erichkeane What do you think about backporting this? |
I believe there ended up being additional fallout from this, right @Fznamznon ? So we couldn't get away with just cherry-picking this, we'd need at least 1 or 2 follow-up patches. Additionally while this does seem to be a regression, this is a C++20 only feature, and I believe we consider all of C++20 to be experimental for Clang 16, so I don't believe it meets the cherry-pick criteria for 16. |
No, I don't think so. Hope I didn't forget anything. https://reviews.llvm.org/D146234 turned out pretty self-contained. Though there was several other serious |
Thanks! Then @tstellar : this is a low-risk patch, so this I would think backporting would be acceptable. I think the motivation isn't huge (since C++20, particularly consteval/concepts support is experimental in Clang16) . |
Before this patch it was expected that if there was several immediate invocations they all belong to the same expression evaluation context. During parsing of non local variable initializer a new evaluation context is pushed, so code like this ``` namespace scope { struct channel { consteval channel(const char* name) noexcept { } }; consteval const char* make_channel_name(const char* name) { return name;} channel rsx_log(make_channel_name("rsx_log")); } ``` produced a nested immediate invocation whose subexpressions are attached to different expression evaluation contexts. The constructor call belongs to TU context and `make_channel_name` call to context of variable initializer. This patch removes this assumption and adds tracking of previously failed immediate invocations, so it is possible when handling an immediate invocation th check that its subexpressions from possibly another evaluation context contains errors and not produce duplicate diagnostics. Fixes llvm/llvm-project#58207 Reviewed By: aaron.ballman, shafik Differential Revision: https://reviews.llvm.org/D146234 (cherry picked from commit a5e1a93)
Merge commit a5e1a93ea10f from llvm-project (by Mariya Podchishchaeva): [clang] Fix crash when handling nested immediate invocations Before this patch it was expected that if there was several immediate invocations they all belong to the same expression evaluation context. During parsing of non local variable initializer a new evaluation context is pushed, so code like this ``` namespace scope { struct channel { consteval channel(const char* name) noexcept { } }; consteval const char* make_channel_name(const char* name) { return name;} channel rsx_log(make_channel_name("rsx_log")); } ``` produced a nested immediate invocation whose subexpressions are attached to different expression evaluation contexts. The constructor call belongs to TU context and `make_channel_name` call to context of variable initializer. This patch removes this assumption and adds tracking of previously failed immediate invocations, so it is possible when handling an immediate invocation th check that its subexpressions from possibly another evaluation context contains errors and not produce duplicate diagnostics. Fixes llvm/llvm-project#58207 Reviewed By: aaron.ballman, shafik Differential Revision: https://reviews.llvm.org/D146234 PR: 269489 MFC after: 3 days
Merge commit a5e1a93ea10f from llvm-project (by Mariya Podchishchaeva): [clang] Fix crash when handling nested immediate invocations Before this patch it was expected that if there was several immediate invocations they all belong to the same expression evaluation context. During parsing of non local variable initializer a new evaluation context is pushed, so code like this ``` namespace scope { struct channel { consteval channel(const char* name) noexcept { } }; consteval const char* make_channel_name(const char* name) { return name;} channel rsx_log(make_channel_name("rsx_log")); } ``` produced a nested immediate invocation whose subexpressions are attached to different expression evaluation contexts. The constructor call belongs to TU context and `make_channel_name` call to context of variable initializer. This patch removes this assumption and adds tracking of previously failed immediate invocations, so it is possible when handling an immediate invocation th check that its subexpressions from possibly another evaluation context contains errors and not produce duplicate diagnostics. Fixes llvm/llvm-project#58207 Reviewed By: aaron.ballman, shafik Differential Revision: https://reviews.llvm.org/D146234 PR: 269489 MFC after: 3 days (cherry picked from commit 56f2446575c78d962b6dda5e3310bec078622f3d)
Before this patch it was expected that if there was several immediate invocations they all belong to the same expression evaluation context. During parsing of non local variable initializer a new evaluation context is pushed, so code like this ``` namespace scope { struct channel { consteval channel(const char* name) noexcept { } }; consteval const char* make_channel_name(const char* name) { return name;} channel rsx_log(make_channel_name("rsx_log")); } ``` produced a nested immediate invocation whose subexpressions are attached to different expression evaluation contexts. The constructor call belongs to TU context and `make_channel_name` call to context of variable initializer. This patch removes this assumption and adds tracking of previously failed immediate invocations, so it is possible when handling an immediate invocation th check that its subexpressions from possibly another evaluation context contains errors and not produce duplicate diagnostics. Fixes llvm#58207 Reviewed By: aaron.ballman, shafik Differential Revision: https://reviews.llvm.org/D146234
Clang v15.0.2 seems to fail to compile rpcs3 ( https://github.com/RPCS3/rpcs3 ):
I wish I could give you a small sample but all I can give you are those 5MB preprocessed sources:
cache_utils-93deb0..zip
Clang15 seems to compile all the submodules(including llvm14 itself) just fine but fails on rpcs3 itself.
Of note is that Rpcs3 uses C++20 extensively.
The text was updated successfully, but these errors were encountered: