Hi,<br><br><div class="gmail_quote">On Thu, Apr 19, 2012 at 5:40 AM, Daniel Jasper <span dir="ltr"><<a href="mailto:djasper@google.com" target="_blank">djasper@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

Please find a new version of the patch attached. This also fixes the same problem in nested function templates and includes corresponding tests. I am still not sure whether this is just a workaround for an underlying problem: Shouldn't the Decl fulfill isThisDeclarationADefinition()?</blockquote>

<div><br></div><div>When a template is a member of another template, instantiating the outer template doesn't cause an instantiation of the inner template. In your added testcase, we instantiate X<A>::Y<A> directly from X::Y, and never instantiate X<A>::Y. Since isThisDeclarationADefinition is used to determine whether we have an available definition (rather than a definition which could be instantiated), it has to return false for X<A>::Y.</div>

<div><br></div><div>I don't think we have any convenient way of asking the question which this code wants to ask (which is, "is this the declaration with which the instantiations of this template should be associated?"), but what you have there looks reasonable.</div>
<div><br></div><div>I have one concern: it looks like we don't currently visit instantiations of template classes which are declared, but not defined. With your change, I think we will visit those instantiations for member templates of class templates:</div>
<div><br></div><div>// I think we don't visit the instantiations of A</div><div>template<typename T> struct A;</div><div>A<int> *p;</div><div><br></div><div>template<typename T> struct B {</div><div>
  // With your patch, I think we do visit the instantiations of B<int>::C</div><div>  template<typename U> struct C;</div><div>};</div><div>B<int>::C<int> *q;</div><div><br></div><div>I'm not sure to what extent this matters, but it would be good to be consistent. Perhaps we should follow the getInstantiatedFromMemberTemplate chain back to the original template, and check whether that declaration is a definition?</div>

<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div>Kind regards,<br>Daniel<br><div><br><div class="gmail_quote">On Thu, Apr 12, 2012 at 10:32 PM, Daniel Jasper <span dir="ltr"><<a href="mailto:djasper@google.com" target="_blank">djasper@google.com</a>></span> wrote:<br>


<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div>Hi all,</div><div><br></div><div>we have noticed that the RecursiveASTMatcher does not seem to traverse nested template instantiations as in this code segment:</div>


<div><br></div><div>template <typename Rhs> struct Outer {</div>
<div>  template <typename Lhs> struct Inner {</div><div>    void Compare() {</div><div>      Lhs y;</div><div>      y.x();</div><div>    }</div><div>  };</div><div>};</div><div>struct A { void x(); };</div><div>int main() {</div>



<div>  (new Outer<A>::Inner<A>())->Compare();</div><div>}</div><div><br></div><div>Here, the templates Outer and Inner are instantiated with type A, but the Inner-instantiation is not traversed even if the RecursiveASTMatcher's subclass implements shouldVisitTemplateInstantiations() to return true. The reason is, that isThisDeclarationADefinition() does (erroneously?) return false for this instantiation. The attached patch works around this. As far as I can tell, isThisDeclarationADefinition() is checked in order to prevent forward-declared templates to be traversed multiple times. However, if this template is instantiated from a member template, this cannot happen.</div>



<div><br></div><div>Kind regards,</div><div>Daniel</div>
</blockquote></div><br></div></div>
</blockquote></div><br>