r206444 - PR19340: If we see a declaration of a member of an unspecialized class template

Timur Iskhodzhanov timurrrr at google.com
Thu Apr 17 01:13:12 PDT 2014


FYI this doesn't build with VS2013

tools\clang\lib\Sema\SemaTemplate.cpp(1736) : error C3486: a parameter
for a lambda cannot have a default argument

tools\clang\lib\Sema\SemaTemplate.cpp(1826) : error C2064: term does
not evaluate to a function taking 1 arguments
        class does not define an 'operator()' or a user defined
conversion operator to a pointer-to-function or reference-to-function
that takes appropriate number of arguments

tools\clang\lib\Sema\SemaTemplate.cpp(1962) : error C2064: term does
not evaluate to a function taking 1 arguments
        class does not define an 'operator()' or a user defined
conversion operator to a pointer-to-function or reference-to-function
that takes appropriate number of arguments

2014-04-17 7:52 GMT+04:00 Richard Smith <richard-llvm at metafoo.co.uk>:
> Author: rsmith
> Date: Wed Apr 16 22:52:20 2014
> New Revision: 206444
>
> URL: http://llvm.org/viewvc/llvm-project?rev=206444&view=rev
> Log:
> PR19340: If we see a declaration of a member of an unspecialized class template
> that looks like it might be an explicit specialization, don't recover as an
> explicit specialization (bypassing the check that would reject that).
>
> Modified:
>     cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>     cfe/trunk/lib/Sema/SemaTemplate.cpp
>     cfe/trunk/test/SemaTemplate/explicit-specialization-member.cpp
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=206444&r1=206443&r2=206444&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Apr 16 22:52:20 2014
> @@ -3267,8 +3267,8 @@ def err_template_qualified_declarator_no
>    "nested name specifier '%0' for declaration does not refer into a class, "
>    "class template or class template partial specialization">;
>  def err_specialize_member_of_template : Error<
> -  "cannot specialize (with 'template<>') a member of an unspecialized "
> -  "template">;
> +  "cannot specialize %select{|(with 'template<>') }0a member of an "
> +  "unspecialized template">;
>
>  // C++ Class Template Partial Specialization
>  def err_default_arg_in_partial_spec : Error<
>
> Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=206444&r1=206443&r2=206444&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Apr 16 22:52:20 2014
> @@ -1721,6 +1721,38 @@ TemplateParameterList *Sema::MatchTempla
>    //   template<> for each enclosing class template that is
>    //   explicitly specialized.
>    bool SawNonEmptyTemplateParameterList = false;
> +
> +  auto CheckExplicitSpecialization = [&](SourceRange Range,
> +                                         bool Recovery = false) {
> +    if (SawNonEmptyTemplateParameterList) {
> +      Diag(DeclLoc, diag::err_specialize_member_of_template)
> +        << !Recovery << Range;
> +      Invalid = true;
> +      IsExplicitSpecialization = false;
> +      return true;
> +    }
> +
> +    return false;
> +  };
> +
> +  auto DiagnoseMissingExplicitSpecialization = [&] (SourceRange Range) {
> +    // Check that we can have an explicit specialization here.
> +    if (CheckExplicitSpecialization(Range, true))
> +      return true;
> +
> +    // We don't have a template header, but we should.
> +    SourceLocation ExpectedTemplateLoc;
> +    if (!ParamLists.empty())
> +      ExpectedTemplateLoc = ParamLists[0]->getTemplateLoc();
> +    else
> +      ExpectedTemplateLoc = DeclStartLoc;
> +
> +    Diag(DeclLoc, diag::err_template_spec_needs_header)
> +      << Range
> +      << FixItHint::CreateInsertion(ExpectedTemplateLoc, "template<> ");
> +    return false;
> +  };
> +
>    unsigned ParamIdx = 0;
>    for (unsigned TypeIdx = 0, NumTypes = NestedTypes.size(); TypeIdx != NumTypes;
>         ++TypeIdx) {
> @@ -1791,13 +1823,8 @@ TemplateParameterList *Sema::MatchTempla
>      //   are not explicitly specialized as well.
>      if (ParamIdx < ParamLists.size()) {
>        if (ParamLists[ParamIdx]->size() == 0) {
> -        if (SawNonEmptyTemplateParameterList) {
> -          Diag(DeclLoc, diag::err_specialize_member_of_template)
> -            << ParamLists[ParamIdx]->getSourceRange();
> -          Invalid = true;
> -          IsExplicitSpecialization = false;
> +        if (CheckExplicitSpecialization(ParamLists[ParamIdx]->getSourceRange()))
>            return 0;
> -        }
>        } else
>          SawNonEmptyTemplateParameterList = true;
>      }
> @@ -1820,29 +1847,20 @@ TemplateParameterList *Sema::MatchTempla
>            Invalid = true;
>            return 0;
>          }
> -
> +
>          // Consume this template header.
>          ++ParamIdx;
>          continue;
> -      }
> -
> -      if (!IsFriend) {
> -        // We don't have a template header, but we should.
> -        SourceLocation ExpectedTemplateLoc;
> -        if (!ParamLists.empty())
> -          ExpectedTemplateLoc = ParamLists[0]->getTemplateLoc();
> -        else
> -          ExpectedTemplateLoc = DeclStartLoc;
> -
> -        // FIXME: Don't recover this way if we SawNonEmptyTemplateParameterList.
> -        Diag(DeclLoc, diag::err_template_spec_needs_header)
> -          << getRangeOfTypeInNestedNameSpecifier(Context, T, SS)
> -          << FixItHint::CreateInsertion(ExpectedTemplateLoc, "template<> ");
>        }
> -
> +
> +      if (!IsFriend)
> +        if (DiagnoseMissingExplicitSpecialization(
> +                getRangeOfTypeInNestedNameSpecifier(Context, T, SS)))
> +          return 0;
> +
>        continue;
>      }
> -
> +
>      if (NeedNonemptyTemplateHeader) {
>        // In friend declarations we can have template-ids which don't
>        // depend on the corresponding template parameter lists.  But
> @@ -1886,18 +1904,11 @@ TemplateParameterList *Sema::MatchTempla
>    // the declaration itself.
>    if (ParamIdx >= ParamLists.size()) {
>      if (TemplateId && !IsFriend) {
> -      // FIXME: Don't recover this way if we SawNonEmptyTemplateParameterList.
>        // We don't have a template header for the declaration itself, but we
>        // should.
> -      SourceLocation ExpectedTemplateLoc;
> -      if (!ParamLists.empty())
> -        ExpectedTemplateLoc = ParamLists[0]->getTemplateLoc();
> -      else
> -        ExpectedTemplateLoc = DeclStartLoc;
> -      Diag(DeclLoc, diag::err_template_spec_needs_header)
> -          << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)
> -          << FixItHint::CreateInsertion(ExpectedTemplateLoc, "template<> ");
>        IsExplicitSpecialization = true;
> +      DiagnoseMissingExplicitSpecialization(SourceRange(TemplateId->LAngleLoc,
> +                                                        TemplateId->RAngleLoc));
>
>        // Fabricate an empty template parameter list for the invented header.
>        return TemplateParameterList::Create(Context, SourceLocation(),
> @@ -1947,14 +1958,10 @@ TemplateParameterList *Sema::MatchTempla
>    //   unspecialized, except that the declaration shall not explicitly
>    //   specialize a class member template if its en- closing class templates
>    //   are not explicitly specialized as well.
> -  if (ParamLists.back()->size() == 0 && SawNonEmptyTemplateParameterList) {
> -    Diag(DeclLoc, diag::err_specialize_member_of_template)
> -      << ParamLists[ParamIdx]->getSourceRange();
> -    Invalid = true;
> -    IsExplicitSpecialization = false;
> +  if (ParamLists.back()->size() == 0 &&
> +      CheckExplicitSpecialization(ParamLists[ParamIdx]->getSourceRange()))
>      return 0;
> -  }
> -
> +
>    // Return the last template parameter list, which corresponds to the
>    // entity being declared.
>    return ParamLists.back();
>
> Modified: cfe/trunk/test/SemaTemplate/explicit-specialization-member.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/explicit-specialization-member.cpp?rev=206444&r1=206443&r2=206444&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaTemplate/explicit-specialization-member.cpp (original)
> +++ cfe/trunk/test/SemaTemplate/explicit-specialization-member.cpp Wed Apr 16 22:52:20 2014
> @@ -38,12 +38,22 @@ namespace PR18246 {
>
>    template<typename T>
>    template<int N>
> -  void Baz<T>::bar() {
> +  void Baz<T>::bar() { // expected-note {{couldn't infer template argument 'N'}}
>    }
>
> -  // FIXME: Don't suggest the 'template<>' correction here, because this cannot
> -  // be an explicit specialization.
> +  // FIXME: We shouldn't try to match this against a prior declaration if
> +  // template parameter matching failed.
>    template<typename T>
> -  void Baz<T>::bar<0>() { // expected-error {{requires 'template<>'}}
> +  void Baz<T>::bar<0>() { // expected-error {{cannot specialize a member of an unspecialized template}} \
> +                          // expected-error {{no function template matches}}
>    }
>  }
> +
> +namespace PR19340 {
> +template<typename T> struct Helper {
> +  template<int N> static void func(const T *m) {} // expected-note {{failed template argument deduction}}
> +};
> +
> +template<typename T> void Helper<T>::func<2>() {} // expected-error {{cannot specialize a member}} \
> +                                                  // expected-error {{no function template matches}}
> +}
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits



More information about the cfe-commits mailing list