Is clang's c++11 support reliable? - c++

I ran into an interesting issue when trying to mix clang (Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn, Target: x86_64-apple-darwin14.0.0), c++11 and CGAL (via MacPorts).
It seems that whether or not I call std::vector<>::reserve will determine whether my program will even compile.
I've trimmed down the problem into a minimal example (as minimal as CGAL examples get):
#include <vector>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/AABB_tree.h>
#include <CGAL/AABB_traits.h>
#include <CGAL/AABB_triangle_primitive.h>
// CGAL::Epeck works fine, suggesting the problem is in CGAL::Epick
typedef CGAL::Epick Kernel;
typedef CGAL::Triangle_3<Kernel> Triangle_3;
typedef typename std::vector<Triangle_3>::iterator Iterator;
typedef CGAL::AABB_triangle_primitive<Kernel, Iterator> Primitive;
typedef CGAL::AABB_traits<Kernel, Primitive> AABB_triangle_traits;
typedef CGAL::AABB_tree<AABB_triangle_traits> Tree;
typedef typename Tree::Point_and_primitive_id Point_and_primitive_id;
typedef CGAL::Point_3<Kernel> Point_3;
template <typename BKernel>
void A()
{
const CGAL::AABB_tree<
CGAL::AABB_traits<BKernel,
CGAL::AABB_triangle_primitive<BKernel,
typename std::vector<CGAL::Triangle_3<BKernel> >::iterator
>
>
> tree;
Point_and_primitive_id pp = tree.closest_point_and_primitive(Point_3());
}
void B()
{
std::vector<Triangle_3> T;
#ifdef MAGIC
T.reserve(0);
#endif
return A<Kernel>();
}
Issuing:
clang++ -std=c++11 -c example.cpp -I/opt/local/include
This fails to compile. Giving errors like:
In file included from example.cpp:1:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:265:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__bit_reference:15:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/algorithm:626:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/utility:157:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__tuple:228:60: error:
no member named 'value' in 'std::__1::is_convertible<const CGAL::Point_3<CGAL::Epick> &,
CGAL::Point_3<CGAL::Epick> >'
is_convertible<_Tp0, _Up0>::value &&
~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__tuple:242:14: note:
in instantiation of template class 'std::__1::__tuple_convertible_imp<true, std::__1::__tuple_types<const
CGAL::Point_3<CGAL::Epick> &, const CGAL::Vector_3<CGAL::Epick> &>,
std::__1::__tuple_types<CGAL::Point_3<CGAL::Epick>, CGAL::Vector_3<CGAL::Epick> > >' requested here
: public __tuple_convertible_imp<tuple_size<typename remove_reference<_Tp>::type>::value ==
However, this does compile if I make this magic call to std::vector::reserve, issuing:
clang++ -std=c++11 -c example.cpp -I/opt/local/include -DMAGIC
or by disabling c++11
clang++ -c example.cpp -I/opt/local/include
Is this a bug in CGAL or clang?
What explanation can there be for such erratic compiler behavior?
Is there a clean way of avoiding this (hopefully without really changing the templating or function prototype set up as I need the solution to fit my larger project).

Since Apple's GCC is outdated (latest GPL v2 version from 2007, GCC 4.2.1) and not C++11 feature complete (hence the libstdc++ provided with it), you can install a more modern version of GCC through MacPorts (sudo port install gcc48 or sudo port install gcc49) and that will provide you a more modern version of libstdc++. I tested your code with:
/opt/local/bin/g++-mp-4.8 -std=c++11 -c example.cpp -I/opt/local/include
and it compiled succesfully.
If you prefer this solution and want a cleaner compiler call; you can set MacPorts' GCC as the default using gcc_select with the command (in my case for gcc48):
sudo port select --set gcc mp-gcc48
only once. Then, you can compile it with just
g++ -std=c++11 -c example.cpp -I/opt/local/include
in a new terminal session.

Related

Upgrading to G++ 4.8 - exception_ptr.h Does not support exception propagation

