|
@@ -2495,35 +2495,76 @@ Decl *TemplateDeclInstantiator::VisitConstructorUsingShadowDecl(
|
|
return nullptr;
|
|
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
|
|
NestedNameSpecifierLoc QualifierLoc
|
|
- = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(), TemplateArgs);
|
|
|
|
|
|
+ = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(),
|
|
|
|
+ TemplateArgs);
|
|
if (!QualifierLoc)
|
|
if (!QualifierLoc)
|
|
return nullptr;
|
|
return nullptr;
|
|
|
|
|
|
@@ -2533,17 +2574,48 @@ Decl * TemplateDeclInstantiator
|
|
DeclarationNameInfo NameInfo
|
|
DeclarationNameInfo NameInfo
|
|
= SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs);
|
|
= 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)
|
|
if (UD)
|
|
SemaRef.Context.setInstantiatedFromUsingDecl(UD, D);
|
|
SemaRef.Context.setInstantiatedFromUsingDecl(UD, D);
|
|
|
|
|
|
return UD;
|
|
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(
|
|
Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl(
|
|
ClassScopeFunctionSpecializationDecl *Decl) {
|
|
ClassScopeFunctionSpecializationDecl *Decl) {
|
|
@@ -4513,22 +4585,36 @@ static bool isInstantiationOf(UsingShadowDecl *Pattern,
|
|
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) {
|
|
ASTContext &C) {
|
|
return declaresSameEntity(C.getInstantiatedFromUsingDecl(Instance), Pattern);
|
|
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,
|
|
static bool isInstantiationOfStaticDataMember(VarDecl *Pattern,
|
|
@@ -4549,21 +4635,14 @@ static bool isInstantiationOfStaticDataMember(VarDecl *Pattern,
|
|
// Other is the prospective instantiation
|
|
// Other is the prospective instantiation
|
|
// D is the prospective pattern
|
|
// D is the prospective pattern
|
|
static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) {
|
|
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;
|
|
return false;
|
|
- }
|
|
|
|
|
|
|
|
if (auto *Record = dyn_cast<CXXRecordDecl>(Other))
|
|
if (auto *Record = dyn_cast<CXXRecordDecl>(Other))
|
|
return isInstantiationOf(cast<CXXRecordDecl>(D), Record);
|
|
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))
|
|
if (auto *Using = dyn_cast<UsingDecl>(Other))
|
|
return isInstantiationOf(cast<UsingDecl>(D), Using, Ctx);
|
|
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))
|
|
if (auto *Shadow = dyn_cast<UsingShadowDecl>(Other))
|
|
return isInstantiationOf(cast<UsingShadowDecl>(D), Shadow, Ctx);
|
|
return isInstantiationOf(cast<UsingShadowDecl>(D), Shadow, Ctx);
|
|
|
|
|
|
@@ -4846,6 +4919,8 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
|
|
}
|
|
}
|
|
|
|
|
|
NamedDecl *Result = nullptr;
|
|
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()) {
|
|
if (D->getDeclName()) {
|
|
DeclContext::lookup_result Found = ParentDC->lookup(D->getDeclName());
|
|
DeclContext::lookup_result Found = ParentDC->lookup(D->getDeclName());
|
|
Result = findInstantiationOf(Context, D, Found.begin(), Found.end());
|
|
Result = findInstantiationOf(Context, D, Found.begin(), Found.end());
|