Linker error with clang++ for some standard library classes - c++

I am facing a weird linker issue with clang++ - it is able to find the definition of std::string class but not of std::ios_base::failure class.
$ cat foo.cpp
#include <string>
#include <iostream>
int main()
{
std::string msg = "hello world";
std::ios_base::failure f(msg);
std::cout << msg << std::endl;
return 0;
}
$ clang++ foo.cpp
/tmp/foo-b77625.o: In function `main':
foo.cpp:(.text+0x4d): undefined reference to `std::ios_base::failure::failure(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
clang-3.7: error: linker command failed with exit code 1 (use -v to see invocation)
$ clang++ --version
clang version 3.7.0 (trunk 239466)
Target: x86_64-unknown-linux-gnu
Thread model: posix
I noticed that if I comment the instantiation of std::ios_base::failure, the program links (and executes) correctly.
$ clang++ foo.cpp && ./a.out
hello world
Can someone please help me understand this behavior and how to fix it?
P.S. I observed the same behavior with clang version 3.6.0 as well.

Assuming you are intent on using clang's own standard-library (libc++), then you are not far off - you will have to provide the include-path of the standard-library (where ever your libcxx-build installed to):
$> clang++ foo.cpp -stdlib=libc++ -I/path/to/libcxx-build/include/c++/v1
(add "-v" switch to the above, if you want verbose output).
P.S. unless the includes go elsewhere for your clang-3.7, the above aught to work - as tested with my clang-3.8

Try adding the include at the beginning of your fie
#include <ios>
According to cpprefrence it is defined in the header <ios>

Related

How to link libcxx application to a C++ library compiled with gcc

I am trying to link an application that is compiled with clang/libc++ to the v8-devel system library on Fedora. However the latter is compiled with gcc/libstdc++ which leads to a linking error for std::unique_ptr, I think due to inlining.
Is there anything I can change in eiher my application code, or the compiler/linker flags (other than -stdlib) , such that my program can be linked to v8-devel while being still compiled with clang+libcxx?
Below a minimal toy example to reproduce the problem on Fedora (in reality, the only compiler that I have available is a custom clang version with libcxx, so switching to libstdc++ is not an option):
#include <libplatform/libplatform.h>
#include <v8.h>
using namespace v8;
int main(){
std::unique_ptr<Platform> platform = platform::NewDefaultPlatform();
V8::InitializePlatform(platform.get());
}
Then on Fedora we do:
# Install dependencies
yum install -y clang libcxx-devel v8-devel
# Try to compile test program
clang++ test.cpp -std=gnu++17 -stdlib=libc++ -lv8 -lv8_libplatform
Which gives the following linker error:
/usr/bin/ld: /tmp/test-9925a1.o: in function `main':
test.cpp:(.text+0x24): undefined reference to `v8::platform::NewDefaultPlatform(int, v8::platform::IdleTaskSupport, v8::platform::InProcessStackDumping, std::__1::unique_ptr<v8::TracingController, std::__1::default_delete<v8::TracingController> >)'
clang-14: error: linker command failed with exit code 1 (use -v to see invocation)
You can automatically run the steps above using this Dockerfile.

Unable to use aligned `operator new` in a module with Clang

I'm experimenting with Clang "modules" feature, and I'm trying to compile following piece of code:
export module a;
#include <new>
export void *foo()
{
return ::operator new(1, std::align_val_t(1));
}
export int main() {}
Try it live
When I tried clang++ -std=c++2a -pedantic-errors -fmodules-ts --precompile -x c++-module a.cpp -o a.pcm, I got
error: ISO C++ requires a definition in this translation unit for function 'operator new'
because its type does not have linkage [-Werror,-Wundefined-internal-type]
a.cpp:7:14: note: used here
return ::operator new(1, std::align_val_t(1));
^
1 error generated.
Removing -pedantic-errors fixes the error, but when I try to link the resulting module using clang++ -std=c++2a -fmodules-ts a.pcm -o a.exe, I get
Z:\Lander\msys2\tmp\a-cfaf65.o:a.pcm:(.text+0x10): undefined reference to
`_ZnwyW1aESt11align_val_t'
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
It's especially annoying since <iostream> (indirectly) seems to rely on the aligned operator new, so I can't use it in modules too. As well as some other standard headers.
What's going on here?
It it's a Clang bug, how can I work around it?
My Clang is the latest version provided by MSYS2:
# clang++ --version
clang version 8.0.0 (tags/RELEASE_800/final)
Target: x86_64-w64-windows-gnu
Thread model: posix
EDIT:
Filed a bug report, let's see what happens...
The standard library isn't part of your module a. So don't include the header after the export module a;. Include the header before that.

Compile error: 'stoi' is not a member of 'std'

My code:
#include <iostream>
#include <string>
int main()
{
std::string test = "45";
int myint = std::stoi(test);
std::cout << myint << '\n';
}
Gives me the compile error:
error: 'stoi' is not a member of 'std'
int myint = std::stoi(test);
^
However, according to here, this code should compile fine. I am using the line set(CMAKE_CXX_FLAGS "-std=c++11 -O3") in my CMakeLists.txt file.
Why is it not compiling?
Update: I am using gcc, and running gcc --version prints out:
gcc (Ubuntu 5.2.1-22ubuntu2) 5.2.1 20151010
In libstdc++, the definitions of stoi, stol, etc., as well as the to_string functions, are guarded by the condition
#if ((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \
&& !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF))
I have had this fail on one platform before (namely Termux on Android), resulting in to_string not being available even with g++ 6.1 and the C++14 standard. In that case, I just did
#define _GLIBCXX_USE_C99 1
before including anything, and voilà, suddenly the functions existed. (You should put this first, or even on the command line, rather than just before including <string>, because another header may include <string> first, and then its include guards will keep it from ever seeing your macro.)
I did not investigate why this macro wasn't set in the first place. Obviously this is a cause for concern if you want your code to actually work (in my case I didn't particularly, but FWIW there were no problems.)
You should check if _GLIBCXX_USE_C99 is not defined, or if _GLIBCXX_HAVE_BROKEN_VSWPRINTF is defined (which may be the case on MinGW?)
std::stoi is a C++11 function. You have to use the -std=c++11 to enable it in both g++ and clang++. This is the actual issue, not a linking error or a specific preprocessor define.
$ cat test.cxx
#include <iostream>
#include <string>
int main()
{
std::string test = "45";
int myint = std::stoi(test);
std::cout << myint << '\n';
}
$ g++ -otest test.cxx
test.cxx: In Funktion »int main()«:
test.cxx:7:17: Fehler: »stoi« ist kein Element von »std«
int myint = std::stoi(test);
^
$ g++ -otest test.cxx -std=c++11
$ ./test
45
$
edit: I just saw that you used c++11. Are you sure that's making it into your compile options? Check the generated makefile and watch the executed commands to be certain.
Your version seems up to date, so there shouldn't be an issue. I think it may be related to gcc. Try g++ instead.(Most likely automatically linking issue. If you just run gcc on a C++ file, it will not 'just work' like g++ does. That's because it won't automatically link to the C++ std library, etc.). My second advise is try std::atoi.
# I have fixed the issue. std::stoi uses libstdc++. It is about The GNU Standard C++ Library. In gcc you have to link adding -lstdc++. However, in g++, libstdc++ is linked automatically.
using gcc and using g++
Pay attention how it is compiled
using g++: g++ -std=c++11 -O3 -Wall -pedantic main.cpp && ./a.out
using gcc: gcc -std=c++11 -O3 -Wall -pedantic -lstdc++ main.cpp && ./a.out
I think you should set flag like set(CMAKE_EXE_LINKER_FLAGS "-libgcc -lstdc++") (Not tested)
#include <cstdlib>
int myInt = std::atoi(test.c_str());
If you are using Cmake to compile, add line:
"add_definitions(-std=c++11)"
after find_package command.
Use 'set(CMAKE_CXX_STANDARD 11)' for Cmake

How to compile boost unit test module with clang++?

I'm trying to compile a boost unit test module with cmake and clang but ran into a linker error. I was able to produce the following minimal test case:
$ cat boost_test_test.cc
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE scanio
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_CASE(foo) { BOOST_CHECK(1); }
This compiles fine with g++:
$ g++ boost_test_test.cc -lboost_unit_test_framework
$ echo $?
0
But it does not with clang++:
$ /usr/bin/clang++-3.7 boost_test_test.cc -lboost_unit_test_framework
/tmp/boost_test_test-7e4892.o: In function `boost::unit_test::make_test_case(boost::unit_test::callback0<boost::unit_test::ut_detail::unused> const&, boost::unit_test::basic_cstring<char const>)':
boost_test_test.cc:(.text._ZN5boost9unit_test14make_test_caseERKNS0_9callback0INS0_9ut_detail6unusedEEENS0_13basic_cstringIKcEE[_ZN5boost9unit_test14make_test_caseERKNS0_9callback0INS0_9ut_detail6unusedEEENS0_13basic_cstringIKcEE]+0x58): undefined reference to `boost::unit_test::ut_detail::normalize_test_case_name(boost::unit_test::basic_cstring<char const>)'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
So during the linker stage I get an undefined reference error and this problem persists no matter the order of arguments to clang++.
Since it works fine with g++ I suppose there is something clang++ specific going on here?
This is with g++ 5.2.1, clang++ 3.7 and boost 1.58 on Debian Sid.
In Ubuntu Willy, Boost 1.58 Unit Test library is compiled with GCC 5.0. The library file libboost_unit_test_framework.a contains the mangled function _ZN5boost9unit_test9ut_detail24normalize_test_case_nameB5cxx11ENS0_13basic_cstringIKcEE that resolves to boost::unit_test::ut_detail::normalize_test_case_name[abi:cxx11](boost::unit_test::basic_cstring<char const>)
However, CLang does not seem to use the new ABI, so it searches for _ZN5boost9unit_test9ut_detail24normalize_test_case_nameENS0_13basic_cstringIKcEE, which is boost::unit_test::ut_detail::normalize_test_case_name(boost::unit_test::basic_cstring<char const>).
In order to overcome this, define your own function in the test file:
namespace boost { namespace unit_test { namespace ut_detail {
std::string normalize_test_case_name(const_string name) {
return ( name[0] == '&' ? std::string(name.begin()+1, name.size()-1) : std::string(name.begin(), name.size() ));
}
}}}
This should resolve the issue. If compiled with the same version of the compiler as Boost, it should be no problem, as the linker will simply ignore the library version of the function.

What library do I need to link to use std::list in clang++?

I am trying to use the std::list class in C++, and I need to use clang++ to compile the program. g++ compiles the following program just fine, but I can't figure out how to compile/link it with clang++:
#include <iostream>
#include <list>
int main(){
std::list<int> L;
L.push_back(10);
std::cout << L.back() << std::endl;
return 0;
}
I've tried clang++ -lstdc++ listTest.cpp but still get the following error:
/tmp/listTest-3175a9.o: In function `std::list<int, std::allocator<int> >::_M_insert(std::_List_iterator<int>, int const&)':
listTest.cpp:(.text._ZNSt4listIiSaIiEE9_M_insertESt14_List_iteratorIiERKi[_ZNSt4listIiSaIiEE9_M_insertESt14_List_iteratorIiERKi]+0x31): undefined reference to `std::__detail::_List_node_base::_M_hook(std::__detail::_List_node_base*)'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Clang version:
clang version 3.4 (tags/RELEASE_34/final)
linux version:
LSB_VERSION=base-4.0-amd64:base-4.0-noarch:core-4.0-amd64:core-4.0-noarch:graphics-4.0-amd64:graphics-4.0-noarch:printing-4.0-amd64:printing-4.0-noarch
Red Hat Enterprise Linux Server release 6.5 (Santiago)
You should provide library arguments after the translation unit that uses them:
clang++ listTest.cpp -lstdc++
I should note that I couldn't reproduce your issue, but that could easily be down to differences in version/configuration (particularly w.r.t. a stdlib implementation selected for use by default).
I solved it on mine (redhat, clang 3.4, gcc 4.7.2).
By default this project was linking against /usr/lib/libstdc++. I have a build of gcc 4.7.2 installed in a separate location; when I add lines analogous to the following to the link step it works fine
-L${GCC_PATH}/lib -Wl,-R${GCC_PATH}/lib
... provided they appear in the link step before analogous statements for /usr/lib.
edit
You can use strace to help diagnose this problem; I did something like the following:
// copy the link step into a temp shell script
strace -f ./temp.sh |& grep -P 'lib(std)?c\+\+'
... which is when I realized I probably needed a different build of the C++ runtime because I saw it was finding and linking against the one in /usr/lib.