I'm trying to recompile a huge legacy app with g++ 4.8 in order debug a glibc detected memory corruption problem (using AddressSanitizer). Previously we used g++ 4.4.7.
However, compilation fails with:
/opt/rh/devtoolset-2/root/usr/include/c++/4.8.2/bits/exception_ptr.h:40:4: error: #error This platform does not support exception propagation.
while compiling a custom exception handler (I guess). The custom exception handler uses exception_ptr in only one place:
void reportOtherException(void) const
{
std::exception_ptr p = std::current_exception();
std::string s = (p != 0 ? p.__cxa_exception_type()->name() : "null");
printf("DvMain Bad Exception: '%s'\n", s.c_str());
mErrorReporter(0, DvLog::WARNING, 0, Dv::NO_PROFILE, 0, DvLog::UNHANDLED_OTHER_EXCEPTION);
}
And reportOtherException() is used like this:
try
{
// Catch and log uncaught exceptions, then exit.
catch (const std::bad_exception& e) { exHandler.reportBadException(e); }
catch (const std::exception& e) { exHandler.reportStandardException(e); }
catch (...) { exHandler.reportOtherException(); }
}
I'm pretty new to C++ and don't know what the error even means. Worked with 4.4.7 and doesn't work with 4.8.
Any pointers on what needs to be changed to compile on 4.8?
EDIT I
Here's some additional info:
g++ --version
g++ (GCC) 4.8.2 20140120 (Red Hat 4.8.2-15)
Minimum Code
DvComDefaultExceptionHandler_test.h
#include "DvCommon.h"
#include "evt/DvEvt.h"
#include "log/DvLog.h"
#include "com/DvComErrorReporter.h"
#include <new>
#include <exception>
#include <sys/time.h>
#include <sys/resource.h>
#include <stdlib.h>
#include <unistd.h>
#include <malloc.h>
#include <bits/exception_ptr.h>
class DvComDefaultExceptionHandler
{
public:
DvComDefaultExceptionHandler(const DvComErrorReporter& er) {}
~DvComDefaultExceptionHandler() { }
void reportOtherException(void) const
{
std::exception_ptr p = std::current_exception();
}
private:
static const DvComDefaultExceptionHandler* mpInstance;
};
DvComDefaultExceptionHandler_test.cpp
#include "DvCommon.h"
#include "com/DvComDefaultExceptionHandler_test.h"
// Pointer to the single instance of the DvComDefaultExceptionHandler class.
const DvComDefaultExceptionHandler*
DvComDefaultExceptionHandler::mpInstance = 0;
Compile command and output
g++ -c -g -O0 -DDEBUG -Wall -Wextra -Wno-sign-compare -Wcast-align
--ftemplate-depth-32 -march=native -ggdb -fPIC -Iinclude -I../../include
-I../../src -I/usr/include/libxml2 -D_GNU_SOURCE
-I/mnt/swdevel/DVMon/source_build/ext/ACE -D__ACE_INLINE__
-I/usr/local/include -I/usr/lib/qt-3.3/include
-o DvComDefaultExceptionHandler.o DvComDefaultExceptionHandler_test.cpp
In file included from ../../include/com/DvComDefaultExceptionHandler_test.h:76:0,
from DvComDefaultExceptionHandler_test.cpp:13:
/opt/rh/devtoolset-2/root/usr/include/c++/4.8.2/bits/exception_ptr.h:40:4: error: #error This platform does not support exception propagation.
# error This platform does not support exception propagation.
EDIT II
Tracing through the include files comes down to the value of __GCC_ATOMIC_INT_LOCK_FREE. Running this simple program prints '2' as the value for __GCC_ATOMIC_INT_LOCK_FREE.
int
main(int argc, char **argv)
{
printf("__GCC_ATOMIC_INT_LOCK_FREE = %d\n", __GCC_ATOMIC_INT_LOCK_FREE);
}
G++ VERSION:
$ g++ --version
g++ (GCC) 4.8.2 20140120 (Red Hat 4.8.2-15)
EDIT II
I've tried it with g++ 6.3.1, running on a Centos 7 VM. Still the same problem.
Source File - one line only
#include <bits/exception_ptr.h>
Compile command: g++ -c -o test.o test.cpp
First of all, including <bits/exception_ptr.h> directly is technically unsupported. It says so right in the header file. This worked in GCC 4.4 by more or less by accident. The C++11 migration of this header file broke it because for namespace reasons, C++98 code cannot use the ATOMIC_INT_LOCK_FREE macro, and the header does not work anymore.
In GCC 7, this was fixed (again accidentally) as part of this bug:
std::future broken on armel
The trick to include <bits/exception_ptr.h> directly should work again in this version.
This means that your options are:
Compile your code in C++11 or later mode (C++14 with GCC 6 recommended).
Upgrade to DTS 7 with GCC 7 if and when it becomes available, which has the upstream fix which re-enables the C++98 hack.
Wrap the use of std::exception_ptr in an opaque type, compile its implementation in C++11 or later mode, and keep the rest of the system in C++98 mode.
Use another hack, perhaps like this one:
#include <exception>
#ifndef ATOMIC_INT_LOCK_FREE
# define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE
#endif
#include <bits/exception_ptr.h>
Again, this is completely unsupported, but it should not be any worse than what you have today (with GCC 4.4).
I was able to reproduce your issue using dockerized Centos6, with gcc 4.8.2. After upgrading dev tools to version 6 (gcc 6.3.1), your code compiled without any problem. Try upgrading dev tools using these steps (suggested for testing only):
add sclo centos6 repository via adding file /etc/yum.repos.d/devtools-sclo.repo :
[testing-devtools]
name=devtools multiple for CentOS
baseurl=http://mirror.centos.org/centos/6/sclo/x86_64/rh/
gpgcheck=0
install devtoolset-6 packages:
yum install devtoolset-6-binutils devtoolset-6-gcc-c++
set bash environment to new version:
scl enable devtoolset-6 bash
Now try recompiling your base example and full source.
NOTE: This same repository contains packages for devtoolset-3 and devtoolset-4 also. Very easy to try if ever needed.

