Can somebody review the fix? Thanks, --Serge
2013/5/27 Serge Pavlov <[email protected]> > sepavloff added you to the CC list for the revision "PR12262 - assertion > when substituting explicit template arguments does not substitute a > sizeof-pack expression.". > > Hi all, > > This patch fixes PR12262 - assertion when substituting explicit template > arguments does not substitute a sizeof-pack expression. When > sizeof...(pack) is used in function declaration, it cannot be calculated > until all parameters are deduced from the function arguments. So during > substitution of explicit parameters, which takes place before parameter > deduction, the pack is represented by its name. However this name isn't > present in current scope , this causes assertion failure. As a solution, > introduce parameter pack into the instantiation scope. Similar approach is > used when instantiating template methods. > > Please review the fix. > > Thank you. > > http://llvm-reviews.chandlerc.com/D869 > > Files: > include/clang/AST/DeclTemplate.h > lib/AST/DeclTemplate.cpp > lib/Sema/SemaTemplateDeduction.cpp > lib/Sema/SemaTemplateInstantiateDecl.cpp > test/CXX/temp/temp.decls/temp.variadic/sizeofpack.cpp > > Index: include/clang/AST/DeclTemplate.h > =================================================================== > --- include/clang/AST/DeclTemplate.h > +++ include/clang/AST/DeclTemplate.h > @@ -948,6 +948,15 @@ > static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C, > unsigned ID); > > + /// \brief Creates a copy of this template type parameter. > + /// > + /// \param C AST context in which the new parameter is created. > + /// \param DC Declaration context of the new parameter. > + /// \param RelDepth Relative depth of the new parameter. > + /// \returns Pointer to the created copy. > + TemplateTypeParmDecl *Clone(const ASTContext &C, DeclContext *DC, > + unsigned RelDepth); > + > /// \brief Whether this template type parameter was declared with > /// the 'typename' keyword. > /// > @@ -1068,7 +1077,6 @@ > static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C, > unsigned ID, > unsigned > NumExpandedTypes); > - > using TemplateParmPosition::getDepth; > using TemplateParmPosition::setDepth; > using TemplateParmPosition::getPosition; > Index: lib/AST/DeclTemplate.cpp > =================================================================== > --- lib/AST/DeclTemplate.cpp > +++ lib/AST/DeclTemplate.cpp > @@ -468,6 +468,19 @@ > 0, false); > } > > +TemplateTypeParmDecl * > +TemplateTypeParmDecl::Clone(const ASTContext &C, DeclContext *DC, > + unsigned RelDepth) { > + assert(RelDepth <= getDepth()); > + TemplateTypeParmDecl *Result; > + Result = Create(C, DC, getLocStart(), getLocation(), getDepth() - > RelDepth, > + getIndex(), getIdentifier(), wasDeclaredWithTypename(), > + isParameterPack()); > + if (hasDefaultArgument()) > + Result->setDefaultArgument(getDefaultArgumentInfo(), false); > + return Result; > +} > + > SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const { > return hasDefaultArgument() > ? DefaultArgument->getTypeLoc().getBeginLoc() > Index: lib/Sema/SemaTemplateDeduction.cpp > =================================================================== > --- lib/Sema/SemaTemplateDeduction.cpp > +++ lib/Sema/SemaTemplateDeduction.cpp > @@ -3133,6 +3133,36 @@ > LocalInstantiationScope InstScope(*this); > TemplateParameterList *TemplateParams > = FunctionTemplate->getTemplateParameters(); > + > + // If function template parameters contain a pack, the latter cannot be > + // expanded until all parameters are deduced from the function > arguments. > + // If the pack is referenced in the declaration, will be represented by > + // name. For instance (PR12262): > + // \code > + // template <unsigned N> class array {}; > + // template<typename T, typename... Types> > + // array<sizeof...(Types)> make_array(Types&&... args); > + // ... > + // auto arr = make_array<int>(1,2,3); > + // \endcode > + // In this case when the explicit parameter is substituted, the pack > remains > + // unexpanded. It should be represented by a named declaration, use the > + // parameter declaration for this purpose. > + assert(TemplateParams); > + for (TemplateParameterList::iterator Param = TemplateParams->begin(), > + ParamEnd = TemplateParams->end(); > + Param != ParamEnd; ++Param) { > + if (TemplateTypeParmDecl *D = dyn_cast<TemplateTypeParmDecl>(*Param)) > { > + if (D->isParameterPack()) { > + TemplateTypeParmDecl *Inst = D->Clone(Context, 0, 0); > + Inst->setAccess(AS_public); > + // Introduce this template parameter's instantiation into the > + // instantiation scope. > + CurrentInstantiationScope->InstantiatedLocal(D, Inst); > + } > + } > + } > + > SmallVector<DeducedTemplateArgument, 4> Deduced; > SmallVector<QualType, 4> ParamTypes; > unsigned NumExplicitlySpecified = 0; > Index: lib/Sema/SemaTemplateInstantiateDecl.cpp > =================================================================== > --- lib/Sema/SemaTemplateInstantiateDecl.cpp > +++ lib/Sema/SemaTemplateInstantiateDecl.cpp > @@ -1760,18 +1760,9 @@ > // TODO: don't always clone when decls are refcounted. > assert(D->getTypeForDecl()->isTemplateTypeParmType()); > > - TemplateTypeParmDecl *Inst = > - TemplateTypeParmDecl::Create(SemaRef.Context, Owner, > - D->getLocStart(), D->getLocation(), > - D->getDepth() - > TemplateArgs.getNumLevels(), > - D->getIndex(), D->getIdentifier(), > - D->wasDeclaredWithTypename(), > - D->isParameterPack()); > + TemplateTypeParmDecl *Inst = D->Clone(SemaRef.Context, Owner, > + TemplateArgs.getNumLevels()); > Inst->setAccess(AS_public); > - > - if (D->hasDefaultArgument()) > - Inst->setDefaultArgument(D->getDefaultArgumentInfo(), false); > - > // Introduce this template parameter's instantiation into the > instantiation > // scope. > SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Inst); > Index: test/CXX/temp/temp.decls/temp.variadic/sizeofpack.cpp > =================================================================== > --- /dev/null > +++ test/CXX/temp/temp.decls/temp.variadic/sizeofpack.cpp > @@ -0,0 +1,46 @@ > +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s > +// expected-no-diagnostics > + > +// PR12262 > + > +template<typename T, typename... Ts> > +void abc1(int (*xxx)[sizeof ... (Ts) + 1]); > + > +void qq1 () { > + abc1<int>(0); > + abc1<int,double>(0); > +} > + > + > +template <unsigned N> class array {}; > + > + > +template<typename T, typename... Types> > +array<sizeof...(Types)> make_array1(Types&&... args); > + > +void qq2 () { > + array<1> arr = make_array1<int>(1); > + array<3> arr2 = make_array1<int>(1,array<5>(),0.1); > +} > + > + > +template<typename T, typename... Types> > +int make_array(array<sizeof...(Types)>&, Types... args); > + > +void qq3 () { > + array<1> a1; > + int aa1 = make_array<int>(a1,1); > + array<2> a2; > + int aa2 = make_array<int>(a2, 0L, "abc"); > +} > + > + > +template<typename ... Ts> > +struct AAA { > + template<typename T, typename... Types> > + static array<sizeof...(Types)> make_array(Types ... args); > +}; > + > +void qq4 () { > + array<2> arr2 = AAA<int, int>::make_array<int>(1,2); > +} > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > > -- Thanks, --Serge
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
