summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2016-12-20 21:35:28 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2016-12-20 21:35:28 +0000
commitc8c1a1961a459f5f79ba8dfb08a2d53d5443bf32 (patch)
treec042187cdc68b1038bde77c652ded7a849bd53d3 /lib
parenta966b1fd6ce257ab259c534488003e7aef57a0ff (diff)
[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. This is a re-commit of r290080 (reverted in r290092) with a fix for a use-after-lifetime bug. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@290203 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/DeclBase.cpp5
-rw-r--r--lib/AST/DeclCXX.cpp36
-rw-r--r--lib/CodeGen/CGDecl.cpp4
-rw-r--r--lib/Parse/ParseDeclCXX.cpp79
-rw-r--r--lib/Sema/SemaDeclCXX.cpp74
-rw-r--r--lib/Sema/SemaExprCXX.cpp14
-rw-r--r--lib/Sema/SemaOverload.cpp8
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp193
-rw-r--r--lib/Sema/SemaTemplateVariadic.cpp19
-rw-r--r--lib/Sema/TreeTransform.h143
-rw-r--r--lib/Serialization/ASTCommon.cpp1
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp15
-rw-r--r--lib/Serialization/ASTWriterDecl.cpp12
13 files changed, 375 insertions, 228 deletions
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 8deef3343d..6111abab64 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -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:
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 8563416a48..1860b948d6 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -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() { }
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 4657347758..d761363801 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -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));
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index d31d114237..4002b09d2b 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -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)));
}
}
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index ac643af149..21bdd945f0 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -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,
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 74beeac724..5c3900adbd 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -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);
}
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index d49142b8d8..2129729dab 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -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();
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 0956a1cc50..dbc322ebfd 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -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());
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index c8bc2c3880..54556b505e 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -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);
}
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index a76a078fd0..9671b9b35d 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -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");
diff --git a/lib/Serialization/ASTCommon.cpp b/lib/Serialization/ASTCommon.cpp
index 79ccffc5ab..ecd249cc50 100644
--- a/lib/Serialization/ASTCommon.cpp
+++ b/lib/Serialization/ASTCommon.cpp
@@ -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:
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 913a1419b3..dc29a61c0a 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -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;
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index 21468619db..ee220f00a8 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -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;
}