Clang refuses to compile libstdc++'s <filesystem> header - c++

Consider this minimal example:
#include <filesystem>
#include <iostream>
int main()
{
std::cout << std::filesystem::current_path() << '\n';
}
It works as expected in GCC 9.2, but Clang 8.0.1 refuses to compile the <filesystem> header (from GCC 9.2's libstdc++):
# clang++ 1.cpp -std=c++17
In file included from 1.cpp:1:
In file included from Z:\Lander\msys2\mingw64\include\c++\9.2.0\filesystem:37:
Z:\Lander\msys2\mingw64\include\c++\9.2.0\bits/fs_path.h:636:31: error: invalid use of incomplete
type 'std::filesystem::__cxx11::filesystem_error'
_GLIBCXX_THROW_OR_ABORT(filesystem_error(
^~~~~~~~~~~~~~~~~
Z:\Lander\msys2\mingw64\include\c++\9.2.0\x86_64-w64-mingw32\bits/c++config.h:177:49: note: expanded
from macro '_GLIBCXX_THROW_OR_ABORT'
# define _GLIBCXX_THROW_OR_ABORT(_EXC) (throw (_EXC))
^~~~
Z:\Lander\msys2\mingw64\include\c++\9.2.0\bits/fs_fwd.h:61:9: note: forward declaration of
'std::filesystem::__cxx11::filesystem_error'
class filesystem_error;
^
1 error generated.
Is it a Clang bug, or a libstdc++ bug?
I found this bug report on MSYS2 bug tracker, but there is no useful information in there.
Is there a way to patch <filesystem> header to get rid of this error, while we're waiting for an official fix?
I'm on Windows. I'm using latest GCC & Clang available in MSYS2 packages.
GCC identifies as:
# g++ --version
g++.exe (Rev2, Built by MSYS2 project) 9.2.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Clang identifies as:
# clang++ --version
clang version 8.0.1 (tags/RELEASE_801/final)
Target: x86_64-w64-windows-gnu
Thread model: posix
InstalledDir: Z:\Lander\msys2\mingw64\bin
Clang uses libstdc++ that comes with this GCC.

The issue can be fixed by patching <msys2_path>/mingw64/include/c++/9.2.0/bits/fs_path.h.
At lines 666-692, there is a definition of class filesystem_error. It has to be moved up to line 614, to be right above the definition of u8path().
I think it's a libstdc++ bug. I've reported it here.
class filesystem_error is used several times in bits/fs_path.h, and every use of it is below the definition, except for the problematic line 636.
That line is wrapped in #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS, so I guess the Clang developers don't run libstdc++ compatibility tests on Windows.
UPD: This is fixed in GCC 9.3.

Related

How to configure g++ as the default compiler in Mac OS (M1)

So, I wanted to use some header files native to GNU C++:
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
I read that in MacOS, gcc and g++ are both linked to clang. So, we had to install the gcc using homebrew and use that.
But after installing gcc using homebrew. When I run
g++ --version
I get
Apple clang version 12.0.5 (clang-1205.0.22.9)
Target: arm64-apple-darwin22.1.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
But running g++-12 --version I get:
g++-12 (Homebrew GCC 12.2.0) 12.2.0
Copyright (C) 2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
My VSCode runs g++ (Apple One) to compile C/C++ files. For the goal I wanted to accomplish at the start, I read that we need to have the g++ (installed using homebrew) do the compiling.
So, I ran the following commands:
cd /opt/homebrew/bin
ls -s g++-12 g++
But now, even when I compile the following code:
#include <iostream>
int main()
{
std::cout << 1;
}
I get the following error:
In file included from /opt/homebrew/Cellar/gcc/12.2.0/include/c++/12/bits/postypes.h:40,
from /opt/homebrew/Cellar/gcc/12.2.0/include/c++/12/iosfwd:40,
from /opt/homebrew/Cellar/gcc/12.2.0/include/c++/12/ios:38,
from /opt/homebrew/Cellar/gcc/12.2.0/include/c++/12/ostream:38,
from /opt/homebrew/Cellar/gcc/12.2.0/include/c++/12/iostream:39,
from test.cpp:1:
/opt/homebrew/Cellar/gcc/12.2.0/include/c++/12/cwchar:44:10: fatal error: wchar.h: No such file or directory
44 | #include <wchar.h>
| ^~~~~~~~~
compilation terminated.
Now, removing the link using rm g++ reverts back to my original configuration. But that configuration can't run the headers I requested at the start. Is there any way to solve this?
Most of the above have mostly been taken from here. But I didn't find any solution. But, I have seen people using the same and getting successful.
EDIT:
I found a website where there was a solution. It was to compile not using g++. Rather use
g++-12 --sysroot=$(xcrun --show-sdk-path)
When I used this, it solved the problem. Can someone explain why this happened?
The header error likely indicates the g++ you installed via Homebrew may not be compatible with the Apple Xcode version installed in the macos system directories.
The solution is probably to reinstall one or both packages.
EDIT:
g++-12 --sysroot=$(xcrun --show-sdk-path) changes the search path for system header includes from the default (which was probably set when homebrew installed g++) to the one provided by the Xcode SDK currently installed.

Why does MinGW GCC tolerate missing return types even with `-pedantic-errors`, unlike regular GCC?

Here's the code:
main() {}
On gcc.godbolt.org, both GCC 10.1 and Clang 10 (with -Wall -Wextra -pedantic-errors -std=c++20) refuse to compile this.
GCC: error: ISO C++ forbids declaration of 'main' with no type [-Wpedantic]
Clang: error: C++ requires a type specifier for all declarations
But on my local machine, MinGW GCC happily accepts this code without any errors or warnings (with the same flags). This is not something new; this specific peculiarity was there for years.
Why does MinGW GCC behave differntly from the regular GCC in this case? Are there any flags to make it diagnose this error?
I got my GCC from MSYS2. It identifies as
# g++ --version
g++.exe (Rev3, Built by MSYS2 project) 10.1.0
Copyright (C) 2020 Free Software Foundation, Inc.
Clang 10 on the same machine does reject the code (the official binary, using libstdc++ from this GCC).
As noted by #ssbssa, MinGW GCC enables -fms-extensions by default, and it's one of the effects of that flag.
Compile with -fno-ms-extensions to fix that.

Apple Clang; using C++11 with libstdc++

I have an issue when compiling a simple Hello file with an empty function taking initializer_list argument when using both -stdlib=libstdc++ and -std=c++11
If I use only -std=c++11 (which means compiling with libc++)
then the file compiles and prints Hello!
If I comment function_test and I use both -std=c++11 and -stdlib=libstdc++
then the file compiles and prints Hello!
If I keep the function function_test and I use both -std=c++11 and -stdlib=libstdc++
then I get the following error:
$ g++ -stdlib=libstdc++ -std=c++11 -o test test.cpp
test.cpp:1:10: fatal error: 'initializer_list' file not found
#include <initializer_list>
^
1 error generated.
Here is my file
#include <initializer_list>
#include <iostream>
using namespace std;
void function_test(initializer_list<int> something){}
int main(int argc, char * argv[])
{
cout << "Hello!" << endl;
function_test({0});
return 0;
}
Here is my apple clang version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr
--with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.3.0
Thread model: posix
--with-gxx-include-dir=/usr/include/c++/4.2.1
^^^^^^^
Notice the "4.2". Your libstdc++ is way to old for C++11. Upgrade it to some 5.x version for full C++11 support.
I found out that upgrading to a newer version of libstdc++ is just not possible with apple-llvm(clang). So using some features of C++11 with libstdc++ is not possible. The reason is this one:
Mainline libstdc++ has switched to GPL3, a license which the
developers of libc++ cannot use. libstdc++ 4.2 (the last GPL2 version)
could be independently extended to support C++11, but this would be a
fork of the codebase (which is often seen as worse for a project than
starting a new independent one). Another problem with libstdc++ is
that it is tightly integrated with G++ development, tending to be tied
fairly closely to the matching version of G++.
source:
http://libcxx.llvm.org/docs/
Thanks to all the answers/comments that helped me reach the answer.

Why doesn't g++ (4.9.2) compile (a very simple program)?

My overall problem is trying to install HEALPix C++ version and, to isolate the problem, I created foo.cpp:
#include <string>
#include <iostream>
I then run
g++ foo.cpp
to which I get the following error message:
foo.cpp:1:18: fatal error: string: No such file or directory
#include <string>
^
compilation terminated.
I am running
g++ (GCC) 4.9.2 20141029 (prerelease)
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
downloaded from http://hpc.sourceforge.net/
on OS X Yosemite 10.10
I get the same error message with gcc 5.0 and 4.8 as well. I tried downloading gcc 4.9 from homebrew but this also doesn't work (though with a different error message).
I then try
g++ -I/usr/local/include/c++/4.9.2 foo.cpp
to which I get the error message:
In file included from foo.cpp:1:0:
/usr/local/include/c++/4.9.2/string:38:28: fatal error: bits/c++config.h: No such file
or directory
#include <bits/c++config.h>
^
compilation terminated.
Now, obviously, I don't want to have to find (recursively) the directory of each required header (for my HEALPix installation, this could take forever!) It seems to me that there is a problem with where #include is looking? How can I change this? Also, if the workaround is to specify the directories of required headers, it is not immediately obvious to me how to specify this within my configuration for the HEALPix installation.
Hope someone can suggest a solution!
Thanks

clang seems to use the gcc libraries

This is the first time I use clang. What I notices is that any error from clang referencing the std library looks like this:
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/ostream:245:7:
^^^ ^^^ ^^^
So it looks like clang links — or at least includes — the gcc libraries.
The command I used: clang++ -c -Wall -Wextra -Werror -g test.cpp -o test.o. (The program had a intentional error just to prove this).
How is this possible? What can I do to make clang use its own libraries (but not break gcc)?
Additional information:
I am on a Ubuntu 14.04 machine.
clang++ --version
Ubuntu clang version 3.5-1ubuntu1 (trunk) (based on LLVM 3.5)
Target: x86_64-pc-linux-gnu
Thread model: posix
g++ --version
g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2
Copyright (C) 2013 Free Software Foundation, Inc.
I had previously installed several versions (at the same time, used them with update-alternatives) of gcc with apt-get. Right now I have only 4.8 (I have uninstalled the others). Could I have messed up something then? I have never installed clang (I guess it is default with Ubuntu).
Just to clarify: the correct programs compile and run in clang++.
Further tests: I know that gcc didn’t implement yet types like is_trivially_constructible and move operations on iostream in their standard c++11 library (https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html) and that clang has full c++11 conforming library so I tested those compiling with clang and I got the corresponding gcc errors, which only confirms that clang is using gcc libraries.
A very basic program
#include <iostream>
using namespace std;
int main() {
cout << "Yada Yada" << endl;
return 0;
}
gives this error when compiling with -std=c++1y in clang++:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/iostream:39:
...
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/cstdio:120:11: error: no member named 'gets' in the global namespace
using ::gets;
~~^
So right now I can’t compile anything with c++1y in clang.
You need to install libc++ and make clang use it with -stdlib=libc++
I had similar issue: GCC (g++) already was installed on my LinuxMint (Ubuntu base) so when compile with clang, was getting an " error: no member named 'gets' in the global namespace using ::gets ".
resolved by installing libc++-dev (sudo apt-get install libc++-dev) and compiling with -stdlib++ (clang++ -g -std=c++1y -stdlib=libc++ helloworld.cpp -o helloworld)
Your real problem is that you're using C++14 (c++1y was the informal name used to refer to it when it wasn't yet fully formed), with a C++ library belonging to GCC 4.8. GCC 4.8 has complete C++11 support, but hardly even started on C++14 features.
This is caused by C++14 removing std::gets, and the GNU C library anticipating on that by not defining gets in the global namespace while the C++ library has not yet caught up and is trying to make it available in the std namespace.
The proper way to solve this does not require using libc++, just to use a C++ library with C++14 support. GLIBCXX 4.9 (aka libstdc++) already suffices.