[cfe-commits] r122498 - in /cfe/trunk: lib/AST/DeclTemplate.cpp test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp
Douglas Gregor
dgregor at apple.com
Thu Dec 23 08:00:31 PST 2010
Author: dgregor
Date: Thu Dec 23 10:00:30 2010
New Revision: 122498
URL: http://llvm.org/viewvc/llvm-project?rev=122498&view=rev
Log:
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).
Added:
cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp (with props)
Modified:
cfe/trunk/lib/AST/DeclTemplate.cpp
Modified: cfe/trunk/lib/AST/DeclTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclTemplate.cpp?rev=122498&r1=122497&r2=122498&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclTemplate.cpp (original)
+++ cfe/trunk/lib/AST/DeclTemplate.cpp Thu Dec 23 10:00:30 2010
@@ -300,10 +300,13 @@
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<TemplateArgument, 16> TemplateArgs;
@@ -311,20 +314,34 @@
for (TemplateParameterList::iterator Param = Params->begin(),
ParamEnd = Params->end();
Param != ParamEnd; ++Param) {
- if (isa<TemplateTypeParmDecl>(*Param)) {
- QualType ParamType = Context.getTypeDeclType(cast<TypeDecl>(*Param));
- TemplateArgs.push_back(TemplateArgument(ParamType));
+ TemplateArgument Arg;
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) {
+ QualType ArgType = Context.getTypeDeclType(TTP);
+ if (TTP->isParameterPack())
+ ArgType = Context.getPackExpansionType(ArgType);
+
+ Arg = TemplateArgument(ArgType);
} else if (NonTypeTemplateParmDecl *NTTP =
dyn_cast<NonTypeTemplateParmDecl>(*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<TemplateTemplateParmDecl>(*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
Added: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp?rev=122498&view=auto
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp Thu Dec 23 10:00:30 2010
@@ -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<typename T, typename ...Types>
+struct X0 {
+ typedef T type;
+
+ void f0(T);
+ type f1(T);
+};
+
+template<typename T, typename ...Types>
+void X0<T, Types...>::f0(T) { }
+
+template<typename T, typename ...Types>
+typename X0<T, Types...>::type X0<T, Types...>::f1(T) { }
+
+template<typename T, typename ...Types>
+struct X0<T, T, Types...> {
+ typedef T* result;
+ result f3();
+
+ template<typename... InnerTypes>
+ struct Inner;
+};
+
+template<typename T, typename ...Types>
+typename X0<T, T, Types...>::result X0<T, T, Types...>::f3() { return 0; }
+
+template<typename T, typename ...Types>
+template<typename ...InnerTypes>
+struct X0<T, T, Types...>::Inner {
+ template<typename ...ReallyInner> void f4();
+};
+
+template<typename T, typename ...Types>
+template<typename ...InnerTypes>
+template<typename ...ReallyInner>
+void X0<T, T, Types...>::Inner<InnerTypes...>::f4() { }
Propchange: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp
------------------------------------------------------------------------------
svn:mime-type = text/plain
More information about the cfe-commits
mailing list