Add src/traits.h
Contains some intimidating template magic for inferring the first parameter type of a function or function-like.
Will be used by the CloneContext for transforming the AST while cloning.
Bug: tint:390
Change-Id: I432059d13e65fa0f0f3e52588eb43abe9a4efadd
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/34566
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index 2f831c8..019da76 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -369,6 +369,7 @@
"src/ast/type/vector_type.h",
"src/ast/type/void_type.cc",
"src/ast/type/void_type.h",
+ "src/ast/traits.h",
"src/ast/type_constructor_expression.cc",
"src/ast/type_constructor_expression.h",
"src/ast/type_decoration.cc",
@@ -805,6 +806,7 @@
"src/ast/type/struct_type_test.cc",
"src/ast/type/u32_type_test.cc",
"src/ast/type/vector_type_test.cc",
+ "src/ast/traits_test.cc",
"src/ast/type_constructor_expression_test.cc",
"src/ast/type_manager_test.cc",
"src/ast/uint_literal_test.cc",
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b3eb97a..870a44a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -152,6 +152,7 @@
ast/struct_member_offset_decoration.h
ast/switch_statement.cc
ast/switch_statement.h
+ ast/traits.h
ast/type_constructor_expression.h
ast/type_constructor_expression.cc
ast/type_decoration.cc
@@ -415,6 +416,7 @@
ast/type/struct_type_test.cc
ast/type/u32_type_test.cc
ast/type/vector_type_test.cc
+ ast/traits_test.cc
ast/type_constructor_expression_test.cc
ast/type_manager_test.cc
ast/uint_literal_test.cc
diff --git a/src/ast/traits.h b/src/ast/traits.h
new file mode 100644
index 0000000..5871765
--- /dev/null
+++ b/src/ast/traits.h
@@ -0,0 +1,62 @@
+// Copyright 2020 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_AST_TRAITS_H_
+#define SRC_AST_TRAITS_H_
+
+#include <type_traits>
+
+namespace tint {
+namespace ast {
+namespace traits {
+
+/// FirstParamType is a traits helper that infers the type of the first
+/// parameter of the function, method, static method, lambda, or function-like
+/// object `F`.
+template <typename F>
+struct FirstParamType {
+ /// The type of the first parameter of the function-like object `F`
+ using type = typename FirstParamType<decltype(&F::operator())>::type;
+};
+
+/// FirstParamType specialization for a regular function or static method.
+template <typename R, typename Arg>
+struct FirstParamType<R (*)(Arg)> {
+ /// The type of the first parameter of the function
+ using type = typename std::decay<Arg>::type;
+};
+
+/// FirstParamType specialization for a non-static method.
+template <typename R, typename C, typename Arg>
+struct FirstParamType<R (C::*)(Arg)> {
+ /// The type of the first parameter of the function
+ using type = typename std::decay<Arg>::type;
+};
+
+/// FirstParamType specialization for a non-static, const method.
+template <typename R, typename C, typename Arg>
+struct FirstParamType<R (C::*)(Arg) const> {
+ /// The type of the first parameter of the function
+ using type = typename std::decay<Arg>::type;
+};
+
+/// FirstParamTypeT is an alias to `typename FirstParamType<F>::type`.
+template <typename F>
+using FirstParamTypeT = typename FirstParamType<F>::type;
+
+} // namespace traits
+} // namespace ast
+} // namespace tint
+
+#endif // SRC_AST_TRAITS_H_
diff --git a/src/ast/traits_test.cc b/src/ast/traits_test.cc
new file mode 100644
index 0000000..05ccced
--- /dev/null
+++ b/src/ast/traits_test.cc
@@ -0,0 +1,74 @@
+// Copyright 2020 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/ast/traits.h"
+
+#include <functional>
+
+#include "gtest/gtest.h"
+
+namespace tint {
+namespace ast {
+namespace traits {
+
+namespace {
+struct S {};
+void F(S) {}
+} // namespace
+
+TEST(FirstParamType, Function) {
+ F({}); // Avoid unused method warning
+ static_assert(std::is_same<FirstParamTypeT<decltype(&F)>, S>::value, "");
+}
+
+TEST(FirstParamType, Method) {
+ class C {
+ public:
+ void f(S) {}
+ };
+ C().f({}); // Avoid unused method warning
+ static_assert(std::is_same<FirstParamTypeT<decltype(&C::f)>, S>::value, "");
+}
+
+TEST(FirstParamType, ConstMethod) {
+ class C {
+ public:
+ void f(S) const {}
+ };
+ C().f({}); // Avoid unused method warning
+ static_assert(std::is_same<FirstParamTypeT<decltype(&C::f)>, S>::value, "");
+}
+
+TEST(FirstParamType, StaticMethod) {
+ class C {
+ public:
+ static void f(S) {}
+ };
+ C().f({}); // Avoid unused method warning
+ static_assert(std::is_same<FirstParamTypeT<decltype(&C::f)>, S>::value, "");
+}
+
+TEST(FirstParamType, FunctionLike) {
+ static_assert(std::is_same<FirstParamTypeT<std::function<void(S)>>, S>::value,
+ "");
+}
+
+TEST(FirstParamType, Lambda) {
+ auto l = [](S) {};
+ static_assert(std::is_same<FirstParamTypeT<decltype(l)>, S>::value, "");
+}
+
+} // namespace traits
+} // namespace ast
+} // namespace tint