[PATCH] Avoid spurious error messages if parent template class cannot be instantiated
Serge Pavlov
sepavloff at gmail.com
Mon Jul 8 04:42:25 PDT 2013
Friendly ping.
2013/6/7 Serge Pavlov <sepavloff at gmail.com>
> In this version a new method, Parser::skipTemplateArguments is added,
> which should
> make skipping tokens more correct.
>
> Hi rsmith,
>
> http://llvm-reviews.chandlerc.com/D924
>
> CHANGE SINCE LAST DIFF
> http://llvm-reviews.chandlerc.com/D924?vs=2288&id=2311#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
> @@ -762,6 +762,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
> @@ -917,8 +917,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
> @@ -650,6 +650,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,47 @@
> }
> }
>
> +// 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'}}
>
--
Thanks,
--Serge
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130708/257a9b56/attachment.html>
More information about the cfe-commits
mailing list