From de09096a9ee7f670dc74c6a5b7771953ffaf5c62 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 9 Feb 2010 00:37:32 +0000 Subject: [PATCH] Implement a specific diagnostic when a class template partial specialization does not use any of its template parameters, then recover far more gracefully. Fixes PR6181. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95629 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 2 ++ lib/Sema/SemaTemplate.cpp | 29 +++++++++++++++------- test/SemaTemplate/temp_class_spec.cpp | 13 ++++++++++ 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 5849d9b1cc..05dca15cae 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1271,6 +1271,8 @@ def err_partial_spec_redeclared : Error< "class template partial specialization %0 cannot be redeclared">; def note_prev_partial_spec_here : Note< "previous declaration of class template partial specialization %0 is here">; +def err_partial_spec_fully_specialized : Error< + "partial specialization of %0 does not use any of its template parameters">; // C++ Function template specializations def err_function_template_spec_no_match : Error< diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index b77702ba3f..1779bde666 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -3400,12 +3400,23 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, // FIXME: Diagnose friend partial specializations - // FIXME: Template parameter list matters, too - ClassTemplatePartialSpecializationDecl::Profile(ID, - Converted.getFlatArguments(), - Converted.flatSize(), - Context); - } else + if (!Name.isDependent() && + !TemplateSpecializationType::anyDependentTemplateArguments( + TemplateArgs.getArgumentArray(), + TemplateArgs.size())) { + Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized) + << ClassTemplate->getDeclName(); + isPartialSpecialization = false; + } else { + // FIXME: Template parameter list matters, too + ClassTemplatePartialSpecializationDecl::Profile(ID, + Converted.getFlatArguments(), + Converted.flatSize(), + Context); + } + } + + if (!isPartialSpecialization) ClassTemplateSpecializationDecl::Profile(ID, Converted.getFlatArguments(), Converted.flatSize(), @@ -3435,7 +3446,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, QualType CanonType; if (PrevDecl && (PrevDecl->getSpecializationKind() == TSK_Undeclared || - TUK == TUK_Friend)) { + TUK == TUK_Friend)) { // Since the only prior class template specialization with these // arguments was referenced but not declared, or we're only // referencing this specialization as a friend, reuse that @@ -3448,8 +3459,8 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, } else if (isPartialSpecialization) { // Build the canonical type that describes the converted template // arguments of the class template partial specialization. - CanonType = Context.getTemplateSpecializationType( - TemplateName(ClassTemplate), + TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name); + CanonType = Context.getTemplateSpecializationType(CanonTemplate, Converted.getFlatArguments(), Converted.flatSize()); diff --git a/test/SemaTemplate/temp_class_spec.cpp b/test/SemaTemplate/temp_class_spec.cpp index e86f07a02f..8a07fd7292 100644 --- a/test/SemaTemplate/temp_class_spec.cpp +++ b/test/SemaTemplate/temp_class_spec.cpp @@ -348,3 +348,16 @@ namespace PR6025 { { }; } + +namespace PR6181 { + template + class a; + + class s; + + template + class a // expected-error{{partial specialization of 'a' does not use any of its template parameters}} + { + }; + +} -- 2.40.0