[Bug 1199943] New: clangd does not understand C++17
http://bugzilla.opensuse.org/show_bug.cgi?id=1199943 Bug ID: 1199943 Summary: clangd does not understand C++17 Classification: openSUSE Product: openSUSE Tumbleweed Version: Current Hardware: x86-64 OS: openSUSE Tumbleweed Status: NEW Severity: Normal Priority: P5 - None Component: Development Assignee: screening-team-bugs@suse.de Reporter: andreas_nordal_4@hotmail.com QA Contact: qa-bugs@suse.de Found By: --- Blocker: --- I'm using (KDE) Kate's LSP client, which uses clangd to understand my code. Despite that clangd appears to find the correct compile_commands.json (it's able to find headers in nonstandard locations for example), it does not honor the "-std=c++17" argument in it. Minimal reproducer: /tmp/compile_commands.json: [{ "directory": "/tmp", "command": "g++ -std=c++17 -Iweird_include -c takes_string_view.cpp -o takes_string_view.o", "file": "takes_string_view.o" }] /tmp/weird_include/weird_header.h: // empty /tmp/takes_string_view.cpp: #include <string> #include <string_view> #include <weird_header.h> // works void f(std::string); // works void f(std::string_view); // No type named 'string_view' in namespace 'std' In case I had any old headers, I have uninstalled all old compilers and related libraries, so I only have g++12 and clang++14 left. Didn't help. -- You are receiving this mail because: You are on the CC list for the bug.
http://bugzilla.opensuse.org/show_bug.cgi?id=1199943 http://bugzilla.opensuse.org/show_bug.cgi?id=1199943#c1 --- Comment #1 from Andreas Nordal <andreas_nordal_4@hotmail.com> --- Same error on Leap 15.3 with g++-7.5.0 and clang++-11.0.1 -- You are receiving this mail because: You are on the CC list for the bug.
http://bugzilla.opensuse.org/show_bug.cgi?id=1199943 http://bugzilla.opensuse.org/show_bug.cgi?id=1199943#c2 --- Comment #2 from Aaron Puchert <aaronpuchert@alice-dsl.net> --- (In reply to Andreas Nordal from comment #0)
Minimal reproducer:
/tmp/compile_commands.json:
[{ "directory": "/tmp", "command": "g++ -std=c++17 -Iweird_include -c takes_string_view.cpp -o takes_string_view.o", "file": "takes_string_view.o" }]
What if you use clang++ instead of g++? Not sure how clangd reads that file, it might ignore some flags if the compiler isn't clang, as GCC and Clang flags aren't fully compatible. If that doesn't work, please try passing --log=info or --log=verbose to clangd itself (not via compile_commands.json), maybe that gives us more information. -- You are receiving this mail because: You are on the CC list for the bug.
http://bugzilla.opensuse.org/show_bug.cgi?id=1199943 http://bugzilla.opensuse.org/show_bug.cgi?id=1199943#c3 --- Comment #3 from Andreas Nordal <andreas_nordal_4@hotmail.com> --- clang++: Same story, as expected (I only used options in compile_commands.json that both compilers support). I found a way to eliminate the editor from the equation: clangd --check=takes_string_view.cpp Output of that on openSUSE Leap 15.4: I[19:42:18.098] clangd version 13.0.1 I[19:42:18.099] Features: linux I[19:42:18.099] PID: 19436 I[19:42:18.099] Working directory: /tmp I[19:42:18.099] argv[0]: clangd I[19:42:18.099] argv[1]: --log=info I[19:42:18.099] argv[2]: --check=takes_string_view.cpp I[19:42:18.099] Entering check mode (no LSP server) I[19:42:18.099] Testing on source file /tmp/takes_string_view.cpp I[19:42:18.099] Loading compilation database... I[19:42:18.099] Loaded compilation database from /tmp/compile_commands.json I[19:42:18.100] Compile command from CDB is: /usr/bin/clang++ --driver-mode=g++ -Iweird_include -c -resource-dir=/usr/lib64/clang/13.0.1 -- /tmp/takes_string_view.cpp I[19:42:18.100] Parsing command... I[19:42:18.101] internal (cc1) args are: -cc1 -triple x86_64-suse-linux-gnu -fsyntax-only -disable-free -disable-llvm-verifier -discard-value-names -main-file-name takes_string_view.cpp -mrelocation-model static -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/tmp -resource-dir /usr/lib64/clang/13.0.1 -I weird_include -internal-isystem /usr/bin/../lib64/gcc/x86_64-suse-linux/7/../../../../include/c++/7 -internal-isystem /usr/bin/../lib64/gcc/x86_64-suse-linux/7/../../../../include/c++/7/x86_64-suse-linux -internal-isystem /usr/bin/../lib64/gcc/x86_64-suse-linux/7/../../../../include/c++/7/backward -internal-isystem /usr/lib64/clang/13.0.1/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib64/gcc/x86_64-suse-linux/7/../../../../x86_64-suse-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdeprecated-macro -fdebug-compilation-dir=/tmp -ferror-limit 19 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -x c++ /tmp/takes_string_view.cpp I[19:42:18.101] Building preamble... I[19:42:18.250] Indexing headers... I[19:42:18.325] Building AST... E[19:42:18.344] [typename_nested_not_found] Line 7: no type named 'string_view' in namespace 'std' I[19:42:18.344] Indexing AST... I[19:42:18.345] Testing features at each token (may be slow in large files) I[19:42:18.347] All checks completed, 1 errors --log=info is apparently the default (gives the same output). The verbose log is more verbose, but doesn't add more clues that I can see. What I see is that -std=c++17 looks suspiciously absent in those internal args. Indeed, I can reproduce the error by running clang++ with those arguments, and then make it go away by adding -std=c++17! I think I found the missing argument! Dunno how to fix it though. -- You are receiving this mail because: You are on the CC list for the bug.
http://bugzilla.opensuse.org/show_bug.cgi?id=1199943 http://bugzilla.opensuse.org/show_bug.cgi?id=1199943#c4 --- Comment #4 from Aaron Puchert <aaronpuchert@alice-dsl.net> --- (In reply to Andreas Nordal from comment #3)
I[19:42:18.100] Compile command from CDB is: /usr/bin/clang++ --driver-mode=g++ -Iweird_include -c -resource-dir=/usr/lib64/clang/13.0.1 -- /tmp/takes_string_view.cpp
That looks like it's really being dropped. Not nice. I haven't yet figured out why, but looking through clangd/CompileCommands.cpp indicates that -Xclang -std=c++17 should be passed through. That should have the same effect (I think). I tried this locally and get /usr/bin/clang++ --driver-mode=g++ -Xclang -std=c++17 [...] So that should give you a workaround for now. The bug is somewhat perplexing to me, because we don't have any patch in that area, and this bug seems like something many users should notice. But I find no reports of it upstream. -- You are receiving this mail because: You are on the CC list for the bug.
http://bugzilla.opensuse.org/show_bug.cgi?id=1199943 http://bugzilla.opensuse.org/show_bug.cgi?id=1199943#c5 Aaron Puchert <aaronpuchert@alice-dsl.net> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |RESOLVED Resolution|--- |INVALID --- Comment #5 from Aaron Puchert <aaronpuchert@alice-dsl.net> --- (In reply to Andreas Nordal from comment #0)
/tmp/compile_commands.json:
[{ "directory": "/tmp", "command": "g++ -std=c++17 -Iweird_include -c takes_string_view.cpp -o takes_string_view.o", "file": "takes_string_view.o" }]
The "file" needs to be "takes_string_view.cpp" [1]:
file: The main translation unit source processed by this compilation step. This is used by tools as the key into the compilation database. There can be multiple command objects for the same file, for example if the same source file is compiled with different configurations.
Then -std=c++17 is passed through. Possibly clangd thinks that since takes_string_view.o does not have a C++ source file ending, an option like -std=c++17 has to be dropped. (Clang can also process other files, such as assembly .s, LLVM IR .ll/.bc and some more.) [1] https://clang.llvm.org/docs/JSONCompilationDatabase.html#format -- You are receiving this mail because: You are on the CC list for the bug.
http://bugzilla.opensuse.org/show_bug.cgi?id=1199943 http://bugzilla.opensuse.org/show_bug.cgi?id=1199943#c6 --- Comment #6 from Andreas Nordal <andreas_nordal_4@hotmail.com> --- Thanks, Aaron, and sorry, I messed up when reducing the problem. The confusing thing was that clangd defeated my sanity check (-Iweird_include worked when -std=c++17 did not). When reducing the problem again, it seems to be a header name collision between newlib and host headers (cross compilation). I thought I managed to minimize it down to a single header, sys/cdefs.h, but when renaming the include directory (just as a sanity check), the problem evaporated (as if clangd was stateful). New reproducer (not reduced to a single header): Install /usr/riscv64-elf/include zypper in cross-riscv64-newlib-devel /tmp/compile_commands.json: [{ "directory": "/tmp", "command": "clang++ -std=c++17 -isystem /usr/riscv64-elf/include -c takes_string_view.cpp -o takes_string_view.o", "file": "takes_string_view.cpp" }] /tmp/takes_string_view.cpp: #include <cstdlib> // Not relevant, but erases string_view. #include <string_view> void f(std::string_view str); // No member named 'string_view' in namespace 'std' -- You are receiving this mail because: You are on the CC list for the bug.
http://bugzilla.opensuse.org/show_bug.cgi?id=1199943 http://bugzilla.opensuse.org/show_bug.cgi?id=1199943#c7 --- Comment #7 from Aaron Puchert <aaronpuchert@alice-dsl.net> --- (In reply to Andreas Nordal from comment #6)
The confusing thing was that clangd defeated my sanity check (-Iweird_include worked when -std=c++17 did not).
That's indeed confusing.
When reducing the problem again, it seems to be a header name collision between newlib and host headers (cross compilation).
Presumably newlib is a glibc replacement? In that case you might consider adding -nostdinc and specifying all necessary include directories manually to make sure they don't mix.
New reproducer (not reduced to a single header):
Install /usr/riscv64-elf/include
zypper in cross-riscv64-newlib-devel
/tmp/compile_commands.json:
[{ "directory": "/tmp", "command": "clang++ -std=c++17 -isystem /usr/riscv64-elf/include -c takes_string_view.cpp -o takes_string_view.o", "file": "takes_string_view.cpp" }]
/tmp/takes_string_view.cpp:
#include <cstdlib> // Not relevant, but erases string_view. #include <string_view>
void f(std::string_view str); // No member named 'string_view' in namespace 'std'
That doesn't work for me with standalone clang: $ clang++ -std=c++17 -isystem /usr/riscv64-elf/include -c takes_string_view.cpp -o takes_string_view.o In file included from takes_string_view.cpp:1: In file included from /usr/bin/../lib64/gcc/x86_64-suse-linux/12/../../../../include/c++/12/cstdlib:75: /usr/include/stdlib.h:98:53: error: expected function body after function declarator extern size_t __ctype_get_mb_cur_max (void) __THROW __wur; ^ [...] Now line 75 has "#include_next <stdlib.h>", and since it works without "-isystem /usr/riscv64-elf/include", a previous include is the issue. Compiling with -E reveals that we go off the beaten path here: # 490 "/usr/include/features.h" 3 4 # 1 "/usr/riscv64-elf/include/sys/cdefs.h" 1 3 4 Now in glibc's /usr/include/sys/cdefs.h we find # define __wur __attribute_warn_unused_result__ but there is no definition in /usr/riscv64-elf/include/sys/cdefs.h. So I think you need to make sure to not mix glibc and newlib. I'm not sure if libstdc++ can deal with newlib though. Of course with -nostdinc you'll have to add the headers manually, you can find out which with -v on a regular compilation. As a side note: if you're observing the same, what you're seeing is likely just a follow-up error. For IDEs, only errors in the current file are typically printed, and clangd might just swallow all these earlier errors in system headers and print this error when coming back. Another problem: this compiles the riscv64 newlib to your native target. Now I assume that word sizes are the same, but there might be other difficulties. For true cross-compilation you need to add --target=riscv64-suse-linux-gnu. With libstdc++ I then end up with takes_string_view.cpp:1:10: fatal error: 'cstdlib' file not found #include <cstdlib> // Not relevant, but erases string_view. ^~~~~~~~~ because Clang doesn't find the header directories suitable for cross compilation (likely because it doesn't find a replacement for /usr/include/c++/12/x86_64-suse-linux/, not sure where I might get that). With -stdlib=libc++ I end up with lots of errors like this: In file included from takes_string_view.cpp:2: In file included from /usr/bin/../include/c++/v1/string_view:206: In file included from /usr/bin/../include/c++/v1/algorithm:667: In file included from /usr/bin/../include/c++/v1/functional:506: In file included from /usr/bin/../include/c++/v1/__functional/function.h:22: In file included from /usr/bin/../include/c++/v1/__memory/shared_ptr.h:35: In file included from /usr/bin/../include/c++/v1/atomic:524: In file included from /usr/bin/../include/c++/v1/__thread/timed_backoff_policy.h:16: /usr/bin/../include/c++/v1/__threading_support:260:14: error: use of undeclared identifier 'pthread_mutexattr_init'; did you mean 'pthread_mutexattr_t'? int __ec = pthread_mutexattr_init(&attr); ^ /usr/riscv64-elf/include/sys/_pthreadtypes.h:169:3: note: 'pthread_mutexattr_t' declared here } pthread_mutexattr_t; ^ So here it seems like libc++ and newlib are not compatible. Without newlib it boils down to only two: In file included from takes_string_view.cpp:2: In file included from /usr/bin/../include/c++/v1/string_view:205: In file included from /usr/bin/../include/c++/v1/__string:13: In file included from /usr/bin/../include/c++/v1/__algorithm/copy.h:12: In file included from /usr/bin/../include/c++/v1/__algorithm/unwrap_iter.h:14: In file included from /usr/bin/../include/c++/v1/iterator:587: In file included from /usr/bin/../include/c++/v1/__functional_base:25: /usr/bin/../include/c++/v1/typeinfo:246:14: error: cast from pointer to smaller type 'std::__type_info_implementations::__non_unique_arm_rtti_bit_impl::__type_name_t' (aka 'unsigned int') loses information return reinterpret_cast<__type_name_t>(__v); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In file included from takes_string_view.cpp:2: In file included from /usr/bin/../include/c++/v1/string_view:206: In file included from /usr/bin/../include/c++/v1/algorithm:759: /usr/bin/../include/c++/v1/__algorithm/shuffle.h:57:12: error: cast from pointer to smaller type 'uintptr_t' (aka 'unsigned int') loses information return reinterpret_cast<uintptr_t>(&__x); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Still unexpected, but maybe they could be hacked around. In any event, you should check if libstdc++ supports newlib underneath. Those GNU projects tend to be tied together. We can CC the maintainers for libstdc++ if you want. -- You are receiving this mail because: You are on the CC list for the bug.
participants (1)
-
bugzilla_noreply@suse.com