Issue 90751
Summary [Clang] [C++] Anonymous unions can cause crash when the name of their type escapes
Labels clang
Assignees
Reporter MitalAshok
    Small example <https://godbolt.org/z/eEYzYxd9x>:

```c++
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: https://github.com/llvm/llvm-project/blob/477c705cb0d7cc857fad8184faac523f8ef72c84/clang/lib/Sema/SemaDeclCXX.cpp#L9787-L9792
This function dubious: https://github.com/llvm/llvm-project/blob/477c705cb0d7cc857fad8184faac523f8ef72c84/clang/lib/Sema/SemaAccess.cpp#L66-L78
And this loop cause the above crash: https://github.com/llvm/llvm-project/blob/477c705cb0d7cc857fad8184faac523f8ef72c84/clang/lib/Sema/SemaExpr.cpp#L14654-L14655

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
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to