[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