diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-06-12 19:43:02 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-06-12 19:43:02 +0000 |
commit | ba1ecb564c05c2b749193e8deef1df3b69ea3f54 (patch) | |
tree | 51e80f25ae47a7bf14cb8b4f2e4f0e1de9378dc1 | |
parent | 7e8976b22e61ff8fb7a9c298df52dc12c0665a68 (diff) |
Verify that the template parameters of a class template partial
specialization do not have default arguments
(C++ [temp.class.spec]p10).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@73245 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 10 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 46 | ||||
-rw-r--r-- | test/SemaTemplate/temp_class_spec_neg.cpp | 11 |
3 files changed, 60 insertions, 7 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index b0a3da0d04..1a1fdbf77c 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -742,9 +742,6 @@ def err_template_spec_needs_header : Error< "template specialization requires 'template<>'">; def err_template_spec_extra_headers : Error< "template specialization must have a single 'template<>' header">; -def unsup_template_partial_spec_ordering : Error< - "partial ordering of class template partial specializations is not yet " - "supported">; def err_template_spec_decl_out_of_scope_global : Error< "class template specialization of %0 must occur in the global scope">; def err_template_spec_decl_out_of_scope : Error< @@ -759,6 +756,13 @@ def err_template_spec_redecl_global_scope : Error< "%select{class template specialization|explicit instantiation}0 of %1 must " "occur at global scope">; +// C++ Class Template Partial Specialization +def err_default_arg_in_partial_spec : Error< + "default template argument in a class template partial specialization">; +def unsup_template_partial_spec_ordering : Error< + "partial ordering of class template partial specializations is not yet " + "supported">; + // C++ Template Instantiation def err_template_recursion_depth_exceeded : Error< "recursive template instantiation exceeded maximum depth of %0">,DefaultFatal; diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 7c1c7cf0e1..d08e268b63 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1731,7 +1731,12 @@ bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param, // template template argument with the corresponding parameter; // partial specializations are not considered even if their // parameter lists match that of the template template parameter. - if (!isa<ClassTemplateDecl>(Template)) { + // + // Note that we also allow template template parameters here, which + // will happen when we are dealing with, e.g., class template + // partial specializations. + if (!isa<ClassTemplateDecl>(Template) && + !isa<TemplateTemplateParmDecl>(Template)) { assert(isa<FunctionTemplateDecl>(Template) && "Only function templates are possible here"); Diag(Arg->getSourceRange().getBegin(), @@ -2033,9 +2038,41 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, return true; } - // FIXME: We'll need more checks, here! - if (TemplateParams->size() > 0) + if (TemplateParams->size() > 0) { isPartialSpecialization = true; + + // C++ [temp.class.spec]p10: + // The template parameter list of a specialization shall not + // contain default template argument values. + for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) { + Decl *Param = TemplateParams->getParam(I); + if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) { + if (TTP->hasDefaultArgument()) { + Diag(TTP->getDefaultArgumentLoc(), + diag::err_default_arg_in_partial_spec); + TTP->setDefaultArgument(QualType(), SourceLocation(), false); + } + } else if (NonTypeTemplateParmDecl *NTTP + = dyn_cast<NonTypeTemplateParmDecl>(Param)) { + if (Expr *DefArg = NTTP->getDefaultArgument()) { + Diag(NTTP->getDefaultArgumentLoc(), + diag::err_default_arg_in_partial_spec) + << DefArg->getSourceRange(); + NTTP->setDefaultArgument(0); + DefArg->Destroy(Context); + } + } else { + TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(Param); + if (Expr *DefArg = TTP->getDefaultArgument()) { + Diag(TTP->getDefaultArgumentLoc(), + diag::err_default_arg_in_partial_spec) + << DefArg->getSourceRange(); + TTP->setDefaultArgument(0); + DefArg->Destroy(Context); + } + } + } + } } // Check that the specialization uses the same tag kind as the @@ -2078,11 +2115,12 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, // Find the class template (partial) specialization declaration that // corresponds to these arguments. llvm::FoldingSetNodeID ID; - if (isPartialSpecialization) + if (isPartialSpecialization) { // FIXME: Template parameter list matters, too ClassTemplatePartialSpecializationDecl::Profile(ID, ConvertedTemplateArgs.getFlatArgumentList(), ConvertedTemplateArgs.flatSize()); + } else ClassTemplateSpecializationDecl::Profile(ID, ConvertedTemplateArgs.getFlatArgumentList(), diff --git a/test/SemaTemplate/temp_class_spec_neg.cpp b/test/SemaTemplate/temp_class_spec_neg.cpp new file mode 100644 index 0000000000..e9114349a3 --- /dev/null +++ b/test/SemaTemplate/temp_class_spec_neg.cpp @@ -0,0 +1,11 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<typename T> struct vector; + +template<typename T, int N, template<typename X> class TT> +struct Test0; + +template<typename T = int, // expected-error{{default template argument}} + int N = 17, // expected-error{{default template argument}} + template<typename X> class TT = ::vector> // expected-error{{default template argument}} + struct Test0<T*, N, TT> { }; |