[PATCH] Avoid spurious error messages if parent template class cannot be instantiated
Serge Pavlov
sepavloff at gmail.com
Sun Aug 4 19:44:53 PDT 2013
Friendly ping.
2013/7/19 Serge Pavlov <sepavloff at gmail.com>
> Friendly ping.
>
>
> 2013/7/15 Serge Pavlov <sepavloff at gmail.com>
>
>> Friendly ping.
>>
>>
>> 2013/7/8 Serge Pavlov <sepavloff at gmail.com>
>>
>>> 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'}}
>>>
>>
>>
>>
>> --
>> Thanks,
>> --Serge
>>
>
>
>
> --
> Thanks,
> --Serge
>
--
Thanks,
--Serge
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130805/90bcef1f/attachment.html>
More information about the cfe-commits
mailing list