r290080 - [c++1z] P0195R2: Support pack-expansion of using-declarations.

Daniel Jasper via cfe-commits cfe-commits at lists.llvm.org
Mon Dec 19 03:28:20 PST 2016


I have reverted this in r290092 as it was leading to Clang crashes on the
bots and elsewhere, e.g.:
http://lab.llvm.org:8011/builders/clang-cmake-aarch64-quick/builds/1814

On Mon, Dec 19, 2016 at 5:08 AM, Richard Smith via cfe-commits <
cfe-commits at lists.llvm.org> wrote:

> Author: rsmith
> Date: Sun Dec 18 22:08:53 2016
> New Revision: 290080
>
> URL: http://llvm.org/viewvc/llvm-project?rev=290080&view=rev
> Log:
> [c++1z] P0195R2: Support pack-expansion of using-declarations.
>
> This change introduces UsingPackDecl as a marker for the set of UsingDecls
> produced by pack expansion of a single (unresolved) using declaration.
> This is
> not strictly necessary (we just need to be able to map from the original
> using
> declaration to its expansions somehow), but it's useful to maintain the
> invariant that each declaration reference instantiates to refer to one
> declaration.
>
> Added:
>     cfe/trunk/test/PCH/cxx1z-using-declaration.cpp
>     cfe/trunk/test/SemaTemplate/cxx1z-using-declaration.cpp
> Modified:
>     cfe/trunk/include/clang/AST/DeclCXX.h
>     cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
>     cfe/trunk/include/clang/Basic/DeclNodes.td
>     cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
>     cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>     cfe/trunk/include/clang/Parse/Parser.h
>     cfe/trunk/include/clang/Sema/Sema.h
>     cfe/trunk/include/clang/Sema/Template.h
>     cfe/trunk/include/clang/Serialization/ASTBitCodes.h
>     cfe/trunk/lib/AST/DeclBase.cpp
>     cfe/trunk/lib/AST/DeclCXX.cpp
>     cfe/trunk/lib/CodeGen/CGDecl.cpp
>     cfe/trunk/lib/Parse/ParseDeclCXX.cpp
>     cfe/trunk/lib/Sema/SemaDeclCXX.cpp
>     cfe/trunk/lib/Sema/SemaExprCXX.cpp
>     cfe/trunk/lib/Sema/SemaOverload.cpp
>     cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
>     cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
>     cfe/trunk/lib/Sema/TreeTransform.h
>     cfe/trunk/lib/Serialization/ASTCommon.cpp
>     cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
>     cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
>     cfe/trunk/test/Parser/cxx1z-using-declaration.cpp
>     cfe/trunk/tools/libclang/CIndex.cpp
>
> Modified: cfe/trunk/include/clang/AST/DeclCXX.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/AST/DeclCXX.h?rev=290080&r1=290079&r2=290080&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/AST/DeclCXX.h (original)
> +++ cfe/trunk/include/clang/AST/DeclCXX.h Sun Dec 18 22:08:53 2016
> @@ -3140,6 +3140,77 @@ public:
>    friend class ASTDeclWriter;
>  };
>
> +/// Represents a pack of using declarations that a single
> +/// using-declarator pack-expanded into.
> +///
> +/// \code
> +/// template<typename ...T> struct X : T... {
> +///   using T::operator()...;
> +///   using T::operator T...;
> +/// };
> +/// \endcode
> +///
> +/// In the second case above, the UsingPackDecl will have the name
> +/// 'operator T' (which contains an unexpanded pack), but the individual
> +/// UsingDecls and UsingShadowDecls will have more reasonable names.
> +class UsingPackDecl final
> +    : public NamedDecl, public Mergeable<UsingPackDecl>,
> +      private llvm::TrailingObjects<UsingPackDecl, NamedDecl *> {
> +  void anchor() override;
> +
> +  /// The UnresolvedUsingValueDecl or UnresolvedUsingTypenameDecl from
> +  /// which this waas instantiated.
> +  NamedDecl *InstantiatedFrom;
> +
> +  /// The number of using-declarations created by this pack expansion.
> +  unsigned NumExpansions;
> +
> +  UsingPackDecl(DeclContext *DC, NamedDecl *InstantiatedFrom,
> +                ArrayRef<NamedDecl *> UsingDecls)
> +      : NamedDecl(UsingPack, DC,
> +                  InstantiatedFrom ? InstantiatedFrom->getLocation()
> +                                   : SourceLocation(),
> +                  InstantiatedFrom ? InstantiatedFrom->getDeclName()
> +                                   : DeclarationName()),
> +        InstantiatedFrom(InstantiatedFrom),
> NumExpansions(UsingDecls.size()) {
> +    std::uninitialized_copy(UsingDecls.begin(), UsingDecls.end(),
> +                            getTrailingObjects<NamedDecl *>());
> +  }
> +
> +public:
> +  /// Get the using declaration from which this was instantiated. This
> will
> +  /// always be an UnresolvedUsingValueDecl or an
> UnresolvedUsingTypenameDecl
> +  /// that is a pack expansion.
> +  NamedDecl *getInstantiatedFromUsingDecl() { return InstantiatedFrom; }
> +
> +  /// Get the set of using declarations that this pack expanded into.
> Note that
> +  /// some of these may still be unresolved.
> +  ArrayRef<NamedDecl *> expansions() const {
> +    return llvm::makeArrayRef(getTrailingObjects<NamedDecl *>(),
> NumExpansions);
> +  }
> +
> +  static UsingPackDecl *Create(ASTContext &C, DeclContext *DC,
> +                               NamedDecl *InstantiatedFrom,
> +                               ArrayRef<NamedDecl *> UsingDecls);
> +
> +  static UsingPackDecl *CreateDeserialized(ASTContext &C, unsigned ID,
> +                                           unsigned NumExpansions);
> +
> +  SourceRange getSourceRange() const override LLVM_READONLY {
> +    return InstantiatedFrom->getSourceRange();
> +  }
> +
> +  UsingPackDecl *getCanonicalDecl() override { return getFirstDecl(); }
> +  const UsingPackDecl *getCanonicalDecl() const { return getFirstDecl(); }
> +
> +  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
> +  static bool classofKind(Kind K) { return K == UsingPack; }
> +
> +  friend class ASTDeclReader;
> +  friend class ASTDeclWriter;
> +  friend TrailingObjects;
> +};
> +
>  /// \brief Represents a dependent using declaration which was not marked
> with
>  /// \c typename.
>  ///
> @@ -3158,6 +3229,9 @@ class UnresolvedUsingValueDecl : public
>    /// \brief The source location of the 'using' keyword
>    SourceLocation UsingLocation;
>
> +  /// \brief If this is a pack expansion, the location of the '...'.
> +  SourceLocation EllipsisLoc;
> +
>    /// \brief The nested-name-specifier that precedes the name.
>    NestedNameSpecifierLoc QualifierLoc;
>
> @@ -3168,11 +3242,12 @@ class UnresolvedUsingValueDecl : public
>    UnresolvedUsingValueDecl(DeclContext *DC, QualType Ty,
>                             SourceLocation UsingLoc,
>                             NestedNameSpecifierLoc QualifierLoc,
> -                           const DeclarationNameInfo &NameInfo)
> +                           const DeclarationNameInfo &NameInfo,
> +                           SourceLocation EllipsisLoc)
>      : ValueDecl(UnresolvedUsingValue, DC,
>                  NameInfo.getLoc(), NameInfo.getName(), Ty),
> -      UsingLocation(UsingLoc), QualifierLoc(QualifierLoc),
> -      DNLoc(NameInfo.getInfo())
> +      UsingLocation(UsingLoc), EllipsisLoc(EllipsisLoc),
> +      QualifierLoc(QualifierLoc), DNLoc(NameInfo.getInfo())
>    { }
>
>  public:
> @@ -3198,10 +3273,20 @@ public:
>      return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
>    }
>
> +  /// \brief Determine whether this is a pack expansion.
> +  bool isPackExpansion() const {
> +    return EllipsisLoc.isValid();
> +  }
> +
> +  /// \brief Get the location of the ellipsis if this is a pack expansion.
> +  SourceLocation getEllipsisLoc() const {
> +    return EllipsisLoc;
> +  }
> +
>    static UnresolvedUsingValueDecl *
>      Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc,
>             NestedNameSpecifierLoc QualifierLoc,
> -           const DeclarationNameInfo &NameInfo);
> +           const DeclarationNameInfo &NameInfo, SourceLocation
> EllipsisLoc);
>
>    static UnresolvedUsingValueDecl *
>    CreateDeserialized(ASTContext &C, unsigned ID);
> @@ -3242,6 +3327,9 @@ class UnresolvedUsingTypenameDecl
>    /// \brief The source location of the 'typename' keyword
>    SourceLocation TypenameLocation;
>
> +  /// \brief If this is a pack expansion, the location of the '...'.
> +  SourceLocation EllipsisLoc;
> +
>    /// \brief The nested-name-specifier that precedes the name.
>    NestedNameSpecifierLoc QualifierLoc;
>
> @@ -3249,10 +3337,12 @@ class UnresolvedUsingTypenameDecl
>                                SourceLocation TypenameLoc,
>                                NestedNameSpecifierLoc QualifierLoc,
>                                SourceLocation TargetNameLoc,
> -                              IdentifierInfo *TargetName)
> +                              IdentifierInfo *TargetName,
> +                              SourceLocation EllipsisLoc)
>      : TypeDecl(UnresolvedUsingTypename, DC, TargetNameLoc, TargetName,
>                 UsingLoc),
> -      TypenameLocation(TypenameLoc), QualifierLoc(QualifierLoc) { }
> +      TypenameLocation(TypenameLoc), EllipsisLoc(EllipsisLoc),
> +      QualifierLoc(QualifierLoc) { }
>
>    friend class ASTDeclReader;
>
> @@ -3272,10 +3362,25 @@ public:
>      return QualifierLoc.getNestedNameSpecifier();
>    }
>
> +  DeclarationNameInfo getNameInfo() const {
> +    return DeclarationNameInfo(getDeclName(), getLocation());
> +  }
> +
> +  /// \brief Determine whether this is a pack expansion.
> +  bool isPackExpansion() const {
> +    return EllipsisLoc.isValid();
> +  }
> +
> +  /// \brief Get the location of the ellipsis if this is a pack expansion.
> +  SourceLocation getEllipsisLoc() const {
> +    return EllipsisLoc;
> +  }
> +
>    static UnresolvedUsingTypenameDecl *
>      Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc,
>             SourceLocation TypenameLoc, NestedNameSpecifierLoc
> QualifierLoc,
> -           SourceLocation TargetNameLoc, DeclarationName TargetName);
> +           SourceLocation TargetNameLoc, DeclarationName TargetName,
> +           SourceLocation EllipsisLoc);
>
>    static UnresolvedUsingTypenameDecl *
>    CreateDeserialized(ASTContext &C, unsigned ID);
>
> Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/AST/RecursiveASTVisitor.h?rev=290080&r1=290079&r2=290080&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
> +++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Sun Dec 18 22:08:53
> 2016
> @@ -1505,6 +1505,8 @@ DEF_TRAVERSE_DECL(UsingDecl, {
>    TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
>  })
>
> +DEF_TRAVERSE_DECL(UsingPackDecl, {})
> +
>  DEF_TRAVERSE_DECL(UsingDirectiveDecl, {
>    TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
>  })
>
> Modified: cfe/trunk/include/clang/Basic/DeclNodes.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Basic/DeclNodes.td?rev=290080&r1=290079&r2=290080&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Basic/DeclNodes.td (original)
> +++ cfe/trunk/include/clang/Basic/DeclNodes.td Sun Dec 18 22:08:53 2016
> @@ -67,6 +67,7 @@ def Named : Decl<1>;
>      def TemplateTemplateParm : DDecl<Template>;
>      def BuiltinTemplate : DDecl<Template>;
>    def Using : DDecl<Named>;
> +  def UsingPack : DDecl<Named>;
>    def UsingShadow : DDecl<Named>;
>      def ConstructorUsingShadow : DDecl<UsingShadow>;
>    def ObjCMethod : DDecl<Named>, DeclContext;
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/
> DiagnosticParseKinds.td?rev=290080&r1=290079&r2=290080&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Sun Dec 18
> 22:08:53 2016
> @@ -740,6 +740,8 @@ def err_alias_declaration_not_identifier
>    "name defined in alias declaration must be an identifier">;
>  def err_alias_declaration_specialization : Error<
>    "%select{partial specialization|explicit specialization|explicit
> instantiation}0 of alias templates is not permitted">;
> +def err_alias_declaration_pack_expansion : Error<
> +  "alias declaration cannot be a pack expansion">;
>
>  // C++1z using-declaration pack expansions
>  def ext_multi_using_declaration : ExtWarn<
> @@ -749,6 +751,11 @@ def warn_cxx1z_compat_multi_using_declar
>    "use of multiple declarators in a single using declaration is "
>    "incompatible with C++ standards before C++1z">,
>    InGroup<CXXPre1zCompat>, DefaultIgnore;
> +def ext_using_declaration_pack : ExtWarn<
> +  "pack expansion of using declaration is a C++1z extension">,
> InGroup<CXX1z>;
> +def warn_cxx1z_compat_using_declaration_pack : Warning<
> +  "pack expansion using declaration is incompatible with C++ standards "
> +  "before C++1z">, InGroup<CXXPre1zCompat>, DefaultIgnore;
>
>  // C++11 override control
>  def ext_override_control_keyword : ExtWarn<
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/
> DiagnosticSemaKinds.td?rev=290080&r1=290079&r2=290080&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sun Dec 18
> 22:08:53 2016
> @@ -474,6 +474,8 @@ def err_using_decl_conflict : Error<
>  def err_using_decl_conflict_reverse : Error<
>    "declaration conflicts with target of using declaration already in
> scope">;
>  def note_using_decl : Note<"%select{|previous }0using declaration">;
> +def err_using_decl_redeclaration_expansion : Error<
> +  "using declaration pack expansion at block scope produces multiple
> values">;
>
>  def warn_access_decl_deprecated : Warning<
>    "access declarations are deprecated; use using declarations instead">,
> @@ -4155,6 +4157,9 @@ def err_variable_instantiates_to_functio
>  def err_nested_name_spec_non_tag : Error<
>    "type %0 cannot be used prior to '::' because it has no members">;
>
> +def err_using_pack_expansion_empty : Error<
> +  "%select{|member}0 using declaration %1 instantiates to an empty pack">;
> +
>  // C++ Explicit Instantiation
>  def err_explicit_instantiation_duplicate : Error<
>      "duplicate explicit instantiation of %0">;
>
> Modified: cfe/trunk/include/clang/Parse/Parser.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Parse/Parser.h?rev=290080&r1=290079&r2=290080&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Parse/Parser.h (original)
> +++ cfe/trunk/include/clang/Parse/Parser.h Sun Dec 18 22:08:53 2016
> @@ -2436,9 +2436,10 @@ private:
>      CXXScopeSpec SS;
>      SourceLocation TemplateKWLoc;
>      UnqualifiedId Name;
> +    SourceLocation EllipsisLoc;
>
>      void clear() {
> -      TypenameLoc = TemplateKWLoc = SourceLocation();
> +      TypenameLoc = TemplateKWLoc = EllipsisLoc = SourceLocation();
>        SS.clear();
>        Name.clear();
>      }
> @@ -2450,9 +2451,6 @@ private:
>                                         SourceLocation UsingLoc,
>                                         SourceLocation &DeclEnd,
>                                         AccessSpecifier AS = AS_none);
> -  Decl *ParseAliasTemplate(const ParsedTemplateInfo &TemplateInfo,
> -                           SourceLocation &DeclEnd, AccessSpecifier AS,
> -                           ParsedAttributesWithRange &MisplacedAttrs1);
>    Decl *ParseAliasDeclarationAfterDeclarator(
>        const ParsedTemplateInfo &TemplateInfo, SourceLocation UsingLoc,
>        UsingDeclarator &D, SourceLocation &DeclEnd, AccessSpecifier AS,
>
> Modified: cfe/trunk/include/clang/Sema/Sema.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Sema/Sema.h?rev=290080&r1=290079&r2=290080&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Sema/Sema.h (original)
> +++ cfe/trunk/include/clang/Sema/Sema.h Sun Dec 18 22:08:53 2016
> @@ -4324,12 +4324,15 @@ public:
>
>    NamedDecl *BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
>                                     SourceLocation UsingLoc,
> +                                   bool HasTypenameKeyword,
> +                                   SourceLocation TypenameLoc,
>                                     CXXScopeSpec &SS,
>                                     DeclarationNameInfo NameInfo,
> +                                   SourceLocation EllipsisLoc,
>                                     AttributeList *AttrList,
> -                                   bool IsInstantiation,
> -                                   bool HasTypenameKeyword,
> -                                   SourceLocation TypenameLoc);
> +                                   bool IsInstantiation);
> +  NamedDecl *BuildUsingPackDecl(NamedDecl *InstantiatedFrom,
> +                                ArrayRef<NamedDecl *> Expansions);
>
>    bool CheckInheritingConstructorUsingDecl(UsingDecl *UD);
>
> @@ -4343,10 +4346,11 @@ public:
>    Decl *ActOnUsingDeclaration(Scope *CurScope,
>                                AccessSpecifier AS,
>                                SourceLocation UsingLoc,
> +                              SourceLocation TypenameLoc,
>                                CXXScopeSpec &SS,
>                                UnqualifiedId &Name,
> -                              AttributeList *AttrList,
> -                              SourceLocation TypenameLoc);
> +                              SourceLocation EllipsisLoc,
> +                              AttributeList *AttrList);
>    Decl *ActOnAliasDeclaration(Scope *CurScope,
>                                AccessSpecifier AS,
>                                MultiTemplateParamsArg TemplateParams,
> @@ -6351,7 +6355,7 @@ public:
>    ///
>    /// \param SS The nested-name-specifier that will be traversed to find
>    /// unexpanded parameter packs.
> -  void collectUnexpandedParameterPacks(CXXScopeSpec &SS,
> +  void collectUnexpandedParameterPacks(NestedNameSpecifierLoc NNS,
>                           SmallVectorImpl<UnexpandedParameterPack>
> &Unexpanded);
>
>    /// \brief Collect the set of unexpanded parameter packs within the
> given
>
> Modified: cfe/trunk/include/clang/Sema/Template.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Sema/Template.h?rev=290080&r1=290079&r2=290080&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Sema/Template.h (original)
> +++ cfe/trunk/include/clang/Sema/Template.h Sun Dec 18 22:08:53 2016
> @@ -515,6 +515,11 @@ namespace clang {
>          VarTemplateDecl *VarTemplate,
>          VarTemplatePartialSpecializationDecl *PartialSpec);
>      void InstantiateEnumDefinition(EnumDecl *Enum, EnumDecl *Pattern);
> +
> +  private:
> +    template<typename T>
> +    Decl *instantiateUnresolvedUsingDecl(T *D,
> +                                         bool InstantiatingPackElement =
> false);
>    };
>  }
>
>
> Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Serialization/ASTBitCodes.h?rev=290080&r1=290079&r2=290080&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
> +++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Sun Dec 18
> 22:08:53 2016
> @@ -1103,6 +1103,8 @@ namespace clang {
>        DECL_NAMESPACE_ALIAS,
>        /// \brief A UsingDecl record.
>        DECL_USING,
> +      /// \brief A UsingPackDecl record.
> +      DECL_USING_PACK,
>        /// \brief A UsingShadowDecl record.
>        DECL_USING_SHADOW,
>        /// \brief A ConstructorUsingShadowDecl record.
>
> Modified: cfe/trunk/lib/AST/DeclBase.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/
> DeclBase.cpp?rev=290080&r1=290079&r2=290080&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/AST/DeclBase.cpp (original)
> +++ cfe/trunk/lib/AST/DeclBase.cpp Sun Dec 18 22:08:53 2016
> @@ -651,11 +651,13 @@ unsigned Decl::getIdentifierNamespaceFor
>      case Typedef:
>      case TypeAlias:
>      case TypeAliasTemplate:
> -    case UnresolvedUsingTypename:
>      case TemplateTypeParm:
>      case ObjCTypeParam:
>        return IDNS_Ordinary | IDNS_Type;
>
> +    case UnresolvedUsingTypename:
> +      return IDNS_Ordinary | IDNS_Type | IDNS_Using;
> +
>      case UsingShadow:
>        return 0; // we'll actually overwrite this later
>
> @@ -663,6 +665,7 @@ unsigned Decl::getIdentifierNamespaceFor
>        return IDNS_Ordinary | IDNS_Using;
>
>      case Using:
> +    case UsingPack:
>        return IDNS_Using;
>
>      case ObjCProtocol:
>
> Modified: cfe/trunk/lib/AST/DeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/
> DeclCXX.cpp?rev=290080&r1=290079&r2=290080&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/AST/DeclCXX.cpp (original)
> +++ cfe/trunk/lib/AST/DeclCXX.cpp Sun Dec 18 22:08:53 2016
> @@ -2250,15 +2250,37 @@ SourceRange UsingDecl::getSourceRange()
>    return SourceRange(Begin, getNameInfo().getEndLoc());
>  }
>
> +void UsingPackDecl::anchor() { }
> +
> +UsingPackDecl *UsingPackDecl::Create(ASTContext &C, DeclContext *DC,
> +                                     NamedDecl *InstantiatedFrom,
> +                                     ArrayRef<NamedDecl *> UsingDecls) {
> +  size_t Extra = additionalSizeToAlloc<NamedDecl *>(UsingDecls.size());
> +  return new (C, DC, Extra) UsingPackDecl(DC, InstantiatedFrom,
> UsingDecls);
> +}
> +
> +UsingPackDecl *UsingPackDecl::CreateDeserialized(ASTContext &C, unsigned
> ID,
> +                                                 unsigned NumExpansions) {
> +  size_t Extra = additionalSizeToAlloc<NamedDecl *>(NumExpansions);
> +  auto *Result = new (C, ID, Extra) UsingPackDecl(nullptr, nullptr, None);
> +  Result->NumExpansions = NumExpansions;
> +  auto *Trail = Result->getTrailingObjects<NamedDecl *>();
> +  for (unsigned I = 0; I != NumExpansions; ++I)
> +    new (Trail + I) NamedDecl*(nullptr);
> +  return Result;
> +}
> +
>  void UnresolvedUsingValueDecl::anchor() { }
>
>  UnresolvedUsingValueDecl *
>  UnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC,
>                                   SourceLocation UsingLoc,
>                                   NestedNameSpecifierLoc QualifierLoc,
> -                                 const DeclarationNameInfo &NameInfo) {
> +                                 const DeclarationNameInfo &NameInfo,
> +                                 SourceLocation EllipsisLoc) {
>    return new (C, DC) UnresolvedUsingValueDecl(DC, C.DependentTy, UsingLoc,
> -                                              QualifierLoc, NameInfo);
> +                                              QualifierLoc, NameInfo,
> +                                              EllipsisLoc);
>  }
>
>  UnresolvedUsingValueDecl *
> @@ -2266,7 +2288,8 @@ UnresolvedUsingValueDecl::CreateDeserial
>    return new (C, ID) UnresolvedUsingValueDecl(nullptr, QualType(),
>                                                SourceLocation(),
>                                                NestedNameSpecifierLoc(),
> -                                              DeclarationNameInfo());
> +                                              DeclarationNameInfo(),
> +                                              SourceLocation());
>  }
>
>  SourceRange UnresolvedUsingValueDecl::getSourceRange() const {
> @@ -2283,17 +2306,18 @@ UnresolvedUsingTypenameDecl::Create(ASTC
>                                      SourceLocation TypenameLoc,
>                                      NestedNameSpecifierLoc QualifierLoc,
>                                      SourceLocation TargetNameLoc,
> -                                    DeclarationName TargetName) {
> +                                    DeclarationName TargetName,
> +                                    SourceLocation EllipsisLoc) {
>    return new (C, DC) UnresolvedUsingTypenameDecl(
>        DC, UsingLoc, TypenameLoc, QualifierLoc, TargetNameLoc,
> -      TargetName.getAsIdentifierInfo());
> +      TargetName.getAsIdentifierInfo(), EllipsisLoc);
>  }
>
>  UnresolvedUsingTypenameDecl *
>  UnresolvedUsingTypenameDecl::CreateDeserialized(ASTContext &C, unsigned
> ID) {
>    return new (C, ID) UnresolvedUsingTypenameDecl(
>        nullptr, SourceLocation(), SourceLocation(),
> NestedNameSpecifierLoc(),
> -      SourceLocation(), nullptr);
> +      SourceLocation(), nullptr, SourceLocation());
>  }
>
>  void StaticAssertDecl::anchor() { }
>
> Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/
> CGDecl.cpp?rev=290080&r1=290079&r2=290080&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGDecl.cpp Sun Dec 18 22:08:53 2016
> @@ -113,6 +113,10 @@ void CodeGenFunction::EmitDecl(const Dec
>      if (CGDebugInfo *DI = getDebugInfo())
>          DI->EmitUsingDecl(cast<UsingDecl>(D));
>      return;
> +  case Decl::UsingPack:
> +    for (auto *Using : cast<UsingPackDecl>(D).expansions())
> +      EmitDecl(*Using);
> +    return;
>    case Decl::UsingDirective: // using namespace X; [C++]
>      if (CGDebugInfo *DI = getDebugInfo())
>        DI->EmitUsingDirective(cast<UsingDirectiveDecl>(D));
>
> Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/
> ParseDeclCXX.cpp?rev=290080&r1=290079&r2=290080&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Sun Dec 18 22:08:53 2016
> @@ -560,7 +560,9 @@ bool Parser::ParseUsingDeclarator(unsign
>    //   nested-name-specifier, the name is [...] considered to name the
>    //   constructor.
>    if (getLangOpts().CPlusPlus11 && Context == Declarator::MemberContext &&
> -      Tok.is(tok::identifier) && NextToken().is(tok::semi) &&
> +      Tok.is(tok::identifier) &&
> +      (NextToken().is(tok::semi) || NextToken().is(tok::comma) ||
> +       NextToken().is(tok::ellipsis)) &&
>        D.SS.isNotEmpty() && LastII == Tok.getIdentifierInfo() &&
>        !D.SS.getScopeRep()->getAsNamespace() &&
>        !D.SS.getScopeRep()->getAsNamespaceAlias()) {
> @@ -578,7 +580,10 @@ bool Parser::ParseUsingDeclarator(unsign
>        return true;
>    }
>
> -  // FIXME: Parse optional ellipsis
> +  if (TryConsumeToken(tok::ellipsis, D.EllipsisLoc))
> +    Diag(Tok.getLocation(), getLangOpts().CPlusPlus1z ?
> +         diag::warn_cxx1z_compat_using_declaration_pack :
> +         diag::ext_using_declaration_pack);
>
>    return false;
>  }
> @@ -678,9 +683,9 @@ Parser::ParseUsingDeclaration(unsigned C
>          D.TypenameLoc = SourceLocation();
>        }
>
> -      Decl *UD =
> -          Actions.ActOnUsingDeclaration(getCurScope(), AS, UsingLoc,
> D.SS,
> -                                        D.Name, Attrs.getList(),
> D.TypenameLoc);
> +      Decl *UD = Actions.ActOnUsingDeclaration(getCurScope(), AS,
> UsingLoc,
> +                                               D.TypenameLoc, D.SS,
> D.Name,
> +                                               D.EllipsisLoc,
> Attrs.getList());
>        if (UD)
>          DeclsInGroup.push_back(UD);
>      }
> @@ -708,62 +713,6 @@ Parser::ParseUsingDeclaration(unsigned C
>    return Actions.BuildDeclaratorGroup(DeclsInGroup,
> /*MayContainAuto*/false);
>  }
>
> -Decl *Parser::ParseAliasTemplate(const ParsedTemplateInfo &TemplateInfo,
> -                                 SourceLocation &DeclEnd, AccessSpecifier
> AS,
> -                                 ParsedAttributesWithRange
> &MisplacedAttrs1) {
> -  assert(Tok.is(tok::kw_using) && "Not using token");
> -  ObjCDeclContextSwitch ObjCDC(*this);
> -
> -  // Eat 'using'.
> -  SourceLocation UsingLoc = ConsumeToken();
> -  if (Tok.is(tok::code_completion)) {
> -    Actions.CodeCompleteUsing(getCurScope());
> -    cutOffParsing();
> -    return nullptr;
> -  }
> -
> -  // 'using namespace' means this is a using-directive.
> -  if (Tok.is(tok::kw_namespace)) {
> -    SourceRange R = TemplateInfo.getSourceRange();
> -    Diag(UsingLoc, diag::err_templated_using_directive_declaration)
> -        << 0 /* directive */ << R;
> -    SkipUntil(tok::semi);
> -    return nullptr;
> -  }
> -
> -  // Check for misplaced attributes before the identifier.
> -  ParsedAttributesWithRange MisplacedAttrs2(AttrFactory);
> -  MaybeParseCXX11Attributes(MisplacedAttrs2);
> -
> -  // FIXME: Just parse an identifier here?
> -  UsingDeclarator D;
> -  if (ParseUsingDeclarator(Declarator::FileContext, D)) {
> -    SkipUntil(tok::semi);
> -    return nullptr;
> -  }
> -
> -  ParsedAttributesWithRange Attrs(AttrFactory);
> -
> -  // If we had any misplaced attributes from earlier, this is where they
> -  // should have been written.
> -  for (auto *MisplacedAttrs : {&MisplacedAttrs1, &MisplacedAttrs2}) {
> -    if (MisplacedAttrs->Range.isValid()) {
> -      Diag(MisplacedAttrs->Range.getBegin(), diag::err_attributes_not_
> allowed)
> -        << FixItHint::CreateInsertionFromRange(
> -               Tok.getLocation(),
> -               CharSourceRange::getTokenRange(MisplacedAttrs->Range))
> -        << FixItHint::CreateRemoval(MisplacedAttrs->Range);
> -      Attrs.takeAllFrom(*MisplacedAttrs);
> -    }
> -  }
> -
> -  MaybeParseGNUAttributes(Attrs);
> -  MaybeParseCXX11Attributes(Attrs);
> -
> -  return ParseAliasDeclarationAfterDeclarator(TemplateInfo, UsingLoc, D,
> -                                              DeclEnd, AS, Attrs);
> -}
> -
>  Decl *Parser::ParseAliasDeclarationAfterDeclarator(
>      const ParsedTemplateInfo &TemplateInfo, SourceLocation UsingLoc,
>      UsingDeclarator &D, SourceLocation &DeclEnd, AccessSpecifier AS,
> @@ -813,6 +762,9 @@ Decl *Parser::ParseAliasDeclarationAfter
>    else if (D.SS.isNotEmpty())
>      Diag(D.SS.getBeginLoc(), diag::err_alias_declaration_not_identifier)
>        << FixItHint::CreateRemoval(D.SS.getRange());
> +  if (D.EllipsisLoc.isValid())
> +    Diag(D.EllipsisLoc, diag::err_alias_declaration_pack_expansion)
> +      << FixItHint::CreateRemoval(SourceRange(D.EllipsisLoc));
>
>    Decl *DeclFromDeclSpec = nullptr;
>    TypeResult TypeAlias =
> @@ -2487,8 +2439,9 @@ Parser::ParseCXXClassMemberDeclaration(A
>        }
>
>        return DeclGroupPtrTy::make(DeclGroupRef(Actions.
> ActOnUsingDeclaration(
> -          getCurScope(), AS, /*UsingLoc*/SourceLocation(), SS, Name,
> -          /*AttrList*/nullptr, /*TypenameLoc*/SourceLocation())));
> +          getCurScope(), AS, /*UsingLoc*/ SourceLocation(),
> +          /*TypenameLoc*/ SourceLocation(), SS, Name,
> +          /*EllipsisLoc*/ SourceLocation(), /*AttrList*/ nullptr)));
>      }
>    }
>
>
> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> SemaDeclCXX.cpp?rev=290080&r1=290079&r2=290080&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sun Dec 18 22:08:53 2016
> @@ -8533,12 +8533,18 @@ void Sema::PushUsingDirective(Scope *S,
>  Decl *Sema::ActOnUsingDeclaration(Scope *S,
>                                    AccessSpecifier AS,
>                                    SourceLocation UsingLoc,
> +                                  SourceLocation TypenameLoc,
>                                    CXXScopeSpec &SS,
>                                    UnqualifiedId &Name,
> -                                  AttributeList *AttrList,
> -                                  SourceLocation TypenameLoc) {
> +                                  SourceLocation EllipsisLoc,
> +                                  AttributeList *AttrList) {
>    assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
>
> +  if (SS.isEmpty()) {
> +    Diag(Name.getLocStart(), diag::err_using_requires_qualname);
> +    return nullptr;
> +  }
> +
>    switch (Name.getKind()) {
>    case UnqualifiedId::IK_ImplicitSelfParam:
>    case UnqualifiedId::IK_Identifier:
> @@ -8584,14 +8590,23 @@ Decl *Sema::ActOnUsingDeclaration(Scope
>        << FixItHint::CreateInsertion(SS.getRange().getBegin(), "using ");
>    }
>
> -  if (DiagnoseUnexpandedParameterPack(SS, UPPC_UsingDeclaration) ||
> -      DiagnoseUnexpandedParameterPack(TargetNameInfo,
> UPPC_UsingDeclaration))
> -    return nullptr;
> +  if (EllipsisLoc.isInvalid()) {
> +    if (DiagnoseUnexpandedParameterPack(SS, UPPC_UsingDeclaration) ||
> +        DiagnoseUnexpandedParameterPack(TargetNameInfo,
> UPPC_UsingDeclaration))
> +      return nullptr;
> +  } else {
> +    if (!SS.getScopeRep()->containsUnexpandedParameterPack() &&
> +        !TargetNameInfo.containsUnexpandedParameterPack()) {
> +      Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
> +        << SourceRange(SS.getBeginLoc(), TargetNameInfo.getEndLoc());
> +      EllipsisLoc = SourceLocation();
> +    }
> +  }
>
> -  NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS,
> -                                        TargetNameInfo, AttrList,
> -                                        /* IsInstantiation */ false,
> -                                        TypenameLoc.isValid(),
> TypenameLoc);
> +  NamedDecl *UD =
> +      BuildUsingDeclaration(S, AS, UsingLoc, TypenameLoc.isValid(),
> TypenameLoc,
> +                            SS, TargetNameInfo, EllipsisLoc, AttrList,
> +                            /*IsInstantiation*/false);
>    if (UD)
>      PushOnScopeChains(UD, S, /*AddToContext*/ false);
>
> @@ -8654,6 +8669,7 @@ bool Sema::CheckUsingShadowDecl(UsingDec
>               diag::err_using_decl_nested_name_specifier_is_current_class)
>            << Using->getQualifierLoc().getSourceRange();
>          Diag(Orig->getLocation(), diag::note_using_decl_target);
> +        Using->setInvalidDecl();
>          return true;
>        }
>
> @@ -8663,6 +8679,7 @@ bool Sema::CheckUsingShadowDecl(UsingDec
>          << cast<CXXRecordDecl>(CurContext)
>          << Using->getQualifierLoc().getSourceRange();
>        Diag(Orig->getLocation(), diag::note_using_decl_target);
> +      Using->setInvalidDecl();
>        return true;
>      }
>    }
> @@ -8686,7 +8703,7 @@ bool Sema::CheckUsingShadowDecl(UsingDec
>      // We can have UsingDecls in our Previous results because we use the
> same
>      // LookupResult for checking whether the UsingDecl itself is a valid
>      // redeclaration.
> -    if (isa<UsingDecl>(D))
> +    if (isa<UsingDecl>(D) || isa<UsingPackDecl>(D))
>        continue;
>
>      if (IsEquivalentForUsingDecl(Context, D, Target)) {
> @@ -8732,6 +8749,7 @@ bool Sema::CheckUsingShadowDecl(UsingDec
>
>      Diag(Target->getLocation(), diag::note_using_decl_target);
>      Diag(OldDecl->getLocation(), diag::note_using_decl_conflict);
> +    Using->setInvalidDecl();
>      return true;
>    }
>
> @@ -8744,6 +8762,7 @@ bool Sema::CheckUsingShadowDecl(UsingDec
>      Diag(Using->getLocation(), diag::err_using_decl_conflict);
>      Diag(Target->getLocation(), diag::note_using_decl_target);
>      Diag(Tag->getLocation(), diag::note_using_decl_conflict);
> +    Using->setInvalidDecl();
>      return true;
>    }
>
> @@ -8753,6 +8772,7 @@ bool Sema::CheckUsingShadowDecl(UsingDec
>    Diag(Using->getLocation(), diag::err_using_decl_conflict);
>    Diag(Target->getLocation(), diag::note_using_decl_target);
>    Diag(NonTag->getLocation(), diag::note_using_decl_conflict);
> +  Using->setInvalidDecl();
>    return true;
>  }
>
> @@ -8960,23 +8980,19 @@ private:
>  ///   the lookup differently for these declarations.
>  NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
>                                         SourceLocation UsingLoc,
> +                                       bool HasTypenameKeyword,
> +                                       SourceLocation TypenameLoc,
>                                         CXXScopeSpec &SS,
>                                         DeclarationNameInfo NameInfo,
> +                                       SourceLocation EllipsisLoc,
>                                         AttributeList *AttrList,
> -                                       bool IsInstantiation,
> -                                       bool HasTypenameKeyword,
> -                                       SourceLocation TypenameLoc) {
> +                                       bool IsInstantiation) {
>    assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
>    SourceLocation IdentLoc = NameInfo.getLoc();
>    assert(IdentLoc.isValid() && "Invalid TargetName location.");
>
>    // FIXME: We ignore attributes for now.
>
> -  if (SS.isEmpty()) {
> -    Diag(IdentLoc, diag::err_using_requires_qualname);
> -    return nullptr;
> -  }
> -
>    // For an inheriting constructor declaration, the name of the using
>    // declaration is the name of a constructor in this class, not in the
>    // base class.
> @@ -9042,16 +9058,17 @@ NamedDecl *Sema::BuildUsingDeclaration(S
>    DeclContext *LookupContext = computeDeclContext(SS);
>    NamedDecl *D;
>    NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
> -  if (!LookupContext) {
> +  if (!LookupContext || EllipsisLoc.isValid()) {
>      if (HasTypenameKeyword) {
>        // FIXME: not all declaration name kinds are legal here
>        D = UnresolvedUsingTypenameDecl::Create(Context, CurContext,
>                                                UsingLoc, TypenameLoc,
>                                                QualifierLoc,
> -                                              IdentLoc,
> NameInfo.getName());
> +                                              IdentLoc,
> NameInfo.getName(),
> +                                              EllipsisLoc);
>      } else {
>        D = UnresolvedUsingValueDecl::Create(Context, CurContext, UsingLoc,
> -                                           QualifierLoc, NameInfo);
> +                                           QualifierLoc, NameInfo,
> EllipsisLoc);
>      }
>      D->setAccess(AS);
>      CurContext->addDecl(D);
> @@ -9211,6 +9228,19 @@ NamedDecl *Sema::BuildUsingDeclaration(S
>    return UD;
>  }
>
> +NamedDecl *Sema::BuildUsingPackDecl(NamedDecl *InstantiatedFrom,
> +                                    ArrayRef<NamedDecl *> Expansions) {
> +  assert(isa<UnresolvedUsingValueDecl>(InstantiatedFrom) ||
> +         isa<UnresolvedUsingTypenameDecl>(InstantiatedFrom) ||
> +         isa<UsingPackDecl>(InstantiatedFrom));
> +
> +  auto *UPD =
> +      UsingPackDecl::Create(Context, CurContext, InstantiatedFrom,
> Expansions);
> +  UPD->setAccess(InstantiatedFrom->getAccess());
> +  CurContext->addDecl(UPD);
> +  return UPD;
> +}
> +
>  /// Additional checks for a using declaration referring to a constructor
> name.
>  bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) {
>    assert(!UD->hasTypename() && "expecting a constructor name");
> @@ -9264,7 +9294,7 @@ bool Sema::CheckUsingDeclRedeclaration(S
>      // scope?
>      if (Qual->isDependent() && !HasTypenameKeyword) {
>        for (auto *D : Prev) {
> -        if (!isa<TypeDecl>(D) && !isa<UsingDecl>(D)) {
> +        if (!isa<TypeDecl>(D) && !isa<UsingDecl>(D) &&
> !isa<UsingPackDecl>(D)) {
>            bool OldCouldBeEnumerator =
>                isa<UnresolvedUsingValueDecl>(D) ||
> isa<EnumConstantDecl>(D);
>            Diag(NameLoc,
>
> Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> SemaExprCXX.cpp?rev=290080&r1=290079&r2=290080&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Sun Dec 18 22:08:53 2016
> @@ -7462,17 +7462,11 @@ Sema::CheckMicrosoftIfExistsSymbol(Scope
>                                     UnqualifiedId &Name) {
>    DeclarationNameInfo TargetNameInfo = GetNameFromUnqualifiedId(Name);
>
> -  // Check for unexpanded parameter packs.
> -  SmallVector<UnexpandedParameterPack, 4> Unexpanded;
> -  collectUnexpandedParameterPacks(SS, Unexpanded);
> -  collectUnexpandedParameterPacks(TargetNameInfo, Unexpanded);
> -  if (!Unexpanded.empty()) {
> -    DiagnoseUnexpandedParameterPacks(KeywordLoc,
> -                                     IsIfExists? UPPC_IfExists
> -                                               : UPPC_IfNotExists,
> -                                     Unexpanded);
> +  // Check for an unexpanded parameter pack.
> +  auto UPPC = IsIfExists ? UPPC_IfExists : UPPC_IfNotExists;
> +  if (DiagnoseUnexpandedParameterPack(SS, UPPC) ||
> +      DiagnoseUnexpandedParameterPack(TargetNameInfo, UPPC))
>      return IER_Error;
> -  }
>
>    return CheckMicrosoftIfExistsSymbol(S, SS, TargetNameInfo);
>  }
>
> Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> SemaOverload.cpp?rev=290080&r1=290079&r2=290080&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaOverload.cpp Sun Dec 18 22:08:53 2016
> @@ -981,7 +981,7 @@ Sema::CheckOverload(Scope *S, FunctionDe
>          Match = *I;
>          return Ovl_Match;
>        }
> -    } else if (isa<UsingDecl>(OldD)) {
> +    } else if (isa<UsingDecl>(OldD) || isa<UsingPackDecl>(OldD)) {
>        // We can overload with these, which can show up when doing
>        // redeclaration checks for UsingDecls.
>        assert(Old.getLookupKind() == LookupUsingDeclName);
> @@ -11420,6 +11420,12 @@ BuildRecoveryCallExpr(Sema &SemaRef, Sco
>
>    assert(!R.empty() && "lookup results empty despite recovery");
>
> +  // If recovery created an ambiguity, just bail out.
> +  if (R.isAmbiguous()) {
> +    R.suppressDiagnostics();
> +    return ExprError();
> +  }
> +
>    // Build an implicit member call if appropriate.  Just drop the
>    // casts and such from the call, we don't really care.
>    ExprResult NewFn = ExprError();
>
> Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> SemaTemplateInstantiateDecl.cpp?rev=290080&r1=290079&r2=290080&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Sun Dec 18
> 22:08:53 2016
> @@ -2495,35 +2495,76 @@ Decl *TemplateDeclInstantiator::VisitCon
>    return nullptr;
>  }
>
> -Decl * TemplateDeclInstantiator
> -    ::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
> -  NestedNameSpecifierLoc QualifierLoc
> -    = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(),
> -                                          TemplateArgs);
> -  if (!QualifierLoc)
> -    return nullptr;
> +template <typename T>
> +Decl *TemplateDeclInstantiator::instantiateUnresolvedUsingDecl(
> +    T *D, bool InstantiatingPackElement) {
> +  // If this is a pack expansion, expand it now.
> +  if (D->isPackExpansion() && !InstantiatingPackElement) {
> +    SmallVector<UnexpandedParameterPack, 2> Unexpanded;
> +    SemaRef.collectUnexpandedParameterPacks(D->getQualifierLoc(),
> Unexpanded);
> +    SemaRef.collectUnexpandedParameterPacks(D->getNameInfo(),
> Unexpanded);
> +
> +    // Determine whether the set of unexpanded parameter packs can and
> should
> +    // be expanded.
> +    bool Expand = true;
> +    bool RetainExpansion = false;
> +    Optional<unsigned> NumExpansions;
> +    if (SemaRef.CheckParameterPacksForExpansion(
> +          D->getEllipsisLoc(), D->getSourceRange(), Unexpanded,
> TemplateArgs,
> +            Expand, RetainExpansion, NumExpansions))
> +      return nullptr;
>
> -  CXXScopeSpec SS;
> -  SS.Adopt(QualifierLoc);
> +    // This declaration cannot appear within a function template
> signature,
> +    // so we can't have a partial argument list for a parameter pack.
> +    assert(!RetainExpansion &&
> +           "should never need to retain an expansion for UsingPackDecl");
> +
> +    if (!Expand) {
> +      // We cannot fully expand the pack expansion now, so substitute
> into the
> +      // pattern and create a new pack expansion.
> +      Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1);
> +      return instantiateUnresolvedUsingDecl(D, true);
> +    }
> +
> +    // Within a function, we don't have any normal way to check for
> conflicts
> +    // between shadow declarations from different using declarations in
> the
> +    // same pack expansion, but this is always ill-formed because all
> expansions
> +    // must produce (conflicting) enumerators.
> +    //
> +    // Sadly we can't just reject this in the template definition because
> it
> +    // could be valid if the pack is empty or has exactly one expansion.
> +    if (D->getDeclContext()->isFunctionOrMethod() && *NumExpansions > 1)
> {
> +      SemaRef.Diag(D->getEllipsisLoc(),
> +                   diag::err_using_decl_redeclaration_expansion);
> +      return nullptr;
> +    }
>
> -  // Since NameInfo refers to a typename, it cannot be a C++ special name.
> -  // Hence, no transformation is required for it.
> -  DeclarationNameInfo NameInfo(D->getDeclName(), D->getLocation());
> -  NamedDecl *UD =
> -    SemaRef.BuildUsingDeclaration(/*Scope*/ nullptr, D->getAccess(),
> -                                  D->getUsingLoc(), SS, NameInfo, nullptr,
> -                                  /*instantiation*/ true,
> -                                  /*typename*/ true, D->getTypenameLoc());
> -  if (UD)
> -    SemaRef.Context.setInstantiatedFromUsingDecl(UD, D);
> +    // Instantiate the slices of this pack and build a UsingPackDecl.
> +    SmallVector<NamedDecl*, 8> Expansions;
> +    for (unsigned I = 0; I != *NumExpansions; ++I) {
> +      Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, I);
> +      Decl *Slice = instantiateUnresolvedUsingDecl(D, true);
> +      if (!Slice)
> +        return nullptr;
> +      // Note that we can still get unresolved using declarations here,
> if we
> +      // had arguments for all packs but the pattern also contained other
> +      // template arguments (this only happens during partial
> substitution, eg
> +      // into the body of a generic lambda in a function template).
> +      Expansions.push_back(cast<NamedDecl>(Slice));
> +    }
> +
> +    auto *NewD = SemaRef.BuildUsingPackDecl(D, Expansions);
> +    if (isDeclWithinFunction(D))
> +      SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewD);
> +    return NewD;
> +  }
>
> -  return UD;
> -}
> +  UnresolvedUsingTypenameDecl *TD = dyn_cast<
> UnresolvedUsingTypenameDecl>(D);
> +  SourceLocation TypenameLoc = TD ? TD->getTypenameLoc() :
> SourceLocation();
>
> -Decl * TemplateDeclInstantiator
> -    ::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
>    NestedNameSpecifierLoc QualifierLoc
> -      = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(),
> TemplateArgs);
> +    = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(),
> +                                          TemplateArgs);
>    if (!QualifierLoc)
>      return nullptr;
>
> @@ -2533,17 +2574,48 @@ Decl * TemplateDeclInstantiator
>    DeclarationNameInfo NameInfo
>      = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs);
>
> -  NamedDecl *UD =
> -    SemaRef.BuildUsingDeclaration(/*Scope*/ nullptr, D->getAccess(),
> -                                  D->getUsingLoc(), SS, NameInfo, nullptr,
> -                                  /*instantiation*/ true,
> -                                  /*typename*/ false, SourceLocation());
> +  // Produce a pack expansion only if we're not instantiating a particular
> +  // slice of a pack expansion.
> +  bool InstantiatingSlice = D->getEllipsisLoc().isValid() &&
> +                            SemaRef.ArgumentPackSubstitutionIndex != -1;
> +  SourceLocation EllipsisLoc =
> +      InstantiatingSlice ? SourceLocation() : D->getEllipsisLoc();
> +
> +  NamedDecl *UD = SemaRef.BuildUsingDeclaration(
> +      /*Scope*/ nullptr, D->getAccess(), D->getUsingLoc(),
> +      /*HasTypename*/ TD, TypenameLoc, SS, NameInfo, EllipsisLoc, nullptr,
> +      /*IsInstantiation*/ true);
>    if (UD)
>      SemaRef.Context.setInstantiatedFromUsingDecl(UD, D);
>
>    return UD;
>  }
>
> +Decl *TemplateDeclInstantiator::VisitUnresolvedUsingTypenameDecl(
> +    UnresolvedUsingTypenameDecl *D) {
> +  return instantiateUnresolvedUsingDecl(D);
> +}
> +
> +Decl *TemplateDeclInstantiator::VisitUnresolvedUsingValueDecl(
> +    UnresolvedUsingValueDecl *D) {
> +  return instantiateUnresolvedUsingDecl(D);
> +}
> +
> +Decl *TemplateDeclInstantiator::VisitUsingPackDecl(UsingPackDecl *D) {
> +  SmallVector<NamedDecl*, 8> Expansions;
> +  for (auto *UD : D->expansions()) {
> +    if (auto *NewUD =
> +            SemaRef.FindInstantiatedDecl(D->getLocation(), UD,
> TemplateArgs))
> +      Expansions.push_back(cast<NamedDecl>(NewUD));
> +    else
> +      return nullptr;
> +  }
> +
> +  auto *NewD = SemaRef.BuildUsingPackDecl(D, Expansions);
> +  if (isDeclWithinFunction(D))
> +    SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewD);
> +  return NewD;
> +}
>
>  Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecial
> izationDecl(
>                                       ClassScopeFunctionSpecializationDecl
> *Decl) {
> @@ -4513,22 +4585,36 @@ static bool isInstantiationOf(UsingShado
>                              Pattern);
>  }
>
> -static bool isInstantiationOf(UsingDecl *Pattern,
> -                              UsingDecl *Instance,
> -                              ASTContext &C) {
> -  return declaresSameEntity(C.getInstantiatedFromUsingDecl(Instance),
> Pattern);
> -}
> -
> -static bool isInstantiationOf(UnresolvedUsingValueDecl *Pattern,
> -                              NamedDecl *Instance,
> +static bool isInstantiationOf(UsingDecl *Pattern, UsingDecl *Instance,
>                                ASTContext &C) {
>    return declaresSameEntity(C.getInstantiatedFromUsingDecl(Instance),
> Pattern);
>  }
>
> -static bool isInstantiationOf(UnresolvedUsingTypenameDecl *Pattern,
> -                              NamedDecl *Instance,
> -                              ASTContext &C) {
> -  return declaresSameEntity(C.getInstantiatedFromUsingDecl(Instance),
> Pattern);
> +template<typename T>
> +static bool isInstantiationOfUnresolvedUsingDecl(T *Pattern, Decl *Other,
> +                                                 ASTContext &Ctx) {
> +  // An unresolved using declaration can instantiate to an unresolved
> using
> +  // declaration, or to a using declaration or a using declaration pack.
> +  //
> +  // Multiple declarations can claim to be instantiated from an unresolved
> +  // using declaration if it's a pack expansion. We want the UsingPackDecl
> +  // in that case, not the individual UsingDecls within the pack.
> +  bool OtherIsPackExpansion;
> +  NamedDecl *OtherFrom;
> +  if (auto *OtherUUD = dyn_cast<T>(Other)) {
> +    OtherIsPackExpansion = OtherUUD->isPackExpansion();
> +    OtherFrom = Ctx.getInstantiatedFromUsingDecl(OtherUUD);
> +  } else if (auto *OtherUPD = dyn_cast<UsingPackDecl>(Other)) {
> +    OtherIsPackExpansion = true;
> +    OtherFrom = OtherUPD->getInstantiatedFromUsingDecl();
> +  } else if (auto *OtherUD = dyn_cast<UsingDecl>(Other)) {
> +    OtherIsPackExpansion = false;
> +    OtherFrom = Ctx.getInstantiatedFromUsingDecl(OtherUD);
> +  } else {
> +    return false;
> +  }
> +  return Pattern->isPackExpansion() == OtherIsPackExpansion &&
> +         declaresSameEntity(OtherFrom, Pattern);
>  }
>
>  static bool isInstantiationOfStaticDataMember(VarDecl *Pattern,
> @@ -4549,21 +4635,14 @@ static bool isInstantiationOfStaticDataM
>  // Other is the prospective instantiation
>  // D is the prospective pattern
>  static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other)
> {
> -  if (D->getKind() != Other->getKind()) {
> -    if (auto *UUD = dyn_cast<UnresolvedUsingTypenameDecl>(D)) {
> -      if (UsingDecl *UD = dyn_cast<UsingDecl>(Other)) {
> -        return isInstantiationOf(UUD, UD, Ctx);
> -      }
> -    }
> +  if (auto *UUD = dyn_cast<UnresolvedUsingTypenameDecl>(D))
> +    return isInstantiationOfUnresolvedUsingDecl(UUD, Other, Ctx);
>
> -    if (auto *UUD = dyn_cast<UnresolvedUsingValueDecl>(D)) {
> -      if (UsingDecl *UD = dyn_cast<UsingDecl>(Other)) {
> -        return isInstantiationOf(UUD, UD, Ctx);
> -      }
> -    }
> +  if (auto *UUD = dyn_cast<UnresolvedUsingValueDecl>(D))
> +    return isInstantiationOfUnresolvedUsingDecl(UUD, Other, Ctx);
>
> +  if (D->getKind() != Other->getKind())
>      return false;
> -  }
>
>    if (auto *Record = dyn_cast<CXXRecordDecl>(Other))
>      return isInstantiationOf(cast<CXXRecordDecl>(D), Record);
> @@ -4600,12 +4679,6 @@ static bool isInstantiationOf(ASTContext
>    if (auto *Using = dyn_cast<UsingDecl>(Other))
>      return isInstantiationOf(cast<UsingDecl>(D), Using, Ctx);
>
> -  if (auto *Using = dyn_cast<UnresolvedUsingValueDecl>(Other))
> -    return isInstantiationOf(cast<UnresolvedUsingValueDecl>(D), Using,
> Ctx);
> -
> -  if (auto *Using = dyn_cast<UnresolvedUsingTypenameDecl>(Other))
> -    return isInstantiationOf(cast<UnresolvedUsingTypenameDecl>(D),
> Using, Ctx);
> -
>    if (auto *Shadow = dyn_cast<UsingShadowDecl>(Other))
>      return isInstantiationOf(cast<UsingShadowDecl>(D), Shadow, Ctx);
>
> @@ -4846,6 +4919,8 @@ NamedDecl *Sema::FindInstantiatedDecl(So
>      }
>
>      NamedDecl *Result = nullptr;
> +    // FIXME: If the name is a dependent name, this lookup won't
> necessarily
> +    // find it. Does that ever matter?
>      if (D->getDeclName()) {
>        DeclContext::lookup_result Found = ParentDC->lookup(D->
> getDeclName());
>        Result = findInstantiationOf(Context, D, Found.begin(),
> Found.end());
>
> Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> SemaTemplateVariadic.cpp?rev=290080&r1=290079&r2=290080&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Sun Dec 18 22:08:53 2016
> @@ -390,21 +390,18 @@ void Sema::collectUnexpandedParameterPac
>  void Sema::collectUnexpandedParameterPacks(TypeLoc TL,
>                     SmallVectorImpl<UnexpandedParameterPack> &Unexpanded)
> {
>    CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(TL);
> -}
> +}
>
> -void Sema::collectUnexpandedParameterPacks(CXXScopeSpec &SS,
> -                                           SmallVectorImpl<UnexpandedParameterPack>
> &Unexpanded) {
> -  NestedNameSpecifier *Qualifier = SS.getScopeRep();
> -  if (!Qualifier)
> -    return;
> -
> -  NestedNameSpecifierLoc QualifierLoc(Qualifier, SS.location_data());
> +void Sema::collectUnexpandedParameterPacks(
> +    NestedNameSpecifierLoc NNS,
> +    SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
>    CollectUnexpandedParameterPacksVisitor(Unexpanded)
> -    .TraverseNestedNameSpecifierLoc(QualifierLoc);
> +      .TraverseNestedNameSpecifierLoc(NNS);
>  }
>
> -void Sema::collectUnexpandedParameterPacks(const DeclarationNameInfo
> &NameInfo,
> -                         SmallVectorImpl<UnexpandedParameterPack>
> &Unexpanded) {
> +void Sema::collectUnexpandedParameterPacks(
> +    const DeclarationNameInfo &NameInfo,
> +    SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
>    CollectUnexpandedParameterPacksVisitor(Unexpanded)
>      .TraverseDeclarationNameInfo(NameInfo);
>  }
>
> Modified: cfe/trunk/lib/Sema/TreeTransform.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> TreeTransform.h?rev=290080&r1=290079&r2=290080&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/TreeTransform.h (original)
> +++ cfe/trunk/lib/Sema/TreeTransform.h Sun Dec 18 22:08:53 2016
> @@ -457,6 +457,10 @@ public:
>      return cast_or_null<NamedDecl>(getDerived().TransformDecl(Loc, D));
>    }
>
> +  /// Transform the set of declarations in an OverloadExpr.
> +  bool TransformOverloadExprDecls(OverloadExpr *Old, bool RequiresADL,
> +                                  LookupResult &R);
> +
>    /// \brief Transform the given nested-name-specifier with
> source-location
>    /// information.
>    ///
> @@ -821,7 +825,7 @@ public:
>
>    /// \brief Rebuild an unresolved typename type, given the decl that
>    /// the UnresolvedUsingTypenameDecl was transformed to.
> -  QualType RebuildUnresolvedUsingType(Decl *D);
> +  QualType RebuildUnresolvedUsingType(SourceLocation NameLoc, Decl *D);
>
>    /// \brief Build a new typedef type.
>    QualType RebuildTypedefType(TypedefNameDecl *Typedef) {
> @@ -5161,7 +5165,7 @@ TreeTransform<Derived>::TransformUnresol
>
>    QualType Result = TL.getType();
>    if (getDerived().AlwaysRebuild() || D != T->getDecl()) {
> -    Result = getDerived().RebuildUnresolvedUsingType(D);
> +    Result = getDerived().RebuildUnresolvedUsingType(TL.getNameLoc(), D);
>      if (Result.isNull())
>        return QualType();
>    }
> @@ -9794,44 +9798,71 @@ TreeTransform<Derived>::TransformCXXPseu
>                                                       Destroyed);
>  }
>
> -template<typename Derived>
> -ExprResult
> -TreeTransform<Derived>::TransformUnresolvedLookupExpr(
> -                                                  UnresolvedLookupExpr
> *Old) {
> -  LookupResult R(SemaRef, Old->getName(), Old->getNameLoc(),
> -                 Sema::LookupOrdinaryName);
> -
> +template <typename Derived>
> +bool TreeTransform<Derived>::TransformOverloadExprDecls(OverloadExpr
> *Old,
> +                                                        bool RequiresADL,
> +                                                        LookupResult &R) {
>    // Transform all the decls.
> -  for (UnresolvedLookupExpr::decls_iterator I = Old->decls_begin(),
> -         E = Old->decls_end(); I != E; ++I) {
> -    NamedDecl *InstD = static_cast<NamedDecl*>(
> -                                 getDerived().TransformDecl(
> Old->getNameLoc(),
> -                                                            *I));
> +  bool AllEmptyPacks = true;
> +  for (auto *OldD : Old->decls()) {
> +    Decl *InstD = getDerived().TransformDecl(Old->getNameLoc(), OldD);
>      if (!InstD) {
>        // Silently ignore these if a UsingShadowDecl instantiated to
> nothing.
>        // This can happen because of dependent hiding.
> -      if (isa<UsingShadowDecl>(*I))
> +      if (isa<UsingShadowDecl>(OldD))
>          continue;
>        else {
>          R.clear();
> -        return ExprError();
> +        return true;
>        }
>      }
>
> +    // Expand using pack declarations.
> +    ArrayRef<NamedDecl*> Decls = cast<NamedDecl>(InstD);
> +    if (auto *UPD = dyn_cast<UsingPackDecl>(InstD))
> +      Decls = UPD->expansions();
> +
>      // Expand using declarations.
> -    if (isa<UsingDecl>(InstD)) {
> -      UsingDecl *UD = cast<UsingDecl>(InstD);
> -      for (auto *I : UD->shadows())
> -        R.addDecl(I);
> -      continue;
> +    for (auto *D : Decls) {
> +      if (auto *UD = dyn_cast<UsingDecl>(D)) {
> +        for (auto *SD : UD->shadows())
> +          R.addDecl(SD);
> +      } else {
> +        R.addDecl(D);
> +      }
>      }
>
> -    R.addDecl(InstD);
> +    AllEmptyPacks &= Decls.empty();
> +  };
> +
> +  // C++ [temp.res]/8.4.2:
> +  //   The program is ill-formed, no diagnostic required, if [...] lookup
> for
> +  //   a name in the template definition found a using-declaration, but
> the
> +  //   lookup in the corresponding scope in the instantiation odoes not
> find
> +  //   any declarations because the using-declaration was a pack
> expansion and
> +  //   the corresponding pack is empty
> +  if (AllEmptyPacks && !RequiresADL) {
> +    getSema().Diag(Old->getNameLoc(), diag::err_using_pack_
> expansion_empty)
> +        << isa<UnresolvedMemberExpr>(Old) << Old->getNameInfo().getName();
> +    return true;
>    }
>
>    // Resolve a kind, but don't do any further analysis.  If it's
>    // ambiguous, the callee needs to deal with it.
>    R.resolveKind();
> +  return false;
> +}
> +
> +template<typename Derived>
> +ExprResult
> +TreeTransform<Derived>::TransformUnresolvedLookupExpr(
> +                                                  UnresolvedLookupExpr
> *Old) {
> +  LookupResult R(SemaRef, Old->getName(), Old->getNameLoc(),
> +                 Sema::LookupOrdinaryName);
> +
> +  // Transform the declaration set.
> +  if (TransformOverloadExprDecls(Old, Old->requiresADL(), R))
> +    return ExprError();
>
>    // Rebuild the nested-name qualifier, if present.
>    CXXScopeSpec SS;
> @@ -10699,35 +10730,9 @@ TreeTransform<Derived>::TransformUnresol
>    LookupResult R(SemaRef, Old->getMemberNameInfo(),
>                   Sema::LookupOrdinaryName);
>
> -  // Transform all the decls.
> -  for (UnresolvedMemberExpr::decls_iterator I = Old->decls_begin(),
> -         E = Old->decls_end(); I != E; ++I) {
> -    NamedDecl *InstD = static_cast<NamedDecl*>(
> -                                getDerived().TransformDecl(
> Old->getMemberLoc(),
> -                                                           *I));
> -    if (!InstD) {
> -      // Silently ignore these if a UsingShadowDecl instantiated to
> nothing.
> -      // This can happen because of dependent hiding.
> -      if (isa<UsingShadowDecl>(*I))
> -        continue;
> -      else {
> -        R.clear();
> -        return ExprError();
> -      }
> -    }
> -
> -    // Expand using declarations.
> -    if (isa<UsingDecl>(InstD)) {
> -      UsingDecl *UD = cast<UsingDecl>(InstD);
> -      for (auto *I : UD->shadows())
> -        R.addDecl(I);
> -      continue;
> -    }
> -
> -    R.addDecl(InstD);
> -  }
> -
> -  R.resolveKind();
> +  // Transform the declaration set.
> +  if (TransformOverloadExprDecls(Old, /*RequiresADL*/false, R))
> +    return ExprError();
>
>    // Determine the naming class.
>    if (Old->getNamingClass()) {
> @@ -11842,21 +11847,48 @@ QualType TreeTransform<Derived>::Rebuild
>  }
>
>  template<typename Derived>
> -QualType TreeTransform<Derived>::RebuildUnresolvedUsingType(Decl *D) {
> +QualType TreeTransform<Derived>::RebuildUnresolvedUsingType(SourceLocation
> Loc,
> +                                                            Decl *D) {
>    assert(D && "no decl found");
>    if (D->isInvalidDecl()) return QualType();
>
>    // FIXME: Doesn't account for ObjCInterfaceDecl!
>    TypeDecl *Ty;
> -  if (isa<UsingDecl>(D)) {
> -    UsingDecl *Using = cast<UsingDecl>(D);
> +  if (auto *UPD = dyn_cast<UsingPackDecl>(D)) {
> +    // A valid resolved using typename pack expansion decl can have
> multiple
> +    // UsingDecls, but they must each have exactly one type, and it must
> be
> +    // the same type in every case. But we must have at least one
> expansion!
> +    if (UPD->expansions().empty()) {
> +      getSema().Diag(Loc, diag::err_using_pack_expansion_empty)
> +          << UPD->isCXXClassMember() << UPD;
> +      return QualType();
> +    }
> +
> +    // We might still have some unresolved types. Try to pick a resolved
> type
> +    // if we can. The final instantiation will check that the remaining
> +    // unresolved types instantiate to the type we pick.
> +    QualType FallbackT;
> +    QualType T;
> +    for (auto *E : UPD->expansions()) {
> +      QualType ThisT = RebuildUnresolvedUsingType(Loc, E);
> +      if (ThisT.isNull())
> +        continue;
> +      else if (ThisT->getAs<UnresolvedUsingType>())
> +        FallbackT = ThisT;
> +      else if (T.isNull())
> +        T = ThisT;
> +      else
> +        assert(getSema().Context.hasSameType(ThisT, T) &&
> +               "mismatched resolved types in using pack expansion");
> +    }
> +    return T.isNull() ? FallbackT : T;
> +  } else if (auto *Using = dyn_cast<UsingDecl>(D)) {
>      assert(Using->hasTypename() &&
>             "UnresolvedUsingTypenameDecl transformed to non-typename
> using");
>
>      // A valid resolved using typename decl points to exactly one type
> decl.
>      assert(++Using->shadow_begin() == Using->shadow_end());
>      Ty = cast<TypeDecl>((*Using->shadow_begin())->getTargetDecl());
> -
>    } else {
>      assert(isa<UnresolvedUsingTypenameDecl>(D) &&
>             "UnresolvedUsingTypenameDecl transformed to non-using decl");
>
> Modified: cfe/trunk/lib/Serialization/ASTCommon.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/
> Serialization/ASTCommon.cpp?rev=290080&r1=290079&r2=290080&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Serialization/ASTCommon.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTCommon.cpp Sun Dec 18 22:08:53 2016
> @@ -285,6 +285,7 @@ bool serialization::isRedeclarableDeclKi
>    case Decl::NonTypeTemplateParm:
>    case Decl::TemplateTemplateParm:
>    case Decl::Using:
> +  case Decl::UsingPack:
>    case Decl::ObjCMethod:
>    case Decl::ObjCCategory:
>    case Decl::ObjCCategoryImpl:
>
> Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/
> Serialization/ASTReaderDecl.cpp?rev=290080&r1=290079&r2=290080&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Sun Dec 18 22:08:53 2016
> @@ -322,6 +322,7 @@ namespace clang {
>      void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
>      void VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
>      void VisitUsingDecl(UsingDecl *D);
> +    void VisitUsingPackDecl(UsingPackDecl *D);
>      void VisitUsingShadowDecl(UsingShadowDecl *D);
>      void VisitConstructorUsingShadowDecl(ConstructorUsingShadowDecl *D);
>      void VisitLinkageSpecDecl(LinkageSpecDecl *D);
> @@ -1419,6 +1420,15 @@ void ASTDeclReader::VisitUsingDecl(Using
>    mergeMergeable(D);
>  }
>
> +void ASTDeclReader::VisitUsingPackDecl(UsingPackDecl *D) {
> +  VisitNamedDecl(D);
> +  D->InstantiatedFrom = ReadDeclAs<NamedDecl>();
> +  NamedDecl **Expansions = D->getTrailingObjects<NamedDecl*>();
> +  for (unsigned I = 0; I != D->NumExpansions; ++I)
> +    Expansions[I] = ReadDeclAs<NamedDecl>();
> +  mergeMergeable(D);
> +}
> +
>  void ASTDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) {
>    RedeclarableResult Redecl = VisitRedeclarable(D);
>    VisitNamedDecl(D);
> @@ -1452,6 +1462,7 @@ void ASTDeclReader::VisitUnresolvedUsing
>    D->setUsingLoc(ReadSourceLocation());
>    D->QualifierLoc = Record.ReadNestedNameSpecifierLoc(Idx);
>    ReadDeclarationNameLoc(D->DNLoc, D->getDeclName());
> +  D->EllipsisLoc = ReadSourceLocation();
>    mergeMergeable(D);
>  }
>
> @@ -1460,6 +1471,7 @@ void ASTDeclReader::VisitUnresolvedUsing
>    VisitTypeDecl(D);
>    D->TypenameLocation = ReadSourceLocation();
>    D->QualifierLoc = Record.ReadNestedNameSpecifierLoc(Idx);
> +  D->EllipsisLoc = ReadSourceLocation();
>    mergeMergeable(D);
>  }
>
> @@ -3297,6 +3309,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID I
>    case DECL_USING:
>      D = UsingDecl::CreateDeserialized(Context, ID);
>      break;
> +  case DECL_USING_PACK:
> +    D = UsingPackDecl::CreateDeserialized(Context, ID, Record[Idx++]);
> +    break;
>    case DECL_USING_SHADOW:
>      D = UsingShadowDecl::CreateDeserialized(Context, ID);
>      break;
>
> Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/
> Serialization/ASTWriterDecl.cpp?rev=290080&r1=290079&r2=290080&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Sun Dec 18 22:08:53 2016
> @@ -107,6 +107,7 @@ namespace clang {
>      void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
>      void VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
>      void VisitUsingDecl(UsingDecl *D);
> +    void VisitUsingPackDecl(UsingPackDecl *D);
>      void VisitUsingShadowDecl(UsingShadowDecl *D);
>      void VisitConstructorUsingShadowDecl(ConstructorUsingShadowDecl *D);
>      void VisitLinkageSpecDecl(LinkageSpecDecl *D);
> @@ -1142,6 +1143,15 @@ void ASTDeclWriter::VisitUsingDecl(Using
>    Code = serialization::DECL_USING;
>  }
>
> +void ASTDeclWriter::VisitUsingPackDecl(UsingPackDecl *D) {
> +  Record.push_back(D->NumExpansions);
> +  VisitNamedDecl(D);
> +  Record.AddDeclRef(D->getInstantiatedFromUsingDecl());
> +  for (auto *E : D->expansions())
> +    Record.AddDeclRef(E);
> +  Code = serialization::DECL_USING_PACK;
> +}
> +
>  void ASTDeclWriter::VisitUsingShadowDecl(UsingShadowDecl *D) {
>    VisitRedeclarable(D);
>    VisitNamedDecl(D);
> @@ -1175,6 +1185,7 @@ void ASTDeclWriter::VisitUnresolvedUsing
>    Record.AddSourceLocation(D->getUsingLoc());
>    Record.AddNestedNameSpecifierLoc(D->getQualifierLoc());
>    Record.AddDeclarationNameLoc(D->DNLoc, D->getDeclName());
> +  Record.AddSourceLocation(D->getEllipsisLoc());
>    Code = serialization::DECL_UNRESOLVED_USING_VALUE;
>  }
>
> @@ -1183,6 +1194,7 @@ void ASTDeclWriter::VisitUnresolvedUsing
>    VisitTypeDecl(D);
>    Record.AddSourceLocation(D->getTypenameLoc());
>    Record.AddNestedNameSpecifierLoc(D->getQualifierLoc());
> +  Record.AddSourceLocation(D->getEllipsisLoc());
>    Code = serialization::DECL_UNRESOLVED_USING_TYPENAME;
>  }
>
>
> Added: cfe/trunk/test/PCH/cxx1z-using-declaration.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/
> cxx1z-using-declaration.cpp?rev=290080&view=auto
> ============================================================
> ==================
> --- cfe/trunk/test/PCH/cxx1z-using-declaration.cpp (added)
> +++ cfe/trunk/test/PCH/cxx1z-using-declaration.cpp Sun Dec 18 22:08:53
> 2016
> @@ -0,0 +1,35 @@
> +// No PCH:
> +// RUN: %clang_cc1 -pedantic -std=c++1z -include %s -verify %s
> +//
> +// With PCH:
> +// RUN: %clang_cc1 -pedantic -std=c++1z -emit-pch %s -o %t
> +// RUN: %clang_cc1 -pedantic -std=c++1z -include-pch %t -verify %s
> +
> +#ifndef HEADER
> +#define HEADER
> +
> +template<typename ...T> struct A : T... {
> +  using T::f ...;
> +  template<typename ...U> void g(U ...u) { f(u...); }
> +};
> +
> +struct X { void f(); };
> +struct Y { void f(int); };
> +struct Z { void f(int, int); };
> +
> +inline A<X, Y, Z> a;
> +
> +#else
> +
> +void test() {
> +  a.g();
> +  a.g(0);
> +  a.g(0, 0);
> +  // expected-error at 13 {{no match}}
> +  // expected-note at 16 {{candidate}}
> +  // expected-note at 17 {{candidate}}
> +  // expected-note at 18 {{candidate}}
> +  a.g(0, 0, 0); // expected-note {{instantiation of}}
> +}
> +
> +#endif
>
> Modified: cfe/trunk/test/Parser/cxx1z-using-declaration.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/
> cxx1z-using-declaration.cpp?rev=290080&r1=290079&r2=290080&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/Parser/cxx1z-using-declaration.cpp (original)
> +++ cfe/trunk/test/Parser/cxx1z-using-declaration.cpp Sun Dec 18 22:08:53
> 2016
> @@ -10,10 +10,10 @@ namespace B {
>  }
>
>  struct X {
> -  int x1, x2, y, z; // expected-note {{conflicting}}
> +  int x1, x2, y, z; // expected-note 2{{conflicting}}
>  };
>  struct Y {
> -  int x1, x2, y, z; // expected-note {{target}}
> +  int x1, x2, y, z; // expected-note 2{{target}}
>  };
>  struct Z : X, Y {
>    using X::x1,
> @@ -28,3 +28,8 @@ int X::*px1 = &Z::x1;
>  int X::*px2 = &Z::x2;
>  int Y::*py = &Z::y;
>  int X::*pz = &Z::z;
> +
> +template<typename ...T> struct Q : T... {
> +  using T::z...; // expected-error {{conflicts}}
> +};
> +Q<X,Y> q; // expected-note {{instantiation of}}
>
> Added: cfe/trunk/test/SemaTemplate/cxx1z-using-declaration.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
> SemaTemplate/cxx1z-using-declaration.cpp?rev=290080&view=auto
> ============================================================
> ==================
> --- cfe/trunk/test/SemaTemplate/cxx1z-using-declaration.cpp (added)
> +++ cfe/trunk/test/SemaTemplate/cxx1z-using-declaration.cpp Sun Dec 18
> 22:08:53 2016
> @@ -0,0 +1,230 @@
> +// RUN: %clang_cc1 -std=c++1z -verify %s
> +
> +// Test that we cope with failure to expand a pack.
> +template<typename ...T> struct Unexpanded : T... {
> +  using T::f; // expected-error {{unexpanded}}
> +  using typename T::type; // expected-error {{unexpanded}}
> +  template<typename ...U> void g(U ...u) { f(u...); } // expected-error
> {{undeclared identifier 'f'}}
> +  void h() {
> +    Unexpanded<type...> *p; // expected-error {{undeclared identifier
> 'type'}}
> +  }
> +};
> +void test_Unexpanded() {
> +  struct A { void f(); }; // expected-note {{must qualify}}
> +  struct B { void f(int); }; // expected-note {{must qualify}}
> +  Unexpanded<A, B>().g(0); // expected-note {{instantiation of}}
> +}
> +
> +// Test using non-type members from pack of base classes.
> +template<typename ...T> struct A : T... { // expected-note 2{{candidate}}
> +  using T::T ...; // expected-note 6{{inherited here}}
> +  using T::operator() ...;
> +  using T::operator T* ...;
> +  using T::h ...;
> +
> +  void f(int n) { h(n); } // expected-error {{ambiguous}}
> +  void f(int n, int m) { h(n, m); } // expected-error {{member using
> declaration 'h' instantiates to an empty pack}}
> +  void g(int n) { (*this)(n); } // expected-error {{ambiguous}}
> +  void g(int n, int m) { (*this)(n, m); } // expected-error {{does not
> provide a call operator}}
> +};
> +
> +namespace test_A {
> +  struct X { // expected-note 2{{candidate}}
> +    X();
> +    X(int); // expected-note {{candidate}}
> +    void operator()(int); // expected-note 2{{candidate}}
> +    operator X *();
> +    void h(int); // expected-note {{candidate}}
> +  };
> +  struct Y {
> +    Y();
> +    Y(int, int);
> +    void operator()(int, int);
> +    operator Y *();
> +    void h(int, int); // expected-note {{not viable}}
> +  };
> +  struct Z { // expected-note 2{{candidate}}
> +    Z();
> +    Z(int); // expected-note {{candidate}}
> +    void operator()(int); // expected-note 2{{candidate}}
> +    operator Z *();
> +    void h(int); // expected-note {{candidate}}
> +  };
> +
> +  void f() {
> +    A<> a;
> +    a.f(0, 0); // expected-note {{instantiation of}}
> +    a.g(0, 0); // expected-note {{instantiation of}}
> +
> +    A<X, Y> axy(0);
> +    A<X, Y>(0, 0);
> +    axy.f(0);
> +    axy.f(0, 0);
> +    axy.g(0);
> +    axy.g(0, 0);
> +    axy(0);
> +    axy(0, 0);
> +
> +    A<X, Y, Z>(0); // expected-error {{ambiguous}}
> +    A<X, Y, Z> axyz(0, 0);
> +    axyz.f(0); // expected-note {{instantiation of}}
> +    axyz.f(0, 0);
> +    axyz.g(0); // expected-note {{instantiation of}}
> +    axyz.g(0, 0);
> +    axyz(0); // expected-error {{ambiguous}}
> +    axyz(0, 0);
> +
> +    X *x;
> +    x = a; // expected-error {{incompatible}}
> +    x = axy;
> +    x = axyz;
> +    x = a.operator X*(); // expected-error {{no member}}
> +    x = axy.operator X*();
> +    x = axyz.operator X*();
> +
> +    Z *z;
> +    z = axyz;
> +    z = axyz.operator Z*();
> +  }
> +}
> +
> +// Test using pack of non-type members from single base class.
> +template<typename X, typename Y, typename ...T> struct B : X, Y {
> +  using X::operator T* ...;
> +};
> +
> +namespace test_B {
> +  struct X { operator int*(); operator float*(); operator char*(); }; //
> expected-note {{candidate}}
> +  struct Y { operator int*(); operator float*(); operator char*(); }; //
> expected-note {{candidate}}
> +  B<X, Y, int, float> bif;
> +  int *pi = bif;
> +  float *pf = bif;
> +  char *pc = bif; // expected-error {{ambiguous}}
> +}
> +
> +// Test using type member from pack of base classes.
> +template<typename ...T> struct C : T... {
> +  using typename T::type ...; // expected-error {{target of using
> declaration conflicts}}
> +  void f() { type value; } // expected-error {{member using declaration
> 'type' instantiates to an empty pack}}
> +};
> +
> +namespace test_C {
> +  struct X { typedef int type; };
> +  struct Y { typedef int type; }; // expected-note {{conflicting}}
> +  struct Z { typedef float type; }; // expected-note {{target}}
> +
> +  void f() {
> +    C<> c;
> +    c.f(); // expected-note {{instantiation of}}
> +
> +    C<X, Y> cxy;
> +    cxy.f();
> +
> +    C<X, Y, Z> cxyz; // expected-note {{instantiation of}}
> +    cxyz.f();
> +  }
> +}
> +
> +// Test using pack of non-types at block scope.
> +template<typename ...T> int fn1() {
> +  using T::e ...; // expected-error 2{{class member}} expected-note
> 2{{instead}}
> +  // expected-error at -1 2{{produces multiple values}}
> +  return e; // expected-error {{using declaration 'e' instantiates to an
> empty pack}}
> +}
> +
> +namespace test_fn1 {
> +  struct X { static int e; };
> +  struct Y { typedef int e; };
> +  inline namespace P { enum E { e }; }
> +  inline namespace Q { enum F { e }; }
> +  void f() {
> +    fn1<>(); // expected-note {{instantiation of}}
> +    fn1<X>(); // expected-note {{instantiation of}}
> +    fn1<Y>(); // expected-note {{instantiation of}}
> +    fn1<E>();
> +    fn1<E, F>(); // expected-note {{instantiation of}}
> +    fn1<E, X>(); // expected-note {{instantiation of}}
> +  }
> +}
> +
> +// Test using pack of types at block scope.
> +template<typename ...T> void fn2() {
> +  // This cannot ever be valid: in order for T::type to be a type, T must
> be a
> +  // class, and a class member cannot be named by a block-scope using
> declaration.
> +  using typename T::type ...; // expected-error {{class member}}
> +  type x; // expected-error {{unknown type name 'type'}}
> +}
> +
> +// Test partial substitution into class-scope pack.
> +template<typename ...T> auto lambda1() {
> +  return [](auto x) {
> +    struct A : T::template X<decltype(x)>... { // expected-note
> 1+{{instantiation of}}
> +      using T::template X<decltype(x)>::f ...;
> +      using typename T::template X<decltype(x)>::type ...;
> +      void g(int n) { f(n); } // expected-error {{empty pack}}
> expected-error {{expected 2, have 1}} expected-error {{ambiguous}}
> +      void h() { type value; } // expected-error {{empty pack}}
> +    };
> +    return A();
> +  };
> +}
> +
> +namespace test_lambda1 {
> +  struct A {
> +    template<typename> struct X {
> +      void f(int); // expected-note {{candidate}}
> +      using type = int;
> +    };
> +  };
> +  struct B {
> +    template<typename> struct X {
> +      void f(int, int); // expected-note {{declared here}} expected-note
> {{not viable}}
> +      using type = int;
> +    };
> +  };
> +  struct C {
> +    template<typename> struct X {
> +      void f(int); // expected-note {{candidate}}
> +      void f(int, int); // expected-note {{not viable}}
> +      using type = int;
> +    };
> +  };
> +
> +  void f() {
> +    lambda1<>() // expected-note 2{{instantiation of}}
> +      (0)
> +      // FIXME: This is poor error recovery
> +      .g(0); // expected-error {{no member named 'g'}}
> +    lambda1<A>()
> +      (0)
> +      .g(0);
> +    lambda1<B>()
> +      (0) // expected-note {{instantiation of}}
> +      .g(0);
> +    lambda1<A, B, C>()
> +      (0) // expected-note {{instantiation of}}
> +      .g(0);
> +  }
> +}
> +
> +namespace p0195r2_example {
> +  template<typename ...Ts>
> +  struct Overloader : Ts... {
> +    using Ts::operator() ...;
> +  };
> +
> +  template<typename ...Ts>
> +  constexpr auto make_overloader(Ts &&...ts) {
> +    return Overloader<Ts...>{static_cast<Ts&&>(ts)...};
> +  }
> +
> +  void test() {
> +    auto o = make_overloader(
> +      [&](int &r) -> int & { return r; }, // expected-note {{candidate
> function}}
> +      [&](float &r) -> float & { return r; } // expected-note {{candidate
> function}}
> +    );
> +    int a; float f; double d;
> +    int &ra = o(a);
> +    float &rf = o(f);
> +    double &rd = o(d); // expected-error {{no matching function}}
> +  }
> +}
>
> Modified: cfe/trunk/tools/libclang/CIndex.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/
> libclang/CIndex.cpp?rev=290080&r1=290079&r2=290080&view=diff
> ============================================================
> ==================
> --- cfe/trunk/tools/libclang/CIndex.cpp (original)
> +++ cfe/trunk/tools/libclang/CIndex.cpp Sun Dec 18 22:08:53 2016
> @@ -5733,6 +5733,7 @@ CXCursor clang_getCursorDefinition(CXCur
>    case Decl::BuiltinTemplate:
>    case Decl::PragmaComment:
>    case Decl::PragmaDetectMismatch:
> +  case Decl::UsingPack:
>      return C;
>
>    // Declaration kinds that don't make any sense here, but are
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20161219/d883a83b/attachment-0001.html>


More information about the cfe-commits mailing list