<div dir="ltr">I'm totally fine with a void cast as a workaround. I've added one in r257927.<div><br></div><div>- Lang.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Jan 15, 2016 at 11:14 AM, Aaron Ballman <span dir="ltr"><<a href="mailto:aaron@aaronballman.com" target="_blank">aaron@aaronballman.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">On Fri, Jan 15, 2016 at 2:07 PM, David Blaikie <<a href="mailto:dblaikie@gmail.com">dblaikie@gmail.com</a>> wrote:<br>
><br>
><br>
> On Fri, Jan 15, 2016 at 8:36 AM, Aaron Ballman via llvm-commits<br>
> <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br>
>><br>
>> On Mon, Jan 11, 2016 at 12:44 AM, Lang Hames via llvm-commits<br>
>> <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br>
>> > Author: lhames<br>
>> > Date: Sun Jan 10 23:44:39 2016<br>
>> > New Revision: 257316<br>
>> ><br>
>> > URL: <a href="http://llvm.org/viewvc/llvm-project?rev=257316&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=257316&view=rev</a><br>
>> > Log:<br>
>> > [ORC] Move ORC RPC helper classes that rely on partial specialization<br>
>> > into a<br>
>> > non-template base class.<br>
>> ><br>
>> > Hopefully this should fix the issues with the windows bots arrising from<br>
>> > r257305.<br>
>> ><br>
>> > Modified:<br>
>> >     llvm/trunk/include/llvm/ExecutionEngine/Orc/RPCUtils.h<br>
>> ><br>
>> > Modified: llvm/trunk/include/llvm/ExecutionEngine/Orc/RPCUtils.h<br>
>> > URL:<br>
>> > <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/RPCUtils.h?rev=257316&r1=257315&r2=257316&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/RPCUtils.h?rev=257316&r1=257315&r2=257316&view=diff</a><br>
>> ><br>
>> > ==============================================================================<br>
>> > --- llvm/trunk/include/llvm/ExecutionEngine/Orc/RPCUtils.h (original)<br>
>> > +++ llvm/trunk/include/llvm/ExecutionEngine/Orc/RPCUtils.h Sun Jan 10<br>
>> > 23:44:39 2016<br>
>> > @@ -20,6 +20,76 @@ namespace llvm {<br>
>> >  namespace orc {<br>
>> >  namespace remote {<br>
>> ><br>
>> > +// Base class containing utilities that require partial specialization.<br>
>> > +// These cannot be included in RPC, as template class members cannot be<br>
>> > +// partially specialized.<br>
>> > +class RPCBase {<br>
>> > +protected:<br>
>> > +  template <typename ProcedureIdT, ProcedureIdT ProcId, typename... Ts><br>
>> > +  class ProcedureHelper {<br>
>> > +  public:<br>
>> > +    static const ProcedureIdT Id = ProcId;<br>
>> > +  };<br>
>> > +<br>
>> > +  template <typename ChannelT, typename Proc> class CallHelper;<br>
>> > +<br>
>> > +  template <typename ChannelT, typename ProcedureIdT, ProcedureIdT<br>
>> > ProcId,<br>
>> > +            typename... ArgTs><br>
>> > +  class CallHelper<ChannelT, ProcedureHelper<ProcedureIdT, ProcId,<br>
>> > ArgTs...>> {<br>
>> > +  public:<br>
>> > +    static std::error_code call(ChannelT &C, const ArgTs &... Args) {<br>
>> > +      if (auto EC = serialize(C, ProcId))<br>
>> > +        return EC;<br>
>> > +      // If you see a compile-error on this line you're probably<br>
>> > calling a<br>
>> > +      // function with the wrong signature.<br>
>> > +      return serialize_seq(C, Args...);<br>
>> > +    }<br>
>> > +  };<br>
>> > +<br>
>> > +  template <typename ChannelT, typename Proc> class HandlerHelper;<br>
>> > +<br>
>> > +  template <typename ChannelT, typename ProcedureIdT, ProcedureIdT<br>
>> > ProcId,<br>
>> > +            typename... ArgTs><br>
>> > +  class HandlerHelper<ChannelT,<br>
>> > +                      ProcedureHelper<ProcedureIdT, ProcId, ArgTs...>><br>
>> > {<br>
>> > +  public:<br>
>> > +    template <typename HandlerT><br>
>> > +    static std::error_code handle(ChannelT &C, HandlerT Handler) {<br>
>> > +      return readAndHandle(C, Handler,<br>
>> > llvm::index_sequence_for<ArgTs...>());<br>
>> > +    }<br>
>> > +<br>
>> > +  private:<br>
>> > +    template <typename HandlerT, size_t... Is><br>
>> > +    static std::error_code readAndHandle(ChannelT &C, HandlerT Handler,<br>
>> > +                                         llvm::index_sequence<Is...> _)<br>
>> > {<br>
>> > +      std::tuple<ArgTs...> RPCArgs;<br>
>> > +      if (auto EC = deserialize_seq(C, std::get<Is>(RPCArgs)...))<br>
>> > +        return EC;<br>
>> > +      return Handler(std::get<Is>(RPCArgs)...);<br>
>><br>
>> This is causing several instances of the following diagnostic:<br>
>><br>
>><br>
>> /opt/llvm/build-llvm/src/llvm/include/llvm/ExecutionEngine/Orc/RPCUtils.h:65:28:<br>
>> warning: variable ‘RPCArgs’ set but not used<br>
>> [-Wunused-but-set-variable]<br>
>> /opt/llvm/build-llvm/src/llvm/include/llvm/ExecutionEngine/Orc/RPCUtils.h:<br>
>> In instantiation of ‘static std::error_code<br>
>> llvm::orc::remote::RPCBase::HandlerHelper<ChannelT,<br>
>> llvm::orc::remote::RPCBase::ProcedureHelper<ProcedureIdT, ProcId,<br>
>> ArgTs ...> >::readAndHandle(ChannelT&, HandlerT,<br>
>> llvm::index_sequence<Is ...>) [with HandlerT =<br>
>><br>
>> llvm::orc::remote::RPCBase::MemberFnWrapper<llvm::orc::remote::OrcRemoteTargetServer<FDRPCChannel,<br>
>> llvm::orc::OrcX86_64> >; long unsigned int ...Is = {}; ChannelT =<br>
>> llvm::orc::remote::RPCChannel; ProcedureIdT = unsigned int;<br>
>> ProcedureIdT ProcId = 15u; ArgTs = {}]’:<br>
>><br>
>> /opt/llvm/build-llvm/src/llvm/include/llvm/ExecutionEngine/Orc/RPCUtils.h:58:76:<br>
>>   required from ‘static std::error_code<br>
>> llvm::orc::remote::RPCBase::HandlerHelper<ChannelT,<br>
>> llvm::orc::remote::RPCBase::ProcedureHelper<ProcedureIdT, ProcId,<br>
>> ArgTs ...> >::handle(ChannelT&, HandlerT) [with HandlerT =<br>
>><br>
>> llvm::orc::remote::RPCBase::MemberFnWrapper<llvm::orc::remote::OrcRemoteTargetServer<FDRPCChannel,<br>
>> llvm::orc::OrcX86_64> >; ChannelT = llvm::orc::remote::RPCChannel;<br>
>> ProcedureIdT = unsigned int; ProcedureIdT ProcId = 15u; ArgTs = {}]’<br>
>><br>
>> /opt/llvm/build-llvm/src/llvm/include/llvm/ExecutionEngine/Orc/RPCUtils.h:207:60:<br>
>>   required from ‘static std::error_code<br>
>> llvm::orc::remote::RPC<ChannelT, ProcedureIdT>::handle(ChannelT&,<br>
>> HandlerT) [with Proc =<br>
>> llvm::orc::remote::RPCBase::ProcedureHelper<unsigned int, 15u>;<br>
>> HandlerT =<br>
>> llvm::orc::remote::RPCBase::MemberFnWrapper<llvm::orc::remote::OrcRemoteTargetServer<FDRPCChannel,<br>
>> llvm::orc::OrcX86_64> >; ChannelT = llvm::orc::remote::RPCChannel;<br>
>> ProcedureIdT = unsigned int]’<br>
>><br>
>> /opt/llvm/build-llvm/src/llvm/include/llvm/ExecutionEngine/Orc/RPCUtils.h:216:70:<br>
>>   required from ‘static std::error_code<br>
>> llvm::orc::remote::RPC<ChannelT, ProcedureIdT>::handle(ChannelT&,<br>
>> ClassT&, std::error_code (ClassT::*)(ArgTs ...)) [with Proc =<br>
>> llvm::orc::remote::RPCBase::ProcedureHelper<unsigned int, 15u>; ClassT<br>
>> = llvm::orc::remote::OrcRemoteTargetServer<FDRPCChannel,<br>
>> llvm::orc::OrcX86_64>; ArgTs = {}; ChannelT =<br>
>> llvm::orc::remote::RPCChannel; ProcedureIdT = unsigned int]’<br>
>><br>
>> /opt/llvm/build-llvm/src/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h:87:75:<br>
>>   required from ‘std::error_code<br>
>> llvm::orc::remote::OrcRemoteTargetServer<ChannelT,<br>
>><br>
>> TargetT>::handleKnownProcedure(llvm::orc::remote::OrcRemoteTargetRPCAPI::JITProcId)<br>
>> [with ChannelT = FDRPCChannel; TargetT = llvm::orc::OrcX86_64]’<br>
>> /opt/llvm/build-llvm/src/llvm/tools/lli/ChildTarget/ChildTarget.cpp:66:51:<br>
>>   required from here<br>
>><br>
>> I'm not comfortable trying to address this myself, but if you could<br>
>> fix it, I would appreciate it.<br>
><br>
><br>
> My best guess is that this is a GCC diagnostic bug. It is warning about the<br>
> local variable being unused when its use in a parameter pack expansion has<br>
> no elements.<br>
><br>
> We could add a (void) cast to workaround it, but I'm not sure how high of a<br>
> priority warning cleanliness with GCC 4.7 is. Actually, this reproduces in<br>
> 4.8 too - not sure beyond that (don't have 4.9/5.0 on hand).<br>
<br>
</div></div>I generally keep this bot warning-free, and I would like to keep it<br>
that way (IIRC, this bot has found some bugs, but I don't recall<br>
whether other bots would have found the same bugs or not). I don't<br>
think that it's a good idea to turn off this warning since it's<br>
generally useful, even if false positive in this case, and so I'd<br>
personally prefer to add the (void) cast to work around it if<br>
possible.<br>
<span class="HOEnZb"><font color="#888888"><br>
~Aaron<br>
</font></span><div class="HOEnZb"><div class="h5"><br>
><br>
> Yep, here's a reproduction of the GCC bug:<br>
><br>
> blaikie@blaikie-linux:/tmp/dbginfo$ g++-4.7 expand.cpp -std=c++11<br>
> -Wunused-but-set-variable<br>
> blaikie@blaikie-linux:/tmp/dbginfo$ g++-4.7 expand.cpp -std=c++11<br>
> -Wunused-but-set-variable -DFAIL<br>
> expand.cpp: In instantiation of ‘static void foo<Args>::func(Args ...) [with<br>
> long unsigned int ...Is = {}; Args = {}]’:<br>
> expand.cpp:17:17:   required from here<br>
> expand.cpp:9:23: warning: variable ‘t’ set but not used<br>
> [-Wunused-but-set-variable]<br>
> blaikie@blaikie-linux:/tmp/dbginfo$ cat expand.cpp<br>
> #include <cstdlib><br>
> #include <tuple><br>
> void f(int) { }<br>
> void f() { }<br>
> template<typename... Args><br>
> struct foo {<br>
>   template<size_t... Is><br>
>   static void func(Args... a) {<br>
>     std::tuple<Args...> t;<br>
>     f(std::get<Is>(t)...);<br>
>   }<br>
> };<br>
><br>
> int main() {<br>
>   foo<int>::func<0>(0);<br>
> #ifdef FAIL<br>
>   foo<>::func<>();<br>
> #endif<br>
> }<br>
><br>
> - Dave<br>
><br>
>><br>
>><br>
>> Thanks!<br>
>><br>
>> ~Aaron<br>
>><br>
>> > +    }<br>
>> > +  };<br>
>> > +<br>
>> > +  template <typename... ArgTs> class ReadArgs {<br>
>> > +  public:<br>
>> > +    std::error_code operator()() { return std::error_code(); }<br>
>> > +  };<br>
>> > +<br>
>> > +  template <typename ArgT, typename... ArgTs><br>
>> > +  class ReadArgs<ArgT, ArgTs...> : public ReadArgs<ArgTs...> {<br>
>> > +  public:<br>
>> > +    ReadArgs(ArgT &Arg, ArgTs &... Args)<br>
>> > +        : ReadArgs<ArgTs...>(Args...), Arg(Arg) {}<br>
>> > +<br>
>> > +    std::error_code operator()(ArgT &ArgVal, ArgTs &... ArgVals) {<br>
>> > +      this->Arg = std::move(ArgVal);<br>
>> > +      return ReadArgs<ArgTs...>::operator()(ArgVals...);<br>
>> > +    }<br>
>> > +<br>
>> > +  private:<br>
>> > +    ArgT &Arg;<br>
>> > +  };<br>
>> > +};<br>
>> > +<br>
>> >  /// Contains primitive utilities for defining, calling and handling<br>
>> > calls to<br>
>> >  /// remote procedures. ChannelT is a bidirectional stream conforming to<br>
>> > the<br>
>> >  /// RPCChannel interface (see RPCChannel.h), and ProcedureIdT is a<br>
>> > procedure<br>
>> > @@ -62,7 +132,8 @@ namespace remote {<br>
>> >  /// read yet. Expect will deserialize the id and assert that it matches<br>
>> > Proc's<br>
>> >  /// id. If it does not, and unexpected RPC call error is returned.<br>
>> ><br>
>> > -template <typename ChannelT, typename ProcedureIdT = uint32_t> class<br>
>> > RPC {<br>
>> > +template <typename ChannelT, typename ProcedureIdT = uint32_t><br>
>> > +class RPC : public RPCBase {<br>
>> >  public:<br>
>> >    /// Utility class for defining/referring to RPC procedures.<br>
>> >    ///<br>
>> > @@ -89,75 +160,16 @@ public:<br>
>> >    ///         })<br>
>> >    ///     /* handle EC */;<br>
>> >    ///<br>
>> > -  template <ProcedureIdT ProcId, typename... Ts> class Procedure {<br>
>> > -  public:<br>
>> > -    static const ProcedureIdT Id = ProcId;<br>
>> > -  };<br>
>> > -<br>
>> > -private:<br>
>> > -  template <typename Proc> class CallHelper;<br>
>> > -<br>
>> > -  template <ProcedureIdT ProcId, typename... ArgTs><br>
>> > -  class CallHelper<Procedure<ProcId, ArgTs...>> {<br>
>> > -  public:<br>
>> > -    static std::error_code call(ChannelT &C, const ArgTs &... Args) {<br>
>> > -      if (auto EC = serialize(C, ProcId))<br>
>> > -        return EC;<br>
>> > -      // If you see a compile-error on this line you're probably<br>
>> > calling a<br>
>> > -      // function with the wrong signature.<br>
>> > -      return serialize_seq(C, Args...);<br>
>> > -    }<br>
>> > -  };<br>
>> > +  template <ProcedureIdT ProcId, typename... Ts><br>
>> > +  using Procedure = ProcedureHelper<ProcedureIdT, ProcId, Ts...>;<br>
>> ><br>
>> > -  template <typename Proc> class HandlerHelper;<br>
>> > -<br>
>> > -  template <ProcedureIdT ProcId, typename... ArgTs><br>
>> > -  class HandlerHelper<Procedure<ProcId, ArgTs...>> {<br>
>> > -  public:<br>
>> > -    template <typename HandlerT><br>
>> > -    static std::error_code handle(ChannelT &C, HandlerT Handler) {<br>
>> > -      return readAndHandle(C, Handler,<br>
>> > llvm::index_sequence_for<ArgTs...>());<br>
>> > -    }<br>
>> > -<br>
>> > -  private:<br>
>> > -    template <typename HandlerT, size_t... Is><br>
>> > -    static std::error_code readAndHandle(ChannelT &C, HandlerT Handler,<br>
>> > -                                         llvm::index_sequence<Is...> _)<br>
>> > {<br>
>> > -      std::tuple<ArgTs...> RPCArgs;<br>
>> > -      if (auto EC = deserialize_seq(C, std::get<Is>(RPCArgs)...))<br>
>> > -        return EC;<br>
>> > -      return Handler(std::get<Is>(RPCArgs)...);<br>
>> > -    }<br>
>> > -  };<br>
>> > -<br>
>> > -  template <typename... ArgTs> class ReadArgs {<br>
>> > -  public:<br>
>> > -    std::error_code operator()() { return std::error_code(); }<br>
>> > -  };<br>
>> > -<br>
>> > -  template <typename ArgT, typename... ArgTs><br>
>> > -  class ReadArgs<ArgT, ArgTs...> : public ReadArgs<ArgTs...> {<br>
>> > -  public:<br>
>> > -    ReadArgs(ArgT &Arg, ArgTs &... Args)<br>
>> > -        : ReadArgs<ArgTs...>(Args...), Arg(Arg) {}<br>
>> > -<br>
>> > -    std::error_code operator()(ArgT &ArgVal, ArgTs &... ArgVals) {<br>
>> > -      this->Arg = std::move(ArgVal);<br>
>> > -      return ReadArgs<ArgTs...>::operator()(ArgVals...);<br>
>> > -    }<br>
>> > -<br>
>> > -  private:<br>
>> > -    ArgT &Arg;<br>
>> > -  };<br>
>> > -<br>
>> > -public:<br>
>> >    /// Serialize Args... to channel C, but do not call C.send().<br>
>> >    ///<br>
>> >    /// For buffered channels, this can be used to queue up several calls<br>
>> > before<br>
>> >    /// flushing the channel.<br>
>> >    template <typename Proc, typename... ArgTs><br>
>> >    static std::error_code appendCall(ChannelT &C, const ArgTs &... Args)<br>
>> > {<br>
>> > -    return CallHelper<Proc>::call(C, Args...);<br>
>> > +    return CallHelper<ChannelT, Proc>::call(C, Args...);<br>
>> >    }<br>
>> ><br>
>> >    /// Serialize Args... to channel C and call C.send().<br>
>> > @@ -178,7 +190,7 @@ public:<br>
>> >    /// the arguments used in the Proc typedef.<br>
>> >    template <typename Proc, typename HandlerT><br>
>> >    static std::error_code handle(ChannelT &C, HandlerT Handler) {<br>
>> > -    return HandlerHelper<Proc>::handle(C, Handler);<br>
>> > +    return HandlerHelper<ChannelT, Proc>::handle(C, Handler);<br>
>> >    }<br>
>> ><br>
>> >    /// Deserialize a ProcedureIdT from C and verify it matches the id<br>
>> > for Proc.<br>
>> ><br>
>> ><br>
>> > _______________________________________________<br>
>> > llvm-commits mailing list<br>
>> > <a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
>> > <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
>> _______________________________________________<br>
>> llvm-commits mailing list<br>
>> <a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
>> <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
><br>
><br>
</div></div></blockquote></div><br></div>