<html>
  <head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    Hi Richard,<br>
    <br>
    <blockquote type="cite">
      <div>
        <blockquote type="cite">
          <div>  template<typename X> T<X> f(T<X>,
            T<X>);</div>
          <div>  auto a = f(T<Double32_t>(), T<double>());</div>
        </blockquote>
        ? We need to make an (at best) arbitrary choice.</div>
    </blockquote>
    Indeed in this case, the result can only be ambiguous :(.  
    Glad-fully, since the intent of the tag is for persistency, I expect
    that the user would seldom rely on auto to define the type and thus
    most source of ambiguity are likely to be avoided.<br>
    <blockquote type="cite"> So, while we may be able to improve the
      situation for you, you need to accept that what you're asking for
      is fundamentally best-effort, rather than a sound extension to the
      language.</blockquote>
    I absolutely agree :)<br>
    <br>
    > With that in mind, it seems to me that the problem you're
    seeing is loss of type sugar when forming the type of a member of a
    class template specialization.<br>
    <br>
    Yes and a few more cases, including the type of the template
    parameters when they are defaulted.<br>
    <br>
    > So, when forming the type of the expression
    'T<Double32_t>::m', we could perform a resugaring step, where
    we would walk the type of 'm' <br>
    <br>
    Where it gets a bit complicated to do resugaring is when there are
    some layer of indirection.  For example a case like:<br>
    <br>
    template <class Collection> class Wrapper <br>
    {<br>
       Collection fMainData;<br>
       typename Collection::value_t fMaxValue;<br>
       std::vector<Collection::value_t> fInterestingValues;<br>
    };<br>
    Wrapper<vector<Double32_t> > userData;<br>
    <br>
    where userData.fMaxValue and userData.fInterestingValues ought to
    have the type Double32_t and vector<Double32_t> respectively.<br>
    <br>
    Thanks,<br>
    Philippe.<br>
    <br>
    <br>
    <div class="moz-cite-prefix">On 8/10/16 3:26 PM, Richard Smith
      wrote:<br>
    </div>
    <blockquote
