Skip to content

Commit 478f47d

Browse files
committed
Add support for later versions of GCC on Linux.
1 parent 87edc46 commit 478f47d

File tree

10 files changed

+202
-128
lines changed

10 files changed

+202
-128
lines changed

Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ HOST_CFLAGS := -g -O2 -Wall -Werror -Wextra -Iinclude
1515
HOST_CXXFLAGS := -std=c++14
1616
HOST_LDFLAGS :=
1717

18+
ifeq ($(HOST_OS),Linux)
19+
HOST_LDFLAGS := -lpthread
20+
endif
21+
1822
OUT := out
1923
OUT_HOST_OBJ := $(OUT)/host-obj
2024

@@ -109,6 +113,7 @@ M_OBJS := \
109113
include build/host-executable.mk
110114

111115
M_NAME := shared_protocol.so
116+
M_CFLAGS := -fPIC
112117
M_LDFLAGS := --shared
113118
M_OBJS := \
114119
examples/shared.o

build/host-executable.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ $(OUT)/$(M_NAME): _CXXFLAGS := $(M_CXXFLAGS)
2929

3030
$(OUT)/$(M_NAME): $(M_OBJS)
3131
@echo link $@
32-
$(QUIET)$(CXX) $(HOST_LDFLAGS) $(HOST_CFLAGS) $(HOST_CXXFLAGS) $(_LDFLAGS) $(_CFLAGS) $(_CXXFLAGS) -o $@ $(_OBJS)
32+
$(QUIET)$(CXX) $(_CFLAGS) $(_CXXFLAGS) -o $@ $(_OBJS) $(HOST_LDFLAGS) $(HOST_CFLAGS) $(HOST_CXXFLAGS) $(_LDFLAGS)
3333

3434
M_OBJS :=
3535
M_NAME :=

include/nop/rpc/interface.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,8 @@ struct InterfaceMethod {
171171
// given passthrough arguments. The return value of the handler is then
172172
// serialized using the given receiver to be returned to the remote caller.
173173
template <typename Receiver, typename... Passthrough>
174-
Status<void> Dispatch(Receiver* receiver, Passthrough&&... passthrough) const {
174+
Status<void> Dispatch(Receiver* receiver,
175+
Passthrough&&... passthrough) const {
175176
return Helper<typename FunctionTraits<Op>::Signature>::Dispatch(
176177
receiver, op, std::forward<Passthrough>(passthrough)...);
177178
}
@@ -355,15 +356,22 @@ struct Interface {
355356
using BASE = Interface<T>;
356357

357358
// Returns the hash of the interface type T.
358-
static std::uint64_t GetInterfaceHash() { return InterfaceType<T>::Hash; }
359+
static std::uint64_t GetInterfaceHash() {
360+
using InterfaceType = typename T::NOP__INTERFACE;
361+
return InterfaceType::Hash;
362+
}
359363

360364
// Returns the name of the interface type T.
361-
static std::string GetInterfaceName() { return InterfaceType<T>::GetName(); }
365+
static std::string GetInterfaceName() {
366+
using InterfaceType = typename T::NOP__INTERFACE;
367+
return InterfaceType::GetName();
368+
}
362369

363370
// Looks up the selector for a method in the interface by numeric index.
364371
template <std::size_t Index>
365372
static constexpr auto GetMethodSelector() {
366-
return InterfaceApiType<T>::template Method<Index>::Selector;
373+
using InterfaceApiType = typename T::NOP__INTERFACE_API;
374+
return InterfaceApiType::template Method<Index>::Selector;
367375
}
368376
};
369377

include/nop/structure.h

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -70,20 +70,25 @@ namespace nop {
7070
struct NOP__MEMBER_TRAITS<type> { \
7171
using MemberList = ::nop::MemberList<_NOP_MEMBER_LIST(type, __VA_ARGS__)>; \
7272
}; \
73-
NOP__MEMBER_TRAITS<type> NOP__GetExternalMemberTraits[[gnu::used]](type*)
73+
inline NOP__MEMBER_TRAITS<type> NOP__GetExternalMemberTraits \
74+
[[gnu::used]] (type*) { \
75+
return {}; \
76+
}
7477

7578
// Similar to NOP_EXTERNAL_STRUCTURE but for template types.
76-
#define NOP_EXTERNAL_TEMPLATE(type, ... /*members*/) \
77-
template <typename> \
78-
struct NOP__MEMBER_TRAITS; \
79-
template <typename... Ts> \
80-
struct NOP__MEMBER_TRAITS<type<Ts...>> { \
81-
using MemberList = \
82-
::nop::MemberList<_NOP_MEMBER_LIST(type<Ts...>, __VA_ARGS__)>; \
83-
}; \
84-
template <typename... Ts> \
85-
NOP__MEMBER_TRAITS<type<Ts...>> NOP__GetExternalMemberTraits[[gnu::used]]( \
86-
type<Ts...>*)
79+
#define NOP_EXTERNAL_TEMPLATE(type, ... /*members*/) \
80+
template <typename> \
81+
struct NOP__MEMBER_TRAITS; \
82+
template <typename... Ts> \
83+
struct NOP__MEMBER_TRAITS<type<Ts...>> { \
84+
using MemberList = \
85+
::nop::MemberList<_NOP_MEMBER_LIST(type<Ts...>, __VA_ARGS__)>; \
86+
}; \
87+
template <typename... Ts> \
88+
inline NOP__MEMBER_TRAITS<type<Ts...>> NOP__GetExternalMemberTraits \
89+
[[gnu::used]] (type<Ts...>*) { \
90+
return {}; \
91+
}
8792

8893
//
8994
// Utility macros used by the macros above.

include/nop/types/enum_flags.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,10 @@ using EnableIfEnumFlags = typename std::enable_if<IsEnumFlags<T>::value>::type;
8383
static_assert(std::is_enum<type>::value, \
8484
"Only enum types may be used for enum flags: type=" #type); \
8585
}; \
86-
NOP__ENUM_FLAGS_TRAITS<type> NOP__GetEnumFlagsTraits[[gnu::used]](type*)
86+
inline NOP__ENUM_FLAGS_TRAITS<type> NOP__GetEnumFlagsTraits \
87+
[[gnu::used]] (type*) { \
88+
return {}; \
89+
}
8790

8891
} // namespace nop
8992

include/nop/types/optional.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ class Optional {
224224
// Constructs the value type, making it active.
225225
template <typename... Args>
226226
constexpr Storage(Args&&... args) noexcept
227-
: value{std::forward<Args>(args)...} {}
227+
: value(std::forward<Args>(args)...) {}
228228

229229
// Non-trivial destructor. This doesn't do anything useful except enable to
230230
// compiler to catch attempts to use this type in a non-trivial context.
@@ -250,7 +250,7 @@ class Optional {
250250
// Constructs the value type, making it active.
251251
template <typename... Args>
252252
constexpr Storage(Args&&... args) noexcept
253-
: value{std::forward<Args>(args)...} {}
253+
: value(std::forward<Args>(args)...) {}
254254

255255
// Trivial destructor.
256256
~Storage() = default;

include/nop/utility/compiler.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright 2017 The Native Object Protocols Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#ifndef LIBNOP_INCLUDE_NOP_UTILITY_COMPILER_H_
18+
#define LIBNOP_INCLUDE_NOP_UTILITY_COMPILER_H_
19+
20+
// Compatability with non-clang compilers.
21+
#ifndef __has_cpp_attribute
22+
#define __has_cpp_attribute(x) 0
23+
#endif
24+
25+
// Test for fallthrough support.
26+
#if __has_cpp_attribute(clang::fallthrough)
27+
#define NOP_FALLTHROUGH [[clang::fallthrough]]
28+
#else
29+
#define NOP_FALLTHROUGH [[fallthrough]]
30+
#endif
31+
32+
#endif // LIBNOP_INCLUDE_NOP_UTILITY_COMPILER_H_

include/nop/utility/sip_hash.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#include <array>
2121
#include <cstdint>
2222

23+
#include <nop/utility/compiler.h>
24+
2325
// A direct port of the SipHash C reference implementation.
2426
//
2527
// https://131002.net/siphash/siphash24.c
@@ -98,18 +100,25 @@ struct SipHash {
98100
switch (kLeftOver) {
99101
case 7:
100102
b |= static_cast<std::uint64_t>(buffer[kEndOffset + 6]) << 48;
103+
NOP_FALLTHROUGH;
101104
case 6:
102105
b |= static_cast<std::uint64_t>(buffer[kEndOffset + 5]) << 40;
106+
NOP_FALLTHROUGH;
103107
case 5:
104108
b |= static_cast<std::uint64_t>(buffer[kEndOffset + 4]) << 32;
109+
NOP_FALLTHROUGH;
105110
case 4:
106111
b |= static_cast<std::uint64_t>(buffer[kEndOffset + 3]) << 24;
112+
NOP_FALLTHROUGH;
107113
case 3:
108114
b |= static_cast<std::uint64_t>(buffer[kEndOffset + 2]) << 16;
115+
NOP_FALLTHROUGH;
109116
case 2:
110117
b |= static_cast<std::uint64_t>(buffer[kEndOffset + 1]) << 8;
118+
NOP_FALLTHROUGH;
111119
case 1:
112120
b |= static_cast<std::uint64_t>(buffer[kEndOffset + 0]) << 0;
121+
NOP_FALLTHROUGH;
113122
case 0:
114123
break;
115124
}

test/endian_tests.cpp

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include <algorithm>
1818
#include <cstdint>
19+
#include <type_traits>
1920

2021
#include <nop/utility/endian.h>
2122

@@ -24,40 +25,50 @@ using nop::HostEndian;
2425
namespace {
2526

2627
template <typename T>
27-
union Bytes {
28+
struct Bytes {
2829
enum : std::size_t { N = sizeof(T) };
2930

30-
Bytes(T value) : value{value} {}
31-
Bytes(const std::uint8_t (&value)[N]) {
32-
std::copy(&value[0], &value[N], bytes);
31+
// Work around GCC crash when constructing Byte({<number>}). This is ugly but
32+
// the simpler version Bytes(T value) causes a segmentation fault in GCC.
33+
template <typename U, typename Enabled = std::enable_if_t<
34+
std::is_constructible<T, U>::value>>
35+
constexpr Bytes(U&& value) : value{std::forward<U>(value)} {}
36+
constexpr Bytes(const std::uint8_t (&bytes)[N]) : value{FromBytes(bytes)} {}
37+
38+
template <std::size_t N, std::size_t... Is>
39+
static constexpr T FromBytes(const std::uint8_t (&value)[N]) {
40+
T temp = 0;
41+
for (std::size_t i = 0; i < N; i++)
42+
temp |= static_cast<T>(value[i]) << (8 * i);
43+
return temp;
3344
}
3445

3546
T value;
36-
std::uint8_t bytes[N];
3747
};
3848

3949
} // anonymous namespace
4050

4151
TEST(EndianTests, Little) {
4252
{
4353
Bytes<std::uint8_t> little_endian{{0x00}};
44-
EXPECT_EQ(0x00, HostEndian<std::uint8_t>::FromLittle(little_endian.value));
45-
EXPECT_EQ(little_endian.value, HostEndian<std::uint8_t>::ToLittle(0x00));
54+
EXPECT_EQ(0x00u, HostEndian<std::uint8_t>::FromLittle(little_endian.value));
55+
EXPECT_EQ(little_endian.value, HostEndian<std::uint8_t>::ToLittle(0x00u));
4656
}
4757

4858
{
4959
Bytes<std::uint16_t> little_endian{{0x00, 0x11}};
50-
EXPECT_EQ(0x1100,
60+
EXPECT_EQ(0x1100u,
5161
HostEndian<std::uint16_t>::FromLittle(little_endian.value));
52-
EXPECT_EQ(little_endian.value, HostEndian<std::uint16_t>::ToLittle(0x1100));
62+
EXPECT_EQ(little_endian.value,
63+
HostEndian<std::uint16_t>::ToLittle(0x1100u));
5364
}
5465

5566
{
5667
Bytes<std::uint32_t> little_endian{{0x00, 0x11, 0x22, 0x33}};
57-
EXPECT_EQ(0x33221100,
68+
EXPECT_EQ(0x33221100u,
5869
HostEndian<std::uint32_t>::FromLittle(little_endian.value));
5970
EXPECT_EQ(little_endian.value,
60-
HostEndian<std::uint32_t>::FromLittle(0x33221100));
71+
HostEndian<std::uint32_t>::FromLittle(0x33221100u));
6172
}
6273

6374
{
@@ -103,20 +114,21 @@ TEST(EndianTests, Little) {
103114
TEST(EndianTests, Big) {
104115
{
105116
Bytes<std::uint8_t> big_endian{{0x00}};
106-
EXPECT_EQ(0x00, HostEndian<std::uint8_t>::FromBig(big_endian.value));
107-
EXPECT_EQ(big_endian.value, HostEndian<std::uint8_t>::ToBig(0x00));
117+
EXPECT_EQ(0x00u, HostEndian<std::uint8_t>::FromBig(big_endian.value));
118+
EXPECT_EQ(big_endian.value, HostEndian<std::uint8_t>::ToBig(0x00u));
108119
}
109120

110121
{
111122
Bytes<std::uint16_t> big_endian{{0x11, 0x00}};
112-
EXPECT_EQ(0x1100, HostEndian<std::uint16_t>::FromBig(big_endian.value));
113-
EXPECT_EQ(big_endian.value, HostEndian<std::uint16_t>::ToBig(0x1100));
123+
EXPECT_EQ(0x1100u, HostEndian<std::uint16_t>::FromBig(big_endian.value));
124+
EXPECT_EQ(big_endian.value, HostEndian<std::uint16_t>::ToBig(0x1100u));
114125
}
115126

116127
{
117128
Bytes<std::uint32_t> big_endian{{0x33, 0x22, 0x11, 0x00}};
118-
EXPECT_EQ(0x33221100, HostEndian<std::uint32_t>::FromBig(big_endian.value));
119-
EXPECT_EQ(big_endian.value, HostEndian<std::uint32_t>::ToBig(0x33221100));
129+
EXPECT_EQ(0x33221100u,
130+
HostEndian<std::uint32_t>::FromBig(big_endian.value));
131+
EXPECT_EQ(big_endian.value, HostEndian<std::uint32_t>::ToBig(0x33221100u));
120132
}
121133

122134
{

0 commit comments

Comments
 (0)