Enable clang_tidy for AIDL-generated C++ libraries

tidy is enabled for the cpp and ndk backends. The AIDL compiler is
modified to emit code that doesn't break the tidy checks.

Bug: 162909698
Test: m checkbuild
Test: run aidl_unittests
Change-Id: I0df916e5df15dba85b75603a544d4666594526ea
diff --git a/aidl_to_cpp_common.cpp b/aidl_to_cpp_common.cpp
index 5e0ef1f..2d69a4a 100644
--- a/aidl_to_cpp_common.cpp
+++ b/aidl_to_cpp_common.cpp
@@ -648,7 +648,8 @@
 {name}& operator=(const {name}&) = default;
 {name}& operator=({name}&&) = default;
 
-template <typename _Tp, std::enable_if_t<_not_self<_Tp>, int> = 0>
+template <typename _Tp, typename = std::enable_if_t<_not_self<_Tp>>>
+// NOLINTNEXTLINE(google-explicit-constructor)
 constexpr {name}(_Tp&& _arg)
     : _value(std::forward<_Tp>(_arg)) {{}}
 
@@ -714,8 +715,21 @@
   for (const auto& variable : decl.GetFields()) {
     out << fmt::format("case {}: {{\n", variable->GetName());
     out.Indent();
-    read_var(value, variable->GetType());
+    const auto& type = variable->GetType();
+    read_var(value, type);
+    out << fmt::format("if constexpr (std::is_trivially_copyable_v<{}>) {{\n",
+                       name_of(type, typenames));
+    out.Indent();
+    out << fmt::format("set<{}>({});\n", variable->GetName(), value);
+    out.Dedent();
+    out << "} else {\n";
+    out.Indent();
+    // Even when the `if constexpr` is false, the compiler runs the tidy check for the
+    // next line, which doesn't make sense. Silence the check for the unreachable code.
+    out << "// NOLINTNEXTLINE(performance-move-const-arg)\n";
     out << fmt::format("set<{}>(std::move({}));\n", variable->GetName(), value);
+    out.Dedent();
+    out << "}\n";
     out << fmt::format("return {}; }}\n", ctx.status_ok);
     out.Dedent();
   }