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

Segmentation fault after upgrade to 0.17 on macOS 11.6.2 #989

Closed
srpgilles opened this issue Jan 3, 2022 · 15 comments · Fixed by #1051
Closed

Segmentation fault after upgrade to 0.17 on macOS 11.6.2 #989

srpgilles opened this issue Jan 3, 2022 · 15 comments · Fixed by #1051
Milestone

Comments

@srpgilles
Copy link

After upgrading to IWYU 0.17 on my BigSur installation (within Homebrew), IWYU stopped working on my codebase due to some pesky segmentation fault.

By trial and error on one file that was segmenting I was able to reduce to a small snippet that cause the segmentation fault:

#include <algorithm>
#include <cassert>
#include <vector>

int main()
{
    constexpr auto unused = static_cast<std::size_t>(-1);
    const auto Ndof = 100ul;

    std::vector<std::size_t> mapping(Ndof, unused);

    assert(std::none_of(mapping.cbegin(),
                        mapping.cend(),
                        [](auto value)
                    {
                        return value == unused;
                    }));

    return EXIT_SUCCESS;
}

This segmentation fault is highly specific:

  • If the algorithm is not inside the assert command, no segmentation fault.
  • If I declare the lambda as a variable auto is_unused = [](auto value) {... } and then use is_unused in the std::none algorithm, no segmentation fault.

Before the upgrade to newest IWYU (LLVM was also upgraded - I did it through brew upgrade), IWYU was working on my entire codebase without issue.

@srpgilles
Copy link
Author

srpgilles commented Jan 3, 2022

I tried reinstalling 0.16 to check: the code above works perfectly fine.

@kimgr
Copy link
Contributor

kimgr commented Jan 6, 2022

Thanks for the reduced repro! Unfortunately it seems to work fine on my Ubuntu/libstdc++-gcc9.3 setup. The main difference is that macOS has libc++ by default, so the standard library implementation probably triggers some path not seen with libstdc++.

Can you get a backtrace for the segfault?

@kimgr
Copy link
Contributor

kimgr commented Feb 5, 2022

@srpgilles This seems like a serious problem, can you please provide more details? Thanks.

@srpgilles
Copy link
Author

I concur it is a serious problem, but I must admit I am a bit at a loss to provide you more...

I build the snippet with the following CMakeLists.txt:

cmake_minimum_required(VERSION 3.12)

project(Debug_IWYU)

set(CMAKE_CXX_STANDARD 20 CACHE STRING "C++ standard; at least 20 is expected.")
set(CMAKE_C_COMPILER /usr/local/Cellar/llvm/13.0.0_2/bin/clang)
set(CMAKE_CXX_COMPILER /usr/local/Cellar/llvm/13.0.0_2/bin/clang++)
set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE /usr/local/Cellar/include-what-you-use/0.17/libexec/bin/include-what-you-use;-Xiwyu;any;-Xiwyu;iwyu;-Xiwyu;args;-Xiwyu;--no_comments;-Xiwyu;--cxx17ns;-Xiwyu;max_line_length=120)

add_executable(test
               snippet.cpp)   

and then the usual

mkdir build
cd build
cmake ..

(I have reduced to the minimum the fluff such as using Ninja rather than make and introducing a mapping file).

When I run make, I get a segmentation fault and no more information; as I said it's by trial and error I pinpointed what could make it work or not. If I run make --trace I don't get much more:

