Skip to content
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] [C++] Anonymous unions can cause crash when the name of their type escapes #90751

Open
MitalAshok opened this issue May 1, 2024 · 2 comments
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" confirmed Verified by a second party crash Prefer [crash-on-valid] or [crash-on-invalid]

Comments

@MitalAshok
Copy link
Contributor

MitalAshok commented May 1, 2024

Small example https://godbolt.org/z/eEYzYxd9x:

void g();

template<typename T>
struct Capture;

template<typename T>
struct Capture<T*>  {
    friend void g() {
        &T::a;
    }
};

struct X;

void f() {
    union {
        int a = sizeof(Capture<decltype(this)>);
    };
    g();
}
clang++: /llvm-project/llvm/include/llvm/Support/Casting.h:578: decltype(auto) llvm::cast(From *) [To = clang::RecordDecl, From = clang::DeclContext]: Assertion `isa<To>(Val) && "cast<Ty>() argument of incompatible type!"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.      Program arguments: /cmake-build-debug/bin/clang++ -fsyntax-only -std=c++11 anon_escape.cpp
1.      <eof> parser at end of file
2.      anon_escape.cpp:8:17: instantiating function definition 'g'
 #0 0x000055f3b6a3740d llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) /llvm-project/llvm/lib/Support/Unix/Signals.inc:723:11
 #1 0x000055f3b6a378fb PrintStackTraceSignalHandler(void*) /llvm-project/llvm/lib/Support/Unix/Signals.inc:798:1
 #2 0x000055f3b6a35966 llvm::sys::RunSignalHandlers() /llvm-project/llvm/lib/Support/Signals.cpp:105:5
 #3 0x000055f3b6a36c8e llvm::sys::CleanupOnSignal(unsigned long) /llvm-project/llvm/lib/Support/Unix/Signals.inc:368:1
 #4 0x000055f3b6963b64 (anonymous namespace)::CrashRecoveryContextImpl::HandleCrash(int, unsigned long) /llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp:0:7
 #5 0x000055f3b6963f02 CrashRecoverySignalHandler(int) /llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp:391:1
 #6 0x00007fd03b058520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #7 0x00007fd03b0ac9fc __pthread_kill_implementation ./nptl/./nptl/pthread_kill.c:44:76
 #8 0x00007fd03b0ac9fc __pthread_kill_internal ./nptl/./nptl/pthread_kill.c:78:10
 #9 0x00007fd03b0ac9fc pthread_kill ./nptl/./nptl/pthread_kill.c:89:10
#10 0x00007fd03b058476 gsignal ./signal/../sysdeps/posix/raise.c:27:6
#11 0x00007fd03b03e7f3 abort ./stdlib/./stdlib/abort.c:81:7
#12 0x00007fd03b03e71b _nl_load_domain ./intl/./intl/loadmsgcat.c:1177:9
#13 0x00007fd03b04fe96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
#14 0x000055f3bb9c6948 decltype(auto) llvm::cast<clang::RecordDecl, clang::DeclContext>(clang::DeclContext*) /llvm-project/llvm/include/llvm/Support/Casting.h:579:10
#15 0x000055f3bbf06ea5 clang::Sema::CheckAddressOfOperand(clang::ActionResult<clang::Expr*, true>&, clang::SourceLocation) /llvm-project/clang/lib/Sema/SemaExpr.cpp:14654:18
#16 0x000055f3bbf0beb4 clang::Sema::CreateBuiltinUnaryOp(clang::SourceLocation, clang::UnaryOperatorKind, clang::Expr*, bool) /llvm-project/clang/lib/Sema/SemaExpr.cpp:15798:18
#17 0x000055f3bbedc6c6 clang::Sema::BuildUnaryOp(clang::Scope*, clang::SourceLocation, clang::UnaryOperatorKind, clang::Expr*, bool) /llvm-project/clang/lib/Sema/SemaExpr.cpp:16073:10
#18 0x000055f3bcb55a1e clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::RebuildUnaryOperator(clang::SourceLocation, clang::UnaryOperatorKind, clang::Expr*) /llvm-project/clang/lib/Sema/TreeTransform.h:2716:22
#19 0x000055f3bcb44261 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformUnaryOperator(clang::UnaryOperator*) /llvm-project/clang/lib/Sema/TreeTransform.h:11562:23
#20 0x000055f3bcb3b672 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformExpr(clang::Expr*) /cmake-build-debug/tools/clang/include/clang/AST/StmtNodes.inc:50:1
#21 0x000055f3bcb3a667 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformStmt(clang::Stmt*, clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::StmtDiscardKind) /llvm-project/clang/lib/Sema/TreeTransform.h:4093:35
#22 0x000055f3bcb579d6 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformCompoundStmt(clang::CompoundStmt*, bool) /llvm-project/clang/lib/Sema/TreeTransform.h:7766:38
#23 0x000055f3bcb87b97 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformCompoundStmt(clang::CompoundStmt*) /llvm-project/clang/lib/Sema/TreeTransform.h:7748:23
#24 0x000055f3bcb3a4df clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformStmt(clang::Stmt*, clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::StmtDiscardKind) /cmake-build-debug/tools/clang/include/clang/AST/StmtNodes.inc:1526:1
#25 0x000055f3bcb39093 clang::Sema::SubstStmt(clang::Stmt*, clang::MultiLevelTemplateArgumentList const&) /llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp:4365:23
#26 0x000055f3bcbd0645 clang::Sema::InstantiateFunctionDefinition(clang::SourceLocation, clang::FunctionDecl*, bool, bool, bool) /llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp:5239:14
#27 0x000055f3bcbd3015 clang::Sema::PerformPendingInstantiations(bool) /llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp:6512:13
#28 0x000055f3bb586515 clang::Sema::ActOnEndOfTranslationUnitFragment(clang::Sema::TUFragmentKind) /llvm-project/clang/lib/Sema/Sema.cpp:1099:3
#29 0x000055f3bb586930 clang::Sema::ActOnEndOfTranslationUnit() /llvm-project/clang/lib/Sema/Sema.cpp:1134:5
#30 0x000055f3bb3cfc57 clang::Parser::ParseTopLevelDecl(clang::OpaquePtr<clang::DeclGroupRef>&, clang::Sema::ModuleImportState&) /llvm-project/clang/lib/Parse/Parser.cpp:731:5
#31 0x000055f3bb3caaed clang::ParseAST(clang::Sema&, bool, bool) /llvm-project/clang/lib/Parse/ParseAST.cpp:163:16
#32 0x000055f3b7f1f8d1 clang::ASTFrontendAction::ExecuteAction() /llvm-project/clang/lib/Frontend/FrontendAction.cpp:1194:1
#33 0x000055f3b7f1f2ec clang::FrontendAction::Execute() /llvm-project/clang/lib/Frontend/FrontendAction.cpp:1082:7
#34 0x000055f3b7e3e69a clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) /llvm-project/clang/lib/Frontend/CompilerInstance.cpp:1062:23
#35 0x000055f3b80f7a3e clang::ExecuteCompilerInvocation(clang::CompilerInstance*) /llvm-project/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:280:8
#36 0x000055f3b4ba3351 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) /llvm-project/clang/tools/driver/cc1_main.cpp:232:13
#37 0x000055f3b4b95d72 ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) /llvm-project/clang/tools/driver/driver.cpp:215:5
#38 0x000055f3b4b9681d clang_main(int, char**, llvm::ToolContext const&)::$_0::operator()(llvm::SmallVectorImpl<char const*>&) const /llvm-project/clang/tools/driver/driver.cpp:355:7
#39 0x000055f3b4b967ed int llvm::function_ref<int (llvm::SmallVectorImpl<char const*>&)>::callback_fn<clang_main(int, char**, llvm::ToolContext const&)::$_0>(long, llvm::SmallVectorImpl<char const*>&) /llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:45:5
#40 0x000055f3b7cce2b1 llvm::function_ref<int (llvm::SmallVectorImpl<char const*>&)>::operator()(llvm::SmallVectorImpl<char const*>&) const /llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:68:5
#41 0x000055f3b7ccaf88 clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, bool*) const::$_1::operator()() const /llvm-project/clang/lib/Driver/Job.cpp:440:34
#42 0x000055f3b7ccaf55 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::$_1>(long) /llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:45:5
#43 0x000055f3b564bd99 llvm::function_ref<void ()>::operator()() const /llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:68:5
#44 0x000055f3b696397a llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) /llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp:427:3
#45 0x000055f3b7cca8eb clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, bool*) const /llvm-project/clang/lib/Driver/Job.cpp:440:7
#46 0x000055f3b7c6603f clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const /llvm-project/clang/lib/Driver/Compilation.cpp:199:15
#47 0x000055f3b7c66247 clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*> >&, bool) const /llvm-project/clang/lib/Driver/Compilation.cpp:253:13
#48 0x000055f3b7c80c92 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*> >&) /llvm-project/clang/lib/Driver/Driver.cpp:1926:7
#49 0x000055f3b4b9584b clang_main(int, char**, llvm::ToolContext const&) /llvm-project/clang/tools/driver/driver.cpp:391:9
#50 0x000055f3b4bc8405 main /cmake-build-debug/tools/clang/tools/driver/clang-driver.cpp:17:3
#51 0x00007fd03b03fd90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#52 0x00007fd03b03fe40 call_init ./csu/../csu/libc-start.c:128:20
#53 0x00007fd03b03fe40 __libc_start_main ./csu/../csu/libc-start.c:379:5
#54 0x000055f3b4b94565 _start (/cmake-build-debug/bin/clang+++0x5a04565)
clang++: error: clang frontend command failed with exit code 134 (use -v to see invocation)
clang version 19.0.0git (https://github.com/llvm/llvm-project.git 5df6f72a5d9c92bfd24aebdcb89938a8d4e9f7b3)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /cmake-build-debug/bin
Build config: +unoptimized, +assertions
clang++: note: diagnostic msg:
********************

PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clang++: note: diagnostic msg: /tmp/-7826fa.cpp
clang++: note: diagnostic msg: /tmp/-7826fa.sh
clang++: note: diagnostic msg:

********************

It seems like RecordDecl::isAnonymousStructOrUnion is sometimes used as "Is this an anonymous union (or GNU extension anonymous struct) inside of another class", when it's not guaranteed to be inside another class.

Making this comment wrong:

// For an anonymous struct or union, the copy and assignment special members
// will never be used, so skip the check. For an anonymous union declared at
// namespace scope, the constructor and destructor are used.
if (CSM != CXXSpecialMemberKind::DefaultConstructor &&
CSM != CXXSpecialMemberKind::Destructor && RD->isAnonymousStructOrUnion())
return false;

This function dubious:
static CXXRecordDecl *FindDeclaringClass(NamedDecl *D) {
DeclContext *DC = D->getDeclContext();
// This can only happen at top: enum decls only "publish" their
// immediate members.
if (isa<EnumDecl>(DC))
DC = cast<EnumDecl>(DC)->getDeclContext();
CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(DC);
while (DeclaringClass->isAnonymousStructOrUnion())
DeclaringClass = cast<CXXRecordDecl>(DeclaringClass->getDeclContext());
return DeclaringClass;
}

And this loop cause the above crash:
while (cast<RecordDecl>(Ctx)->isAnonymousStructOrUnion())
Ctx = Ctx->getParent();

It seems like this could be fixed by checking if the anonymous struct or union is ultimately a field of a named RecordDecl vs. a function-local/namespace-scope anonymous union

@github-actions github-actions bot added the clang Clang issues not falling into any other category label May 1, 2024
@EugeneZelenko EugeneZelenko added clang:frontend Language frontend issues, e.g. anything involving "Sema" crash Prefer [crash-on-valid] or [crash-on-invalid] and removed clang Clang issues not falling into any other category labels May 1, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented May 1, 2024

@llvm/issue-subscribers-clang-frontend

Author: Mital Ashok (MitalAshok)

Small example <https://godbolt.org/z/eEYzYxd9x>:
void g();

template&lt;typename T&gt;
struct Capture;

template&lt;typename T&gt;
struct Capture&lt;T*&gt;  {
    friend void g() {
        &amp;T::a;
    }
};

struct X;

void f() {
    union {
        int a = sizeof(Capture&lt;decltype(this)&gt;);
    };
    g();
}
clang++: /llvm-project/llvm/include/llvm/Support/Casting.h:578: decltype(auto) llvm::cast(From *) [To = clang::RecordDecl, From = clang::DeclContext]: Assertion `isa&lt;To&gt;(Val) &amp;&amp; "cast&lt;Ty&gt;() argument of incompatible type!"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.      Program arguments: /cmake-build-debug/bin/clang++ -fsyntax-only -std=c++11 anon_escape.cpp
1.      &lt;eof&gt; parser at end of file
2.      anon_escape.cpp:8:17: instantiating function definition 'g'
 #<!-- -->0 0x000055f3b6a3740d llvm::sys::PrintStackTrace(llvm::raw_ostream&amp;, int) /llvm-project/llvm/lib/Support/Unix/Signals.inc:723:11
 #<!-- -->1 0x000055f3b6a378fb PrintStackTraceSignalHandler(void*) /llvm-project/llvm/lib/Support/Unix/Signals.inc:798:1
 #<!-- -->2 0x000055f3b6a35966 llvm::sys::RunSignalHandlers() /llvm-project/llvm/lib/Support/Signals.cpp:105:5
 #<!-- -->3 0x000055f3b6a36c8e llvm::sys::CleanupOnSignal(unsigned long) /llvm-project/llvm/lib/Support/Unix/Signals.inc:368:1
 #<!-- -->4 0x000055f3b6963b64 (anonymous namespace)::CrashRecoveryContextImpl::HandleCrash(int, unsigned long) /llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp:0:7
 #<!-- -->5 0x000055f3b6963f02 CrashRecoverySignalHandler(int) /llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp:391:1
 #<!-- -->6 0x00007fd03b058520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #<!-- -->7 0x00007fd03b0ac9fc __pthread_kill_implementation ./nptl/./nptl/pthread_kill.c:44:76
 #<!-- -->8 0x00007fd03b0ac9fc __pthread_kill_internal ./nptl/./nptl/pthread_kill.c:78:10
 #<!-- -->9 0x00007fd03b0ac9fc pthread_kill ./nptl/./nptl/pthread_kill.c:89:10
