[c++1z] P0195R2: Support pack-expansion of using-declarations.
authorRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 20 Dec 2016 21:35:28 +0000 (21:35 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 20 Dec 2016 21:35:28 +0000 (21:35 +0000)
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.

This is a re-commit of r290080 (reverted in r290092) with a fix for a
use-after-lifetime bug.

llvm-svn: 290203

26 files changed:
clang/include/clang/AST/DeclCXX.h
clang/include/clang/AST/RecursiveASTVisitor.h
clang/include/clang/Basic/DeclNodes.td
clang/include/clang/Basic/DiagnosticParseKinds.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Parse/Parser.h
clang/include/clang/Sema/Sema.h
clang/include/clang/Sema/Template.h
clang/include/clang/Serialization/ASTBitCodes.h
clang/lib/AST/DeclBase.cpp
clang/lib/AST/DeclCXX.cpp
clang/lib/CodeGen/CGDecl.cpp
clang/lib/Parse/ParseDeclCXX.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/lib/Sema/SemaExprCXX.cpp
clang/lib/Sema/SemaOverload.cpp
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
clang/lib/Sema/SemaTemplateVariadic.cpp
clang/lib/Sema/TreeTransform.h
clang/lib/Serialization/ASTCommon.cpp
clang/lib/Serialization/ASTReaderDecl.cpp
clang/lib/Serialization/ASTWriterDecl.cpp
clang/test/PCH/cxx1z-using-declaration.cpp [new file with mode: 0644]
clang/test/Parser/cxx1z-using-declaration.cpp
clang/test/SemaTemplate/cxx1z-using-declaration.cpp [new file with mode: 0644]
clang/tools/libclang/CIndex.cpp

index 46434c4..06ecd3c 100644 (file)
@@ -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 ValueDecl,
   /// \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 ValueDecl,
   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);
index 058ab1f..afacfd5 100644 (file)
@@ -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()));
 })
index 6da2c2c..7b581d3 100644 (file)
@@ -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;
index 31e55b4..0943fea 100644 (file)
@@ -740,6 +740,8 @@ def err_alias_declaration_not_identifier : Error<
   "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_declaration : Warning<
   "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<
index 69322f0..f32364e 100644 (file)
@@ -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_function : Error<
 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">;
index 3d098fa..972f13d 100644 (file)
@@ -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,
index 136f848..ebbc1e1 100644 (file)
@@ -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
index 0d12880..401bbbf 100644 (file)
@@ -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);
   };  
 }
 
index 611c00d..4e29ad6 100644 (file)
@@ -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.
index 8deef33..6111aba 100644 (file)
@@ -651,11 +651,13 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
     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::getIdentifierNamespaceForKind(Kind DeclKind) {
       return IDNS_Ordinary | IDNS_Using;
 
     case Using:
+    case UsingPack:
       return IDNS_Using;
 
     case ObjCProtocol:
index 8563416..1860b94 100644 (file)
@@ -2250,15 +2250,37 @@ SourceRange UsingDecl::getSourceRange() const {
   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::CreateDeserialized(ASTContext &C, unsigned ID) {
   return new (C, ID) UnresolvedUsingValueDecl(nullptr, QualType(),
                                               SourceLocation(),
                                               NestedNameSpecifierLoc(),
-                                              DeclarationNameInfo());
+                                              DeclarationNameInfo(),
+                                              SourceLocation());
 }
 
 SourceRange UnresolvedUsingValueDecl::getSourceRange() const {
@@ -2283,17 +2306,18 @@ UnresolvedUsingTypenameDecl::Create(ASTContext &C, DeclContext *DC,
                                     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() { }
index 4657347..d761363 100644 (file)
@@ -113,6 +113,10 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
     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));
index d31d114..4002b09 100644 (file)
@@ -560,7 +560,9 @@ bool Parser::ParseUsingDeclarator(unsigned Context, UsingDeclarator &D) {
   //   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(unsigned Context, UsingDeclarator &D) {
       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 Context,
         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 Context,
   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::ParseAliasDeclarationAfterDeclarator(
   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(AccessSpecifier AS,
       }
 
       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)));
     }
   }
 
index ac643af..21bdd94 100644 (file)
@@ -8533,12 +8533,18 @@ void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) {
 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 *S,
       << 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(UsingDecl *Using, NamedDecl *Orig,
              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(UsingDecl *Using, NamedDecl *Orig,
         << 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(UsingDecl *Using, NamedDecl *Orig,
     // 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(UsingDecl *Using, NamedDecl *Orig,
 
     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(UsingDecl *Using, NamedDecl *Orig,
     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(UsingDecl *Using, NamedDecl *Orig,
   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(Scope *S, AccessSpecifier AS,
   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(Scope *S, AccessSpecifier AS,
   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(SourceLocation UsingLoc,
     // 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,
index 74beeac..5c3900a 100644 (file)
@@ -7462,17 +7462,11 @@ Sema::CheckMicrosoftIfExistsSymbol(Scope *S, SourceLocation KeywordLoc,
                                    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);
 }
index d49142b..2129729 100644 (file)
@@ -981,7 +981,7 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old,
         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, Scope *S, Expr *Fn,
 
   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();
index 0956a1c..dbc322e 100644 (file)
@@ -2495,35 +2495,76 @@ Decl *TemplateDeclInstantiator::VisitConstructorUsingShadowDecl(
   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);
 
-  CXXScopeSpec SS;
-  SS.Adopt(QualifierLoc);
+    // 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;
 
-  // 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);
+    // 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");
 
-  return UD;
-}
+    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;
+    }
+
+    // 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;
+  }
+
+  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::VisitClassScopeFunctionSpecializationDecl(
                                      ClassScopeFunctionSpecializationDecl *Decl) {
@@ -4513,22 +4585,36 @@ static bool isInstantiationOf(UsingShadowDecl *Pattern,
                             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 isInstantiationOfStaticDataMember(VarDecl *Pattern,
 // 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 &Ctx, NamedDecl *D, Decl *Other) {
   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(SourceLocation Loc, NamedDecl *D,
     }
 
     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());
index c8bc2c3..54556b5 100644 (file)
@@ -390,21 +390,18 @@ void Sema::collectUnexpandedParameterPacks(QualType T,
 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);
 }
index a76a078..9671b9b 100644 (file)
@@ -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>::TransformUnresolvedUsingType(TypeLocBuilder &TLB,
 
   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,72 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
                                                      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.
+    NamedDecl *SingleDecl = cast<NamedDecl>(InstD);
+    ArrayRef<NamedDecl*> Decls = SingleDecl;
+    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 +10731,9 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old)
   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 +11848,48 @@ QualType TreeTransform<Derived>::RebuildFunctionNoProtoType(QualType T) {
 }
 
 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");
index 79ccffc..ecd249c 100644 (file)
@@ -285,6 +285,7 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) {
   case Decl::NonTypeTemplateParm:
   case Decl::TemplateTemplateParm:
   case Decl::Using:
+  case Decl::UsingPack:
   case Decl::ObjCMethod:
   case Decl::ObjCCategory:
   case Decl::ObjCCategoryImpl:
index 913a141..dc29a61 100644 (file)
@@ -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(UsingDecl *D) {
   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::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
   D->setUsingLoc(ReadSourceLocation());
   D->QualifierLoc = Record.ReadNestedNameSpecifierLoc(Idx);
   ReadDeclarationNameLoc(D->DNLoc, D->getDeclName());
+  D->EllipsisLoc = ReadSourceLocation();
   mergeMergeable(D);
 }
 
@@ -1460,6 +1471,7 @@ void ASTDeclReader::VisitUnresolvedUsingTypenameDecl(
   VisitTypeDecl(D);
   D->TypenameLocation = ReadSourceLocation();
   D->QualifierLoc = Record.ReadNestedNameSpecifierLoc(Idx);
+  D->EllipsisLoc = ReadSourceLocation();
   mergeMergeable(D);
 }
 
@@ -3297,6 +3309,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
   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;
index 2146861..ee220f0 100644 (file)
@@ -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(UsingDecl *D) {
   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::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
   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::VisitUnresolvedUsingTypenameDecl(
   VisitTypeDecl(D);
   Record.AddSourceLocation(D->getTypenameLoc());
   Record.AddNestedNameSpecifierLoc(D->getQualifierLoc());
+  Record.AddSourceLocation(D->getEllipsisLoc());
   Code = serialization::DECL_UNRESOLVED_USING_TYPENAME;
 }
 
diff --git a/clang/test/PCH/cxx1z-using-declaration.cpp b/clang/test/PCH/cxx1z-using-declaration.cpp
new file mode 100644 (file)
index 0000000..a185ff1
--- /dev/null
@@ -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@13 {{no match}}
+  // expected-note@16 {{candidate}}
+  // expected-note@17 {{candidate}}
+  // expected-note@18 {{candidate}}
+  a.g(0, 0, 0); // expected-note {{instantiation of}}
+}
+
+#endif
index dab1ca8..0be8167 100644 (file)
@@ -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}}
diff --git a/clang/test/SemaTemplate/cxx1z-using-declaration.cpp b/clang/test/SemaTemplate/cxx1z-using-declaration.cpp
new file mode 100644 (file)
index 0000000..7bef36d
--- /dev/null
@@ -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@-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}}
+  }
+}
index df04899..210e74b 100644 (file)
@@ -5738,6 +5738,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
   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