Makefile:179: target 'cmake_check_build_system' does not exist
/usr/local/Cellar/cmake/3.22.2/bin/cmake -S/Users/sebastien/Codes/Sandbox/IWYU -B/Users/sebastien/Codes/Sandbox/IWYU/build_iwyu --check-build-system CMakeFiles/Makefile.cmake 0
Makefile:90: update target 'all' due to: cmake_check_build_system
/usr/local/Cellar/cmake/3.22.2/bin/cmake -E cmake_progress_start /Users/sebastien/Codes/Sandbox/IWYU/build_iwyu/CMakeFiles /Users/sebastien/Codes/Sandbox/IWYU/build_iwyu//CMakeFiles/progress.marks
make -s -f CMakeFiles/Makefile2 all
CMakeFiles/Makefile2:82: target 'CMakeFiles/test.dir/all' does not exist
make -s -f CMakeFiles/test.dir/build.make CMakeFiles/test.dir/depend
CMakeFiles/test.dir/build.make:108: target 'CMakeFiles/test.dir/depend' does not exist
cd /Users/sebastien/Codes/Sandbox/IWYU/build_iwyu && /usr/local/Cellar/cmake/3.22.2/bin/cmake -E cmake_depends "Unix Makefiles" /Users/sebastien/Codes/Sandbox/IWYU /Users/sebastien/Codes/Sandbox/IWYU /Users/sebastien/Codes/Sandbox/IWYU/build_iwyu /Users/sebastien/Codes/Sandbox/IWYU/build_iwyu /Users/sebastien/Codes/Sandbox/IWYU/build_iwyu/CMakeFiles/test.dir/DependInfo.cmake --color=
Consolidate compiler generated dependencies of target test
make -s -f CMakeFiles/test.dir/build.make CMakeFiles/test.dir/build
CMakeFiles/test.dir/build.make:75: update target 'CMakeFiles/test.dir/snippet.cpp.o' due to: ../snippet.cpp
/usr/local/Cellar/cmake/3.22.2/bin/cmake -E cmake_echo_color --switch= --green --progress-dir=/Users/sebastien/Codes/Sandbox/IWYU/build_iwyu/CMakeFiles --progress-num=1 "Building CXX object CMakeFiles/test.dir/snippet.cpp.o"
[ 50%] Building CXX object CMakeFiles/test.dir/snippet.cpp.o
/usr/local/Cellar/cmake/3.22.2/bin/cmake -E __run_co_compile --iwyu="/usr/local/Cellar/include-what-you-use/0.17/libexec/bin/include-what-you-use;-Xiwyu;any;-Xiwyu;iwyu;-Xiwyu;args;-Xiwyu;--no_comments;-Xiwyu;--cxx17ns;-Xiwyu;max_line_length=120;--driver-mode=g++" -- /usr/local/Cellar/llvm/13.0.0_2/bin/clang++   -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk -std=gnu++2a -MD -MT CMakeFiles/test.dir/snippet.cpp.o -MF CMakeFiles/test.dir/snippet.cpp.o.d -o CMakeFiles/test.dir/snippet.cpp.o -c /Users/sebastien/Codes/Sandbox/IWYU/snippet.cpp
Error running '/usr/local/Cellar/include-what-you-use/0.17/libexec/bin/include-what-you-use': Segmentation fault
make[2]: *** [CMakeFiles/test.dir/build.make:76: CMakeFiles/test.dir/snippet.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/test.dir/all] Error 2
make: *** [Makefile:91: all] Error 2

I have since my post upgraded my OS to macOS Monterey and the issue is still there (and IWYU 0.16 is perfectly fine).

@kimgr
Copy link
Contributor

kimgr commented Feb 6, 2022

set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE /usr/local/Cellar/include-what-you-use/0.17/libexec/bin/include-what-you-use;-Xiwyu;any;-Xiwyu;iwyu;-Xiwyu;args;-Xiwyu;--no_comments;-Xiwyu;--cxx17ns;-Xiwyu;max_line_length=120)

That command-line is not valid, I'm surprised that runs at all. I think you want something like:

set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE /usr/local/Cellar/include-what-you-use/0.17/libexec/bin/include-what-you-use;-Xiwyu;--no_comments;-Xiwyu;--cxx17ns;-Xiwyu;--max_line_length=120)

Looking at the output from CMake, then, it appears to run the following command:

/usr/local/Cellar/cmake/3.22.2/bin/cmake -E __run_co_compile --iwyu="/usr/local/Cellar/include-what-you-use/0.17/libexec/bin/include-what-you-use;-Xiwyu;any;-Xiwyu;iwyu;-Xiwyu;args;-Xiwyu;--no_comments;-Xiwyu;--cxx17ns;-Xiwyu;max_line_length=120;--driver-mode=g++" -- /usr/local/Cellar/llvm/13.0.0_2/bin/clang++   -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk -std=gnu++2a -MD -MT CMakeFiles/test.dir/snippet.cpp.o -MF CMakeFiles/test.dir/snippet.cpp.o.d -o CMakeFiles/test.dir/snippet.cpp.o -c /Users/sebastien/Codes/Sandbox/IWYU/snippet.cpp

I'm not 100% sure how CMake translates that to an include-what-you-use command-line, but I suspect it stitches something like this together:

