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
Comments
I tried reinstalling 0.16 to check: the code above works perfectly fine. |
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? |
@srpgilles This seems like a serious problem, can you please provide more details? Thanks. |
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:
and then the usual
(I have reduced to the minimum the fluff such as using Ninja rather than make and introducing a mapping file). When I run
I have since my post upgraded my OS to macOS Monterey and the issue is still there (and IWYU 0.16 is perfectly fine). |
That command-line is not valid, I'm surprised that runs at all. I think you want something like:
Looking at the output from CMake, then, it appears to run the following command:
I'm not 100% sure how CMake translates that to an
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 If you have I'm interested in that backtrace. |
OK, so removing the 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:
(sorry if I made a blunder in using the debugger - I very seldom use one, and it's never directly in the terminal) |
@srpgilles It looks like you're running the debugger on the |
Sorry I was too hasty. Here is the full output:
|
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. |
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.
I believe the small fix in #1051 should close this. |
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.
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.
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.
~~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 What is surprising though is that IWYU before 0.17 could cope with it...~~ In fact my comment was a bit too hasty here:
still yields a segmentation fault.
The reason is likely that the option |
Yes.
The last argument must be So which version of IWYU are you running now? Can you show |
Thanks for the correction and the explanation about cxx17ns!
The IWYU I tried out yesterday was the most recent I could find through Homebrew:
include-what-you-use 0.18 based on Homebrew clang version 14.0.6
I ended up setting as on my previous computer the last working IWYU:
include-what-you-use 0.16 based on Homebrew clang version 12.0.1
|
The fix referenced above went into 1375e56, which is after 0.18. So I guess that's expected :-). |
Ok said like that seems normal it is there... I will therefore check again when the Homebrew version of IWYU has been updated. Thanks! |
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:
This segmentation fault is highly specific:
assert
command, no segmentation fault.auto is_unused = [](auto value) {... }
and then useis_unused
in thestd::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.The text was updated successfully, but these errors were encountered: