<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Wed, May 6, 2015 at 8:53 AM, Reid Kleckner <span dir="ltr"><<a href="mailto:rnk@google.com" target="_blank">rnk@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><span class="">On Thu, Apr 16, 2015 at 11:51 PM, Stephan Bergmann <span dir="ltr"><<a href="mailto:sbergman@redhat.com" target="_blank">sbergman@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">I naively assumed AST::Type::getAs<T>() would work regardless whether T represents sugar or not, and looking closer it is indeed specialized for TypedefType, TemplateSpecializationType, and AttributeType to make those work, but not for other sugar like SubstTemplateTypeParmType.<br>
<br>
For example, t->getAs<SubstTemplateTypeParmType>() does not work if t is a wrapping TypedefType (but happens to work if t itself already is a SubsTemplateTypeParmType).  Is that intended?<br></blockquote><div><br></div></span><div>I don't think it was intended. I also thought I understood how type sugar and getAs work, and this is a surprise to me as well. :)</div><div><br></div><div>I would've expected getAs to work like this:</div><div><br></div><div><div>template <typename T> const T *Type::getAs() const {</div><div>  // If this is directly a T type, return it.<br></div><div>  if (const T *Ty = dyn_cast<T>(this))</div><div>    return Ty;</div><div><div>  // If the canonical type is directly a T type, return it.</div><div>  if (const T *Ty = dyn_cast<T>(CanonicalType))</div></div></div></div></div></div></blockquote><div><br></div><div>Some nodes are only sometimes sugar; we should find the outermost one in such a case and this may find the innermost one.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><div><div>    return Ty;</div></div><div>  // Do repeated single step desugarings until we find the type or return null.</div><div>  ...</div><div>}</div></div></div></div></div></blockquote><div><br></div><div>I too find the current inconsistency troubling, but I don't think the right course of action is completely clear yet. If I have<br></div><div><br></div><div>  template<typename T> struct X { typedef T type; };</div><div><br></div><div>and I take the type X<int>::type and getAs<SubstTemplateTypeParmType>(), should that really find something? (And should getAs<TypedefType>() really find something?) It would be worth looking through the existing uses to see what sugar they expected to look through before we apply this to all the other sugar nodes. I expect there's a useful and consistent answer to be found here, and perhaps it is that we should always act as if we perform a single-step desugaring.<br></div></div></div></div>