/usr/local/Cellar/include-what-you-use/0.17/libexec/bin/include-what-you-use -Xiwyu --no_comments -Xiwyu --cxx17ns -Xiwyu --max_line_length=120 --driver-mode=g++ -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk -std=gnu++2a /Users/sebastien/Codes/Sandbox/IWYU/snippet.cpp

If you could try that command and see if it also segfaults, that would be good.

Then the next step is to run it through a debugger. I don't know what's on Mac systems these days.

If you have gdb, use gdb --args ... where ... is the IWYU command above. Hit r + Enter to run the program. It should trap the segfault and you can use bt to show the backtrace.

If you have lldb, use lldb -- ... where ... is the IWYU command above. Hit r + Enter to run the program. It should trap the segfault and you can use bt to show the backtrace.

I'm interested in that backtrace.

@srpgilles
Copy link
Author

OK, so removing the args and any from the CMAKE_CXX_INCLUDE_WHAT_YOU_USE doesn't change anything.

Through the command line you provide I also reach the seg fault.

I tried the debugger that ships with the OS (lldb) and it wasn't very helpful:

Process 26917 launched: '/usr/local/Cellar/cmake/3.22.2/bin/cmake' (x86_64)
Error running '/usr/local/Cellar/include-what-you-use/0.17/libexec/bin/include-what-you-use': Segmentation fault
Process 26917 exited with status = 1 (0x00000001) 

bt fails due to the thread being finished:

(lldb) bt
error: invalid thread

(sorry if I made a blunder in using the debugger - I very seldom use one, and it's never directly in the terminal)

@kimgr
Copy link
Contributor

kimgr commented Feb 6, 2022

@srpgilles It looks like you're running the debugger on the cmake command. Try on the separate include-what-you-use command instead.

@srpgilles
Copy link
Author

Sorry I was too hasty.

Here is the full output:

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x1c)
    frame #0: 0x0000000100006cdc include-what-you-use`include_what_you_use::IwyuBaseAstVisitor<include_what_you_use::InstantiatedTemplateVisitor>::GetCanonicalUseLocation(clang::SourceLocation, clang::NamedDecl const*) + 688
