[PATCH] Avoid spurious error messages if parent template class cannot be instantiated

Serge Pavlov sepavloff at gmail.com
Thu Jul 18 21:02:02 PDT 2013


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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130719/685dab6d/attachment.html>


More information about the cfe-commits mailing list