<div dir="ltr">Friendly ping.</div><div class="gmail_extra"><br><br><div class="gmail_quote">2013/7/19 Serge Pavlov <span dir="ltr"><<a href="mailto:sepavloff@gmail.com" target="_blank">sepavloff@gmail.com</a>></span><br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Friendly ping.</div><div class="gmail_extra"><div><div class="h5"><br><br><div class="gmail_quote">2013/7/15 Serge Pavlov <span dir="ltr"><<a href="mailto:sepavloff@gmail.com" target="_blank">sepavloff@gmail.com</a>></span><br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Friendly ping.</div><div class="gmail_extra"><div><div><br><br><div class="gmail_quote">2013/7/8 Serge Pavlov <span dir="ltr"><<a href="mailto:sepavloff@gmail.com" target="_blank">sepavloff@gmail.com</a>></span><br>


<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">  Fixed placement of curly brace.<br>
<div><br>
Hi rsmith,<br>
<br>
<a href="http://llvm-reviews.chandlerc.com/D924" target="_blank">http://llvm-reviews.chandlerc.com/D924</a><br>
<br>
CHANGE SINCE LAST DIFF<br>
</div>  <a href="http://llvm-reviews.chandlerc.com/D924?vs=2311&id=2716#toc" target="_blank">http://llvm-reviews.chandlerc.com/D924?vs=2311&id=2716#toc</a><br>
<div><br>
Files:<br>
  include/clang/Parse/Parser.h<br>
  lib/Parse/ParseDeclCXX.cpp<br>
  lib/Parse/ParseTemplate.cpp<br>
  lib/Parse/Parser.cpp<br>
  test/Parser/cxx-template-argument.cpp<br>
  test/SemaCXX/class.cpp<br>
<br>
Index: include/clang/Parse/Parser.h<br>
===================================================================<br>
--- include/clang/Parse/Parser.h<br>
+++ include/clang/Parse/Parser.h<br>
</div>@@ -764,6 +764,17 @@<br>
<div>   /// point for skipping past a simple-declaration.<br>
   void SkipMalformedDecl();<br>
<br>
+  /// \brief Discards tokens of template argument list, including closing '>'.<br>
+  ///<br>
+  /// The method tries to balance angle brackets pairs to skip nested template<br>
+  /// references properly. As there is no guarantee that the brackets are<br>
+  /// balanced, skipping will stop at points that most likely outside the<br>
+  /// discarded argument list. The method assumes that opening '<' is already<br>
+  /// read.<br>
+  ///<br>
+  /// \returns true if closing '>' is found, false otherwise.<br>
+  bool SkipTemplateArguments();<br>
+<br>
 private:<br>
   //===--------------------------------------------------------------------===//<br>
   // Lexing and parsing of C++ inline methods.<br>
</div><div>Index: lib/Parse/ParseDeclCXX.cpp<br>
===================================================================<br>
--- lib/Parse/ParseDeclCXX.cpp<br>
+++ lib/Parse/ParseDeclCXX.cpp<br>
</div>@@ -918,8 +918,10 @@<br>
<div>         << Id;<br>
     }<br>
<br>
-    if (!Template)<br>
+    if (!Template) {<br>
</div>+      SkipTemplateArguments();<br>
<div>       return true;<br>
+    }<br>
<br>
     // Form the template name<br>
     UnqualifiedId TemplateName;<br>
</div><div>Index: lib/Parse/ParseTemplate.cpp<br>
===================================================================<br>
--- lib/Parse/ParseTemplate.cpp<br>
+++ lib/Parse/ParseTemplate.cpp<br>
</div>@@ -680,6 +680,8 @@<br>
<div> /// \param RAngleLoc the location of the consumed '>'.<br>
 ///<br>
 /// \param ConsumeLastToken if true, the '>' is not consumed.<br>
+///<br>
+/// \returns true, if current token does not start with '>', false otherwise.<br>
 bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc,<br>
                                             bool ConsumeLastToken) {<br>
   // What will be left once we've consumed the '>'.<br>
Index: lib/Parse/Parser.cpp<br>
===================================================================<br>
--- lib/Parse/Parser.cpp<br>
+++ lib/Parse/Parser.cpp<br>
</div>@@ -347,6 +347,46 @@<br>
<div>   }<br>
 }<br>
<br>
+// Skip template arguments<br>
+bool Parser::SkipTemplateArguments() {<br>
+  unsigned NestingLevel = 1;<br>
+  SourceLocation GreaterThanLoc;<br>
+  tok::TokenKind SpecDelimiters[] = {<br>
+      tok::less, tok::greater, tok::greatergreater, tok::greaterequal,<br>
+      tok::greatergreaterequal, tok::greatergreatergreater};<br>
+<br>
+  if (Tok.is(tok::less))<br>
+    ConsumeToken();<br>
+  if (Tok.is(tok::semi))<br>
+    return false;<br>
+<br>
+  while (Tok.isNot(tok::eof) && Tok.isNot(tok::semi)) {<br>
</div><div>+    if (SkipUntil(SpecDelimiters, /*StopAtSemi*/true, /*DontConsume*/true)) {<br>
+      switch(Tok.getKind()) {<br>
+      case tok::less:<br>
+        ConsumeToken();<br>
+        ++NestingLevel;<br>
+        break;<br>
+<br>
+      case tok::greater:<br>
+      case tok::greatergreater:<br>
+      case tok::greaterequal:<br>
+      case tok::greatergreaterequal:<br>
+      case tok::greatergreatergreater:<br>
+        ParseGreaterThanInTemplateList(GreaterThanLoc, true);<br>
+        if (--NestingLevel == 0)<br>
+          return true;<br>
+        break;<br>
+<br>
+      default:<br>
+        return false;<br>
</div>+      }<br>
+    }<br>
+  }<br>
+<br>
<div>+  return false;<br>
+}<br>
+<br>
 //===----------------------------------------------------------------------===//<br>
 // Scope manipulation<br>
 //===----------------------------------------------------------------------===//<br>