Build Proxygen under Ubuntu 16.04

I would like to build Facebook's Proxygen c++ http libraries out of github with Ubuntu 16.04. Here's the environment I set up along with the deps.sh command to install dependencies:
gcc --version
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.1) 5.4.0 20160609
export CPPFLAGS="-std=c++14"
export CXXFLAGS="-std=c++14"
git clone git#github.com:facebook/proxygen.git
cd proxygen/proxygen && ./deps.sh
That got me most of the way through building its folly dependency, but I am getting an incomplete type error:
libtool: compile: g++ -DHAVE_CONFIG_H -I./.. -pthread -I/usr/include -std=c++14 -std=gnu++1y -std=c++14 -MT io/async/AsyncPipe.lo -MD -MP -MF io/async/.deps/AsyncPipe.Tpo -c io/async/AsyncPipe.cpp -fPIC -DPIC -o io/async/.libs/AsyncPipe.o
In file included from /usr/include/c++/5/bits/move.h:57:0,
from /usr/include/c++/5/bits/stl_pair.h:59,
from /usr/include/c++/5/utility:70,
from /usr/include/c++/5/algorithm:60,
from ./../folly/Conv.h:26,
from Conv.cpp:16:
/usr/include/c++/5/type_traits: In instantiation of ‘struct std::make_unsigned<__int128>’:
Conv.cpp:528:52: required from ‘folly::detail::ConversionResult<T> folly::detail::digits_to(const char*, const char*) [with Tgt = __int128]’
Conv.cpp:658:16: required from here
/usr/include/c++/5/type_traits:1757:62: error: invalid use of incomplete type ‘class std::__make_unsigned_selector<__int128, false, false>’
{ typedef typename __make_unsigned_selector<_Tp>::__type type; };
^
/usr/include/c++/5/type_traits:1721:11: note: declaration of ‘class std::__make_unsigned_selector<__int128, false, false>’
class __make_unsigned_selector;
^
/usr/include/c++/5/type_traits: In instantiation of ‘struct std::make_unsigned<__int128 unsigned>’:
Conv.cpp:528:52: required from ‘folly::detail::ConversionResult<T> folly::detail::digits_to(const char*, const char*) [with Tgt = __int128 unsigned]’
Conv.cpp:661:16: required from here
Has anyone tried or solved this? I'm not familiar with the code base yet. Tia.
TL;DR Proxygen needs GNU extensions; use -std=gnu++11 or -std=gnu++14
Why do you need to override C++ standard when building proxygen and its dependencies? Folly itself specifies -std=gnu++1y. If you remove
export CPPFLAGS="-std=c++14"
export CXXFLAGS="-std=c++14"
and try to build it, it almost will, the only change that I had to make to folly is to fix membarrier.
If you insist on using -std=c++14, then the problem actually is not in folly, it's in libstdc++ handling of GNU extensions, this simple line:
typedef std::make_unsigned<__int128>::type int128_type;
Will easily compile with -std=gnu++11 or -std=gnu++1y, but will fail with any of -std=c++11 or -std=c++14. And it's hard to tell, whether it is a bug (because the compiler provides __int128 type (and folly detects that in its configure script, BTW) but C++ library has problems with it) or a feature (because __int128 is an extension in the first place and one should use some GNU variant of standard to properly get it).