include-what-you-use`include_what_you_use::IwyuBaseAstVisitor<include_what_you_use::InstantiatedTemplateVisitor>::GetCanonicalUseLocation:
->  0x100006cdc <+688>: movl   0x1c(%rax), %eax
    0x100006cdf <+691>: andl   $0x7f, %eax
    0x100006ce2 <+694>: addl   $-0x34, %eax
    0x100006ce5 <+697>: cmpl   $0x5, %eax
Target 0: (include-what-you-use) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x1c)
  * frame #0: 0x0000000100006cdc include-what-you-use`include_what_you_use::IwyuBaseAstVisitor<include_what_you_use::InstantiatedTemplateVisitor>::GetCanonicalUseLocation(clang::SourceLocation, clang::NamedDecl const*) + 688
    frame #1: 0x0000000100006640 include-what-you-use`include_what_you_use::IwyuBaseAstVisitor<include_what_you_use::InstantiatedTemplateVisitor>::ReportDeclUse(clang::SourceLocation, clang::NamedDecl const*, char const*, unsigned int) + 140
    frame #2: 0x00000001000063c2 include-what-you-use`include_what_you_use::InstantiatedTemplateVisitor::ReportDeclUse(clang::SourceLocation, clang::NamedDecl const*, char const*, unsigned int) + 220
    frame #3: 0x0000000100040b50 include-what-you-use`include_what_you_use::IwyuBaseAstVisitor<include_what_you_use::InstantiatedTemplateVisitor>::ReportDeclsUse(clang::SourceLocation, std::__1::set<clang::NamedDecl const*, std::__1::less<clang::NamedDecl const*>, std::__1::allocator<clang::NamedDecl const*> > const&) + 54
    frame #4: 0x0000000100040657 include-what-you-use`include_what_you_use::InstantiatedTemplateVisitor::ReplayUsesFromCache(include_what_you_use::FullUseCache const&, clang::NamedDecl const*, clang::SourceLocation) + 243
    frame #5: 0x00000001000400a8 include-what-you-use`include_what_you_use::InstantiatedTemplateVisitor::TraverseExpandedTemplateFunctionHelper(clang::FunctionDecl const*, clang::Type const*) + 150
    frame #6: 0x0000000100047165 include-what-you-use`include_what_you_use::IwyuAstConsumer::HandleFunctionCall(clang::FunctionDecl*, clang::Type const*, clang::Expr const*) + 213
    frame #7: 0x000000010001ed69 include-what-you-use`clang::RecursiveASTVisitor<include_what_you_use::IwyuAstConsumer>::TraverseStmt(clang::Stmt*, llvm::SmallVectorImpl<llvm::PointerIntPair<clang::Stmt*, 1u, bool, llvm::PointerLikeTypeTraits<clang::Stmt*>, llvm::PointerIntPairInfo<clang::Stmt*, 1u, llvm::PointerLikeTypeTraits<clang::Stmt*> > > >*) + 165
    frame #8: 0x000000010001ec23 include-what-you-use`include_what_you_use::BaseAstVisitor<include_what_you_use::IwyuAstConsumer>::TraverseStmt(clang::Stmt*) + 101
    frame #9: 0x000000010001f83d include-what-you-use`clang::RecursiveASTVisitor<include_what_you_use::IwyuAstConsumer>::TraverseBreakStmt(clang::BreakStmt*, llvm::SmallVectorImpl<llvm::PointerIntPair<clang::Stmt*, 1u, bool, llvm::PointerLikeTypeTraits<clang::Stmt*>, llvm::PointerIntPairInfo<clang::Stmt*, 1u, llvm::PointerLikeTypeTraits<clang::Stmt*> > > >*) + 115
    frame #10: 0x000000010001ed69 include-what-you-use`clang::RecursiveASTVisitor<include_what_you_use::IwyuAstConsumer>::TraverseStmt(clang::Stmt*, llvm::SmallVectorImpl<llvm::PointerIntPair<clang::Stmt*, 1u, bool, llvm::PointerLikeTypeTraits<clang::Stmt*>, llvm::PointerIntPairInfo<clang::Stmt*, 1u, llvm::PointerLikeTypeTraits<clang::Stmt*> > > >*) + 165
    frame #11: 0x000000010001ec23 include-what-you-use`include_what_you_use::BaseAstVisitor<include_what_you_use::IwyuAstConsumer>::TraverseStmt(clang::Stmt*) + 101
    frame #12: 0x000000010001f83d include-what-you-use`clang::RecursiveASTVisitor<include_what_you_use::IwyuAstConsumer>::TraverseBreakStmt(clang::BreakStmt*, llvm::SmallVectorImpl<llvm::PointerIntPair<clang::Stmt*, 1u, bool, llvm::PointerLikeTypeTraits<clang::Stmt*>, llvm::PointerIntPairInfo<clang::Stmt*, 1u, llvm::PointerLikeTypeTraits<clang::Stmt*> > > >*) + 115
    frame #13: 0x000000010001ed69 include-what-you-use`clang::RecursiveASTVisitor<include_what_you_use::IwyuAstConsumer>::TraverseStmt(clang::Stmt*, llvm::SmallVectorImpl<llvm::PointerIntPair<clang::Stmt*, 1u, bool, llvm::PointerLikeTypeTraits<clang::Stmt*>, llvm::PointerIntPairInfo<clang::Stmt*, 1u, llvm::PointerLikeTypeTraits<clang::Stmt*> > > >*) + 165
    frame #14: 0x000000010001ec23 include-what-you-use`include_what_you_use::BaseAstVisitor<include_what_you_use::IwyuAstConsumer>::TraverseStmt(clang::Stmt*) + 101
    frame #15: 0x00000001000212d1 include-what-you-use`clang::RecursiveASTVisitor<include_what_you_use::IwyuAstConsumer>::TraverseImplicitCastExpr(clang::ImplicitCastExpr*, llvm::SmallVectorImpl<llvm::PointerIntPair<clang::Stmt*, 1u, bool, llvm::PointerLikeTypeTraits<clang::Stmt*>, llvm::PointerIntPairInfo<clang::Stmt*, 1u, llvm::PointerLikeTypeTraits<clang::Stmt*> > > >*) + 115
    frame #16: 0x000000010001ed69 include-what-you-use`clang::RecursiveASTVisitor<include_what_you_use::IwyuAstConsumer>::TraverseStmt(clang::Stmt*, llvm::SmallVectorImpl<llvm::PointerIntPair<clang::Stmt*, 1u, bool, llvm::PointerLikeTypeTraits<clang::Stmt*>, llvm::PointerIntPairInfo<clang::Stmt*, 1u, llvm::PointerLikeTypeTraits<clang::Stmt*> > > >*) + 165
    frame #17: 0x000000010001ec23 include-what-you-use`include_what_you_use::BaseAstVisitor<include_what_you_use::IwyuAstConsumer>::TraverseStmt(clang::Stmt*) + 101
    frame #18: 0x0000000100020cb4 include-what-you-use`clang::RecursiveASTVisitor<include_what_you_use::IwyuAstConsumer>::TraverseCallExpr(clang::CallExpr*, llvm::SmallVectorImpl<llvm::PointerIntPair<clang::Stmt*, 1u, bool, llvm::PointerLikeTypeTraits<clang::Stmt*>, llvm::PointerIntPairInfo<clang::Stmt*, 1u, llvm::PointerLikeTypeTraits<clang::Stmt*> > > >*) + 134
    frame #19: 0x0000000100020d00 include-what-you-use`include_what_you_use::BaseAstVisitor<include_what_you_use::IwyuAstConsumer>::TraverseCallExpr(clang::CallExpr*) + 26
    frame #20: 0x000000010001ed69 include-what-you-use`clang::RecursiveASTVisitor<include_what_you_use::IwyuAstConsumer>::TraverseStmt(clang::Stmt*, llvm::SmallVectorImpl<llvm::PointerIntPair<clang::Stmt*, 1u, bool, llvm::PointerLikeTypeTraits<clang::Stmt*>, llvm::PointerIntPairInfo<clang::Stmt*, 1u, llvm::PointerLikeTypeTraits<clang::Stmt*> > > >*) + 165
    frame #21: 0x000000010001ec23 include-what-you-use`include_what_you_use::BaseAstVisitor<include_what_you_use::IwyuAstConsumer>::TraverseStmt(clang::Stmt*) + 101
    frame #22: 0x00000001000212d1 include-what-you-use`clang::RecursiveASTVisitor<include_what_you_use::IwyuAstConsumer>::TraverseImplicitCastExpr(clang::ImplicitCastExpr*, llvm::SmallVectorImpl<llvm::PointerIntPair<clang::Stmt*, 1u, bool, llvm::PointerLikeTypeTraits<clang::Stmt*>, llvm::PointerIntPairInfo<clang::Stmt*, 1u, llvm::PointerLikeTypeTraits<clang::Stmt*> > > >*) + 115
    frame #23: 0x000000010001ed69 include-what-you-use`clang::RecursiveASTVisitor<include_what_you_use::IwyuAstConsumer>::TraverseStmt(clang::Stmt*, llvm::SmallVectorImpl<llvm::PointerIntPair<clang::Stmt*, 1u, bool, llvm::PointerLikeTypeTraits<clang::Stmt*>, llvm::PointerIntPairInfo<clang::Stmt*, 1u, llvm::PointerLikeTypeTraits<clang::Stmt*> > > >*) + 165
    frame #24: 0x000000010001ec23 include-what-you-use`include_what_you_use::BaseAstVisitor<include_what_you_use::IwyuAstConsumer>::TraverseStmt(clang::Stmt*) + 101
    frame #25: 0x000000010001f83d include-what-you-use`clang::RecursiveASTVisitor<include_what_you_use::IwyuAstConsumer>::TraverseBreakStmt(clang::BreakStmt*, llvm::SmallVectorImpl<llvm::PointerIntPair<clang::Stmt*, 1u, bool, llvm::PointerLikeTypeTraits<clang::Stmt*>, llvm::PointerIntPairInfo<clang::Stmt*, 1u, llvm::PointerLikeTypeTraits<clang::Stmt*> > > >*) + 115
    frame #26: 0x000000010001ed69 include-what-you-use`clang::RecursiveASTVisitor<include_what_you_use::IwyuAstConsumer>::TraverseStmt(clang::Stmt*, llvm::SmallVectorImpl<llvm::PointerIntPair<clang::Stmt*, 1u, bool, llvm::PointerLikeTypeTraits<clang::Stmt*>, llvm::PointerIntPairInfo<clang::Stmt*, 1u, llvm::PointerLikeTypeTraits<clang::Stmt*> > > >*) + 165
    frame #27: 0x000000010001ec23 include-what-you-use`include_what_you_use::BaseAstVisitor<include_what_you_use::IwyuAstConsumer>::TraverseStmt(clang::Stmt*) + 101
    frame #28: 0x000000010001f83d include-what-you-use`clang::RecursiveASTVisitor<include_what_you_use::IwyuAstConsumer>::TraverseBreakStmt(clang::BreakStmt*, llvm::SmallVectorImpl<llvm::PointerIntPair<clang::Stmt*, 1u, bool, llvm::PointerLikeTypeTraits<clang::Stmt*>, llvm::PointerIntPairInfo<clang::Stmt*, 1u, llvm::PointerLikeTypeTraits<clang::Stmt*> > > >*) + 115
    frame #29: 0x000000010001ed69 include-what-you-use`clang::RecursiveASTVisitor<include_what_you_use::IwyuAstConsumer>::TraverseStmt(clang::Stmt*, llvm::SmallVectorImpl<llvm::PointerIntPair<clang::Stmt*, 1u, bool, llvm::PointerLikeTypeTraits<clang::Stmt*>, llvm::PointerIntPairInfo<clang::Stmt*, 1u, llvm::PointerLikeTypeTraits<clang::Stmt*> > > >*) + 165
    frame #30: 0x000000010001ec23 include-what-you-use`include_what_you_use::BaseAstVisitor<include_what_you_use::IwyuAstConsumer>::TraverseStmt(clang::Stmt*) + 101
    frame #31: 0x000000010001f83d include-what-you-use`clang::RecursiveASTVisitor<include_what_you_use::IwyuAstConsumer>::TraverseBreakStmt(clang::BreakStmt*, llvm::SmallVectorImpl<llvm::PointerIntPair<clang::Stmt*, 1u, bool, llvm::PointerLikeTypeTraits<clang::Stmt*>, llvm::PointerIntPairInfo<clang::Stmt*, 1u, llvm::PointerLikeTypeTraits<clang::Stmt*> > > >*) + 115
    frame #32: 0x000000010001ed69 include-what-you-use`clang::RecursiveASTVisitor<include_what_you_use::IwyuAstConsumer>::TraverseStmt(clang::Stmt*, llvm::SmallVectorImpl<llvm::PointerIntPair<clang::Stmt*, 1u, bool, llvm::PointerLikeTypeTraits<clang::Stmt*>, llvm::PointerIntPairInfo<clang::Stmt*, 1u, llvm::PointerLikeTypeTraits<clang::Stmt*> > > >*) + 165
    frame #33: 0x000000010001ec23 include-what-you-use`include_what_you_use::BaseAstVisitor<include_what_you_use::IwyuAstConsumer>::TraverseStmt(clang::Stmt*) + 101
    frame #34: 0x000000010004aa16 include-what-you-use`clang::RecursiveASTVisitor<include_what_you_use::IwyuAstConsumer>::TraverseFunctionHelper(clang::FunctionDecl*) + 602
    frame #35: 0x000000010001db95 include-what-you-use`clang::RecursiveASTVisitor<include_what_you_use::IwyuAstConsumer>::TraverseFunctionDecl(clang::FunctionDecl*) + 51
    frame #36: 0x000000010001c19b include-what-you-use`clang::RecursiveASTVisitor<include_what_you_use::IwyuAstConsumer>::TraverseDecl(clang::Decl*) + 1133
    frame #37: 0x0000000100008b4d include-what-you-use`include_what_you_use::BaseAstVisitor<include_what_you_use::IwyuAstConsumer>::TraverseDecl(clang::Decl*) + 99
    frame #38: 0x0000000100048ec9 include-what-you-use`clang::RecursiveASTVisitor<include_what_you_use::IwyuAstConsumer>::TraverseDeclContextHelper(clang::DeclContext*) + 101
    frame #39: 0x000000010001eb52 include-what-you-use`clang::RecursiveASTVisitor<include_what_you_use::IwyuAstConsumer>::TraverseTranslationUnitDecl(clang::TranslationUnitDecl*) + 248
    frame #40: 0x000000010001c3de include-what-you-use`clang::RecursiveASTVisitor<include_what_you_use::IwyuAstConsumer>::TraverseDecl(clang::Decl*) + 1712
    frame #41: 0x0000000100008b4d include-what-you-use`include_what_you_use::BaseAstVisitor<include_what_you_use::IwyuAstConsumer>::TraverseDecl(clang::Decl*) + 99
    frame #42: 0x00000001000055e6 include-what-you-use`include_what_you_use::IwyuAstConsumer::HandleTranslationUnit(clang::ASTContext&) + 218
    frame #43: 0x00000001040d3d36 libclang-cpp.dylib`clang::ParseAST(clang::Sema&, bool, bool) + 534
    frame #44: 0x0000000105bb15fb libclang-cpp.dylib`clang::FrontendAction::Execute() + 75
    frame #45: 0x0000000105b1d24c libclang-cpp.dylib`clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) + 572
    frame #46: 0x0000000100004c49 include-what-you-use`main + 347
    frame #47: 0x00000001001b94fe dyld`start + 462

