[clang-tools-extra] [clang-tidy] Fix crash in misc-static-initialization-cycle (PR #198155)
Zeyi Xu via cfe-commits
cfe-commits at lists.llvm.org
Sun May 17 04:11:53 PDT 2026
================
@@ -120,6 +120,14 @@ int f1() {
int S::A = f1();
}
+namespace catch_all_handler {
+void f() {
----------------
zeyi2 wrote:
> Does this used to crash before?
Yes, it would crash:
```
% ./build/bin/llvm-lit clang-tools-extra/test/clang-tidy/checkers/misc/static-initialization-cycle.cpp -v
llvm-lit: /Users/zeyi2/Documents/projects/llvm-project/llvm/utils/lit/lit/llvm/config.py:569: note: using clang: /Users/zeyi2/Documents/projects/llvm-project/build/bin/clang
-- Testing: 1 tests, 1 workers --
FAIL: Clang Tools :: clang-tidy/checkers/misc/static-initialization-cycle.cpp (1 of 1)
******************** TEST 'Clang Tools :: clang-tidy/checkers/misc/static-initialization-cycle.cpp' FAILED ********************
Exit Code: 1
Command Output (stdout):
--
# RUN: at line 1
/opt/homebrew/Frameworks/Python.framework/Versions/3.14/bin/python3.14 /Users/zeyi2/Documents/projects/llvm-project/clang-tools-extra/test/../test/clang-tidy/check_clang_tidy.py /Users/zeyi2/Documents/projects/llvm-project/clang-tools-extra/test/clang-tidy/checkers/misc/static-initialization-cycle.cpp misc-static-initialization-cycle /Users/zeyi2/Documents/projects/llvm-project/build/tools/clang/tools/extra/test/clang-tidy/checkers/misc/Output/static-initialization-cycle.cpp.tmp -- -- -fno-delayed-template-parsing
# executed command: /opt/homebrew/Frameworks/Python.framework/Versions/3.14/bin/python3.14 /Users/zeyi2/Documents/projects/llvm-project/clang-tools-extra/test/../test/clang-tidy/check_clang_tidy.py /Users/zeyi2/Documents/projects/llvm-project/clang-tools-extra/test/clang-tidy/checkers/misc/static-initialization-cycle.cpp misc-static-initialization-cycle /Users/zeyi2/Documents/projects/llvm-project/build/tools/clang/tools/extra/test/clang-tidy/checkers/misc/Output/static-initialization-cycle.cpp.tmp -- -- -fno-delayed-template-parsing
# .---command stdout------------
# | Running ['clang-tidy', '--experimental-custom-checks', '/Users/zeyi2/Documents/projects/llvm-project/build/tools/clang/tools/extra/test/clang-tidy/checkers/misc/Output/static-initialization-cycle.cpp.tmp.cpp', '-fix', '--checks=-*,misc-static-initialization-cycle', '--config={}', '--', '-fno-delayed-template-parsing', '-std=c++11', '-nostdinc++', '-isystem', '/Users/zeyi2/Documents/projects/llvm-project/clang-tools-extra/test/../test/clang-tidy/checkers/Inputs/Headers/std']...
# | clang-tidy --experimental-custom-checks /Users/zeyi2/Documents/projects/llvm-project/build/tools/clang/tools/extra/test/clang-tidy/checkers/misc/Output/static-initialization-cycle.cpp.tmp.cpp -fix --checks=-*,misc-static-initialization-cycle --config={} -- -fno-delayed-template-parsing -std=c++11 -nostdinc++ -isystem /Users/zeyi2/Documents/projects/llvm-project/clang-tools-extra/test/../test/clang-tidy/checkers/Inputs/Headers/std failed:
# | PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace and instructions to reproduce the bug.
# | Stack dump:
# | 0. Program arguments: clang-tidy --experimental-custom-checks /Users/zeyi2/Documents/projects/llvm-project/build/tools/clang/tools/extra/test/clang-tidy/checkers/misc/Output/static-initialization-cycle.cpp.tmp.cpp -fix --checks=-*,misc-static-initialization-cycle --config={} -- -fno-delayed-template-parsing -std=c++11 -nostdinc++ -isystem /Users/zeyi2/Documents/projects/llvm-project/clang-tools-extra/test/../test/clang-tidy/checkers/Inputs/Headers/std
# | 1. <eof> parser at end of file
# | 2. ASTMatcher: Processing 'misc-static-initialization-cycle' against:
# | TranslationUnitDecl : <<invalid sloc>>
# | --- Bound Nodes Begin ---
# | TUDecl - { TranslationUnitDecl : <<invalid sloc>> }
# | --- Bound Nodes End ---
# | Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
# | 0 clang-tidy 0x0000000104cff324 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 56
# | 1 clang-tidy 0x0000000104cfcfc8 llvm::sys::RunSignalHandlers() + 204
# | 2 clang-tidy 0x0000000104cffe30 SignalHandler(int, __siginfo*, void*) + 308
# | 3 libsystem_platform.dylib 0x00000001853e57a4 _sigtramp + 56
# | 4 clang-tidy 0x00000001057f0778 (anonymous namespace)::VarUseCollector::TraverseDecl(clang::Decl*) + 32
# | 5 clang-tidy 0x0000000104f86808 clang::DynamicRecursiveASTVisitorBase<false>::TraverseCXXCatchStmt(clang::CXXCatchStmt*) + 88
# | 6 clang-tidy 0x0000000104f623c0 clang::RecursiveASTVisitor<(anonymous namespace)::Impl<true>>::TraverseStmt(clang::Stmt*, llvm::SmallVectorImpl<llvm::PointerIntPair<clang::Stmt*, 1u, bool, llvm::PointerLikeTypeTraits<clang::Stmt*>, llvm::PointerIntPairInfo<clang::Stmt*, 1u, llvm::PointerLikeTypeTraits<clang::Stmt*>>>>*) + 176
# | 7 clang-tidy 0x0000000104f62304 clang::DynamicRecursiveASTVisitorBase<false>::TraverseStmt(clang::Stmt*) + 24
# | 8 clang-tidy 0x0000000104f865fc clang::DynamicRecursiveASTVisitorBase<false>::TraverseCXXTryStmt(clang::CXXTryStmt*) + 240
# | 9 clang-tidy 0x0000000104f623c0 clang::RecursiveASTVisitor<(anonymous namespace)::Impl<true>>::TraverseStmt(clang::Stmt*, llvm::SmallVectorImpl<llvm::PointerIntPair<clang::Stmt*, 1u, bool, llvm::PointerLikeTypeTraits<clang::Stmt*>, llvm::PointerIntPairInfo<clang::Stmt*, 1u, llvm::PointerLikeTypeTraits<clang::Stmt*>>>>*) + 176
# | 10 clang-tidy 0x0000000104f62304 clang::DynamicRecursiveASTVisitorBase<false>::TraverseStmt(clang::Stmt*) + 24
# | 11 clang-tidy 0x0000000104f863b0 clang::DynamicRecursiveASTVisitorBase<false>::TraverseCompoundStmt(clang::CompoundStmt*) + 240
# | 12 clang-tidy 0x0000000104f623c0 clang::RecursiveASTVisitor<(anonymous namespace)::Impl<true>>::TraverseStmt(clang::Stmt*, llvm::SmallVectorImpl<llvm::PointerIntPair<clang::Stmt*, 1u, bool, llvm::PointerLikeTypeTraits<clang::Stmt*>, llvm::PointerIntPairInfo<clang::Stmt*, 1u, llvm::PointerLikeTypeTraits<clang::Stmt*>>>>*) + 176
# | 13 clang-tidy 0x0000000104f62304 clang::DynamicRecursiveASTVisitorBase<false>::TraverseStmt(clang::Stmt*) + 24
# | 14 clang-tidy 0x00000001057f049c (anonymous namespace)::VarUseGraphBuilder::VisitFunctionDecl(clang::FunctionDecl*) + 176
# | 15 clang-tidy 0x0000000104f67a14 clang::DynamicRecursiveASTVisitorBase<false>::TraverseFunctionDecl(clang::FunctionDecl*) + 140
# | 16 clang-tidy 0x0000000104f61904 clang::DynamicRecursiveASTVisitorBase<false>::TraverseDecl(clang::Decl*) + 668
# | 17 clang-tidy 0x0000000104f6e3bc clang::DynamicRecursiveASTVisitorBase<false>::TraverseNamespaceDecl(clang::NamespaceDecl*) + 156
# | 18 clang-tidy 0x0000000104f617d8 clang::DynamicRecursiveASTVisitorBase<false>::TraverseDecl(clang::Decl*) + 368
# | 19 clang-tidy 0x0000000104f63b08 clang::DynamicRecursiveASTVisitorBase<false>::TraverseTranslationUnitDecl(clang::TranslationUnitDecl*) + 240
# | 20 clang-tidy 0x0000000104f616bc clang::DynamicRecursiveASTVisitorBase<false>::TraverseDecl(clang::Decl*) + 84
# | 21 clang-tidy 0x00000001057ef50c clang::tidy::misc::StaticInitializationCycleCheck::check(clang::ast_matchers::MatchFinder::MatchResult const&) + 268
# | 22 clang-tidy 0x00000001054134fc clang::ast_matchers::internal::(anonymous namespace)::MatchASTVisitor::MatchVisitor::visitMatch(clang::ast_matchers::BoundNodes const&) + 164
# | 23 clang-tidy 0x000000010542e0fc clang::ast_matchers::internal::BoundNodesTreeBuilder::visitMatches(clang::ast_matchers::internal::BoundNodesTreeBuilder::Visitor*) + 132
# | 24 clang-tidy 0x0000000105412c34 clang::ast_matchers::internal::(anonymous namespace)::MatchASTVisitor::matchWithFilter(clang::DynTypedNode const&) + 548
# | 25 clang-tidy 0x00000001054163e8 clang::ast_matchers::internal::(anonymous namespace)::MatchASTVisitor::TraverseDecl(clang::Decl*) + 360
# | 26 clang-tidy 0x00000001053f620c clang::ast_matchers::MatchFinder::matchAST(clang::ASTContext&) + 600
# | 27 clang-tidy 0x00000001062a855c clang::MultiplexConsumer::HandleTranslationUnit(clang::ASTContext&) + 52
# | 28 clang-tidy 0x0000000106404890 clang::ParseAST(clang::Sema&, bool, bool) + 544
# | 29 clang-tidy 0x0000000106261d10 clang::FrontendAction::Execute() + 48
# | 30 clang-tidy 0x00000001061fd820 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) + 1216
# | 31 clang-tidy 0x0000000105520fb0 clang::tooling::FrontendActionFactory::runInvocation(std::__1::shared_ptr<clang::CompilerInvocation>, clang::FileManager*, std::__1::shared_ptr<clang::PCHContainerOperations>, clang::DiagnosticConsumer*) + 432
# | 32 clang-tidy 0x000000010552faac clang::tidy::runClangTidy(clang::tidy::ClangTidyContext&, clang::tooling::CompilationDatabase const&, llvm::ArrayRef<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>, llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem>, bool, bool, llvm::StringRef, bool)::ActionFactory::runInvocation(std::__1::shared_ptr<clang::CompilerInvocation>, clang::FileManager*, std::__1::shared_ptr<clang::PCHContainerOperations>, clang::DiagnosticConsumer*) + 128
# | 33 clang-tidy 0x0000000105520d7c clang::tooling::ToolInvocation::runInvocation(char const*, clang::driver::Compilation*, std::__1::shared_ptr<clang::CompilerInvocation>, std::__1::shared_ptr<clang::PCHContainerOperations>) + 268
# | 34 clang-tidy 0x000000010551fc00 clang::tooling::ToolInvocation::run() + 1000
# | 35 clang-tidy 0x00000001055226d8 clang::tooling::ClangTool::run(clang::tooling::ToolAction*) + 3576
# | 36 clang-tidy 0x000000010552ceb4 clang::tidy::runClangTidy(clang::tidy::ClangTidyContext&, clang::tooling::CompilationDatabase const&, llvm::ArrayRef<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>, llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem>, bool, bool, llvm::StringRef, bool) + 1080
# | 37 clang-tidy 0x0000000105553a98 clang::tidy::clangTidyMain(int, char const**) + 9292
# | 38 dyld 0x000000018501fda4 start + 6992
# |
# `-----------------------------
# .---command stderr------------
```
> I can't understand what was the nullptr decl, is it `<<<NULL>>>`?
If I understand correctly, `<<<NULL>>>` is the null exception declaration for `catch (...)`. Before this patch, `TraverseDecl` (called while traversing `CXXCatchStmt`) passed that null pointer to `DC->containsDecl(D)`.
Sorry that my original PR description was too terse, I'll add a more detailed description.
https://github.com/llvm/llvm-project/pull/198155
More information about the cfe-commits
mailing list