From b7d09d627c8576b9bc85f44f05befdd44fedc7ed Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 23 Dec 2010 16:00:30 +0000 Subject: [PATCH] When forming the injected-class-name of a variadic template, the template argument corresponding to a template parameter pack is an argument pack of a pack expansion of that template parameter pack. Implements C++0x [temp.dep.type]p2 (at least, as much of it as we can). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122498 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/DeclTemplate.cpp | 35 ++++++++++++---- .../temp.variadic/injected-class-name.cpp | 41 +++++++++++++++++++ 2 files changed, 67 insertions(+), 9 deletions(-) create mode 100644 test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index f21c9a3af3..422e5e30f8 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -300,10 +300,13 @@ ClassTemplateDecl::getInjectedClassNameSpecialization() { if (!CommonPtr->InjectedClassNameType.isNull()) return CommonPtr->InjectedClassNameType; - // FIXME: n2800 14.6.1p1 should say how the template arguments - // corresponding to template parameter packs should be pack - // expansions. We already say that in 14.6.2.1p2, so it would be - // better to fix that redundancy. + // C++0x [temp.dep.type]p2: + // The template argument list of a primary template is a template argument + // list in which the nth template argument has the value of the nth template + // parameter of the class template. If the nth template parameter is a + // template parameter pack (14.5.3), the nth template argument is a pack + // expansion (14.5.3) whose pattern is the name of the template parameter + // pack. ASTContext &Context = getASTContext(); TemplateParameterList *Params = getTemplateParameters(); llvm::SmallVector TemplateArgs; @@ -311,20 +314,34 @@ ClassTemplateDecl::getInjectedClassNameSpecialization() { for (TemplateParameterList::iterator Param = Params->begin(), ParamEnd = Params->end(); Param != ParamEnd; ++Param) { - if (isa(*Param)) { - QualType ParamType = Context.getTypeDeclType(cast(*Param)); - TemplateArgs.push_back(TemplateArgument(ParamType)); + TemplateArgument Arg; + if (TemplateTypeParmDecl *TTP = dyn_cast(*Param)) { + QualType ArgType = Context.getTypeDeclType(TTP); + if (TTP->isParameterPack()) + ArgType = Context.getPackExpansionType(ArgType); + + Arg = TemplateArgument(ArgType); } else if (NonTypeTemplateParmDecl *NTTP = dyn_cast(*Param)) { Expr *E = new (Context) DeclRefExpr(NTTP, NTTP->getType().getNonLValueExprType(Context), Expr::getValueKindForType(NTTP->getType()), NTTP->getLocation()); - TemplateArgs.push_back(TemplateArgument(E)); + // FIXME: Variadic templates. + Arg = TemplateArgument(E); } else { TemplateTemplateParmDecl *TTP = cast(*Param); - TemplateArgs.push_back(TemplateArgument(TemplateName(TTP))); + // FIXME: Variadic templates. + Arg = TemplateArgument(TemplateName(TTP)); } + + if ((*Param)->isTemplateParameterPack()) { + TemplateArgument *Pack = new (Context) TemplateArgument [1]; + *Pack = Arg; + Arg = TemplateArgument(Pack, 1); + } + + TemplateArgs.push_back(Arg); } CommonPtr->InjectedClassNameType diff --git a/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp b/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp new file mode 100644 index 0000000000..bcdbe5351e --- /dev/null +++ b/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// Check for declaration matching with out-of-line declarations and +// variadic templates, which involves proper computation of the +// injected-class-name. +template +struct X0 { + typedef T type; + + void f0(T); + type f1(T); +}; + +template +void X0::f0(T) { } + +template +typename X0::type X0::f1(T) { } + +template +struct X0 { + typedef T* result; + result f3(); + + template + struct Inner; +}; + +template +typename X0::result X0::f3() { return 0; } + +template +template +struct X0::Inner { + template void f4(); +}; + +template +template +template +void X0::Inner::f4() { } -- 2.40.0