@kimgr
Copy link
Contributor

kimgr commented Feb 6, 2022

Thanks! I can't say I understand what's wrong anyway but this looks like a problem in IWYU, not in upstream, so that's really useful information.

kimgr added a commit to kimgr/include-what-you-use that referenced this issue May 19, 2022
For instantiated templates, CanIgnoreDecl is quite sophisticated and uses a
set to ignore subtrees we've visited before.

Non-template code only allows the null decl pointer to be ignored. It's funny
it's taken so long to notice this, but there are cases in templated code where
the decl can be null as well -- most prominently for builtin types.

With this test input:

  $ cat t.cc
  #include <algorithm>
  #include <cassert>
  #include <vector>

  void f() {
    std::vector<int> v;
    assert(std::none_of(v.cbegin(), v.cend(),
                        [](auto value) { return value == 100; }));
  }

  $ include-what-you-use -stdlib=libc++ t.cc

std::vector::const_iterator collapses to a 'const int *', which has no
declaration, and so yields a null decl. Prior to this fix, that would lead to a
cast assertion or segfault attempting to cast the resulting null pointer to a
NamedDecl.

I have not found a way to capture this in a reduced testcase.

Fixes include-what-you-use#989.
@kimgr
Copy link
Contributor

kimgr commented May 19, 2022

