[PATCH] Avoid spurious error messages if parent template class cannot be instantiated
Serge Pavlov
sepavloff at gmail.com
Mon Jul 8 07:29:44 PDT 2013
Fixed placement of curly brace.
Hi rsmith,
http://llvm-reviews.chandlerc.com/D924
CHANGE SINCE LAST DIFF
http://llvm-reviews.chandlerc.com/D924?vs=2311&id=2716#toc
Files:
include/clang/Parse/Parser.h
lib/Parse/ParseDeclCXX.cpp
lib/Parse/ParseTemplate.cpp
lib/Parse/Parser.cpp
test/Parser/cxx-template-argument.cpp
test/SemaCXX/class.cpp
Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h
+++ include/clang/Parse/Parser.h
@@ -764,6 +764,17 @@
/// point for skipping past a simple-declaration.
void SkipMalformedDecl();
+ /// \brief Discards tokens of template argument list, including closing '>'.
+ ///
+ /// The method tries to balance angle brackets pairs to skip nested template
+ /// references properly. As there is no guarantee that the brackets are
+ /// balanced, skipping will stop at points that most likely outside the
+ /// discarded argument list. The method assumes that opening '<' is already
+ /// read.
+ ///
+ /// \returns true if closing '>' is found, false otherwise.
+ bool SkipTemplateArguments();
+
private:
//===--------------------------------------------------------------------===//
// Lexing and parsing of C++ inline methods.
Index: lib/Parse/ParseDeclCXX.cpp
===================================================================
--- lib/Parse/ParseDeclCXX.cpp
+++ lib/Parse/ParseDeclCXX.cpp
@@ -918,8 +918,10 @@
<< Id;
}
- if (!Template)
+ if (!Template) {
+ SkipTemplateArguments();
return true;
+ }
// Form the template name
UnqualifiedId TemplateName;
Index: lib/Parse/ParseTemplate.cpp
===================================================================
--- lib/Parse/ParseTemplate.cpp
+++ lib/Parse/ParseTemplate.cpp
@@ -680,6 +680,8 @@
/// \param RAngleLoc the location of the consumed '>'.
///
/// \param ConsumeLastToken if true, the '>' is not consumed.
+///
+/// \returns true, if current token does not start with '>', false otherwise.
bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc,
bool ConsumeLastToken) {
// What will be left once we've consumed the '>'.
Index: lib/Parse/Parser.cpp
===================================================================
--- lib/Parse/Parser.cpp
+++ lib/Parse/Parser.cpp
@@ -347,6 +347,46 @@
}
}
+// Skip template arguments
+bool Parser::SkipTemplateArguments() {
+ unsigned NestingLevel = 1;
+ SourceLocation GreaterThanLoc;
+ tok::TokenKind SpecDelimiters[] = {
+ tok::less, tok::greater, tok::greatergreater, tok::greaterequal,
+ tok::greatergreaterequal, tok::greatergreatergreater};
+
+ if (Tok.is(tok::less))
+ ConsumeToken();
+ if (Tok.is(tok::semi))
+ return false;
+
+ while (Tok.isNot(tok::eof) && Tok.isNot(tok::semi)) {
+ if (SkipUntil(SpecDelimiters, /*StopAtSemi*/true, /*DontConsume*/true)) {
+ switch(Tok.getKind()) {
+ case tok::less:
+ ConsumeToken();
+ ++NestingLevel;
+ break;
+
+ case tok::greater:
+ case tok::greatergreater:
+ case tok::greaterequal:
+ case tok::greatergreaterequal:
+ case tok::greatergreatergreater:
+ ParseGreaterThanInTemplateList(GreaterThanLoc, true);
+ if (--NestingLevel == 0)
+ return true;
+ break;
+
+ default:
+ return false;
+ }
+ }
+ }
+
+ return false;
+}
+
//===----------------------------------------------------------------------===//
// Scope manipulation
//===----------------------------------------------------------------------===//
Index: test/Parser/cxx-template-argument.cpp
===================================================================
--- test/Parser/cxx-template-argument.cpp
+++ test/Parser/cxx-template-argument.cpp
@@ -42,3 +42,59 @@
new C(); // expected-error {{requires template arguments}}
}
}
+
+// Don't emit spurious messages
+namespace pr16225add {
+
+ template<class T1, typename T2> struct Known { }; // expected-note 3 {{template is declared here}}
+ template<class T1, typename T2> struct X;
+
+ template<class T1, typename T2> struct foo :
+ UnknownBase<T1,T2> // expected-error {{unknown template name 'UnknownBase'}}
+ { };
+
+ template<class T1, typename T2> struct foo2 :
+ UnknownBase<T1,T2>, // expected-error {{unknown template name 'UnknownBase'}}
+ Known<T1> // expected-error {{too few template arguments for class template 'Known'}}
+ { };
+
+ template<class T1, typename T2> struct foo3 :
+ UnknownBase<T1,T2,ABC<T2,T1> > // expected-error {{unknown template name 'UnknownBase'}}
+ { };
+
+ template<class T1, typename T2> struct foo4 :
+ UnknownBase<T1,ABC<T2> >, // expected-error {{unknown template name 'UnknownBase'}}
+ Known<T1> // expected-error {{too few template arguments for class template 'Known'}}
+ { };
+
+ template<class T1, typename T2> struct foo5 :
+ UnknownBase<T1,T2,ABC<T2,T1>> // expected-error {{unknown template name 'UnknownBase'}} \
+ // expected-error {{use '> >'}}
+ { };
+
+ template<class T1, typename T2> struct foo6 :
+ UnknownBase<T1,ABC<T2>>, // expected-error {{unknown template name 'UnknownBase'}} \
+ // expected-error {{use '> >'}}
+ Known<T1> // expected-error {{too few template arguments for class template 'Known'}}
+ { };
+
+ template<class T1, typename T2, int N> struct foo7 :
+ UnknownBase<T1,T2,(N>1)> // expected-error {{unknown template name 'UnknownBase'}}
+ { };
+
+ template<class T1, typename T2> struct foo8 :
+ UnknownBase<X<int,int>,X<int,int>> // expected-error {{unknown template name 'UnknownBase'}} \
+ // expected-error {{use '> >'}}
+ { };
+
+ template<class T1, typename T2> struct foo9 :
+ UnknownBase<Known<int>,X<int,int>> // expected-error {{unknown template name 'UnknownBase'}} \
+ // expected-error {{use '> >'}}
+ { };
+
+ template<class T1, typename T2> struct foo10 :
+ UnknownBase<Known<int>,X<int,X<int>>> // expected-error {{unknown template name 'UnknownBase'}} \
+ // expected-error {{use '> >'}}
+ { };
+
+}
Index: test/SemaCXX/class.cpp
===================================================================
--- test/SemaCXX/class.cpp
+++ test/SemaCXX/class.cpp
@@ -126,12 +126,8 @@
// Don't crash on this bogus code.
namespace pr6629 {
- // TODO: most of these errors are spurious
template<class T1, class T2> struct foo :
- bogus<foo<T1,T2> > // expected-error {{unknown template name 'bogus'}} \
- // BOGUS expected-error {{expected '{' after base class list}} \
- // BOGUS expected-error {{expected ';' after struct}} \
- // BOGUS expected-error {{expected unqualified-id}}
+ bogus<foo<T1,T2> > // expected-error {{unknown template name 'bogus'}}
{ };
template<> struct foo<unknown,unknown> { // expected-error {{undeclared identifier 'unknown'}}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D924.3.patch
Type: text/x-patch
Size: 6785 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130708/04ca648a/attachment.bin>
More information about the cfe-commits
mailing list