Index: test/Parser/cxx-template-argument.cpp<br>
===================================================================<br>
--- test/Parser/cxx-template-argument.cpp<br>
+++ test/Parser/cxx-template-argument.cpp<br>
@@ -42,3 +42,59 @@<br>
     new C(); // expected-error {{requires template arguments}}<br>
   }<br>
 }<br>
+<br>
</div><div>+// Don't emit spurious messages<br>
+namespace pr16225add {<br>
+<br>
</div>+  template<class T1, typename T2> struct Known { }; // expected-note 3 {{template is declared here}}<br>
+  template<class T1, typename T2> struct X;<br>
<div>+<br>
+  template<class T1, typename T2> struct foo :<br>
+    UnknownBase<T1,T2> // expected-error {{unknown template name 'UnknownBase'}}<br>
+  { };<br>
+<br>
+  template<class T1, typename T2> struct foo2 :<br>
+    UnknownBase<T1,T2>, // expected-error {{unknown template name 'UnknownBase'}}<br>
+    Known<T1>  // expected-error {{too few template arguments for class template 'Known'}}<br>
+  { };<br>
+<br>
+  template<class T1, typename T2> struct foo3 :<br>
+    UnknownBase<T1,T2,ABC<T2,T1> > // expected-error {{unknown template name 'UnknownBase'}}<br>
+  { };<br>
+<br>
+  template<class T1, typename T2> struct foo4 :<br>
+    UnknownBase<T1,ABC<T2> >, // expected-error {{unknown template name 'UnknownBase'}}<br>
+    Known<T1>  // expected-error {{too few template arguments for class template 'Known'}}<br>
+  { };<br>
+<br>
+  template<class T1, typename T2> struct foo5 :<br>
+    UnknownBase<T1,T2,ABC<T2,T1>> // expected-error {{unknown template name 'UnknownBase'}} \<br>
</div>+                                  // expected-error {{use '> >'}}<br>
<div>+  { };<br>
+<br>
+  template<class T1, typename T2> struct foo6 :<br>
+    UnknownBase<T1,ABC<T2>>, // expected-error {{unknown template name 'UnknownBase'}} \<br>
</div>+                             // expected-error {{use '> >'}}<br>
<div>+    Known<T1>  // expected-error {{too few template arguments for class template 'Known'}}<br>
+  { };<br>
+<br>
+  template<class T1, typename T2, int N> struct foo7 :<br>
+    UnknownBase<T1,T2,(N>1)> // expected-error {{unknown template name 'UnknownBase'}}<br>
+  { };<br>
+<br>
</div><div>+  template<class T1, typename T2> struct foo8 :<br>
</div>+    UnknownBase<X<int,int>,X<int,int>> // expected-error {{unknown template name 'UnknownBase'}} \<br>
+                                       // expected-error {{use '> >'}}<br>
+  { };<br>
+<br>
<div>+  template<class T1, typename T2> struct foo9 :<br>
</div>+    UnknownBase<Known<int>,X<int,int>> // expected-error {{unknown template name 'UnknownBase'}} \<br>
+                                       // expected-error {{use '> >'}}<br>
+  { };<br>
+<br>
<div>+  template<class T1, typename T2> struct foo10 :<br>
</div>+    UnknownBase<Known<int>,X<int,X<int>>> // expected-error {{unknown template name 'UnknownBase'}} \<br>
<div>+                                          // expected-error {{use '> >'}}<br>
+  { };<br>
+<br>
+}<br>
</div><div><div>Index: test/SemaCXX/class.cpp<br>
===================================================================<br>
--- test/SemaCXX/class.cpp<br>
+++ test/SemaCXX/class.cpp<br>
@@ -126,12 +126,8 @@<br>
<br>
 // Don't crash on this bogus code.<br>
 namespace pr6629 {<br>
-  // TODO: most of these errors are spurious<br>
   template<class T1, class T2> struct foo :<br>
-    bogus<foo<T1,T2> > // expected-error {{unknown template name 'bogus'}} \<br>
-                       // BOGUS expected-error {{expected '{' after base class list}} \<br>
-                       // BOGUS expected-error {{expected ';' after struct}} \<br>
-                       // BOGUS expected-error {{expected unqualified-id}}<br>
+    bogus<foo<T1,T2> > // expected-error {{unknown template name 'bogus'}}<br>
   { };<br>
<br>
   template<> struct foo<unknown,unknown> { // expected-error {{undeclared identifier 'unknown'}}<br>
</div></div></blockquote></div><br><br clear="all"><div><br></div></div></div><span><font color="#888888">-- <br>Thanks,<br>--Serge<br>
</font></span></div>
</blockquote></div><br><br clear="all"><div><br></div></div></div><span class="HOEnZb"><font color="#888888">-- <br>Thanks,<br>--Serge<br>
</font></span></div>
</blockquote></div><br><br clear="all"><div><br></div>-- <br>Thanks,<br>--Serge<br>
</div>