[cfe-commits] r122508 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/SemaTemplate.cpp test/CXX/temp/temp.decls/temp.class.spec/p9-0x.cpp
Douglas Gregor
dgregor at apple.com
Thu Dec 23 09:13:55 PST 2010
Author: dgregor
Date: Thu Dec 23 11:13:55 2010
New Revision: 122508
URL: http://llvm.org/viewvc/llvm-project?rev=122508&view=rev
Log:
Reimplement the comparison of a class template partial
specialization's template arguments against the primary template's
template arguments using the obvious, correct method of checking the
injected-class-name type (C++ [temp.class.spec]p9b3). The previous
incarnation of this comparison attempted to use its own formulation of
the injected-class-name, which is redudant and, with the introduction
of variadic templates, became wrong (again).
Added:
cfe/trunk/test/CXX/temp/temp.decls/temp.class.spec/p9-0x.cpp (with props)
Modified:
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaTemplate.cpp
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=122508&r1=122507&r2=122508&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Dec 23 11:13:55 2010
@@ -2912,8 +2912,7 @@
bool CheckClassTemplatePartialSpecializationArgs(
TemplateParameterList *TemplateParams,
- llvm::SmallVectorImpl<TemplateArgument> &TemplateArgs,
- bool &MirrorsPrimaryTemplate);
+ llvm::SmallVectorImpl<TemplateArgument> &TemplateArgs);
DeclResult
ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagUseKind TUK,
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=122508&r1=122507&r2=122508&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Dec 23 11:13:55 2010
@@ -3915,71 +3915,25 @@
/// \param TemplateArg the template arguments of the class template
/// partial specialization.
///
-/// \param MirrorsPrimaryTemplate will be set true if the class
-/// template partial specialization arguments are identical to the
-/// implicit template arguments of the primary template. This is not
-/// necessarily an error (C++0x), and it is left to the caller to diagnose
-/// this condition when it is an error.
-///
/// \returns true if there was an error, false otherwise.
bool Sema::CheckClassTemplatePartialSpecializationArgs(
TemplateParameterList *TemplateParams,
- llvm::SmallVectorImpl<TemplateArgument> &TemplateArgs,
- bool &MirrorsPrimaryTemplate) {
- // FIXME: the interface to this function will have to change to
- // accommodate variadic templates.
- MirrorsPrimaryTemplate = true;
-
+ llvm::SmallVectorImpl<TemplateArgument> &TemplateArgs) {
const TemplateArgument *ArgList = TemplateArgs.data();
for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
- // Determine whether the template argument list of the partial
- // specialization is identical to the implicit argument list of
- // the primary template. The caller may need to diagnostic this as
- // an error per C++ [temp.class.spec]p9b3.
- TemplateArgument MirrorArg = ArgList[I];
- if (MirrorsPrimaryTemplate &&
- MirrorArg.getKind() == TemplateArgument::Pack) {
- if (MirrorArg.pack_size() == 1)
- MirrorArg = *MirrorArg.pack_begin();
- else
- MirrorsPrimaryTemplate = false;
- }
-
- if (MirrorsPrimaryTemplate) {
- if (TemplateTypeParmDecl *TTP
- = dyn_cast<TemplateTypeParmDecl>(TemplateParams->getParam(I))) {
- if (MirrorsPrimaryTemplate &&
- !Context.hasSameType(Context.getTypeDeclType(TTP),
- MirrorArg.getAsType()))
- MirrorsPrimaryTemplate = false;
- } else if (TemplateTemplateParmDecl *TTP
- = dyn_cast<TemplateTemplateParmDecl>(
- TemplateParams->getParam(I))) {
- // FIXME: Variadic templates pack expansion/parameter pack
- TemplateName Name = MirrorArg.getAsTemplate();
- TemplateTemplateParmDecl *ArgDecl
- = dyn_cast_or_null<TemplateTemplateParmDecl>(Name.getAsTemplateDecl());
- if (!ArgDecl ||
- ArgDecl->getIndex() != TTP->getIndex() ||
- ArgDecl->getDepth() != TTP->getDepth())
- MirrorsPrimaryTemplate = false;
- }
- }
-
NonTypeTemplateParmDecl *Param
= dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(I));
- if (!Param) {
+ if (!Param)
continue;
- }
Expr *ArgExpr = ArgList[I].getAsExpr();
if (!ArgExpr) {
- // FIXME: Variadic templates pack expansion/parameter pack
- MirrorsPrimaryTemplate = false;
continue;
}
+ // FIXME: Variadic templates. Unwrap argument packs.
+
// 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
@@ -3989,16 +3943,9 @@
// specialized non-type arguments, so skip any non-specialized
// arguments.
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ArgExpr))
- if (NonTypeTemplateParmDecl *NTTP
- = dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl())) {
- if (MirrorsPrimaryTemplate &&
- (Param->getIndex() != NTTP->getIndex() ||
- Param->getDepth() != NTTP->getDepth()))
- MirrorsPrimaryTemplate = false;
-
+ if (llvm::isa<NonTypeTemplateParmDecl>(DRE->getDecl()))
continue;
- }
-
+
// C++ [temp.class.spec]p9:
// Within the argument list of a class template partial
// specialization, the following restrictions apply:
@@ -4024,8 +3971,6 @@
Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
-
- MirrorsPrimaryTemplate = false;
}
return false;
@@ -4184,30 +4129,11 @@
// Find the class template (partial) specialization declaration that
// corresponds to these arguments.
if (isPartialSpecialization) {
- bool MirrorsPrimaryTemplate;
if (CheckClassTemplatePartialSpecializationArgs(
ClassTemplate->getTemplateParameters(),
- Converted, MirrorsPrimaryTemplate))
+ Converted))
return true;
- if (MirrorsPrimaryTemplate) {
- // C++ [temp.class.spec]p9b3:
- //
- // -- The argument list of the specialization shall not be identical
- // to the implicit argument list of the primary template.
- Diag(TemplateNameLoc, diag::err_partial_spec_args_match_primary_template)
- << (TUK == TUK_Definition)
- << FixItHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc));
- return CheckClassTemplate(S, TagSpec, TUK, KWLoc, SS,
- ClassTemplate->getIdentifier(),
- TemplateNameLoc,
- Attr,
- TemplateParams,
- AS_none);
- }
-
- // FIXME: Diagnose friend partial specializations
-
if (!Name.isDependent() &&
!TemplateSpecializationType::anyDependentTemplateArguments(
TemplateArgs.getArgumentArray(),
@@ -4261,8 +4187,25 @@
// arguments of the class template partial specialization.
TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name);
CanonType = Context.getTemplateSpecializationType(CanonTemplate,
- Converted.data(),
- Converted.size());
+ Converted.data(),
+ Converted.size());
+
+ if (Context.hasSameType(CanonType,
+ ClassTemplate->getInjectedClassNameSpecialization())) {
+ // C++ [temp.class.spec]p9b3:
+ //
+ // -- The argument list of the specialization shall not be identical
+ // to the implicit argument list of the primary template.
+ Diag(TemplateNameLoc, diag::err_partial_spec_args_match_primary_template)
+ << (TUK == TUK_Definition)
+ << FixItHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc));
+ return CheckClassTemplate(S, TagSpec, TUK, KWLoc, SS,
+ ClassTemplate->getIdentifier(),
+ TemplateNameLoc,
+ Attr,
+ TemplateParams,
+ AS_none);
+ }
// Create a new class template partial specialization declaration node.
ClassTemplatePartialSpecializationDecl *PrevPartial
Added: cfe/trunk/test/CXX/temp/temp.decls/temp.class.spec/p9-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.class.spec/p9-0x.cpp?rev=122508&view=auto
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.class.spec/p9-0x.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.class.spec/p9-0x.cpp Thu Dec 23 11:13:55 2010
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+// -- The argument list of the specialization shall not be identical
+// to the implicit argument list of the primary template.
+
+template<typename T, typename ...Types>
+struct X1;
+
+template<typename T, typename ...Types>
+struct X1<T, Types...> // expected-error{{class template partial specialization does not specialize any template argument; to define the primary template, remove the template argument list}}
+{ };
+
+
Propchange: cfe/trunk/test/CXX/temp/temp.decls/temp.class.spec/p9-0x.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cfe/trunk/test/CXX/temp/temp.decls/temp.class.spec/p9-0x.cpp
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: cfe/trunk/test/CXX/temp/temp.decls/temp.class.spec/p9-0x.cpp
------------------------------------------------------------------------------
svn:mime-type = text/plain
More information about the cfe-commits
mailing list