diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-06-12 21:21:02 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-06-12 21:21:02 +0000 |
commit | e94866ffc12d33d30b351f30aac4aa3828bc05d7 (patch) | |
tree | 093ed36b2a82d220682404c1bb41d55cbf813d4c /lib/Sema/SemaTemplate.cpp | |
parent | 0b32600195ad729de9e78f073aa509cd9991d52e (diff) |
Diagnose the incorrect use of non-type template arguments for class
template partial specializations.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@73254 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 5fb1fb89f0..113ed98eb3 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -2003,6 +2003,68 @@ Sema::CheckClassTemplateSpecializationScope(ClassTemplateDecl *ClassTemplate, return false; } +/// \brief Check the non-type template arguments of a class template +/// partial specialization according to C++ [temp.class.spec]p9. +/// +/// \returns true if there was an error, false otherwise. +bool Sema::CheckClassTemplatePartialSpecializationArgs( + TemplateParameterList *TemplateParams, + const TemplateArgument *TemplateArgs) { + // FIXME: the interface to this function will have to change to + // accommodate variadic templates. + + for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) { + NonTypeTemplateParmDecl *Param + = dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(I)); + if (!Param) + continue; + + Expr *ArgExpr = TemplateArgs[I].getAsExpr(); + if (!ArgExpr) + continue; + + // C++ [temp.class.spec]p8: + // A non-type argument is non-specialized if it is the name of a + // non-type parameter. All other non-type arguments are + // specialized. + // + // Below, we check the two conditions that only apply to + // specialized non-type arguments, so skip any non-specialized + // arguments. + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ArgExpr)) + if (isa<NonTypeTemplateParmDecl>(DRE->getDecl())) + continue; + + // C++ [temp.class.spec]p9: + // Within the argument list of a class template partial + // specialization, the following restrictions apply: + // -- A partially specialized non-type argument expression + // shall not involve a template parameter of the partial + // specialization except when the argument expression is a + // simple identifier. + if (ArgExpr->isTypeDependent() || ArgExpr->isValueDependent()) { + Diag(ArgExpr->getLocStart(), + diag::err_dependent_non_type_arg_in_partial_spec) + << ArgExpr->getSourceRange(); + return true; + } + + // -- The type of a template parameter corresponding to a + // specialized non-type argument shall not be dependent on a + // parameter of the specialization. + if (Param->getType()->isDependentType()) { + Diag(ArgExpr->getLocStart(), + diag::err_dependent_typed_non_type_arg_in_partial_spec) + << Param->getType() + << ArgExpr->getSourceRange(); + Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } + } + + return false; +} + Sema::DeclResult Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, SourceLocation KWLoc, @@ -2117,6 +2179,11 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, // corresponds to these arguments. llvm::FoldingSetNodeID ID; if (isPartialSpecialization) { + if (CheckClassTemplatePartialSpecializationArgs( + ClassTemplate->getTemplateParameters(), + ConvertedTemplateArgs.getFlatArgumentList())) + return true; + // FIXME: Template parameter list matters, too ClassTemplatePartialSpecializationDecl::Profile(ID, ConvertedTemplateArgs.getFlatArgumentList(), |