[PATCH] PR12262 - assertion when substituting explicit template arguments does not substitute a sizeof-pack expression.
Serge Pavlov
sepavloff at gmail.com
Thu Jun 27 05:43:42 PDT 2013
Can somebody review the fix?
Thanks,
--Serge
2013/5/27 Serge Pavlov <sepavloff at gmail.com>
> 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
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
>
--
Thanks,
--Serge
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130627/3602147e/attachment.html>
More information about the cfe-commits
mailing list