I believe the small fix in #1051 should close this.

@kimgr kimgr added this to the iwyu 0.19 milestone May 19, 2022
kimgr added a commit to kimgr/include-what-you-use that referenced this issue May 27, 2022
Non-template code only allows the null decl pointer to be ignored.

For instantiated templates, CanIgnoreDecl is quite sophisticated and uses a
set to ignore subtrees we've visited before, but it doesn't explicitly ignore
the null decl.

There are cases in templated code where the decl can be null as well -- most
prominently for builtin types.

With this test input:

  $ cat t.cc
  #include <algorithm>
  #include <cassert>
  #include <vector>

  void f() {
    std::vector<int> v;
    assert(std::none_of(v.cbegin(), v.cend(),
                        [](auto value) { return value == 100; }));
  }

  $ include-what-you-use -stdlib=libc++ t.cc

(note the explicit use of libc++)

std::vector<int>::const_iterator collapses to a 'const int *', which has no
declaration, and so yields a null decl. Prior to this fix, that would lead to a
cast assertion or segfault attempting to cast the resulting null pointer to a
NamedDecl.

Add an assertion for non-null to GetCanonicalUseLocation to clarify that
null filtering should happen before needing the use-location.

I have not found a way to capture this in a reduced testcase.

Fixes include-what-you-use#989.
kimgr added a commit to kimgr/include-what-you-use that referenced this issue May 27, 2022
Non-template code only allows the null decl pointer to be ignored.

