message-append: char* passed to sd-bus as char**

If a call to message::append resulted in the templates generating
a call to sd_bus_message_append_basic, all flavors of char* were
being passed to sd_bus as char**.

Fix by adding type-templates to distinguish between T and T* for
the parameters to sd_bus_message_append_basic.

Fixes openbmc/openbmc#1025.

Change-Id: I2f3a204ae10803c677d1c3aecfa4d9eabc40b593
Signed-off-by: Patrick Williams <patrick@stwcx.xyz>
diff --git a/sdbusplus/message/append.hpp b/sdbusplus/message/append.hpp
index c91ef08..8818220 100644
--- a/sdbusplus/message/append.hpp
+++ b/sdbusplus/message/append.hpp
@@ -83,6 +83,24 @@
     template<typename T>
     using Td = types::details::type_id_downcast_t<T>;
 
+    // sd_bus_message_append_basic expects a T* (cast to void*) for most types,
+    // so t& is appropriate.  In the case of char*, it expects the void* is
+    // the char*.  If we use &t, that is a char** and not a char*.
+    //
+    // Use these helper templates 'address_of(t)' in place of '&t' to
+    // handle both cases.
+    template<typename T>
+    static auto address_of_helper(T&& t, std::false_type) { return &t; }
+    template<typename T>
+    static auto address_of_helper(T&& t, std::true_type) { return t; }
+
+    template<typename T>
+    static auto address_of(T&& t)
+    {
+        return address_of_helper(std::forward<T>(t),
+                                 std::is_pointer<std::remove_reference_t<T>>());
+    }
+
     /** @brief Do the operation to append element.
      *
      *  @tparam T - Type of element to append.
@@ -107,7 +125,8 @@
                       "Non-basic types are not allowed.");
 
         constexpr auto dbusType = std::get<0>(types::type_id<T>());
-        sd_bus_message_append_basic(m, dbusType, &t);
+        sd_bus_message_append_basic(m, dbusType,
+                                    address_of(std::forward<T>(t)));
     }
 };