[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