#<!-- -->10 0x00007fd03b058476 gsignal ./signal/../sysdeps/posix/raise.c:27:6
#<!-- -->11 0x00007fd03b03e7f3 abort ./stdlib/./stdlib/abort.c:81:7
#<!-- -->12 0x00007fd03b03e71b _nl_load_domain ./intl/./intl/loadmsgcat.c:1177:9
#<!-- -->13 0x00007fd03b04fe96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
#<!-- -->14 0x000055f3bb9c6948 decltype(auto) llvm::cast&lt;clang::RecordDecl, clang::DeclContext&gt;(clang::DeclContext*) /llvm-project/llvm/include/llvm/Support/Casting.h:579:10
#<!-- -->15 0x000055f3bbf06ea5 clang::Sema::CheckAddressOfOperand(clang::ActionResult&lt;clang::Expr*, true&gt;&amp;, clang::SourceLocation) /llvm-project/clang/lib/Sema/SemaExpr.cpp:14654:18
#<!-- -->16 0x000055f3bbf0beb4 clang::Sema::CreateBuiltinUnaryOp(clang::SourceLocation, clang::UnaryOperatorKind, clang::Expr*, bool) /llvm-project/clang/lib/Sema/SemaExpr.cpp:15798:18
#<!-- -->17 0x000055f3bbedc6c6 clang::Sema::BuildUnaryOp(clang::Scope*, clang::SourceLocation, clang::UnaryOperatorKind, clang::Expr*, bool) /llvm-project/clang/lib/Sema/SemaExpr.cpp:16073:10
#<!-- -->18 0x000055f3bcb55a1e clang::TreeTransform&lt;(anonymous namespace)::TemplateInstantiator&gt;::RebuildUnaryOperator(clang::SourceLocation, clang::UnaryOperatorKind, clang::Expr*) /llvm-project/clang/lib/Sema/TreeTransform.h:2716:22
#<!-- -->19 0x000055f3bcb44261 clang::TreeTransform&lt;(anonymous namespace)::TemplateInstantiator&gt;::TransformUnaryOperator(clang::UnaryOperator*) /llvm-project/clang/lib/Sema/TreeTransform.h:11562:23
#<!-- -->20 0x000055f3bcb3b672 clang::TreeTransform&lt;(anonymous namespace)::TemplateInstantiator&gt;::TransformExpr(clang::Expr*) /cmake-build-debug/tools/clang/include/clang/AST/StmtNodes.inc:50:1
#<!-- -->21 0x000055f3bcb3a667 clang::TreeTransform&lt;(anonymous namespace)::TemplateInstantiator&gt;::TransformStmt(clang::Stmt*, clang::TreeTransform&lt;(anonymous namespace)::TemplateInstantiator&gt;::StmtDiscardKind) /llvm-project/clang/lib/Sema/TreeTransform.h:4093:35
#<!-- -->22 0x000055f3bcb579d6 clang::TreeTransform&lt;(anonymous namespace)::TemplateInstantiator&gt;::TransformCompoundStmt(clang::CompoundStmt*, bool) /llvm-project/clang/lib/Sema/TreeTransform.h:7766:38
#<!-- -->23 0x000055f3bcb87b97 clang::TreeTransform&lt;(anonymous namespace)::TemplateInstantiator&gt;::TransformCompoundStmt(clang::CompoundStmt*) /llvm-project/clang/lib/Sema/TreeTransform.h:7748:23
#<!-- -->24 0x000055f3bcb3a4df clang::TreeTransform&lt;(anonymous namespace)::TemplateInstantiator&gt;::TransformStmt(clang::Stmt*, clang::TreeTransform&lt;(anonymous namespace)::TemplateInstantiator&gt;::StmtDiscardKind) /cmake-build-debug/tools/clang/include/clang/AST/StmtNodes.inc:1526:1
#<!-- -->25 0x000055f3bcb39093 clang::Sema::SubstStmt(clang::Stmt*, clang::MultiLevelTemplateArgumentList const&amp;) /llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp:4365:23
#<!-- -->26 0x000055f3bcbd0645 clang::Sema::InstantiateFunctionDefinition(clang::SourceLocation, clang::FunctionDecl*, bool, bool, bool) /llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp:5239:14
#<!-- -->27 0x000055f3bcbd3015 clang::Sema::PerformPendingInstantiations(bool) /llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp:6512:13
#<!-- -->28 0x000055f3bb586515 clang::Sema::ActOnEndOfTranslationUnitFragment(clang::Sema::TUFragmentKind) /llvm-project/clang/lib/Sema/Sema.cpp:1099:3
#<!-- -->29 0x000055f3bb586930 clang::Sema::ActOnEndOfTranslationUnit() /llvm-project/clang/lib/Sema/Sema.cpp:1134:5
#<!-- -->30 0x000055f3bb3cfc57 clang::Parser::ParseTopLevelDecl(clang::OpaquePtr&lt;clang::DeclGroupRef&gt;&amp;, clang::Sema::ModuleImportState&amp;) /llvm-project/clang/lib/Parse/Parser.cpp:731:5
#<!-- -->31 0x000055f3bb3caaed clang::ParseAST(clang::Sema&amp;, bool, bool) /llvm-project/clang/lib/Parse/ParseAST.cpp:163:16
#<!-- -->32 0x000055f3b7f1f8d1 clang::ASTFrontendAction::ExecuteAction() /llvm-project/clang/lib/Frontend/FrontendAction.cpp:1194:1
#<!-- -->33 0x000055f3b7f1f2ec clang::FrontendAction::Execute() /llvm-project/clang/lib/Frontend/FrontendAction.cpp:1082:7
#<!-- -->34 0x000055f3b7e3e69a clang::CompilerInstance::ExecuteAction(clang::FrontendAction&amp;) /llvm-project/clang/lib/Frontend/CompilerInstance.cpp:1062:23
#<!-- -->35 0x000055f3b80f7a3e clang::ExecuteCompilerInvocation(clang::CompilerInstance*) /llvm-project/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:280:8
#<!-- -->36 0x000055f3b4ba3351 cc1_main(llvm::ArrayRef&lt;char const*&gt;, char const*, void*) /llvm-project/clang/tools/driver/cc1_main.cpp:232:13
#<!-- -->37 0x000055f3b4b95d72 ExecuteCC1Tool(llvm::SmallVectorImpl&lt;char const*&gt;&amp;, llvm::ToolContext const&amp;) /llvm-project/clang/tools/driver/driver.cpp:215:5
#<!-- -->38 0x000055f3b4b9681d clang_main(int, char**, llvm::ToolContext const&amp;)::$_0::operator()(llvm::SmallVectorImpl&lt;char const*&gt;&amp;) const /llvm-project/clang/tools/driver/driver.cpp:355:7
#<!-- -->39 0x000055f3b4b967ed int llvm::function_ref&lt;int (llvm::SmallVectorImpl&lt;char const*&gt;&amp;)&gt;::callback_fn&lt;clang_main(int, char**, llvm::ToolContext const&amp;)::$_0&gt;(long, llvm::SmallVectorImpl&lt;char const*&gt;&amp;) /llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:45:5
#<!-- -->40 0x000055f3b7cce2b1 llvm::function_ref&lt;int (llvm::SmallVectorImpl&lt;char const*&gt;&amp;)&gt;::operator()(llvm::SmallVectorImpl&lt;char const*&gt;&amp;) const /llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:68:5
#<!-- -->41 0x000055f3b7ccaf88 clang::driver::CC1Command::Execute(llvm::ArrayRef&lt;std::optional&lt;llvm::StringRef&gt; &gt;, std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt;*, bool*) const::$_1::operator()() const /llvm-project/clang/lib/Driver/Job.cpp:440:34
#<!-- -->42 0x000055f3b7ccaf55 void llvm::function_ref&lt;void ()&gt;::callback_fn&lt;clang::driver::CC1Command::Execute(llvm::ArrayRef&lt;std::optional&lt;llvm::StringRef&gt; &gt;, std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt;*, bool*) const::$_1&gt;(long) /llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:45:5
#<!-- -->43 0x000055f3b564bd99 llvm::function_ref&lt;void ()&gt;::operator()() const /llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:68:5
#<!-- -->44 0x000055f3b696397a llvm::CrashRecoveryContext::RunSafely(llvm::function_ref&lt;void ()&gt;) /llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp:427:3
#<!-- -->45 0x000055f3b7cca8eb clang::driver::CC1Command::Execute(llvm::ArrayRef&lt;std::optional&lt;llvm::StringRef&gt; &gt;, std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt;*, bool*) const /llvm-project/clang/lib/Driver/Job.cpp:440:7
#<!-- -->46 0x000055f3b7c6603f clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&amp;, clang::driver::Command const*&amp;, bool) const /llvm-project/clang/lib/Driver/Compilation.cpp:199:15
#<!-- -->47 0x000055f3b7c66247 clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&amp;, llvm::SmallVectorImpl&lt;std::pair&lt;int, clang::driver::Command const*&gt; &gt;&amp;, bool) const /llvm-project/clang/lib/Driver/Compilation.cpp:253:13
#<!-- -->48 0x000055f3b7c80c92 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&amp;, llvm::SmallVectorImpl&lt;std::pair&lt;int, clang::driver::Command const*&gt; &gt;&amp;) /llvm-project/clang/lib/Driver/Driver.cpp:1926:7
#<!-- -->49 0x000055f3b4b9584b clang_main(int, char**, llvm::ToolContext const&amp;) /llvm-project/clang/tools/driver/driver.cpp:391:9
#<!-- -->50 0x000055f3b4bc8405 main /cmake-build-debug/tools/clang/tools/driver/clang-driver.cpp:17:3
#<!-- -->51 0x00007fd03b03fd90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#<!-- -->52 0x00007fd03b03fe40 call_init ./csu/../csu/libc-start.c:128:20
#<!-- -->53 0x00007fd03b03fe40 __libc_start_main ./csu/../csu/libc-start.c:379:5
#<!-- -->54 0x000055f3b4b94565 _start (/cmake-build-debug/bin/clang+++0x5a04565)
clang++: error: clang frontend command failed with exit code 134 (use -v to see invocation)
clang version 19.0.0git (https://github.com/llvm/llvm-project.git 5df6f72a5d9c92bfd24aebdcb89938a8d4e9f7b3)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /cmake-build-debug/bin
Build config: +unoptimized, +assertions
clang++: note: diagnostic msg:
********************

PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clang++: note: diagnostic msg: /tmp/-7826fa.cpp
clang++: note: diagnostic msg: /tmp/-7826fa.sh
clang++: note: diagnostic msg:

********************

It seems like RecordDecl::isAnonymousStructOrUnion is sometimes used as "Is this an anonymous union (or GNU extension anonymous struct) inside of another class", when it's not guaranteed to be inside another class.

Making this comment wrong:

// For an anonymous struct or union, the copy and assignment special members
// will never be used, so skip the check. For an anonymous union declared at
// namespace scope, the constructor and destructor are used.
if (CSM != CXXSpecialMemberKind::DefaultConstructor &&
CSM != CXXSpecialMemberKind::Destructor && RD->isAnonymousStructOrUnion())
return false;

This function dubious:
static CXXRecordDecl *FindDeclaringClass(NamedDecl *D) {
DeclContext *DC = D->getDeclContext();
// This can only happen at top: enum decls only "publish" their
// immediate members.
if (isa<EnumDecl>(DC))
DC = cast<EnumDecl>(DC)->getDeclContext();
CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(DC);
while (DeclaringClass->isAnonymousStructOrUnion())
DeclaringClass = cast<CXXRecordDecl>(DeclaringClass->getDeclContext());
return DeclaringClass;
}

And this loop cause the above crash:
while (cast<RecordDecl>(Ctx)->isAnonymousStructOrUnion())
Ctx = Ctx->getParent();

It seems like this could be fixed by checking if the anonymous struct or union is ultimately a field of a named RecordDecl vs. a function-local/namespace-scope anonymous union

@pinskia
Copy link

pinskia commented May 1, 2024

Note GCC also ICEs on this testcase, filed as https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114911 .

@shafik shafik added the confirmed Verified by a second party label May 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" confirmed Verified by a second party crash Prefer [crash-on-valid] or [crash-on-invalid]
Projects
None yet
Development

No branches or pull requests

5 participants