llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.83k stars 11.91k forks source link

clang-tidy with no checks segfaults on variant overload code snippet #80564

Open tonyelewis opened 9 months ago

tonyelewis commented 9 months ago

Running clang-tidy a.cpp -checks= -- -x c++ -std=c++20 with up to date build (987087df90026605fc8d03ebda5a1cd31b71e609, 2024-01-23) on:

template <class... Ts> struct overload : Ts... {};

template <class... Ts> overload( Ts... ) -> overload<Ts...>;

auto f() {
    return overload([] () {});
}

…(which I think is valid code and which is accepted by clang++) segfaults:

PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.      Program arguments: /the-llvm-dir/bin/clang-tidy a.cpp -checks= -- -x c++ -std=c++20
1.      <eof> parser at end of file
2.      While analyzing stack: 
        #0 Calling f()
3.      /tmp/a.cpp:6:18: Error evaluating statement
4.      /tmp/a.cpp:6:18: Error evaluating statement
 #0 0x00005630cc668740 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/the-llvm-dir/bin/clang-tidy+0x4435740)
 #1 0x00005630cc665d0e SignalHandler(int) Signals.cpp:0:0
 #2 0x00007fc45fa42520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x00005630cb53a873 clang::Decl::getTranslationUnitDecl() (.part.0) DeclBase.cpp:0:0
 #4 0x00005630cb540255 clang::Decl::getASTContext() const (/the-llvm-dir/bin/clang-tidy+0x330d255)
 #5 0x00005630cb54bfe4 clang::CXXMethodDecl::getThisType() const (/the-llvm-dir/bin/clang-tidy+0x3318fe4)
 #6 0x00005630ca05b259 clang::ento::SValBuilder::getCXXThis(clang::CXXMethodDecl const*, clang::StackFrameContext const*) (/the-llvm-dir/bin/clang-tidy+0x1e28259)
 #7 0x00005630c9fa1367 clang::ento::ExprEngine::handleConstructor(clang::Expr const*, clang::ento::ExplodedNode*, clang::ento::ExplodedNodeSet&) (/the-llvm-dir/bin/clang-tidy+0x1d6e367)
 #8 0x00005630c9f7cc46 clang::ento::ExprEngine::Visit(clang::Stmt const*, clang::ento::ExplodedNode*, clang::ento::ExplodedNodeSet&) (/the-llvm-dir/bin/clang-tidy+0x1d49c46)
 #9 0x00005630c9f7df0b clang::ento::ExprEngine::ProcessStmt(clang::Stmt const*, clang::ento::ExplodedNode*) (/the-llvm-dir/bin/clang-tidy+0x1d4af0b)
#10 0x00005630c9f8c7bc clang::ento::ExprEngine::processCFGElement(clang::CFGElement, clang::ento::ExplodedNode*, unsigned int, clang::ento::NodeBuilderContext*) (/the-llvm-dir/bin/clang-tidy+0x1d597bc)
#11 0x00005630c9f388c1 clang::ento::CoreEngine::dispatchWorkItem(clang::ento::ExplodedNode*, clang::ProgramPoint, clang::ento::WorkListUnit const&) (/the-llvm-dir/bin/clang-tidy+0x1d058c1)
#12 0x00005630c9f38b2e clang::ento::CoreEngine::ExecuteWorkList(clang::LocationContext const*, unsigned int, llvm::IntrusiveRefCntPtr<clang::ento::ProgramState const>) (/the-llvm-dir/bin/clang-tidy+0x1d05b2e)
#13 0x00005630c9a8b3c6 (anonymous namespace)::AnalysisConsumer::HandleCode(clang::Decl*, unsigned int, clang::ento::ExprEngine::InliningModes, llvm::DenseSet<clang::Decl const*, llvm::DenseMapInfo<clang::Decl const*, void>>*) AnalysisConsumer.cpp:0:0
#14 0x00005630c9a9ce8c (anonymous namespace)::AnalysisConsumer::HandleTranslationUnit(clang::ASTContext&) AnalysisConsumer.cpp:0:0
#15 0x00005630ca264020 clang::MultiplexConsumer::HandleTranslationUnit(clang::ASTContext&) (/the-llvm-dir/bin/clang-tidy+0x2031020)
#16 0x00005630ca4ca409 clang::ParseAST(clang::Sema&, bool, bool) (/the-llvm-dir/bin/clang-tidy+0x2297409)
#17 0x00005630ca225671 clang::FrontendAction::Execute() (/the-llvm-dir/bin/clang-tidy+0x1ff2671)
#18 0x00005630ca19b999 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/the-llvm-dir/bin/clang-tidy+0x1f68999)
#19 0x00005630c9a799f4 clang::tooling::FrontendActionFactory::runInvocation(std::shared_ptr<clang::CompilerInvocation>, clang::FileManager*, std::shared_ptr<clang::PCHContainerOperations>, clang::DiagnosticConsumer*) (/the-llvm-dir/bin/clang-tidy+0x18469f4)
#20 0x00005630c9a1a41e clang::tidy::runClangTidy(clang::tidy::ClangTidyContext&, clang::tooling::CompilationDatabase const&, llvm::ArrayRef<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem>, bool, bool, llvm::StringRef)::ActionFactory::runInvocation(std::shared_ptr<clang::CompilerInvocation>, clang::FileManager*, std::shared_ptr<clang::PCHContainerOperations>, clang::DiagnosticConsumer*) ClangTidy.cpp:0:0
#21 0x00005630c9a72ec5 clang::tooling::ToolInvocation::runInvocation(char const*, clang::driver::Compilation*, std::shared_ptr<clang::CompilerInvocation>, std::shared_ptr<clang::PCHContainerOperations>) (/the-llvm-dir/bin/clang-tidy+0x183fec5)
#22 0x00005630c9a755eb clang::tooling::ToolInvocation::run() (/the-llvm-dir/bin/clang-tidy+0x18425eb)
#23 0x00005630c9a7777f clang::tooling::ClangTool::run(clang::tooling::ToolAction*) (/the-llvm-dir/bin/clang-tidy+0x184477f)
#24 0x00005630c9a239ca clang::tidy::runClangTidy(clang::tidy::ClangTidyContext&, clang::tooling::CompilationDatabase const&, llvm::ArrayRef<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem>, bool, bool, llvm::StringRef) (/the-llvm-dir/bin/clang-tidy+0x17f09ca)
#25 0x00005630c8d55c5f clang::tidy::clangTidyMain(int, char const**) (/the-llvm-dir/bin/clang-tidy+0xb22c5f)
#26 0x00007fc45fa29d90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#27 0x00007fc45fa29e40 call_init ./csu/../csu/libc-start.c:128:20
#28 0x00007fc45fa29e40 __libc_start_main ./csu/../csu/libc-start.c:379:5
#29 0x00005630c8d4cb35 _start (/the-llvm-dir/bin/clang-tidy+0xb19b35)

