When I recently imported llvm and clang 3.8.0 into FreeBSD, our buildbot
that builds the system with gcc 5.3.0 began complaining about a call to
llvm::reverse() in CFGBuilder::buildCFG(). (Note that we are compiling
clang using gcc 5.3.0, but also using libc++ as the C++ library.)
The gist of the errors is that gcc can't match either of the reverse()
variants in include/llvm/ADT/STLExtras.h; the first variant doesn't
match because CXXConstructorDecl::init_range (which is a
llvm::iterator_range) has no rbegin() or rend() methods:
tools/clang/lib/Analysis/CFG.cpp: In member function 'std::__1::unique_ptr<clang::CFG> {anonymous}::CFGBuilder::buildCFG(const clang::Decl*, clang::Stmt*)': tools/clang/lib/Analysis/CFG.cpp:1046:45: error: no matching function for call to 'reverse(clang::CXXConstructorDecl::init_const_range)' for (auto *I : llvm::reverse(CD->inits())) { ^ include/llvm/ADT/STLExtras.h:209:6: note: candidate: template<class ContainerTy> decltype (llvm::make_range(C.rbegin(), C.rend())) llvm::reverse(ContainerTy&&, typename std::__1::enable_if<llvm::has_rbegin<ContainerTy>::value>::type*) auto reverse(ContainerTy &&C, ^ include/llvm/ADT/STLExtras.h:209:6: note: template argument deduction/substitution failed: include/llvm/ADT/STLExtras.h: In substitution of 'template<class ContainerTy> decltype (llvm::make_range(C.rbegin(), C.rend())) llvm::reverse(ContainerTy&&, typename std::__1::enable_if<llvm::has_rbegin<ContainerTy>::value>::type*) [with ContainerTy = llvm::iterator_range<clang::CXXCtorInitializer* const*>]': tools/clang/lib/Analysis/CFG.cpp:1046:45: required from here include/llvm/ADT/STLExtras.h:209:6: error: no type named 'type' in 'struct std::__1::enable_if<false, void>'
The second variant should really match, but for gcc it doesn't, because
llvm::iterator_range has no 'iterator' and 'const_iterator' types:
include/llvm/ADT/STLExtras.h:228:64: error: no matching function for call to 'end(llvm::iterator_range<clang::CXXCtorInitializer* const*>&)' -> decltype(make_range(llvm::make_reverse_iterator(std::end(C)), ^ /usr/include/c++/v1/iterator:1575:1: note: candidate: template<class _Cp> typename _Cp::const_iterator std::__1::end(const _Cp&) end(const _Cp& __c) ^ /usr/include/c++/v1/iterator:1575:1: note: template argument deduction/substitution failed: /usr/include/c++/v1/iterator: In substitution of 'template<class _Cp> typename _Cp::const_iterator std::__1::end(const _Cp&) [with _Cp = llvm::iterator_range<clang::CXXCtorInitializer* const*>]': include/llvm/ADT/STLExtras.h:228:64: required by substitution of 'template<class ContainerTy> decltype (llvm::make_range(llvm::make_reverse_iterator(std::__1::end(C)), llvm::make_reverse_iterator(std::__1::begin(C)))) llvm::reverse(ContainerTy&&, typename std::__1::enable_if<(! llvm::has_rbegin<ContainerTy>::value)>::type*) [with ContainerTy = llvm::iterator_range<clang::CXXCtorInitializer* const*>]' tools/clang/lib/Analysis/CFG.cpp:1046:45: required from here /usr/include/c++/v1/iterator:1575:1: error: no type named 'const_iterator' in 'class llvm::iterator_range<clang::CXXCtorInitializer* const*>' include/llvm/ADT/STLExtras.h: In substitution of 'template<class ContainerTy> decltype (llvm::make_range(llvm::make_reverse_iterator(std::__1::end(C)), llvm::make_reverse_iterator(std::__1::begin(C)))) llvm::reverse(ContainerTy&&, typename std::__1::enable_if<(! llvm::has_rbegin<ContainerTy>::value)>::type*) [with ContainerTy = llvm::iterator_range<clang::CXXCtorInitializer* const*>]': tools/clang/lib/Analysis/CFG.cpp:1046:45: required from here /usr/include/c++/v1/iterator:1567:1: note: candidate: template<class _Cp> typename _Cp::iterator std::__1::end(_Cp&) end(_Cp& __c) ^ /usr/include/c++/v1/iterator:1567:1: note: template argument deduction/substitution failed: /usr/include/c++/v1/iterator: In substitution of 'template<class _Cp> typename _Cp::iterator std::__1::end(_Cp&) [with _Cp = llvm::iterator_range<clang::CXXCtorInitializer* const*>]': include/llvm/ADT/STLExtras.h:228:64: required by substitution of 'template<class ContainerTy> decltype (llvm::make_range(llvm::make_reverse_iterator(std::__1::end(C)), llvm::make_reverse_iterator(std::__1::begin(C)))) llvm::reverse(ContainerTy&&, typename std::__1::enable_if<(! llvm::has_rbegin<ContainerTy>::value)>::type*) [with ContainerTy = llvm::iterator_range<clang::CXXCtorInitializer* const*>]' tools/clang/lib/Analysis/CFG.cpp:1046:45: required from here /usr/include/c++/v1/iterator:1567:1: error: no type named 'iterator' in 'class llvm::iterator_range<clang::CXXCtorInitializer* const*>' include/llvm/ADT/STLExtras.h: In substitution of 'template<class ContainerTy> decltype (llvm::make_range(llvm::make_reverse_iterator(std::__1::end(C)), llvm::make_reverse_iterator(std::__1::begin(C)))) llvm::reverse(ContainerTy&&, typename std::__1::enable_if<(! llvm::has_rbegin<ContainerTy>::value)>::type*) [with ContainerTy = llvm::iterator_range<clang::CXXCtorInitializer* const*>]': tools/clang/lib/Analysis/CFG.cpp:1046:45: required from here
To work around this, add 'iterator' and 'const_iterator' types to
llvm::iterator_range(). I think this might even be a requirement for
being able to use std::begin() and std::end()?
As a side note, maybe it would be more efficient to also add rbegin()
and rend() members to llvm::iterator_range(), then the first variant of
llvm::reverse() can be used?