cite="mid:CAOfiQqnZe_4LqpPngcHeU6MWDn4-j3RS+1TkC19x0sZ1hB5wBw@mail.gmail.com"
      type="cite">
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      <div dir="ltr">Instantiating the same template multiple times with
        canonically-equivalent template arguments with different type
        sugar will lead to an incoherent AST; I don't see any way we can
        support that.
        <div><br>
        </div>
        <div>Also, your requirements do not appear to be coherent. You
          want T<Double32_t> and T<double> to be the same
          type, and also be distinguishable. So what happens here:</div>
        <div><br>
        </div>
        <div>  template<typename X> T<X> f(T<X>,
          T<X>);</div>
        <div>  auto a = f(T<Double32_t>(), T<double>());</div>
        <div><br>
        </div>
        <div>? We need to make an (at best) arbitrary choice. So, while
          we may be able to improve the situation for you, you need to
          accept that what you're asking for is fundamentally
          best-effort, rather than a sound extension to the language.</div>
        <div><br>
        </div>
        <div>With that in mind, it seems to me that the problem you're
          seeing is loss of type sugar when forming the type of a member
          of a class template specialization. Specifically, given
          'T<Double32_t>', clang preserves the type sugar, but
          once you access the 'm' member, the type information is taken
          solely from the instantiation, and the type sugar is gone.</div>
        <div><br>
        </div>
        <div>However, the type sugar is not *entirely* gone: the type of
          'm' in this case is not 'double', it's a type sugar node that
          says the type is canonically double, but non-canonically it's
          the template type parameter at depth 0, index 0. So, when
          forming the type of the expression 'T<Double32_t>::m',
          we could perform a resugaring step, where we would walk the
          type of 'm' and replace each SubstTemplateTypeParmType with
          one that records the sugared template argument from
          'T<Double32_t>'. That should allow you to preserve the
          difference between double and Double32_t across template
          instantiation in more cases, and improve our diagnostic
          quality too.</div>
        <div><br>
        </div>
        <div>Some of what your patches do seem like good steps in this
          direction; in particular, we would need to allow
          SubstTemplateTypeParmType to have a non-canonical sugared
          substituted type in addition to its canonical type.<br>
          <div>
            <div>
              <div>
                <div class="gmail_extra"><br>
                  <div class="gmail_quote">On Sat, Jul 30, 2016 at 8:06
                    AM, Philippe Canal via cfe-dev <span dir="ltr"><<a
                        moz-do-not-send="true"
                        href="mailto:cfe-dev@lists.llvm.org"
                        target="_blank">cfe-dev@lists.llvm.org</a>></span>
                    wrote:<br>
                    <blockquote class="gmail_quote" style="margin:0 0 0
                      .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi,<span
                        class=""><br>
                        <br>
                        > I don't understand exactly how this would
                        work. You might just need to produce the patch
                        so we can discuss something concrete.<br>
                        <br>
                      </span>
                      I attached the 3 commits that implements this
                      patch (but are not in a ready to push upstream
                      state :)).  Essentially what it does is add
                      support for the ability to instantiate a template
                      based on a typedef and have this typedef being
                      propagated all the way through.   The code in the
                      rest of clang still would not use this ability.<span
                        class=""><br>
                        <br>
                        > then Bar<Double32_t> and
                        Bar<double> have the same instantiation.<br>
                        > You can have lots of different names from
                        many different contexts. How many of these do
                        you track and which name do you want to use?<br>
                        <br>
                      </span>
                      In our own code, we keep track of what the user
                      requested, for example (s)he may have requested
                      any of:<br>
                      <br>
                         Foo<double,double><br>
                         Foo<Double32_t,double><br>
                         Foo<double,Double32_t><br>
                         For<Double32_t,Double32_t><br>
                      <br>
                      We keep one representation of the class for each
                      of those instantiation selected by the users.  To
                      generate those instantation, we explicitly
                      construct (or tweak) a TemplateParameterList and
                      call for example Sema::SubstDefaultTemplateArgu<wbr>mentIfAvailable 
                      [This is because we also need the requested type
                      that contains the type to be reflected in the
                      default paramater]<br>
                      <br>
                      Cheers,<br>
                      Philippe.
                      <div class="HOEnZb">
                        <div class="h5"><br>
                          <br>
                          On 7/28/16 1:57 PM, Hal Finkel via cfe-dev
                          wrote:<br>
                          <blockquote class="gmail_quote"
                            style="margin:0 0 0 .8ex;border-left:1px
                            #ccc solid;padding-left:1ex">
                            ----- Original Message -----<br>
                            <blockquote class="gmail_quote"
                              style="margin:0 0 0 .8ex;border-left:1px
                              #ccc solid;padding-left:1ex">
                              From: "Keno Fischer" <<a
                                moz-do-not-send="true"
                                href="mailto:kfischer@college.harvard.edu"
                                target="_blank">kfischer@college.harvard.edu</a>><br>
                              To: "Hal Finkel" <<a
                                moz-do-not-send="true"
                                href="mailto:hfinkel@anl.gov"
                                target="_blank">hfinkel@anl.gov</a>><br>
                              Cc: "clang developer list" <<a
                                moz-do-not-send="true"
                                href="mailto:cfe-dev@lists.llvm.org"
                                target="_blank">cfe-dev@lists.llvm.org</a>>,
                              "Reid Kleckner" <<a
                                moz-do-not-send="true"
                                href="mailto:rnk@google.com"
                                target="_blank">rnk@google.com</a>><br>
                              Sent: Thursday, July 28, 2016 1:48:40 PM<br>
                              Subject: Re: [cfe-dev] Recovering the
                              spelling of a typedef<br>
                              <br>
                              <br>
                              Hi Hal,<br>
                              <br>
                              <br>
                              as Philippe mentioned the patch is used to
                              force through sugar nodes<br>
                              through template instantiation.<br>
                              I think for the ROOT use case, one needs
                              to be careful to only think<br>
                              about this in the context of starting from<br>
                              of fields of a class/struct. I don't think
                              ROOT has any problem with<br>
                              re-doing the template instantiation when<br>
                              it needs to compute the disk layout, but
                              we would need to be sure<br>
                              that all the required information is
                              indeed<br>
                              retained and that there is an API for
                              doing so.<br>
                              <br>
                            </blockquote>
                            I don't understand exactly how this would
                            work. You might just need to produce the
                            patch so we can discuss something concrete.<br>
                            <br>
                              -Hal<br>
                            <br>
                            <blockquote class="gmail_quote"
                              style="margin:0 0 0 .8ex;border-left:1px
                              #ccc solid;padding-left:1ex">
                              Keno<br>
                              <br>
                              <br>
                              <br>
                              <br>
                              On Tue, Jul 26, 2016 at 2:40 PM, Hal
                              Finkel < <a moz-do-not-send="true"
                                href="mailto:hfinkel@anl.gov"
                                target="_blank">hfinkel@anl.gov</a> ><br>
                              wrote:<br>
                              <br>
                              <br>
                              ----- Original Message -----<br>
                              <blockquote class="gmail_quote"
                                style="margin:0 0 0 .8ex;border-left:1px
                                #ccc solid;padding-left:1ex">
                                From: "Keno Fischer via cfe-dev" < <a
                                  moz-do-not-send="true"
                                  href="mailto:cfe-dev@lists.llvm.org"
                                  target="_blank">cfe-dev@lists.llvm.org</a>
                                ><br>
                                To: "Reid Kleckner" < <a
                                  moz-do-not-send="true"
                                  href="mailto:rnk@google.com"
                                  target="_blank">rnk@google.com</a>
                                ><br>
                                Cc: "clang developer list" < <a
                                  moz-do-not-send="true"
                                  href="mailto:cfe-dev@lists.llvm.org"
                                  target="_blank">cfe-dev@lists.llvm.org</a>
                                ><br>
                                Sent: Tuesday, July 26, 2016 1:02:40 PM<br>
                                Subject: Re: [cfe-dev] Recovering the
                                spelling of a typedef<br>
                                <br>
                                Yes, in the very simple cases, no patch
                                is needed, but yes, ROOT<br>
                                needs<br>
                                to be able to look through templates
                                which is where the problem<br>
                                comes<br>
                                in.<br>
                              </blockquote>
                              What does your patch do?<br>
                              <br>
                              The core problem here is that if you have:<br>
                              <br>
                              <blockquote class="gmail_quote"
                                style="margin:0 0 0 .8ex;border-left:1px
                                #ccc solid;padding-left:1ex">
                                <blockquote class="gmail_quote"
                                  style="margin:0 0 0
                                  .8ex;border-left:1px #ccc
                                  solid;padding-left:1ex">
                                  typedef double Double32_t;<br>
                                  template <typename T> struct Bar
                                  { T f; };<br>
                                  template struct Bar<Double32_t>;<br>
                                </blockquote>
                              </blockquote>
                              then Bar<Double32_t> and
                              Bar<double> have the same
                              instantiation. You<br>
                              can have lots of different names from many
                              different contexts. How<br>
                              many of these do you track and which name
                              do you want to use?<br>
                              <br>
                              -Hal<br>
                              <br>
                              <br>
                              <br>
                              <blockquote class="gmail_quote"
                                style="margin:0 0 0 .8ex;border-left:1px
                                #ccc solid;padding-left:1ex">
                                On Tue, Jul 26, 2016 at 1:40 PM, Reid
                                Kleckner < <a moz-do-not-send="true"
                                  href="mailto:rnk@google.com"
                                  target="_blank">rnk@google.com</a>
                                ><br>
                                wrote:<br>
                                <blockquote class="gmail_quote"
                                  style="margin:0 0 0
                                  .8ex;border-left:1px #ccc
                                  solid;padding-left:1ex">
                                  In simple cases, this information is
                                  already available as type<br>
                                  sugar nodes.<br>
                                  Consider this AST dump:<br>
                                  <br>
                                  typedef double Double32_t;<br>
                                  struct Foo { Double32_t f; };<br>
                                  <br>
                                  |-TypedefDecl 0xd3af50 <t.cpp:1:1,
                                  col:16> col:16 referenced<br>
                                  |Double32_t<br>
                                  'double'<br>
                                  | `-BuiltinType 0xd09d50 'double'<br>
                                  `-CXXRecordDecl 0xd3afa0 <line:2:1,
                                  col:28> col:8 struct Foo<br>
                                  definition<br>
                                  |-CXXRecordDecl 0xd3b0c0 <col:1,
                                  col:8> col:8 implicit struct Foo<br>
                                  `-FieldDecl 0xd3b190 <col:14,
                                  col:25> col:25 f<br>
                                  'Double32_t':'double'<br>
                                  <br>
                                  Template instantiation uses the
                                  canonical, desugared types,<br>
                                  though.<br>
                                  You can<br>
                                  see it from this dump:<br>
                                  <br>
                                  typedef double Double32_t;<br>
                                  template <typename T> struct Bar
                                  { T f; };<br>
                                  template struct Bar<Double32_t>;<br>
                                  <br>
                                  `-ClassTemplateSpecializationD<wbr>ecl
                                  0xc3b490 <line:3:1, col:31><br>
                                  col:17 struct<br>
                                  Bar definition<br>
                                  |-TemplateArgument type 'double'<br>
                                  |-CXXRecordDecl 0xc3b688 prev 0xc3b490
                                  <line:2:23, col:30> col:30<br>
                                  |implicit<br>
                                  struct Bar<br>
                                  `-FieldDecl 0xc3b758 <col:36,
                                  col:38> col:38 f 'double':'double'<br>
                                  <br>
                                  Does ROOT need a way to push the type
                                  sugar nodes through<br>
                                  template<br>
                                  instantiation? I seem to recall that
                                  there are reasons why it's<br>
                                  hard to do<br>
                                  that from an implementation
                                  standpoint, but it would also help us<br>
                                  get better<br>
                                  diagnostics when rinsing "std::string"
                                  through a template type<br>
                                  parameter,<br>
                                  for example.<br>
                                  <br>
                                  On Tue, Jul 26, 2016 at 9:58 AM, Keno
                                  Fischer<br>
                                  < <a moz-do-not-send="true"
                                    href="mailto:kfischer@college.harvard.edu"
                                    target="_blank">kfischer@college.harvard.edu</a>
                                  ><br>
                                  wrote:<br>
                                  <blockquote class="gmail_quote"
                                    style="margin:0 0 0
                                    .8ex;border-left:1px #ccc
                                    solid;padding-left:1ex">
                                    Yes, precisely. I am not fully
                                    versed in the details (Axel,<br>
                                    Philippe,<br>
                                    please correct any inaccuracies),
                                    but essentially you can<br>
                                    request<br>
                                    an object<br>
                                    to be written to/ read from disk and
                                    ROOT will look up the<br>
                                    corresponding<br>
                                    class and compute the appropriate
                                    disk format (for which it<br>
                                    needs<br>
                                    to<br>
                                    distinguish between
                                    double/Double32_t for any members).
                                    ROOT use<br>
                                    a<br>
                                    C++<br>
                                    Interpreter/JIT (custom one for a
                                    very long time, transitioning<br>
                                    to<br>
                                    LLVM/Clang) for interactivity and
                                    introspection, so it has the<br>
                                    ASTs for all<br>
                                    classes in the system available.<br>
                                    <br>
                                    On Tue, Jul 26, 2016 at 12:36 PM,
                                    Reid Kleckner < <a
                                      moz-do-not-send="true"
                                      href="mailto:rnk@google.com"
                                      target="_blank">rnk@google.com</a><br>
                                    wrote:<br>
                                    <blockquote class="gmail_quote"
                                      style="margin:0 0 0
                                      .8ex;border-left:1px #ccc
                                      solid;padding-left:1ex">
                                      Can you elaborate on how this
                                      typedef information is used for<br>
                                      I/O? Do you<br>
                                      mean that it is used by some clang
                                      plugin that examines the<br>
                                      AST,<br>
                                      or<br>
                                      something else?<br>
                                      <br>
                                      On Mon, Jul 25, 2016 at 6:55 PM,
                                      Keno Fischer via cfe-dev<br>
                                      < <a moz-do-not-send="true"
                                        href="mailto:cfe-dev@lists.llvm.org"
                                        target="_blank">cfe-dev@lists.llvm.org</a>
                                      > wrote:<br>
                                      <blockquote class="gmail_quote"
                                        style="margin:0 0 0
                                        .8ex;border-left:1px #ccc
                                        solid;padding-left:1ex">
                                        Hi Everyone,<br>
                                        <br>
                                        We're trying to integrate the
                                        CERN ROOT framework with Julia,<br>
                                        both<br>
                                        of which use LLVM/Clang for C++
                                        interoperability. As such,<br>
                                        we're<br>
                                        hoping<br>
                                        to harmonize the versions of
                                        clang used in both projects. One<br>
                                        major<br>
                                        obstacle to this currently is a
                                        patch that the ROOT folks are<br>
                                        carrying<br>
                                        to support their I/O system
                                        which uses the structure of C++<br>
                                        classes to<br>
                                        determine the on-disk format.
                                        The patch as is isn't really in<br>
                                        a<br>
                                        form<br>
                                        that could be submitted
                                        upstream, but we're hoping to
                                        solicit<br>
                                        some<br>
                                        advice<br>
                                        to come up with a solution that
                                        would be acceptable to clang,<br>
                                        and not<br>
                                        require any local code patches.<br>
                                        <br>
                                        With that in mind, let us
                                        describe the problem:<br>
                                        <br>
                                        As mentioned, ROOT uses the
                                        structure of C++ classes to<br>
                                        determine it's<br>
                                        IO format. The one wrinkle to
                                        that is that sometimes the I/O<br>
                                        storage<br>
                                        format and the in-memory format
                                        are not exactly the same. In<br>
                                        particular,<br>
                                        ROOT has a<br>
                                        <br>
                                        typedef double Double32_t;<br>
                                        <br>
                                        where if this typedef appears in
                                        a struct that is serialized<br>
                                        to<br>
                                        disk,<br>
                                        it indicates that it should be
                                        stored with 32bit precision on<br>
                                        disk, but<br>
                                        with 64bit precision in memory.<br>
                                        <br>
                                        That's *only* for I/O
                                        information; for anything
                                        regarding<br>
                                        symbols we<br>
                                        need these two to share their
                                        instantiation data.<br>
                                        <br>
                                        I.e. we want to distinguish the
                                        types of D<double>::m and<br>
                                        D<Double32_t>::m (and also
D<vector<Double32_t>>::m and<br>
D<vector<double>>::m) in<br>
                                        <br>
                                        template <class T><br>
                                        struct D {<br>
                                        using type =
                                        std::remove_reference<D>;<br>
                                        T m;<br>
                                        static int s;<br>
                                        };<br>
                                        <br>
                                        But &D<double>::s must
                                        the the same as
                                        D<Double32_t>::s; more<br>
                                        importantly:<br>
                                        <br>
                                        void f(D<double>);<br>
                                        <br>
                                        must be called by
                                        f(D<Double32_t>{}). That
                                        is (IIRC) in<br>
                                        contrast<br>
                                        of what<br>
                                        the C++ committee discussed for
                                        strong typedefs.<br>
                                        <br>
                                        ______________________________<wbr>_________________<br>
                                        cfe-dev mailing list<br>
                                        <a moz-do-not-send="true"
                                          href="mailto:cfe-dev@lists.llvm.org"
                                          target="_blank">cfe-dev@lists.llvm.org</a><br>
                                        <a moz-do-not-send="true"
                                          href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev"
                                          rel="noreferrer"
                                          target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-dev</a><br>
                                        <br>
                                      </blockquote>
                                    </blockquote>
                                  </blockquote>
                                </blockquote>
                                ______________________________<wbr>_________________<br>
                                cfe-dev mailing list<br>
                                <a moz-do-not-send="true"
                                  href="mailto:cfe-dev@lists.llvm.org"
                                  target="_blank">cfe-dev@lists.llvm.org</a><br>
                                <a moz-do-not-send="true"
                                  href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev"
                                  rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-dev</a><br>
                                <br>
                              </blockquote>
                              --<br>
                              Hal Finkel<br>
                              Assistant Computational Scientist<br>
                              Leadership Computing Facility<br>
                              Argonne National Laboratory<br>
                              <br>
                              <br>
                            </blockquote>
                          </blockquote>
                          <br>
                        </div>
                      </div>
                      <br>
                      ______________________________<wbr>_________________<br>
                      cfe-dev mailing list<br>
                      <a moz-do-not-send="true"
                        href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a><br>
                      <a moz-do-not-send="true"
                        href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev"
                        rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-dev</a><br>
                      <br>
                    </blockquote>
                  </div>
                  <br>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </blockquote>
    <br>
  </body>
</html>