Commit 60145838 authored by Kenton Varda's avatar Kenton Varda

Merge pull request #331 from harrishancock/vs2015-capnp-lite

Re-enable MSVC lite-mode
parents 44d91b41 0c641ecf
......@@ -247,6 +247,8 @@ TEST(Any, AnyStructListCapInSchema) {
checkList(anyList.as<List<int>>(), {123, 456, 789});
}
#if !CAPNP_LITE
// This portion of the test relies on a Client, not present in lite-mode.
{
kj::EventLoop loop;
kj::WaitScope waitScope(loop);
......@@ -259,6 +261,7 @@ TEST(Any, AnyStructListCapInSchema) {
req.send().wait(waitScope);
EXPECT_EQ(1, callCount);
}
#endif
}
......
......@@ -252,7 +252,6 @@ public:
// portion of each segment, whereas tryGetSegment() returns something that includes
// not-yet-allocated space.
#if !CAPNP_LITE
inline CapTableBuilder* getLocalCapTable() {
// Return a CapTableBuilder that merely implements local loopback. That is, you can set
// capabilities, then read the same capabilities back, but there is no intent ever to transmit
......@@ -269,7 +268,6 @@ public:
return &localCapTable;
}
#endif // !CAPNP_LITE
SegmentBuilder* getSegment(SegmentId id);
// Get the segment with the given id. Crashes or throws an exception if no such segment exists.
......@@ -304,8 +302,8 @@ private:
MessageBuilder* message;
ReadLimiter dummyLimiter;
#if !CAPNP_LITE
class LocalCapTable: public CapTableBuilder {
#if !CAPNP_LITE
public:
kj::Maybe<kj::Own<ClientHook>> extractCap(uint index) override;
uint injectCap(kj::Own<ClientHook>&& cap) override;
......@@ -313,10 +311,10 @@ private:
private:
kj::Vector<kj::Maybe<kj::Own<ClientHook>>> capTable;
#endif // ! CAPNP_LITE
};
LocalCapTable localCapTable;
#endif // !CAPNP_LITE
SegmentBuilder segment0;
kj::ArrayPtr<const word> segment0ForOutput;
......
......@@ -77,9 +77,11 @@ using capnproto_test::capnp::test::TestInterface;
static_assert(equalTypes<FromAny<int>, int>(), "");
static_assert(equalTypes<FromAny<TestAllTypes::Reader>, TestAllTypes>(), "");
static_assert(equalTypes<FromAny<TestAllTypes::Builder>, TestAllTypes>(), "");
#if !CAPNP_LITE
static_assert(equalTypes<FromAny<TestAllTypes::Pipeline>, TestAllTypes>(), "");
static_assert(equalTypes<FromAny<TestInterface::Client>, TestInterface>(), "");
static_assert(equalTypes<FromAny<kj::Own<TestInterface::Server>>, TestInterface>(), "");
#endif
} // namespace
} // namespace capnp
......@@ -127,18 +127,7 @@ struct EnumInfo;
namespace _ { // private
template <typename T, typename = typename T::_capnpPrivate::IsStruct> uint8_t kindSfinae(int);
template <typename T, typename = typename T::_capnpPrivate::IsInterface> uint16_t kindSfinae(int);
template <typename T, typename = typename schemas::EnumInfo<T>::IsEnum> uint32_t kindSfinae(int);
template <typename T> uint64_t kindSfinae(...);
template <typename T>
struct MsvcWorkaround {
// TODO(msvc): Remove this once MSVC supports expression SFINAE.
enum { value = sizeof(kindSfinae<T>(0)) };
};
template <typename T, size_t s = MsvcWorkaround<T>::value> struct Kind_;
template <typename T, typename = void> struct Kind_;
template <> struct Kind_<Void> { static constexpr Kind kind = Kind::PRIMITIVE; };
template <> struct Kind_<bool> { static constexpr Kind kind = Kind::PRIMITIVE; };
......@@ -155,19 +144,18 @@ template <> struct Kind_<double> { static constexpr Kind kind = Kind::PRIMITIVE;
template <> struct Kind_<Text> { static constexpr Kind kind = Kind::BLOB; };
template <> struct Kind_<Data> { static constexpr Kind kind = Kind::BLOB; };
template <typename T> struct Kind_<T, sizeof(uint8_t)> { static constexpr Kind kind = Kind::STRUCT; };
template <typename T> struct Kind_<T, sizeof(uint16_t)> { static constexpr Kind kind = Kind::INTERFACE; };
template <typename T> struct Kind_<T, sizeof(uint32_t)> { static constexpr Kind kind = Kind::ENUM; };
template <typename T> struct Kind_<T, kj::VoidSfinae<typename T::_capnpPrivate::IsStruct>> {
static constexpr Kind kind = Kind::STRUCT;
};
template <typename T> struct Kind_<T, kj::VoidSfinae<typename T::_capnpPrivate::IsInterface>> {
static constexpr Kind kind = Kind::INTERFACE;
};
template <typename T> struct Kind_<T, kj::VoidSfinae<typename schemas::EnumInfo<T>::IsEnum>> {
static constexpr Kind kind = Kind::ENUM;
};
} // namespace _ (private)
#if CAPNP_LITE
#define CAPNP_KIND(T) ::capnp::_::Kind_<T>::kind
// Avoid constexpr methods in lite mode (MSVC is bad at constexpr).
#else // CAPNP_LITE
template <typename T, Kind k = _::Kind_<T>::kind>
inline constexpr Kind kind() {
// This overload of kind() matches types which have a Kind_ specialization.
......@@ -175,6 +163,13 @@ inline constexpr Kind kind() {
return k;
}
#if CAPNP_LITE
#define CAPNP_KIND(T) ::capnp::_::Kind_<T>::kind
// Avoid constexpr methods in lite mode (MSVC is bad at constexpr).
#else // CAPNP_LITE
#define CAPNP_KIND(T) ::capnp::kind<T>()
// Use this macro rather than kind<T>() in any code which must work in lite mode.
......@@ -206,7 +201,7 @@ template <typename T> struct ListElementType_<List<T>> { typedef T Type; };
template <typename T> using ListElementType = typename ListElementType_<T>::Type;
namespace _ { // private
template <typename T, Kind k> struct Kind_<List<T, k>, sizeof(uint64_t)> {
template <typename T, Kind k> struct Kind_<List<T, k>> {
static constexpr Kind kind = Kind::LIST;
};
} // namespace _ (private)
......@@ -255,18 +250,42 @@ template <typename T>
using FromServer = typename kj::Decay<T>::Serves;
// FromBuilder<MyType::Server> = MyType (for any Cap'n Proto interface type).
struct FromAny_ {
template <typename T, typename X = FromReader<T>> static X apply(T*, int);
template <typename T, typename X = FromBuilder<T>> static X apply(T*, char);
template <typename T, typename X = FromPipeline<T>> static X apply(T*, long);
// note that ::Client is covered by FromReader
template <typename T, typename X = FromServer<T>> static X apply(kj::Own<T>*, short);
template <typename T, typename = kj::EnableIf<style<T>() == Style::PRIMITIVE>>
static T apply(T*, unsigned int);
template <typename T, typename = void>
struct FromAny_;
template <typename T>
struct FromAny_<T, kj::VoidSfinae<FromReader<T>>> {
using Type = FromReader<T>;
};
template <typename T>
struct FromAny_<T, kj::VoidSfinae<FromBuilder<T>>> {
using Type = FromBuilder<T>;
};
template <typename T>
struct FromAny_<T, kj::VoidSfinae<FromPipeline<T>>> {
using Type = FromPipeline<T>;
};
// Note that T::Client is covered by FromReader
template <typename T>
struct FromAny_<kj::Own<T>, kj::VoidSfinae<FromServer<T>>> {
using Type = FromServer<T>;
};
template <typename T>
struct FromAny_<T,
kj::EnableIf<_::Kind_<T>::kind == Kind::PRIMITIVE || _::Kind_<T>::kind == Kind::ENUM>> {
// TODO(msvc): Ideally the EnableIf condition would be `style<T>() == Style::PRIMITIVE`, but MSVC
// cannot yet use style<T>() in this constexpr context.
using Type = kj::Decay<T>;
};
template <typename T>
using FromAny = kj::Decay<decltype(FromAny_::apply(kj::instance<T*>(), 0))>;
using FromAny = typename FromAny_<T>::Type;
// Given any Cap'n Proto value type as an input, return the Cap'n Proto base type. That is:
//
// Foo::Reader -> Foo
......
......@@ -28,7 +28,7 @@
#include <capnp/schema.capnp.h>
#include <kj/vector.h>
#include <kj/io.h>
#include <unistd.h>
#include <kj/miniposix.h>
#include <kj/debug.h>
#include "../message.h"
#include <iostream>
......@@ -43,9 +43,6 @@
#if _WIN32
#include <process.h>
#include <io.h>
#include <fcntl.h>
#define pipe(fds) _pipe(fds, 8192, _O_BINARY)
#else
#include <sys/wait.h>
#endif
......@@ -447,7 +444,7 @@ public:
}
int pipeFds[2];
KJ_SYSCALL(pipe(pipeFds));
KJ_SYSCALL(kj::miniposix::pipe(pipeFds));
kj::String exeName;
bool shouldSearchPath = true;
......
......@@ -30,7 +30,7 @@
#include <kj/vector.h>
#include "../schema-loader.h"
#include "../dynamic.h"
#include <unistd.h>
#include <kj/miniposix.h>
#include <unordered_map>
#include <unordered_set>
#include <map>
......@@ -50,10 +50,6 @@
#define VERSION "(unknown)"
#endif
#if _WIN32
#define mkdir(path, mode) mkdir(path)
#endif
namespace capnp {
namespace {
......@@ -2917,7 +2913,7 @@ private:
makeDirectory(kj::str(path.slice(0, *slashpos)));
}
if (mkdir(path.cStr(), 0777) < 0) {
if (kj::miniposix::mkdir(path.cStr(), 0777) < 0) {
int error = errno;
if (error != EEXIST) {
KJ_FAIL_SYSCALL("mkdir(path)", error, path);
......
......@@ -30,7 +30,7 @@
#include <kj/vector.h>
#include "../schema-loader.h"
#include "../dynamic.h"
#include <unistd.h>
#include <kj/miniposix.h>
#include <unordered_map>
#include <kj/main.h>
#include <algorithm>
......
......@@ -37,7 +37,7 @@
#include <time.h>
#include <kj/main.h>
#include <kj/io.h>
#include <unistd.h>
#include <kj/miniposix.h>
namespace capnp {
namespace compiler {
......
......@@ -28,7 +28,7 @@
#include <kj/io.h>
#include <capnp/message.h>
#include <map>
#include <unistd.h>
#include <kj/miniposix.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
......@@ -99,7 +99,7 @@ kj::Array<const byte> mmapForRead(kj::StringPtr filename) {
byte buffer[4096];
for (;;) {
ssize_t n;
kj::miniposix::ssize_t n;
KJ_SYSCALL(n = read(fd, buffer, sizeof(buffer)));
if (n == 0) break;
data.addAll(buffer, buffer + n);
......
......@@ -1667,6 +1667,8 @@ TEST(Encoding, Embeds) {
checkTestMessage(reader.getRoot<TestAllTypes>());
}
#if !CAPNP_LITE
{
MallocMessageBuilder builder;
auto root = builder.getRoot<TestAllTypes>();
......@@ -1675,6 +1677,8 @@ TEST(Encoding, Embeds) {
EXPECT_EQ(kj::str(root, '\n').size(), text.size());
}
#endif // CAPNP_LITE
{
checkTestMessage(test::EMBEDDED_STRUCT);
}
......
......@@ -25,7 +25,7 @@
#include "serialize.h"
#include <kj/test.h>
#include <stdlib.h>
#include <unistd.h>
#include <kj/miniposix.h>
#include "test-util.h"
namespace capnp {
......
......@@ -36,9 +36,11 @@ namespace {
class DummyCapTableReader: public _::CapTableReader {
public:
#if !CAPNP_LITE
kj::Maybe<kj::Own<ClientHook>> extractCap(uint index) override {
return nullptr;
}
#endif
};
static constexpr DummyCapTableReader dummyCapTableReader = DummyCapTableReader();
......
......@@ -31,7 +31,7 @@
#include <kj/vector.h>
#include <kj/debug.h>
#include <kj/io.h>
#include <unistd.h>
#include <kj/miniposix.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
......@@ -400,7 +400,7 @@ kj::Array<const char> SchemaFile::DiskFileReader::read(kj::StringPtr path) const
char buffer[4096];
for (;;) {
ssize_t n;
kj::miniposix::ssize_t n;
KJ_SYSCALL(n = ::read(fd, buffer, sizeof(buffer)));
if (n == 0) break;
data.addAll(buffer, buffer + n);
......
......@@ -11,13 +11,13 @@ set(kj_sources_lite
mutex.c++
string.c++
thread.c++
main.c++
arena.c++
)
set(kj_sources_heavy
units.c++
refcount.c++
string-tree.c++
arena.c++
main.c++
parse/char.c++
)
if(NOT CAPNP_LITE)
......
......@@ -340,6 +340,10 @@ template <bool b> using EnableIf = typename EnableIf_<b>::Type;
// template <typename T, typename = EnableIf<isValid<T>()>
// void func(T&& t);
template <typename...> struct VoidSfinae_ { using Type = void; };
template <typename... Ts> using VoidSfinae = typename VoidSfinae_<Ts...>::Type;
// Note: VoidSfinae is std::void_t from C++17.
template <typename T>
T instance() noexcept;
// Like std::declval, but doesn't transform T into an rvalue reference. If you want that, specify
......@@ -790,6 +794,15 @@ class Maybe;
namespace _ { // private
#if _MSC_VER
// TODO(msvc): MSVC barfs on noexcept(instance<T&>().~T()) where T = kj::Exception and
// kj::_::Void. It and every other factorization I've tried produces:
// error C2325: 'kj::Blah' unexpected type to the right of '.~': expected 'void'
#define MSVC_NOEXCEPT_DTOR_WORKAROUND(T) __is_nothrow_destructible(T)
#else
#define MSVC_NOEXCEPT_DTOR_WORKAROUND(T) noexcept(instance<T&>().~T())
#endif
template <typename T>
class NullableValue {
// Class whose interface behaves much like T*, but actually contains an instance of T and a
......@@ -814,7 +827,7 @@ public:
ctor(value, other.value);
}
}
inline ~NullableValue() noexcept(noexcept(instance<T&>().~T())) {
inline ~NullableValue() noexcept(MSVC_NOEXCEPT_DTOR_WORKAROUND(T)) {
if (isSet) {
dtor(value);
}
......
......@@ -22,17 +22,17 @@
#include "main.h"
#include "debug.h"
#include "arena.h"
#include "miniposix.h"
#include <map>
#include <set>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
#if _WIN32
#define NOMINMAX
#include <windows.h>
#include <io.h>
#include <fcntl.h>
#undef NOMINMAX
#else
#include <sys/uio.h>
#endif
......
......@@ -19,8 +19,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef KJ_PORTABLE_FD_H_
#define KJ_PORTABLE_FD_H_
#ifndef KJ_MINIPOSIX_H_
#define KJ_MINIPOSIX_H_
// This header provides a small subset of the POSIX API which also happens to be available on
// Windows under slightly-different names.
......@@ -32,6 +32,7 @@
#if _WIN32
#include <io.h>
#include <direct.h>
#include <fcntl.h> // _O_BINARY
#else
#include <limits.h>
#include <errno.h>
......@@ -61,6 +62,17 @@ inline int close(int fd) {
return ::_close(fd);
}
#ifndef F_OK
#define F_OK 0 // access() existence test
#endif
#ifndef S_ISREG
#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) // stat() regular file test
#endif
#ifndef S_ISDIR
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) // stat() directory test
#endif
#ifndef STDIN_FILENO
#define STDIN_FILENO 0
#endif
......@@ -85,7 +97,7 @@ using ::close;
// We're on Windows, including MinGW. pipe() and mkdir() are non-standard even on MinGW.
inline int pipe(int fds[2]) {
return ::_pipe(fds, 4096, false);
return ::_pipe(fds, 8192, _O_BINARY);
}
inline int mkdir(const char* path, int mode) {
return ::_mkdir(path);
......@@ -133,4 +145,4 @@ inline size_t iovMax(size_t count) {
} // namespace miniposix
} // namespace kj
#endif // KJ_WIN32_FD_H_
#endif // KJ_MINIPOSIX_H_
......@@ -25,7 +25,9 @@
#include <kj/compat/gtest.h>
#if _WIN32
#define NOGDI // NOGDI is needed to make EXPECT_EQ(123u, *lock) compile for some reason
#include <windows.h>
#undef NOGDI
#else
#include <pthread.h>
#include <unistd.h>
......
......@@ -67,10 +67,6 @@ struct Id {
// =======================================================================================
// Quantity and UnitRatio -- implement unit analysis via the type system
#if !_MSC_VER
// TODO(msvc): MSVC has trouble with this intense templating. Luckily Cap'n Proto can deal with
// using regular integers in place of Quantity, so we can just skip all this.
template <typename T> constexpr bool isIntegral() { return false; }
template <> constexpr bool isIntegral<char>() { return true; }
template <> constexpr bool isIntegral<signed char>() { return true; }
......@@ -225,9 +221,12 @@ class Quantity {
public:
inline constexpr Quantity() {}
inline constexpr Quantity(decltype(maxValue)): value(maxValue) {}
inline constexpr Quantity(decltype(minValue)): value(minValue) {}
inline constexpr Quantity(MaxValue_): value(maxValue) {}
inline constexpr Quantity(MinValue_): value(minValue) {}
// Allow initialization from maxValue and minValue.
// TODO(msvc): decltype(maxValue) and decltype(minValue) deduce unknown-type for these function
// parameters, causing the compiler to complain of a duplicate constructor definition, so we
// specify MaxValue_ and MinValue_ types explicitly.
inline explicit constexpr Quantity(Number value): value(value) {}
// This constructor was intended to be private, but GCC complains about it being private in a
......@@ -354,15 +353,11 @@ private:
friend inline constexpr T unit();
};
#endif // !_MSC_VER
template <typename T>
inline constexpr T unit() { return T(1); }
// unit<Quantity<T, U>>() returns a Quantity of value 1. It also, intentionally, works on basic
// numeric types.
#if !_MSC_VER
template <typename Number1, typename Number2, typename Unit>
inline constexpr auto operator*(Number1 a, Quantity<Number2, Unit> b)
-> Quantity<decltype(Number1(1) * Number2(1)), Unit> {
......@@ -433,8 +428,6 @@ inline constexpr T origin() { return T(0 * unit<UnitOf<T>>()); }
// origin<Absolute<T, U>>() returns an Absolute of value 0. It also, intentionally, works on basic
// numeric types.
#endif // !_MSC_VER
} // namespace kj
#endif // KJ_UNITS_H_
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