Skip to content

Commit

Permalink
Make clang-13 work with libstdc++ via convenience header (#547)
Browse files Browse the repository at this point in the history
Once coroutine support moves from std::experimental to std, we don't need this anymore. This will be the case for clang-14.
  • Loading branch information
joka921 committed Jan 24, 2022
1 parent b16a83c commit 838073e
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 58 deletions.
4 changes: 2 additions & 2 deletions src/global/Pattern.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ class CompactVectorOfStrings {

// Forward iterator for a `CompactVectorOfStrings` that reads directly from
// disk without buffering the whole `Vector`.
static cppcoro::generator<vector_type> diskIterator(const string& filename);
static cppcoro::generator<vector_type> diskIterator(string filename);

class Iterator {
private:
Expand Down Expand Up @@ -312,7 +312,7 @@ struct CompactStringVectorWriter {
// disk without buffering the whole `Vector`.
template <typename DataT>
cppcoro::generator<typename CompactVectorOfStrings<DataT>::vector_type>
CompactVectorOfStrings<DataT>::diskIterator(const string& filename) {
CompactVectorOfStrings<DataT>::diskIterator(string filename) {
ad_utility::File dataFile{filename, "r"};
ad_utility::File indexFile{filename, "r"};
AD_CHECK(dataFile.isOpen());
Expand Down
2 changes: 1 addition & 1 deletion src/index/Index.Text.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ void Index::passContextFileIntoVector(const string& contextFile,
// this has to be repeated completely here because we have the possibility to
// only add a text index. In that case the Vocabulary has never been
// initialized before
_vocab = std::move(RdfsVocabulary{});
_vocab = RdfsVocabulary{};
readConfiguration();
_vocab.readFromFile(_onDiskBase + ".vocabulary",
_onDiskLiterals ? _onDiskBase + ".literals-index" : "");
Expand Down
39 changes: 39 additions & 0 deletions src/util/Coroutines.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2022, University of Freiburg,
// Chair of Algorithms and Data Structures.
// Author: Johannes Kalmbach <kalmbach@cs.uni-freiburg.de>

// Clang up to version 13 does not link again libstdc++,
// because coroutines are still expected in the std::experimental
// namespace. This is a helper file that overcomes this limitation,
// simply include this file as a replacement of <coroutine>

// TODO<LLVM14> Remove this file as soon as we have a stable
// clang version that doesn't require this hack.
#ifndef QLEVER_COROUTINES_H
#define QLEVER_COROUTINES_H

#include <version>

#if defined(__clang__) && defined(__GLIBCXX__) && !__cpp_impl_coroutine
// This is the constant that is defined by g++ when using the
// -fcoroutines flag. We have to specify it manually for clang
// before including the coroutine header.
#define __cpp_impl_coroutine 1

#include <coroutine>

namespace std::experimental {
template <typename T, typename... Ts>
struct coroutine_traits : std::coroutine_traits<T, Ts...> {};

template <typename T = void>
struct coroutine_handle : std::coroutine_handle<T> {};
} // namespace std::experimental

#else
// Simply include the coroutine header, no special treatment
// necessary.
#include <coroutine>
#endif

#endif // QLEVER_COROUTINES_H
41 changes: 13 additions & 28 deletions src/util/Generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,9 @@
#include <type_traits>
#include <utility>

// coroutines are still experimental in clang libcpp,
// adapt the appropriate namespaces.
#ifdef _LIBCPP_VERSION
#include <experimental/coroutine>
namespace qlever_stdOrExp = std::experimental;
#else
#include <coroutine>
namespace qlever_stdOrExp = std;
#endif
// Coroutines are still experimental in clang libcpp, therefore adapt the
// appropriate namespaces by including the convenience header.
#include "./Coroutines.h"

namespace cppcoro {
template <typename T>
Expand All @@ -37,23 +31,17 @@ class generator_promise {

generator<T> get_return_object() noexcept;

constexpr qlever_stdOrExp::suspend_always initial_suspend() const noexcept {
return {};
}
constexpr qlever_stdOrExp::suspend_always final_suspend() const noexcept {
return {};
}
constexpr std::suspend_always initial_suspend() const noexcept { return {}; }
constexpr std::suspend_always final_suspend() const noexcept { return {}; }

template <typename U = T,
std::enable_if_t<!std::is_rvalue_reference<U>::value, int> = 0>
qlever_stdOrExp::suspend_always yield_value(
std::remove_reference_t<T>& value) noexcept {
std::suspend_always yield_value(std::remove_reference_t<T>& value) noexcept {
m_value = std::addressof(value);
return {};
}

qlever_stdOrExp::suspend_always yield_value(
std::remove_reference_t<T>&& value) noexcept {
std::suspend_always yield_value(std::remove_reference_t<T>&& value) noexcept {
m_value = std::addressof(value);
return {};
}
Expand All @@ -68,7 +56,7 @@ class generator_promise {

// Don't allow any use of 'co_await' inside the generator coroutine.
template <typename U>
qlever_stdOrExp::suspend_never await_transform(U&& value) = delete;
std::suspend_never await_transform(U&& value) = delete;

void rethrow_if_exception() {
if (m_exception) {
Expand All @@ -85,8 +73,7 @@ struct generator_sentinel {};

template <typename T>
class generator_iterator {
using coroutine_handle =
qlever_stdOrExp::coroutine_handle<generator_promise<T>>;
using coroutine_handle = std::coroutine_handle<generator_promise<T>>;

public:
using iterator_category = std::input_iterator_tag;
Expand Down Expand Up @@ -192,11 +179,10 @@ class [[nodiscard]] generator {
private:
friend class detail::generator_promise<T>;

explicit generator(
qlever_stdOrExp::coroutine_handle<promise_type> coroutine) noexcept
explicit generator(std::coroutine_handle<promise_type> coroutine) noexcept
: m_coroutine(coroutine) {}

qlever_stdOrExp::coroutine_handle<promise_type> m_coroutine;
std::coroutine_handle<promise_type> m_coroutine;
};

template <typename T>
Expand All @@ -207,8 +193,7 @@ void swap(generator<T>& a, generator<T>& b) {
namespace detail {
template <typename T>
generator<T> generator_promise<T>::get_return_object() noexcept {
using coroutine_handle =
qlever_stdOrExp::coroutine_handle<generator_promise<T>>;
using coroutine_handle = std::coroutine_handle<generator_promise<T>>;
return generator<T>{coroutine_handle::from_promise(*this)};
}
} // namespace detail
Expand All @@ -223,4 +208,4 @@ fmap(FUNC func, generator<T> source) {
}
} // namespace cppcoro

#endif
#endif
4 changes: 2 additions & 2 deletions src/util/HttpServer/beast.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
// (TODO<joka921> Figure out, why Boost currently is not able, to deduce
// these automatically.

#include "../../util/Coroutines.h"

// libc++ needs <experimental/coroutine>, libstdc++ needs <coroutine>
#define BOOST_ASIO_HAS_CO_AWAIT
#ifndef __clang__
#define BOOST_ASIO_HAS_STD_COROUTINE
#endif

// Needed for libc++ in C++20 mode, because std::result_of was removed.
#define BOOST_ASIO_HAS_STD_INVOKE_RESULT
Expand Down
34 changes: 11 additions & 23 deletions src/util/streamable_generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,9 @@
#include <exception>
#include <sstream>

// coroutines are still experimental in clang libcpp,
// adapt the appropriate namespaces.
#ifdef _LIBCPP_VERSION
#include <experimental/coroutine>
namespace qlever_stdOrExp = std::experimental;
#else
#include <coroutine>
namespace qlever_stdOrExp = std;
#endif

// Coroutines are still experimental in clang libcpp, therefore
// adapt the appropriate namespaces using the convenience header.
#include "./Coroutines.h"
#include "./ostringstream.h"

namespace ad_utility::stream_generator {
Expand Down Expand Up @@ -49,8 +42,7 @@ class suspend_sometimes {
public:
explicit suspend_sometimes(const bool suspend) : _suspend{suspend} {}
bool await_ready() const noexcept { return !_suspend; }
constexpr void await_suspend(
qlever_stdOrExp::coroutine_handle<>) const noexcept {}
constexpr void await_suspend(std::coroutine_handle<>) const noexcept {}
constexpr void await_resume() const noexcept {}
};

Expand All @@ -68,12 +60,8 @@ class stream_generator_promise {

basic_stream_generator<MIN_BUFFER_SIZE> get_return_object() noexcept;

constexpr qlever_stdOrExp::suspend_always initial_suspend() const noexcept {
return {};
}
constexpr qlever_stdOrExp::suspend_always final_suspend() const noexcept {
return {};
}
constexpr std::suspend_always initial_suspend() const noexcept { return {}; }
constexpr std::suspend_always final_suspend() const noexcept { return {}; }

/**
* Handles values passed using co_yield and stores their respective
Expand Down Expand Up @@ -106,7 +94,7 @@ class stream_generator_promise {

// Don't allow any use of 'co_await' inside the generator coroutine.
template <typename U>
qlever_stdOrExp::suspend_never await_transform(U&& value) = delete;
std::suspend_never await_transform(U&& value) = delete;

void rethrow_if_exception() {
if (_exception) {
Expand Down Expand Up @@ -137,7 +125,7 @@ class [[nodiscard]] basic_stream_generator {
using promise_type = detail::stream_generator_promise<MIN_BUFFER_SIZE>;

private:
qlever_stdOrExp::coroutine_handle<promise_type> _coroutine = nullptr;
std::coroutine_handle<promise_type> _coroutine = nullptr;

static basic_stream_generator noOpGenerator() { co_return; }

Expand Down Expand Up @@ -186,16 +174,16 @@ class [[nodiscard]] basic_stream_generator {
private:
friend class detail::stream_generator_promise<MIN_BUFFER_SIZE>;
explicit basic_stream_generator(
qlever_stdOrExp::coroutine_handle<promise_type> coroutine) noexcept
std::coroutine_handle<promise_type> coroutine) noexcept
: _coroutine{coroutine} {}
};

namespace detail {
template <size_t MIN_BUFFER_SIZE>
inline basic_stream_generator<MIN_BUFFER_SIZE>
stream_generator_promise<MIN_BUFFER_SIZE>::get_return_object() noexcept {
using coroutine_handle = qlever_stdOrExp::coroutine_handle<
stream_generator_promise<MIN_BUFFER_SIZE>>;
using coroutine_handle =
std::coroutine_handle<stream_generator_promise<MIN_BUFFER_SIZE>>;
return basic_stream_generator{coroutine_handle::from_promise(*this)};
}
} // namespace detail
Expand Down
4 changes: 2 additions & 2 deletions toolchains/clang13.cmake
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# CMake toolchain file for using `clang++-13` together with `libc++`
set(CMAKE_C_COMPILER clang-13)
set(CMAKE_CXX_COMPILER clang++-13)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lc++abi")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lc++abi")

0 comments on commit 838073e

Please sign in to comment.