For instantiated templates, CanIgnoreDecl is quite sophisticated and uses a
set to ignore subtrees we've visited before, but it doesn't explicitly ignore
the null decl.

There are cases in templated code where the decl can be null as well -- most
prominently for builtin types.

With this test input:

  $ cat t.cc
  #include <algorithm>
  #include <cassert>
  #include <vector>

  void f() {
    std::vector<int> v;
    assert(std::none_of(v.cbegin(), v.cend(),
                        [](auto value) { return value == 100; }));
  }

  $ include-what-you-use -stdlib=libc++ t.cc

(note the explicit use of libc++)

std::vector<int>::const_iterator collapses to a 'const int *', which has no
declaration, and so yields a null decl. Prior to this fix, that would lead to a
cast assertion or segfault attempting to cast the resulting null pointer to a
FunctionDecl in GetCanonicalUseLocation.

Add an assertion for non-null to GetCanonicalUseLocation to clarify that
null filtering must happen before canonicalizing the use-location.

I have not found a way to capture this in a reduced testcase.

Fixes include-what-you-use#989.
kimgr added a commit that referenced this issue May 27, 2022
Non-template code only allows the null decl pointer to be ignored.

For instantiated templates, CanIgnoreDecl is quite sophisticated and uses a
set to ignore subtrees we've visited before, but it doesn't explicitly ignore
the null decl.

