Commit d75e6a31 authored by Kenton Varda's avatar Kenton Varda

Fix GCC issues.

parent baa3ee3c
......@@ -465,7 +465,8 @@ const Compiler::Node::Content& Compiler::Node::getContent(Content::State minimum
builder.setScopeId(p->id);
}
auto nestedIter = builder.initNestedNodes(locked->orderedNestedNodes.size()).begin();
auto nestedNodes = builder.initNestedNodes(locked->orderedNestedNodes.size());
auto nestedIter = nestedNodes.begin();
for (auto node: locked->orderedNestedNodes) {
nestedIter->setName(node->declaration.getName().getValue());
nestedIter->setId(node->id);
......
......@@ -1297,31 +1297,31 @@ class NodeTranslator::DynamicSlot {
public:
DynamicSlot(DynamicStruct::Builder structBuilder, StructSchema::Member member)
: type(FIELD), structBuilder(structBuilder), member(member) {}
: type(FIELD), struct_{structBuilder, member} {}
DynamicSlot(DynamicList::Builder listBuilder, uint index)
: type(ELEMENT), listBuilder(listBuilder), index(index) {}
: type(ELEMENT), list{listBuilder, index} {}
DynamicSlot(DynamicUnion::Builder unionBuilder, StructSchema::Member unionMember)
: type(UNION_MEMBER), unionBuilder(unionBuilder), unionMember(unionMember) {}
: type(UNION_MEMBER), union_{unionBuilder, unionMember} {}
DynamicSlot(DynamicUnion::Builder unionBuilder, StructSchema::Member unionMember,
StructSchema structMemberSchema)
: type(STRUCT_OBJECT_UNION_MEMBER), unionBuilder(unionBuilder), unionMember(unionMember),
: type(STRUCT_OBJECT_UNION_MEMBER), union_{unionBuilder, unionMember},
structMemberSchema(structMemberSchema) {}
DynamicSlot(DynamicUnion::Builder unionBuilder, StructSchema::Member unionMember,
ListSchema listMemberSchema)
: type(LIST_OBJECT_UNION_MEMBER), unionBuilder(unionBuilder), unionMember(unionMember),
: type(LIST_OBJECT_UNION_MEMBER), union_{unionBuilder, unionMember},
listMemberSchema(listMemberSchema) {}
DynamicSlot(DynamicUnion::Builder unionBuilder, StructSchema::Member unionMember,
EnumSchema enumMemberSchema)
: type(ENUM_UNION_MEMBER), unionBuilder(unionBuilder), unionMember(unionMember),
: type(ENUM_UNION_MEMBER), union_{unionBuilder, unionMember},
enumMemberSchema(enumMemberSchema) {}
DynamicStruct::Builder initStruct() {
switch (type) {
case FIELD: return structBuilder.init(member).as<DynamicStruct>();
case ELEMENT: return listBuilder[index].as<DynamicStruct>();
case UNION_MEMBER: return unionBuilder.init(unionMember).as<DynamicStruct>();
case FIELD: return struct_.builder.init(struct_.member).as<DynamicStruct>();
case ELEMENT: return list.builder[list.index].as<DynamicStruct>();
case UNION_MEMBER: return union_.builder.init(union_.member).as<DynamicStruct>();
case STRUCT_OBJECT_UNION_MEMBER:
return unionBuilder.initObject(unionMember, structMemberSchema);
return union_.builder.initObject(union_.member, structMemberSchema);
case LIST_OBJECT_UNION_MEMBER: KJ_FAIL_REQUIRE("Type mismatch.");
case ENUM_UNION_MEMBER: KJ_FAIL_REQUIRE("Type mismatch.");
}
......@@ -1330,12 +1330,12 @@ public:
DynamicList::Builder initList(uint size) {
switch (type) {
case FIELD: return structBuilder.init(member, size).as<DynamicList>();
case ELEMENT: return listBuilder.init(index, size).as<DynamicList>();
case UNION_MEMBER: return unionBuilder.init(unionMember, size).as<DynamicList>();
case FIELD: return struct_.builder.init(struct_.member, size).as<DynamicList>();
case ELEMENT: return list.builder.init(list.index, size).as<DynamicList>();
case UNION_MEMBER: return union_.builder.init(union_.member, size).as<DynamicList>();
case STRUCT_OBJECT_UNION_MEMBER: KJ_FAIL_REQUIRE("Type mismatch.");
case LIST_OBJECT_UNION_MEMBER:
return unionBuilder.initObject(unionMember, listMemberSchema, size);
return union_.builder.initObject(union_.member, listMemberSchema, size);
case ENUM_UNION_MEMBER: KJ_FAIL_REQUIRE("Type mismatch.");
}
KJ_FAIL_ASSERT("can't get here");
......@@ -1343,9 +1343,9 @@ public:
DynamicUnion::Builder getUnion() {
switch (type) {
case FIELD: return structBuilder.get(member).as<DynamicUnion>();
case FIELD: return struct_.builder.get(struct_.member).as<DynamicUnion>();
case ELEMENT: KJ_FAIL_REQUIRE("Type mismatch.");
case UNION_MEMBER: return unionBuilder.init(unionMember).as<DynamicUnion>();
case UNION_MEMBER: return union_.builder.init(union_.member).as<DynamicUnion>();
case STRUCT_OBJECT_UNION_MEMBER: KJ_FAIL_REQUIRE("Type mismatch.");
case LIST_OBJECT_UNION_MEMBER: KJ_FAIL_REQUIRE("Type mismatch.");
case ENUM_UNION_MEMBER: KJ_FAIL_REQUIRE("Type mismatch.");
......@@ -1355,13 +1355,13 @@ public:
void set(DynamicValue::Reader value) {
switch (type) {
case FIELD: structBuilder.set(member, value); return;
case ELEMENT: listBuilder.set(index, value); return;
case UNION_MEMBER: unionBuilder.set(unionMember, value); return;
case STRUCT_OBJECT_UNION_MEMBER: unionBuilder.set(unionMember, value); return;
case LIST_OBJECT_UNION_MEMBER: unionBuilder.set(unionMember, value); return;
case FIELD: struct_.builder.set(struct_.member, value); return;
case ELEMENT: list.builder.set(list.index, value); return;
case UNION_MEMBER: union_.builder.set(union_.member, value); return;
case STRUCT_OBJECT_UNION_MEMBER: union_.builder.set(union_.member, value); return;
case LIST_OBJECT_UNION_MEMBER: union_.builder.set(union_.member, value); return;
case ENUM_UNION_MEMBER:
unionBuilder.set(unionMember, value.as<DynamicEnum>().getRaw());
union_.builder.set(union_.member, value.as<DynamicEnum>().getRaw());
return;
}
KJ_FAIL_ASSERT("can't get here");
......@@ -1373,14 +1373,14 @@ public:
// This is really ugly.
switch (type) {
case FIELD: return enumIdForMember(member);
case FIELD: return enumIdForMember(struct_.member);
case ELEMENT: {
if (listBuilder.getSchema().whichElementType() == schema::Type::Body::ENUM_TYPE) {
return listBuilder.getSchema().getEnumElementType().getProto().getId();
if (list.builder.getSchema().whichElementType() == schema::Type::Body::ENUM_TYPE) {
return list.builder.getSchema().getEnumElementType().getProto().getId();
}
return nullptr;
}
case UNION_MEMBER: return enumIdForMember(unionMember);
case UNION_MEMBER: return enumIdForMember(union_.member);
case STRUCT_OBJECT_UNION_MEMBER: return nullptr;
case LIST_OBJECT_UNION_MEMBER: return nullptr;
case ENUM_UNION_MEMBER: return enumMemberSchema.getProto().getId();
......@@ -1397,22 +1397,23 @@ private:
union {
struct {
DynamicStruct::Builder structBuilder;
DynamicStruct::Builder builder;
StructSchema::Member member;
};
} struct_;
struct {
DynamicList::Builder listBuilder;
DynamicList::Builder builder;
uint index;
};
} list;
struct {
DynamicUnion::Builder unionBuilder;
StructSchema::Member unionMember;
union {
StructSchema structMemberSchema;
ListSchema listMemberSchema;
EnumSchema enumMemberSchema;
};
};
DynamicUnion::Builder builder;
StructSchema::Member member;
} union_;
};
union {
StructSchema structMemberSchema;
ListSchema listMemberSchema;
EnumSchema enumMemberSchema;
};
static kj::Maybe<uint64_t> enumIdForMember(StructSchema::Member member) {
......
......@@ -1378,7 +1378,7 @@ TEST(Encoding, Threads) {
// Check that none of the values were corrupted.
for (auto item: list.getReader()) {
ASSERT_EQ(4, item.size());
ASSERT_EQ(4u, item.size());
EXPECT_EQ(me, item[0]);
EXPECT_EQ(me + 1, item[1]);
EXPECT_EQ(me + 2, item[2]);
......
......@@ -115,8 +115,8 @@ TEST(Arena, Array) {
Arena arena;
ArrayPtr<TestObject> arr1 = arena.allocateArray<TestObject>(4);
ArrayPtr<TestObject> arr2 = arena.allocateArray<TestObject>(2);
EXPECT_EQ(4, arr1.size());
EXPECT_EQ(2, arr2.size());
EXPECT_EQ(4u, arr1.size());
EXPECT_EQ(2u, arr2.size());
EXPECT_LE(arr1.end(), arr2.begin());
EXPECT_EQ(6, TestObject::count);
}
......@@ -142,8 +142,8 @@ TEST(Arena, OwnArray) {
{
Array<TestObject> arr1 = arena.allocateOwnArray<TestObject>(4);
Array<TestObject> arr2 = arena.allocateOwnArray<TestObject>(2);
EXPECT_EQ(4, arr1.size());
EXPECT_EQ(2, arr2.size());
EXPECT_EQ(4u, arr1.size());
EXPECT_EQ(2u, arr2.size());
EXPECT_LE(arr1.end(), arr2.begin());
EXPECT_EQ(6, TestObject::count);
}
......@@ -191,9 +191,9 @@ TEST(Arena, Alignment) {
char& c2 = arena.allocate<char>();
ArrayPtr<char> arr = arena.allocateArray<char>(8);
EXPECT_EQ(alignof(long) + sizeof(long), &c2 - &c);
EXPECT_EQ(alignof(long), reinterpret_cast<char*>(&l) - &c);
EXPECT_EQ(sizeof(char), arr.begin() - &c2);
EXPECT_EQ(alignof(long) + sizeof(long), implicitCast<size_t>(&c2 - &c));
EXPECT_EQ(alignof(long), implicitCast<size_t>(reinterpret_cast<char*>(&l) - &c));
EXPECT_EQ(sizeof(char), implicitCast<size_t>(arr.begin() - &c2));
}
TEST(Arena, EndOfChunk) {
......@@ -285,7 +285,7 @@ TEST(Arena, MultiSegment) {
TEST(Arena, Constructor) {
Arena arena;
EXPECT_EQ(123, arena.allocate<uint64_t>(123));
EXPECT_EQ(123u, arena.allocate<uint64_t>(123));
EXPECT_EQ("foo", arena.allocate<StringPtr>("foo", 3));
}
......@@ -366,10 +366,10 @@ TEST(Arena, Threads) {
// allowing all the threads to start running. We'll then join each thread.
}
EXPECT_EQ(0, ThreadTestObject::destructorCount);
EXPECT_EQ(0u, ThreadTestObject::destructorCount);
}
EXPECT_EQ(400000, ThreadTestObject::destructorCount);
EXPECT_EQ(400000u, ThreadTestObject::destructorCount);
}
} // namespace
......
......@@ -69,7 +69,7 @@ void Arena::State::cleanup() {
namespace {
constexpr bool isPowerOfTwo(size_t value) {
return (value & value - 1) == 0;
return (value & (value - 1)) == 0;
}
inline byte* alignTo(byte* p, uint alignment) {
......
......@@ -254,13 +254,13 @@ TEST(Common, Defer) {
{
KJ_DEFER(++i);
KJ_DEFER(j += 3; k = true);
EXPECT_EQ(0, i);
EXPECT_EQ(1, j);
EXPECT_EQ(0u, i);
EXPECT_EQ(1u, j);
EXPECT_FALSE(k);
}
EXPECT_EQ(1, i);
EXPECT_EQ(4, j);
EXPECT_EQ(1u, i);
EXPECT_EQ(4u, j);
EXPECT_TRUE(k);
}
......
......@@ -23,6 +23,7 @@
#include "common.h"
#include "debug.h"
#include <stdlib.h>
namespace kj {
namespace _ { // private
......@@ -38,5 +39,12 @@ void inlineRequireFailure(const char* file, int line, const char* expectation,
}
}
void unreachable() {
KJ_FAIL_ASSERT("Supposendly-unreachable branch executed.");
// Really make sure we abort.
abort();
}
} // namespace _ (private)
} // namespace kj
......@@ -134,6 +134,8 @@ void inlineRequireFailure(
const char* file, int line, const char* expectation, const char* macroArgs,
const char* message = nullptr) KJ_NORETURN;
void unreachable() KJ_NORETURN;
} // namespace _ (private)
#ifdef NDEBUG
......@@ -148,6 +150,16 @@ void inlineRequireFailure(
// whether libkj is.
#endif
#define KJ_UNREACHABLE ::kj::_::unreachable();
// Put this on code paths that cannot be reached to suppress compiler warnings about missing
// returns.
#if __clang__
#define KJ_CLANG_KNOWS_THIS_IS_UNREACHABLE_BUT_GCC_DOESNT
#else
#define KJ_CLANG_KNOWS_THIS_IS_UNREACHABLE_BUT_GCC_DOESNT KJ_UNREACHABLE
#endif
// #define KJ_STACK_ARRAY(type, name, size, minStack, maxStack)
//
// Allocate an array, preferably on the stack, unless it is too big. On GCC this will use
......
......@@ -59,7 +59,7 @@ TEST(Function, Method) {
EXPECT_EQ(123 + 456, f(123, 456));
EXPECT_EQ(7 + 8 + 1, f(7, 8));
EXPECT_EQ(9 + 2 + 2, f2(2, 9));
EXPECT_EQ(9u + 2u + 2u, f2(2, 9));
EXPECT_EQ(3, obj.callCount);
......
......@@ -117,7 +117,7 @@ private:
Own<Iface> impl;
};
namespace _ {
namespace _ { // private
template <typename T>
T rvalueOrRef(T&&);
......@@ -128,7 +128,47 @@ T rvalueOrRef(T&&);
// decltype(rvalueOrRef(i)) i2(i); // i2 has type int&.
// decltype(rvalueOrRef(kj::mv(i)) i3(kj::mv(i)); // i3 has type int.
} // namespace _
} // namespace _ (private)
#if 1
namespace _ { // private
template <typename T, typename Signature, Signature method>
class BoundMethod;
template <typename T, typename Return, typename... Params, Return (Decay<T>::*method)(Params...)>
class BoundMethod<T, Return (Decay<T>::*)(Params...), method> {
public:
BoundMethod(T&& t): t(kj::fwd<T>(t)) {}
Return operator()(Params&&... params) {
return (t.*method)(kj::fwd<Params>(params)...);
}
private:
T t;
};
} // namespace _ (private)
#define KJ_BIND_METHOD(obj, method) \
::kj::_::BoundMethod<decltype(::kj::_::rvalueOrRef(obj)), \
decltype(&::kj::Decay<decltype(obj)>::method), \
&::kj::Decay<decltype(obj)>::method>(obj)
// Macro that produces a functor object which forwards to the method `obj.name`. If `obj` is an
// lvalue, the functor will hold a reference to it. If `obj` is an rvalue, the functor will
// contain a copy (by move) of it.
//
// The current implementation requires that the method is not overloaded.
//
// TODO(someday): C++14's generic lambdas may be able to simplify this code considerably, and
// probably make it work with overloaded methods.
#else
// Here's a better implementation of the above that doesn't work with GCC (but does with Clang)
// because it uses a local class with a template method. Sigh. This implementation supports
// overloaded methods.
#define KJ_BIND_METHOD(obj, method) \
({ \
......@@ -150,6 +190,8 @@ T rvalueOrRef(T&&);
// lvalue, the functor will hold a reference to it. If `obj` is an rvalue, the functor will
// contain a copy (by move) of it.
#endif
} // namespace kj
#endif // KJ_FUNCTION_H_
......@@ -161,6 +161,7 @@ int runMainAndExit(ProcessContext& context, MainFunc&& func, int argc, char* arg
return e.exitCode;
}
#endif
KJ_CLANG_KNOWS_THIS_IS_UNREACHABLE_BUT_GCC_DOESNT
}
// =======================================================================================
......@@ -520,6 +521,7 @@ void MainBuilder::MainImpl::usageError(StringPtr programName, StringPtr message)
impl->context.exitError(kj::str(
programName, ": ", message,
"\nTry '", programName, " --help' for more information."));
KJ_CLANG_KNOWS_THIS_IS_UNREACHABLE_BUT_GCC_DOESNT
}
class MainBuilder::Impl::OptionDisplayOrder {
......@@ -662,6 +664,7 @@ void MainBuilder::MainImpl::printHelp(StringPtr programName) {
text.add('\0');
impl->context.exitInfo(String(text.releaseAsArray()));
KJ_CLANG_KNOWS_THIS_IS_UNREACHABLE_BUT_GCC_DOESNT
}
void MainBuilder::MainImpl::wrapText(Vector<char>& output, StringPtr indent, StringPtr text) {
......
......@@ -84,11 +84,11 @@ public:
// are easily confused by quick_exit().
StringPtr getProgramName() override;
void exit() KJ_NORETURN override;
void exit() override KJ_NORETURN;
void warning(StringPtr message) override;
void error(StringPtr message) override;
void exitError(StringPtr message) KJ_NORETURN override;
void exitInfo(StringPtr message) KJ_NORETURN override;
void exitError(StringPtr message) override KJ_NORETURN;
void exitInfo(StringPtr message) override KJ_NORETURN;
void increaseLoggingVerbosity() override;
private:
......@@ -192,8 +192,8 @@ public:
class OptionName {
public:
OptionName() = default;
inline constexpr OptionName(char shortName): isLong(false), shortName(shortName) {}
inline constexpr OptionName(const char* longName): isLong(true), longName(longName) {}
inline OptionName(char shortName): isLong(false), shortName(shortName) {}
inline OptionName(const char* longName): isLong(true), longName(longName) {}
private:
bool isLong;
......
......@@ -38,32 +38,32 @@ TEST(Mutex, MutexGuarded) {
{
Locked<uint> lock = value.lockExclusive();
EXPECT_EQ(123, *lock);
EXPECT_EQ(123u, *lock);
Thread thread([&]() {
Locked<uint> threadLock = value.lockExclusive();
EXPECT_EQ(456, *threadLock);
EXPECT_EQ(456u, *threadLock);
*threadLock = 789;
});
delay();
EXPECT_EQ(123, *lock);
EXPECT_EQ(123u, *lock);
*lock = 456;
auto earlyRelease = kj::mv(lock);
}
EXPECT_EQ(789, *value.lockExclusive());
EXPECT_EQ(789u, *value.lockExclusive());
{
auto rlock1 = value.lockShared();
{
auto rlock2 = value.lockShared();
EXPECT_EQ(789, *rlock2);
EXPECT_EQ(789u, *rlock2);
auto rlock3 = value.lockShared();
EXPECT_EQ(789, *rlock3);
EXPECT_EQ(789u, *rlock3);
auto rlock4 = value.lockShared();
EXPECT_EQ(789, *rlock4);
EXPECT_EQ(789u, *rlock4);
}
Thread thread2([&]() {
......@@ -80,24 +80,24 @@ TEST(Mutex, MutexGuarded) {
// but we'll leave this test here until then to make sure we notice the change.
delay();
EXPECT_EQ(789, *rlock1);
EXPECT_EQ(789u, *rlock1);
{
auto rlock2 = value.lockShared();
EXPECT_EQ(789, *rlock2);
EXPECT_EQ(789u, *rlock2);
auto rlock3 = value.lockShared();
EXPECT_EQ(789, *rlock3);
EXPECT_EQ(789u, *rlock3);
auto rlock4 = value.lockShared();
EXPECT_EQ(789, *rlock4);
EXPECT_EQ(789u, *rlock4);
}
#endif
delay();
EXPECT_EQ(789, *rlock1);
EXPECT_EQ(789u, *rlock1);
auto earlyRelease = kj::mv(rlock1);
}
EXPECT_EQ(321, *value.lockExclusive());
EXPECT_EQ(321u, *value.lockExclusive());
}
TEST(Mutex, Lazy) {
......@@ -105,7 +105,7 @@ TEST(Mutex, Lazy) {
bool initStarted = false;
Thread thread([&]() {
EXPECT_EQ(123, lazy.get([&](SpaceFor<uint>& space) -> Own<uint> {
EXPECT_EQ(123u, lazy.get([&](SpaceFor<uint>& space) -> Own<uint> {
__atomic_store_n(&initStarted, true, __ATOMIC_RELAXED);
delay();
return space.construct(123);
......@@ -117,8 +117,8 @@ TEST(Mutex, Lazy) {
sched_yield();
}
EXPECT_EQ(123, lazy.get([](SpaceFor<uint>& space) { return space.construct(456); }));
EXPECT_EQ(123, lazy.get([](SpaceFor<uint>& space) { return space.construct(789); }));
EXPECT_EQ(123u, lazy.get([](SpaceFor<uint>& space) { return space.construct(456); }));
EXPECT_EQ(123u, lazy.get([](SpaceFor<uint>& space) { return space.construct(789); }));
}
} // namespace
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment