Skip to content

[clang-include-cleaner] <expected> incorrectly diagnosed as unused when using libc++ because of outdated StdSymbolMap.inc #113494

@vvd170501

Description

@vvd170501

The problem

#include <expected>

std::expected<int, char> Foo() {
    return 123;
}

When using libc++, both clangd and misc-include-cleaner check in clang-tidy (trunk versions) diagnose <expected> as unused.
Reproducer: https://godbolt.org/z/T4fesGThr
With libstdc++ the usage is detected correctly.

The cause

In libc++ std::expected is actually defined in __expected/expected.h.
Correct headers for std symbols are defined in clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc, which hasn't been updated since 2022-07-30 and currently doesn't contain an entry for std::expected.

I tried to run gen_std.py with cppreference copy from 2023-08-10, but it doesn't seem to work with newer archives.

  1. Some symbols have become ambiguous and the generator does not include them in the mapping anymore (see resulting diff). Some of these symbols should probably be moved into StdSpecialSymbolMap.inc (like std::atomic_*, because std::atomic is already there), but I'm not sure what to do with the others,

  2. If I manualliy restore deleted symbols and try to build clangd with the new mapping, it crashes immediately when I try to open a file or run clangd with --check.

    Crash backtrace (relwithdebinfo build, assertions are enabled)
    $ /opt/clangd-patched/19/bin/clangd --compile-commands-dir=$HOME/vsc/tasklet --check=.../main.cpp 
    I[23:44:22.985] clangd version 19.1.2 (https://github.com/llvm/llvm-project 7918ef84393878091346d79171da74a8427aa4ec)
    I[23:44:22.985] Features: linux
    I[23:44:22.985] PID: 3422246
    I[23:44:22.985] Working directory: /home/username
    I[23:44:22.985] argv[0]: /opt/clangd-patched/19/bin/clangd
    I[23:44:22.985] argv[1]: --compile-commands-dir=...
    I[23:44:22.985] argv[2]: --check=.../main.cpp
    I[23:44:22.986] Entering check mode (no LSP server)
    I[23:44:22.986] Testing on source file .../main.cpp
    I[23:44:22.988] Loading compilation database...
    I[23:44:23.183] Loaded compilation database from .../compile_commands.json
    I[23:44:23.188] Compile command from CDB is: ...
    I[23:44:23.189] Parsing command...
    I[23:44:23.191] internal (cc1) args are: ...
    I[23:44:23.192] Building preamble...
    PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
    Stack dump:
    0.      Program arguments: /opt/clangd-patched/19/bin/clangd --compile-commands-dir... --check=.../main.cpp
    1.      .../main.cpp:1:2: current parser token 'include'
    #0 0x0000562078ecc108 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) /opt/clangd-patched/19/llvm-project/llvm/lib/Support/Unix/Signals.inc:723:13
    #1 0x0000562078eca3b0 llvm::sys::RunSignalHandlers() /opt/clangd-patched/19/llvm-project/llvm/lib/Support/Signals.cpp:106:18
    #2 0x0000562078ecca98 SignalHandler(int) /opt/clangd-patched/19/llvm-project/llvm/lib/Support/Unix/Signals.inc:413:1
    #3 0x00007f6e2a668520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
    #4 0x00007f6e2a6cb795 __libc_realloc ./malloc/./malloc/malloc.c:3428:35
    #5 0x0000562078e9aeb3 llvm::safe_realloc(void*, unsigned long) /opt/clangd-patched/19/llvm-project/llvm/include/llvm/Support/MemAlloc.h:53:18
    #6 0x0000562078e9aeb3 llvm::SmallVectorBase<unsigned int>::grow_pod(void*, unsigned long, unsigned long) /opt/clangd-patched/19/llvm-project/llvm/lib/Support/SmallVector.cpp:151:15
    #7 0x000056207bf0244f llvm::SmallVectorBase<unsigned int>::size() const /opt/clangd-patched/19/llvm-project/llvm/include/llvm/ADT/SmallVector.h:92:32
    #8 0x000056207bf0244f llvm::SmallVectorTemplateCommon<unsigned int, void>::end() /opt/clangd-patched/19/llvm-project/llvm/include/llvm/ADT/SmallVector.h:283:37
    #9 0x000056207bf0244f llvm::SmallVectorTemplateBase<unsigned int, true>::push_back(unsigned int) /opt/clangd-patched/19/llvm-project/llvm/include/llvm/ADT/SmallVector.h:577:43
    #10 0x000056207bf0244f clang::tooling::stdlib::initialize(clang::tooling::stdlib::Lang)::$_2::operator()(llvm::StringRef, unsigned int, llvm::StringRef) /opt/clangd-patched/18/llvm-project/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp:134:43
    #11 0x000056207bf020f0 clang::tooling::stdlib::initialize(clang::tooling::stdlib::Lang) /opt/clangd-patched/18/llvm-project/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp:164:26
    #12 0x000056207bf020f0 clang::tooling::stdlib::ensureInitialized()::$_0::operator()() const /opt/clangd-patched/18/llvm-project/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp:181:7
    #13 0x000056207bf01439 clang::tooling::stdlib::ensureInitialized() /opt/clangd-patched/18/llvm-project/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp:179:3
    #14 0x000056207bf01439 clang::tooling::stdlib::Header::named(llvm::StringRef, clang::tooling::stdlib::Lang) /opt/clangd-patched/18/llvm-project/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp:197:3
    #15 0x000056207bee061d clang::include_cleaner::PragmaIncludes::RecordPragma::InclusionDirective(clang::SourceLocation, clang::Token const&, llvm::StringRef, bool, clang::CharSourceRange, clang::CustomizableOptional<clang::FileEntryRef>, llvm::StringRef, llvm::StringRef, clang::Module const*, bool, clang::SrcMgr::CharacteristicKind) /opt/clangd-patched/18/llvm-project/clang-tools-extra/include-cleaner/lib/Record.cpp:229:15
    #16 0x000056207947acfc std::__uniq_ptr_impl<clang::PPCallbacks, std::default_delete<clang::PPCallbacks> >::_M_ptr() const /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/unique_ptr.h:173:42
    #17 0x000056207947acfc std::unique_ptr<clang::PPCallbacks, std::default_delete<clang::PPCallbacks> >::get() const /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/unique_ptr.h:422:21
    #18 0x000056207947acfc std::unique_ptr<clang::PPCallbacks, std::default_delete<clang::PPCallbacks> >::operator->() const /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/unique_ptr.h:416:9
    #19 0x000056207947acfc clang::PPChainedCallbacks::InclusionDirective(clang::SourceLocation, clang::Token const&, llvm::StringRef, bool, clang::CharSourceRange, clang::CustomizableOptional<clang::FileEntryRef>, llvm::StringRef, llvm::StringRef, clang::Module const*, bool, clang::SrcMgr::CharacteristicKind) /opt/clangd-patched/18/llvm-project/clang/include/clang/Lex/PPCallbacks.h:533:5
    #20 0x000056207942526c clang::FileEntryRef::hasOptionalValue() const /opt/clangd-patched/18/llvm-project/clang/include/clang/Basic/FileEntry.h:177:42
    #21 0x000056207942526c clang::FileMgr::MapEntryOptionalStorage<clang::FileEntryRef>::has_value() const /opt/clangd-patched/18/llvm-project/clang/include/clang/Basic/DirectoryEntry.h:133:44
    #22 0x000056207942526c clang::CustomizableOptional<clang::FileEntryRef>::has_value() const /opt/clangd-patched/18/llvm-project/clang/include/clang/Basic/CustomizableOptional.h:83:53
    #23 0x000056207942526c clang::CustomizableOptional<clang::FileEntryRef>::operator bool() const /opt/clangd-patched/18/llvm-project/clang/include/clang/Basic/CustomizableOptional.h:82:53
    #24 0x000056207942526c clang::Preprocessor::HandleHeaderIncludeOrImport(clang::SourceLocation, clang::Token&, clang::Token&, clang::SourceLocation, clang::detail::SearchDirIteratorImpl<true>, clang::FileEntry const*) /opt/clangd-patched/18/llvm-project/clang/lib/Lex/PPDirectives.cpp:2486:8
    #25 0x0000562079420978 clang::Preprocessor::HandleIncludeDirective(clang::SourceLocation, clang::Token&, clang::detail::SearchDirIteratorImpl<true>, clang::FileEntry const*) /opt/clangd-patched/18/llvm-project/clang/lib/Lex/PPDirectives.cpp:2069:3
    #26 0x0000562079421187 clang::Preprocessor::HandleDirective(clang::Token&) /opt/clangd-patched/18/llvm-project/clang/lib/Lex/PPDirectives.cpp:0:14
    #27 0x0000562079415dd4 clang::Lexer::LexTokenInternal(clang::Token&, bool) /opt/clangd-patched/18/llvm-project/clang/lib/Lex/Lexer.cpp:4490:7
    #28 0x000056207944ecfd clang::Preprocessor::Lex(clang::Token&) /opt/clangd-patched/18/llvm-project/clang/lib/Lex/Preprocessor.cpp:873:3
    #29 0x000056207c53a30b clang::OpaquePtr<clang::DeclGroupRef>::OpaquePtr(std::nullptr_t) /opt/clangd-patched/18/llvm-project/clang/include/clang/Sema/Ownership.h:51:11
    #30 0x000056207c53a30b clang::ParseAST(clang::Sema&, bool, bool) /opt/clangd-patched/18/llvm-project/clang/lib/Parse/ParseAST.cpp:165:28
    #31 0x000056207c3a0137 clang::FrontendAction::Execute() /opt/clangd-patched/18/llvm-project/clang/lib/Frontend/FrontendAction.cpp:1082:10
    #32 0x000056207c3b68bf llvm::Error::getPtr() const /opt/clangd-patched/19/llvm-project/llvm/include/llvm/Support/Error.h:282:12
    #33 0x000056207c3b68bf llvm::Error::operator bool() /opt/clangd-patched/19/llvm-project/llvm/include/llvm/Support/Error.h:242:16
    #34 0x000056207c3b68bf clang::PrecompiledPreamble::Build(clang::CompilerInvocation const&, llvm::MemoryBuffer const*, clang::PreambleBounds, clang::DiagnosticsEngine&, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::shared_ptr<clang::PCHContainerOperations>, bool, llvm::StringRef, clang::PreambleCallbacks&) /opt/clangd-patched/18/llvm-project/clang/lib/Frontend/PrecompiledPreamble.cpp:536:19
    #35 0x0000562079f4d973 std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/shared_ptr_base.h:704:6
    #36 0x0000562079f4d973 std::__shared_ptr<clang::PCHContainerOperations, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/shared_ptr_base.h:1154:31
    #37 0x0000562079f4d973 clang::clangd::buildPreamble(llvm::StringRef, clang::CompilerInvocation, clang::clangd::ParseInputs const&, bool, std::function<void (clang::clangd::CapturedASTCtx, std::shared_ptr<clang::include_cleaner::PragmaIncludes const>)>, clang::clangd::PreambleBuildStats*) /opt/clangd-patched/18/llvm-project/clang-tools-extra/clangd/Preamble.cpp:663:24
    #38 0x0000562079d84b6e std::__shared_ptr<clang::clangd::PreambleData const, (__gnu_cxx::_Lock_policy)2>::__shared_ptr(std::__shared_ptr<clang::clangd::PreambleData const, (__gnu_cxx::_Lock_policy)2>&&) /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/shared_ptr_base.h:1162:20
    #39 0x0000562079d84b6e std::__shared_ptr<clang::clangd::PreambleData const, (__gnu_cxx::_Lock_policy)2>::operator=(std::__shared_ptr<clang::clangd::PreambleData const, (__gnu_cxx::_Lock_policy)2>&&) /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/shared_ptr_base.h:1250:2
    #40 0x0000562079d84b6e std::shared_ptr<clang::clangd::PreambleData const>::operator=(std::shared_ptr<clang::clangd::PreambleData const>&&) /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/shared_ptr.h:385:27
    #41 0x0000562079d84b6e clang::clangd::(anonymous namespace)::Checker::buildAST() /opt/clangd-patched/18/llvm-project/clang-tools-extra/clangd/tool/Check.cpp:245:14
    #42 0x0000562079d84b6e clang::clangd::check(llvm::StringRef, clang::clangd::ThreadsafeFS const&, clang::clangd::ClangdLSPServer::Options const&) /opt/clangd-patched/18/llvm-project/clang-tools-extra/clangd/tool/Check.cpp:522:10
    #43 0x0000562079d7a957 clang::clangd::clangdMain(int, char**) /opt/clangd-patched/18/llvm-project/clang-tools-extra/clangd/tool/ClangdMain.cpp:982:12
    #44 0x00007f6e2a64fd90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #45 0x00007f6e2a64fe40 call_init ./csu/../csu/libc-start.c:128:20
    #46 0x00007f6e2a64fe40 __libc_start_main ./csu/../csu/libc-start.c:379:5
    #47 0x0000562078de0515 _start (/opt/clangd-patched/19/bin/clangd+0x822515)
    Segmentation fault
    

    Currently I don't have a minimal reproducer for this crash, but will try to create one.
    UPD: the crash is caused by duplicate mappings - for example, mapping for any_cast is already defined in StdSpecialSymbolMap.inc, Removing it fixes the crash. I'll try to create a PR with updated mappings.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions