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