Note that the source line containing a deduction guide isn't necessary to trigger the crash on trunk, but on slightly older versions it prevents a report of a deduction error from masking the segfault.

llvmbot commented 9 months ago

@llvm/issue-subscribers-clang-static-analyzer

Author: Tony E Lewis (tonyelewis)

Running `clang-tidy a.cpp -checks= -- -x c++ -std=c++20` with up to date build (987087df90026605fc8d03ebda5a1cd31b71e609, 2024-01-23) on: ~~~cpp template <class... Ts> struct overload : Ts... {}; template <class... Ts> overload( Ts... ) -> overload<Ts...>; auto f() { return overload([] () {}); } ~~~ …(which I think is valid code and which is accepted by `clang++`) segfaults: ~~~ PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace. Stack dump: 0. Program arguments: /the-llvm-dir/bin/clang-tidy a.cpp -checks= -- -x c++ -std=c++20 1. <eof> parser at end of file 2. While analyzing stack: #0 Calling f() 3. /tmp/a.cpp:6:18: Error evaluating statement 4. /tmp/a.cpp:6:18: Error evaluating statement #0 0x00005630cc668740 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/the-llvm-dir/bin/clang-tidy+0x4435740) #1 0x00005630cc665d0e SignalHandler(int) Signals.cpp:0:0 #2 0x00007fc45fa42520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520) #3 0x00005630cb53a873 clang::Decl::getTranslationUnitDecl() (.part.0) DeclBase.cpp:0:0 #4 0x00005630cb540255 clang::Decl::getASTContext() const (/the-llvm-dir/bin/clang-tidy+0x330d255) #5 0x00005630cb54bfe4 clang::CXXMethodDecl::getThisType() const (/the-llvm-dir/bin/clang-tidy+0x3318fe4) #6 0x00005630ca05b259 clang::ento::SValBuilder::getCXXThis(clang::CXXMethodDecl const*, clang::StackFrameContext const*) (/the-llvm-dir/bin/clang-tidy+0x1e28259) #7 0x00005630c9fa1367 clang::ento::ExprEngine::handleConstructor(clang::Expr const*, clang::ento::ExplodedNode*, clang::ento::ExplodedNodeSet&) (/the-llvm-dir/bin/clang-tidy+0x1d6e367) #8 0x00005630c9f7cc46 clang::ento::ExprEngine::Visit(clang::Stmt const*, clang::ento::ExplodedNode*, clang::ento::ExplodedNodeSet&) (/the-llvm-dir/bin/clang-tidy+0x1d49c46) #9 0x00005630c9f7df0b clang::ento::ExprEngine::ProcessStmt(clang::Stmt const*, clang::ento::ExplodedNode*) (/the-llvm-dir/bin/clang-tidy+0x1d4af0b) #10 0x00005630c9f8c7bc clang::ento::ExprEngine::processCFGElement(clang::CFGElement, clang::ento::ExplodedNode*, unsigned int, clang::ento::NodeBuilderContext*) (/the-llvm-dir/bin/clang-tidy+0x1d597bc) #11 0x00005630c9f388c1 clang::ento::CoreEngine::dispatchWorkItem(clang::ento::ExplodedNode*, clang::ProgramPoint, clang::ento::WorkListUnit const&) (/the-llvm-dir/bin/clang-tidy+0x1d058c1) #12 0x00005630c9f38b2e clang::ento::CoreEngine::ExecuteWorkList(clang::LocationContext const*, unsigned int, llvm::IntrusiveRefCntPtr<clang::ento::ProgramState const>) (/the-llvm-dir/bin/clang-tidy+0x1d05b2e) #13 0x00005630c9a8b3c6 (anonymous namespace)::AnalysisConsumer::HandleCode(clang::Decl*, unsigned int, clang::ento::ExprEngine::InliningModes, llvm::DenseSet<clang::Decl const*, llvm::DenseMapInfo<clang::Decl const*, void>>*) AnalysisConsumer.cpp:0:0 #14 0x00005630c9a9ce8c (anonymous namespace)::AnalysisConsumer::HandleTranslationUnit(clang::ASTContext&) AnalysisConsumer.cpp:0:0 #15 0x00005630ca264020 clang::MultiplexConsumer::HandleTranslationUnit(clang::ASTContext&) (/the-llvm-dir/bin/clang-tidy+0x2031020) #16 0x00005630ca4ca409 clang::ParseAST(clang::Sema&, bool, bool) (/the-llvm-dir/bin/clang-tidy+0x2297409) #17 0x00005630ca225671 clang::FrontendAction::Execute() (/the-llvm-dir/bin/clang-tidy+0x1ff2671) #18 0x00005630ca19b999 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/the-llvm-dir/bin/clang-tidy+0x1f68999) #19 0x00005630c9a799f4 clang::tooling::FrontendActionFactory::runInvocation(std::shared_ptr<clang::CompilerInvocation>, clang::FileManager*, std::shared_ptr<clang::PCHContainerOperations>, clang::DiagnosticConsumer*) (/the-llvm-dir/bin/clang-tidy+0x18469f4) #20 0x00005630c9a1a41e clang::tidy::runClangTidy(clang::tidy::ClangTidyContext&, clang::tooling::CompilationDatabase const&, llvm::ArrayRef<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem>, bool, bool, llvm::StringRef)::ActionFactory::runInvocation(std::shared_ptr<clang::CompilerInvocation>, clang::FileManager*, std::shared_ptr<clang::PCHContainerOperations>, clang::DiagnosticConsumer*) ClangTidy.cpp:0:0 #21 0x00005630c9a72ec5 clang::tooling::ToolInvocation::runInvocation(char const*, clang::driver::Compilation*, std::shared_ptr<clang::CompilerInvocation>, std::shared_ptr<clang::PCHContainerOperations>) (/the-llvm-dir/bin/clang-tidy+0x183fec5) #22 0x00005630c9a755eb clang::tooling::ToolInvocation::run() (/the-llvm-dir/bin/clang-tidy+0x18425eb) #23 0x00005630c9a7777f clang::tooling::ClangTool::run(clang::tooling::ToolAction*) (/the-llvm-dir/bin/clang-tidy+0x184477f) #24 0x00005630c9a239ca clang::tidy::runClangTidy(clang::tidy::ClangTidyContext&, clang::tooling::CompilationDatabase const&, llvm::ArrayRef<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem>, bool, bool, llvm::StringRef) (/the-llvm-dir/bin/clang-tidy+0x17f09ca) #25 0x00005630c8d55c5f clang::tidy::clangTidyMain(int, char const**) (/the-llvm-dir/bin/clang-tidy+0xb22c5f) #26 0x00007fc45fa29d90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16 #27 0x00007fc45fa29e40 call_init ./csu/../csu/libc-start.c:128:20 #28 0x00007fc45fa29e40 __libc_start_main ./csu/../csu/libc-start.c:379:5 #29 0x00005630c8d4cb35 _start (/the-llvm-dir/bin/clang-tidy+0xb19b35) ~~~ Note that the source line containing a deduction guide isn't necessary to trigger the crash on trunk, but on slightly older versions it prevents a report of a deduction error from masking the segfault.
steakhal commented 9 months ago

Thanks for the report. Here is the compiler-explorer repro. This bug is present for a long time, at least since clang-16.

The assertion is from ExprEngine::handleConstructor, which is called with a Delegating constructor, where we cast the LCtx->getDecl() into a CXXMethodDecl, but it's actually only a FunctionDecl ("f" in the example), thus asserting on llvm::cast.

I don't think it's difficult to fix, but I don't really have the time now.

Thanks again for the tiny repro!

tonyelewis commented 9 months ago

Thanks for the quick response and the assessment of the problem.

Thanks again for the tiny repro!

creduce is a wonderful thing. :slightly_smiling_face: