From 4da3337ff8ebb614dad1f5e54eb6644186636080 Mon Sep 17 00:00:00 2001
From: Roman Tsisyk <roman@tsisyk.com>
Date: Fri, 10 Jul 2015 14:30:16 +0300
Subject: [PATCH] Fix compilation on clang

---
 src/exception.cc                |  2 +-
 src/lua/utils.cc                |  1 +
 src/reflection.h                | 20 +++++++++++---------
 test/unit/reflection_cxx.cc     |  6 +++++-
 test/unit/reflection_cxx.result |  3 ++-
 5 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/src/exception.cc b/src/exception.cc
index 020eafec52..15cf0a50cf 100644
--- a/src/exception.cc
+++ b/src/exception.cc
@@ -80,7 +80,7 @@ Exception::~Exception()
 Exception::Exception(const struct type *type_arg, const char *file,
 	unsigned line)
 	:type(type_arg), m_ref(0) {
-	if (m_file != NULL) {
+	if (file != NULL) {
 		snprintf(m_file, sizeof(m_file), "%s", file);
 		m_line = line;
 	} else {
diff --git a/src/lua/utils.cc b/src/lua/utils.cc
index e89ef600ad..9c61376e58 100644
--- a/src/lua/utils.cc
+++ b/src/lua/utils.cc
@@ -100,6 +100,7 @@ int
 luaL_cdef(struct lua_State *L, const char *what)
 {
 	int idx = lua_gettop(L);
+	(void) idx;
 	/* This function calls ffi.cdef  */
 
 	/* Get ffi.typeof function */
diff --git a/src/reflection.h b/src/reflection.h
index 669b66b2b2..746a70fdd6 100644
--- a/src/reflection.h
+++ b/src/reflection.h
@@ -100,8 +100,6 @@ struct method {
 		void *_spacer[2];
 #if defined(__cplusplus)
 		method_thiscall_f thiscall;
-		static_assert(sizeof(thiscall) <= sizeof(_spacer),
-			"sizeof(thiscall)");
 #endif /* defined(__cplusplus) */
 	};
 };
@@ -126,6 +124,9 @@ extern const struct method METHODS_SENTINEL;
 #if defined(__cplusplus)
 } /* extern "C" */
 
+static_assert(sizeof(((struct method *) 0)->thiscall) <=
+	      sizeof(((struct method *) 0)->_spacer), "sizeof(thiscall)");
+
 /*
  * Begin of C++ syntax sugar
  */
@@ -250,6 +251,14 @@ method_invokable(const struct method *method, T *object)
 	return method_helper<0, Args...>::invokable(method);
 }
 
+template<typename R, typename... Args, typename T> inline bool
+method_invokable(const struct method *method, const T *object)
+{
+	if (!method->isconst)
+		return false;
+	return method_invokable<R, Args...>(method, const_cast<T*>(object));
+}
+
 /**
  * Invoke method with object and provided arguments.
  */
@@ -261,13 +270,6 @@ method_invoke(const struct method *method, T *object, Args... args)
 	return (object->*(MemberFunction) method->thiscall)(args...);
 }
 
-template<typename R, typename... Args, typename T > inline R
-method_invoke(const struct method *method, const T *object, Args... args)
-{
-	assert(method->isconst);
-	return method_invoke<R, Args...>(object, args...);
-}
-
 #endif /* defined(__cplusplus) */
 
 #endif /* TARANTOOL_REFLECTION_H_INCLUDED */
diff --git a/test/unit/reflection_cxx.cc b/test/unit/reflection_cxx.cc
index ee100a77dc..6369fd0b30 100644
--- a/test/unit/reflection_cxx.cc
+++ b/test/unit/reflection_cxx.cc
@@ -84,7 +84,7 @@ const struct type type_Tarantool = make_type("Tarantool", &type_Database,
 int
 main()
 {
-	plan(29);
+	plan(30);
 
 	Object obj;
 	Tarantool tntobj;
@@ -170,5 +170,9 @@ main()
 	iret = method_invoke<int>(get_int, &tntobj);
 	is(iret, 49, "invoke (void)");
 
+	const Tarantool *tntconstptr = &tntobj;
+	ok((!method_invokable<void, const char *>(put_string, tntconstptr)),
+		"!invokable<>() on const method with non-const object");
+
 	return check_plan();
 }
diff --git a/test/unit/reflection_cxx.result b/test/unit/reflection_cxx.result
index 92a5459391..0f4f51eb44 100644
--- a/test/unit/reflection_cxx.result
+++ b/test/unit/reflection_cxx.result
@@ -1,4 +1,4 @@
-1..29
+1..30
 ok 1 - type.name
 ok 2 - type.parent
 ok 3 - type.parent
@@ -28,3 +28,4 @@ ok 26 - invokable<void, const char *>
 ok 27 - invoke (int)
 ok 28 - invoke (const char *)
 ok 29 - invoke (void)
+ok 30 - !invokable<>() on const method with non-const object
-- 
GitLab