There are cases in templated code where the decl can be null as well -- most
prominently for builtin types.

With this test input:

  $ cat t.cc
  #include <algorithm>
  #include <cassert>
  #include <vector>

  void f() {
    std::vector<int> v;
    assert(std::none_of(v.cbegin(), v.cend(),
                        [](auto value) { return value == 100; }));
  }

  $ include-what-you-use -stdlib=libc++ t.cc

(note the explicit use of libc++)

std::vector<int>::const_iterator collapses to a 'const int *', which has no
declaration, and so yields a null decl. Prior to this fix, that would lead to a
cast assertion or segfault attempting to cast the resulting null pointer to a
FunctionDecl in GetCanonicalUseLocation.

Add an assertion for non-null to GetCanonicalUseLocation to clarify that
null filtering must happen before canonicalizing the use-location.

I have not found a way to capture this in a reduced testcase.

Fixes #989.
@srpgilles
Copy link
Author

srpgilles commented Aug 11, 2022

~~Ok I finally got time to check this and the segmentation fault was actually still there... but this time I understood my blunder quickly: the option I pass for the C++ version namespace was not consistent with the one specified to CMake.

So replacing --cxx17ns with --cxx20ns solves the segmentation fault.

What is surprising though is that IWYU before 0.17 could cope with it...~~

In fact my comment was a bit too hasty here:

  • Putting both references to C++ 17 keeps failing:
set(CMAKE_CXX_STANDARD 17 CACHE STRING "C++ standard; at least 20 is expected.")
set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE /opt/homebrew//bin/include-what-you-use;-Xiwyu;--no_comments;-Xiwyu;--cxx17ns;-Xiwyu;max_line_length=120)

still yields a segmentation fault.

  • Putting both references to C++ 20 compiles... but does not do any work: if I had unneeded includes nothing is seen:
#include <algorithm>
#include <cassert>
#include <vector>
#include <string>
#include <map>

int main()
{
    constexpr auto unused = static_cast<std::size_t>(-1);
    const auto Ndof = 100ul;

    std::vector<std::size_t> mapping(Ndof, unused);

    assert(std::none_of(mapping.cbegin(),
                        mapping.cend(),
                        [](auto value)
                    {
                        return value == unused;
                    }));

    return EXIT_SUCCESS;
}

The reason is likely that the option cxx20ns doesn't exist at all (I get the exact same result if I put cxx36ns...)

@kimgr
Copy link
Contributor

kimgr commented Aug 11, 2022

The reason is likely that the option cxx20ns doesn't exist at all (I get the exact same result if I put cxx36ns...)

Yes. --cxx17ns just means "use C++17-style nested namespaces for forward declarations", and is not intimately tied to the language standard. Your CMake line is still broken there:

set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE
    /opt/homebrew//bin/include-what-you-use;
    -Xiwyu;--no_comments;
    -Xiwyu;--cxx17ns;
    -Xiwyu;max_line_length=120) 

The last argument must be -Xiwyu;--max_line_length=120 with a double-dash before max_line_length. I think in general, the best way is to first invoke include-what-you-use manually (with the cflags from CMake) until the invocation works, and then back-port into CMake.

So which version of IWYU are you running now? Can you show include-what-you-use --version?

@srpgilles
Copy link
Author

srpgilles commented Aug 12, 2022 via email

@kimgr
Copy link
Contributor

kimgr commented Aug 12, 2022

The fix referenced above went into 1375e56, which is after 0.18. So I guess that's expected :-).

@srpgilles
Copy link
Author

Ok said like that seems normal it is there... I will therefore check again when the Homebrew version of IWYU has been updated.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants