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