From 56bc9832bc8f80604bfddc2c93f81537df6930a1 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Fri, 24 Dec 2010 00:15:10 +0000 Subject: [PATCH] When instantiating a non-type template parameter pack, be sure to extract the appropriate argument from the argument pack (based on the current substitution index, of course). Simple instantiation of pack expansions involving non-type template parameter packs now works. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122532 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/DeclPrinter.cpp | 3 ++ lib/AST/StmtProfile.cpp | 1 + lib/Sema/SemaTemplateInstantiate.cpp | 18 ++++++++--- lib/Sema/SemaTemplateVariadic.cpp | 2 +- test/CXX/temp/temp.decls/temp.variadic/p4.cpp | 30 +++++++++++++++---- 5 files changed, 44 insertions(+), 10 deletions(-) diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index 95421a494b..8941200969 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -681,6 +681,9 @@ void DeclPrinter::VisitTemplateDecl(TemplateDecl *D) { dyn_cast(Param)) { Out << NTTP->getType().getAsString(Policy); + if (NTTP->isParameterPack() && !isa(NTTP->getType())) + Out << "..."; + if (IdentifierInfo *Name = NTTP->getIdentifier()) { Out << ' '; Out << Name->getName(); diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index 418b241009..66c067b7b1 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -894,6 +894,7 @@ void StmtProfiler::VisitDecl(Decl *D) { if (NonTypeTemplateParmDecl *NTTP = dyn_cast(D)) { ID.AddInteger(NTTP->getDepth()); ID.AddInteger(NTTP->getIndex()); + ID.AddInteger(NTTP->isParameterPack()); VisitType(NTTP->getType()); return; } diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 16e1faa7f9..8c9681ffd5 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -638,7 +638,7 @@ namespace { ExprResult TransformDeclRefExpr(DeclRefExpr *E); ExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E); ExprResult TransformTemplateParmRefExpr(DeclRefExpr *E, - NonTypeTemplateParmDecl *D); + NonTypeTemplateParmDecl *D); QualType TransformFunctionProtoType(TypeLocBuilder &TLB, FunctionProtoTypeLoc TL); @@ -836,8 +836,19 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E, NTTP->getPosition())) return SemaRef.Owned(E); - const TemplateArgument &Arg = TemplateArgs(NTTP->getDepth(), - NTTP->getPosition()); + TemplateArgument Arg = TemplateArgs(NTTP->getDepth(), NTTP->getPosition()); + if (NTTP->isParameterPack()) { + assert(Arg.getKind() == TemplateArgument::Pack && + "Missing argument pack"); + + if (getSema().ArgumentPackSubstitutionIndex == -1) { + // FIXME: Variadic templates fun case. + getSema().Diag(Loc, diag::err_pack_expansion_mismatch_unsupported); + return ExprError(); + } + + Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex]; + } // The template argument itself might be an expression, in which // case we just return that expression. @@ -876,7 +887,6 @@ ExprResult TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) { NamedDecl *D = E->getDecl(); if (NonTypeTemplateParmDecl *NTTP = dyn_cast(D)) { - // FIXME: Variadic templates index substitution. if (NTTP->getDepth() < TemplateArgs.getNumLevels()) return TransformTemplateParmRefExpr(E, NTTP); diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp index fe30ba5845..3dac8a0408 100644 --- a/lib/Sema/SemaTemplateVariadic.cpp +++ b/lib/Sema/SemaTemplateVariadic.cpp @@ -395,7 +395,7 @@ bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc, // If we don't have a template argument at this depth/index, then we // cannot expand the pack expansion. Make a note of this, but we still - // want to check that any parameter packs we *do* have arguments for. + // want to check any parameter packs we *do* have arguments for. if (!TemplateArgs.hasTemplateArgument(Depth, Index)) { ShouldExpand = false; continue; diff --git a/test/CXX/temp/temp.decls/temp.variadic/p4.cpp b/test/CXX/temp/temp.decls/temp.variadic/p4.cpp index 7f40e9c438..06a7bf3679 100644 --- a/test/CXX/temp/temp.decls/temp.variadic/p4.cpp +++ b/test/CXX/temp/temp.decls/temp.variadic/p4.cpp @@ -1,6 +1,22 @@ // RUN: %clang_cc1 -std=c++0x -fsyntax-only -fexceptions -verify %s template struct tuple; +template struct int_c; + +template +struct identity { + typedef T type; +}; + +template +struct is_same { + static const bool value = false; +}; + +template +struct is_same { + static const bool value = true; +}; // FIXME: Many more bullets to go @@ -18,15 +34,19 @@ struct extract_nested_types { typedef tuple types; }; -template -struct identity { - typedef T type; -}; - tuple *t_int_float; extract_nested_types, identity >::types *t_int_float_2 = t_int_float; +template +struct tuple_of_ints { + typedef tuple...> type; +}; + +int check_temp_arg_1[is_same::type, + tuple, int_c<2>, int_c<3>, int_c<4>, + int_c<5>>>::value? 1 : -1]; + // In a dynamic-exception-specification (15.4); the pattern is a type-id. template struct f_with_except { -- 2.40.0