<div dir="ltr">Friendly ping.</div><div class="gmail_extra"><br><br><div class="gmail_quote">2013/6/7 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"> In this version a new method, Parser::skipTemplateArguments is added, which should<br>
make skipping tokens more correct.<br>
<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>
<a href="http://llvm-reviews.chandlerc.com/D924?vs=2288&id=2311#toc" target="_blank">http://llvm-reviews.chandlerc.com/D924?vs=2288&id=2311#toc</a><br>
<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>
@@ -762,6 +762,17 @@<br>
/// 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 class="im">Index: lib/Parse/ParseDeclCXX.cpp<br>
===================================================================<br>
--- lib/Parse/ParseDeclCXX.cpp<br>
+++ lib/Parse/ParseDeclCXX.cpp<br>
</div>@@ -917,8 +917,10 @@<br>
<div class="im"> << Id;<br>
}<br>
<br>
- if (!Template)<br>
+ if (!Template) {<br>
</div>+ SkipTemplateArguments();<br>
<div class="im"> return true;<br>
+ }<br>
<br>
// Form the template name<br>
UnqualifiedId TemplateName;<br>
</div>Index: lib/Parse/ParseTemplate.cpp<br>
===================================================================<br>
--- lib/Parse/ParseTemplate.cpp<br>
+++ lib/Parse/ParseTemplate.cpp<br>
@@ -650,6 +650,8 @@<br>
/// \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>
@@ -347,6 +347,47 @@<br>
}<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>
+ {<br>
+ 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>
+ }<br>
+ }<br>
+ }<br>
+<br>
+ 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>
<div class="im"> }<br>
}<br>
+<br>
+// 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 class="im">+<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 class="im">+ { };<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 class="im">+ 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>+ template<class T1, typename T2> struct foo8 :<br>
+ UnknownBase<X<int,int>,X<int,int>> // expected-error {{unknown template name 'UnknownBase'}} \<br>
+ // expected-error {{use '> >'}}<br>
+ { };<br>
+<br>
+ template<class T1, typename T2> struct foo9 :<br>
+ UnknownBase<Known<int>,X<int,int>> // expected-error {{unknown template name 'UnknownBase'}} \<br>
+ // expected-error {{use '> >'}}<br>
+ { };<br>
+<br>
+ template<class T1, typename T2> struct foo10 :<br>
+ UnknownBase<Known<int>,X<int,X<int>>> // expected-error {{unknown template name 'UnknownBase'}} \<br>
+ // expected-error {{use '> >'}}<br>
+ { };<br>
+<br>
+}<br>
<div class="HOEnZb"><div class="h5">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>-- <br>Thanks,<br>--Serge<br>
</div>