https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64867
--- Comment #11 from Jonathan Wakely <redi at gcc dot gnu.org> --- (In reply to Tom Tromey from comment #9) > However my belief is that because this class has a user-provided > default constructor, it is not trivial. True, but ... > I tested this by adding "#include <type_traits>" and then > > static_assert(!std::is_trivial<ConstUTF8CharsZ>::value, "whoops"); That's the wrong thing to assert: Passing a potentially-evaluated argument of class type (Clause 9) having a non-trivial copy constructor, a non-trivial move constructor, or a non-trivial destructor, with no corresponding parameter, is conditionally-supported with implementation-defined semantics. Your type has a trivial copy constructor and trivial move constructor and trivial destructor, so passing it to a varargs function is well-defined. Give it a non-trivial destructor and you get a warning: cs.cc: In function ‘void m(const char*)’: cs.cc:33:12: warning: passing objects of non-trivially-copyable type ‘class ConstUTF8CharsZ’ through ‘...’ is conditionally supported [-Wconditionally-supported] zzz(m, cu); ^