Compiling with unordered_map fails with Xcode 5.1.1 on OS X 10.9.3

I am attempting to compile a project which was originally using tr1/unordered_map. I have removed all the references to the tr1 namespace and am now just using unordered_map (e.g. #include <tr1/unordered_map> becomes #include <unordered_map>). However, I am getting a compilation error. Upon configuration:
CXXR is now configured for x86_64-apple-darwin13.2.0
Source directory: .
Installation directory: /Library/Frameworks
C compiler: gcc -g -O2 -fexceptions
Fortran 77 compiler: gfortran -g -O2
C++ compiler: g++ -g -O2 -Wno-attributes -std=c++11
Fortran 90/95 compiler: gfortran -g -O2
Obj-C compiler: gcc -g -O2 -fobjc-exceptions
Interfaces supported: X11, aqua, tcltk
External libraries: readline, ICU
Additional capabilities: PNG, JPEG, TIFF, NLS
CR Options enabled: framework, shared BLAS, R profiling
CXXR Options enabled:
Recommended packages: yes
When I attempt to compile the project I am faced with the error:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/unordered_map:724:5: error: static_assert failed "Invalid allocator::value_type"
static_assert((is_same<value_type, typename allocator_type::value_type>::value),
Environment.cpp:104:5: note: in instantiation of template class 'std::__1::unordered_map<const CXXR::Symbol *, CXXR::Frame::Binding *, std::__1::hash<const CXXR::Symbol *>,
std::__1::equal_to<const CXXR::Symbol *>, CXXR::Allocator<std::__1::pair<const CXXR::Symbol *, CXXR::Frame::Binding *> > >' requested here
delete s_search_path_cache;
s_search_path_cache is defined as:
typedef
std::unordered_map<const Symbol*, Frame::Binding*,
std::hash<const Symbol*>,
std::equal_to<const Symbol*>,
CXXR::Allocator<std::pair<const Symbol*, Frame::Binding*> >
> Cache;
static Cache* s_search_path_cache;
I was able to find a bug report to Apache OpenOffice for a similar problem (https://issues.apache.org/ooo/show_bug.cgi?id=124422) but have been unable to use this to solve my issue. If anyone has any ideas I would be most appreciative.
You're missing a pesky const in your allocator (the second one):
CXXR::Allocator<std::pair<const Symbol* const, Frame::Binding*> >

clang -cc1 and system includes

I have the following file foo.cpp:
#include <vector>
struct MyClass
{
std::vector<int> v;
};
It can be successfully compiled with clang (I'm using clang 3.3 on Ubuntu 13.04 32bit):
clang++ -c foo.cpp
Now I want to print AST:
clang++ -cc1 -ast-print foo.cpp
and I've got the following error
foo.cpp:1:10: fatal error: 'vector' file not found
#include <vector>
^
struct MyClass {
};
1 error generated.
It looks like clang++ -cc1 doesn't know about system include files etc.
I'm wondering how to set up includes for clang++ -cc1?
You need to set up the right include paths.
on my system I added
-I/usr/include/i386-linux-gnu/c++/4.8 -I/usr/include/c++/4.8
to the compiler flags. The first one was so that it could find
bits/c++config.h
Of course the 4.8 is due to the fact I am using a compiler compatible with g++-4.8
I also added
-std=c++11 -stdlib=libstdc++
as compiler options.
Hope this helps
It's a Frequently Asked Question
#john is correct. For posterity, the relevant portions of the FAQ are (with names tweaked to match the question) :
clang -cc1 is the frontend, clang is the driver. The driver invokes the frontend with options appropriate for your system. To see these options, run:
$ clang++ -### -c foo.cpp
Some clang command line options are driver-only options, some are frontend-only options. Frontend-only options are intended to be used only by clang developers. Users should not run clang -cc1 directly, because -cc1 options are not guaranteed to be stable.
If you want to use a frontend-only option (“a -cc1 option”), for example -ast-dump, then you need to take the clang -cc1 line generated by the driver and add the option you need. Alternatively, you can run clang -Xclang <option> ... to force the driver [to] pass <option> to clang -cc1.
I did the latter (-Xclang) for emitting precompiled headers:
/usr/bin/clang++ -x c++-header foo.hpp -Xclang -emit-pch -o foo.hpp.pch <other options>
^^^^^^^
Without the -Xclang, clang++ ignored the -emit-pch. When I tried -cc1, I had the same problem as the OP — clang++ accepted -emit-pch but didn't have the other options the driver normally provides.

ISO C++ forbids declaration of ‘tuple’ with no type

When trying to compile a simple class (g++ myclass.cpp), I get the following error:
ISO C++ forbids declaration of ‘tuple’ with no type
I searched for this problem, and in most cases people seemed to forget std:: or including <tuple> in the header. But I have both. Here is my code:
myclass.h
#ifndef MYCLASS
#define MYCLASS
#include <iostream>
#include <tuple>
class MyClass {
std::tuple<bool, int, int> my_method();
};
#endif
myclass.cpp
#include "myclass.h"
using namespace std;
tuple<bool, int, int> MyClass::my_method() {
return make_tuple(true, 1, 1);
}
If I do the same using pair instead, leaving out the second int and including <set>, it works.
What am I missing?
EDIT:
Here is the full output:
$ g++ myclass.cpp -o prog
In file included from myclass.cpp:1:
myclass.h:7: error: ISO C++ forbids declaration of ‘tuple’ with no type
myclass.h:7: error: invalid use of ‘::’
myclass.h:7: error: expected ‘;’ before ‘<’ token
myclass.cpp:5: error: expected constructor, destructor, or type conversion
before ‘<’ token
$ g++ --version
i686-apple-darwin11-llvm-g++-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658)
(LLVM build 2336.11.00)
GCC 4.2.1 shipped with every mac is outdated. It will not recognize the C++11.
You need to compile your code using: c++ instead of g++ which calls clang, which is the officially updated compiler on mac.
c++ -std=c++11 -stdlib=libc++ myclass.cpp -o prog
You are required to link against libc++ which is clang lib which knows about c++11 features instead of the default libstdc++ used by gcc.
Update! We're on GCC 4.7 these days.
GCC 4.2.1 is from all the way back on 18th July, 2007. There is only a remote chance that it supports any features from what became C++11.
That said, it may provide some in std::tr1 (i.e. std::tr1::tuple<T1, T2, ...>), which is where some of the C++11 features lived in the time before standardisation, though off the top of my head these were introduced to GCC only in 4.4.
With gcc 4.2, tuple was in namespace std::tr1. You must include <tr1/tuple> and specify your method more or less like this
#ifndef MYCLASS
#define MYCLASS
#include <tr1/tuple>
class MyClass {
std::tr1::tuple<bool, int, int> my_method();
};
#endif
Although, as others already suggested, updating to a more recent gcc might be more appropriate.
If you add the -std=c++11 (or, for older versions of g++ the -std=c++0x) option and add a simicolon after the expression in the member function the code compiles. If this doesn't work you might have a version which only defines tuple in namespace std::tr1 (it seems, the implementation provides a <tuple> header, though, because there is no error about <tuple> not being found).