Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 2c09225

Browse files
committed
[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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@290080 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 7d69588 commit 2c09225

26 files changed

+793
-247
lines changed

Diff for: include/clang/AST/DeclCXX.h

+112-7
Original file line numberDiff line numberDiff line change
@@ -3140,6 +3140,77 @@ class UsingDecl : public NamedDecl, public Mergeable<UsingDecl> {
31403140
friend class ASTDeclWriter;
31413141
};
31423142

3143+
/// Represents a pack of using declarations that a single
3144+
/// using-declarator pack-expanded into.
3145+
///
3146+
/// \code
3147+
/// template<typename ...T> struct X : T... {
3148+
/// using T::operator()...;
3149+
/// using T::operator T...;
3150+
/// };
3151+
/// \endcode
3152+
///
3153+
/// In the second case above, the UsingPackDecl will have the name
3154+
/// 'operator T' (which contains an unexpanded pack), but the individual
3155+
/// UsingDecls and UsingShadowDecls will have more reasonable names.
3156+
class UsingPackDecl final
3157+
: public NamedDecl, public Mergeable<UsingPackDecl>,
3158+
private llvm::TrailingObjects<UsingPackDecl, NamedDecl *> {
3159+
void anchor() override;
3160+
3161+
/// The UnresolvedUsingValueDecl or UnresolvedUsingTypenameDecl from
3162+
/// which this waas instantiated.
3163+
NamedDecl *InstantiatedFrom;
3164+
3165+
/// The number of using-declarations created by this pack expansion.
3166+
unsigned NumExpansions;
3167+
3168+
UsingPackDecl(DeclContext *DC, NamedDecl *InstantiatedFrom,
3169+
ArrayRef<NamedDecl *> UsingDecls)
3170+
: NamedDecl(UsingPack, DC,
3171+
InstantiatedFrom ? InstantiatedFrom->getLocation()
3172+
: SourceLocation(),
3173+
InstantiatedFrom ? InstantiatedFrom->getDeclName()
3174+
: DeclarationName()),
3175+
InstantiatedFrom(InstantiatedFrom), NumExpansions(UsingDecls.size()) {
3176+
std::uninitialized_copy(UsingDecls.begin(), UsingDecls.end(),
3177+
getTrailingObjects<NamedDecl *>());
3178+
}
3179+
3180+
public:
3181+
/// Get the using declaration from which this was instantiated. This will
3182+
/// always be an UnresolvedUsingValueDecl or an UnresolvedUsingTypenameDecl
3183+
/// that is a pack expansion.
3184+
NamedDecl *getInstantiatedFromUsingDecl() { return InstantiatedFrom; }
3185+
3186+
/// Get the set of using declarations that this pack expanded into. Note that
3187+
/// some of these may still be unresolved.
3188+
ArrayRef<NamedDecl *> expansions() const {
3189+
return llvm::makeArrayRef(getTrailingObjects<NamedDecl *>(), NumExpansions);
3190+
}
3191+
3192+
static UsingPackDecl *Create(ASTContext &C, DeclContext *DC,
3193+
NamedDecl *InstantiatedFrom,
3194+
ArrayRef<NamedDecl *> UsingDecls);
3195+
3196+
static UsingPackDecl *CreateDeserialized(ASTContext &C, unsigned ID,
3197+
unsigned NumExpansions);
3198+
3199+
SourceRange getSourceRange() const override LLVM_READONLY {
3200+
return InstantiatedFrom->getSourceRange();
3201+
}
3202+
3203+
UsingPackDecl *getCanonicalDecl() override { return getFirstDecl(); }
3204+
const UsingPackDecl *getCanonicalDecl() const { return getFirstDecl(); }
3205+
3206+
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
3207+
static bool classofKind(Kind K) { return K == UsingPack; }
3208+
3209+
friend class ASTDeclReader;
3210+
friend class ASTDeclWriter;
3211+
friend TrailingObjects;
3212+
};
3213+
31433214
/// \brief Represents a dependent using declaration which was not marked with
31443215
/// \c typename.
31453216
///
@@ -3158,6 +3229,9 @@ class UnresolvedUsingValueDecl : public ValueDecl,
31583229
/// \brief The source location of the 'using' keyword
31593230
SourceLocation UsingLocation;
31603231

3232+
/// \brief If this is a pack expansion, the location of the '...'.
3233+
SourceLocation EllipsisLoc;
3234+
31613235
/// \brief The nested-name-specifier that precedes the name.
31623236
NestedNameSpecifierLoc QualifierLoc;
31633237

@@ -3168,11 +3242,12 @@ class UnresolvedUsingValueDecl : public ValueDecl,
31683242
UnresolvedUsingValueDecl(DeclContext *DC, QualType Ty,
31693243
SourceLocation UsingLoc,
31703244
NestedNameSpecifierLoc QualifierLoc,
3171-
const DeclarationNameInfo &NameInfo)
3245+
const DeclarationNameInfo &NameInfo,
3246+
SourceLocation EllipsisLoc)
31723247
: ValueDecl(UnresolvedUsingValue, DC,
31733248
NameInfo.getLoc(), NameInfo.getName(), Ty),
3174-
UsingLocation(UsingLoc), QualifierLoc(QualifierLoc),
3175-
DNLoc(NameInfo.getInfo())
3249+
UsingLocation(UsingLoc), EllipsisLoc(EllipsisLoc),
3250+
QualifierLoc(QualifierLoc), DNLoc(NameInfo.getInfo())
31763251
{ }
31773252

31783253
public:
@@ -3198,10 +3273,20 @@ class UnresolvedUsingValueDecl : public ValueDecl,
31983273
return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
31993274
}
32003275

3276+
/// \brief Determine whether this is a pack expansion.
3277+
bool isPackExpansion() const {
3278+
return EllipsisLoc.isValid();
3279+
}
3280+
3281+
/// \brief Get the location of the ellipsis if this is a pack expansion.
3282+
SourceLocation getEllipsisLoc() const {
3283+
return EllipsisLoc;
3284+
}
3285+
32013286
static UnresolvedUsingValueDecl *
32023287
Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc,
32033288
NestedNameSpecifierLoc QualifierLoc,
3204-
const DeclarationNameInfo &NameInfo);
3289+
const DeclarationNameInfo &NameInfo, SourceLocation EllipsisLoc);
32053290

32063291
static UnresolvedUsingValueDecl *
32073292
CreateDeserialized(ASTContext &C, unsigned ID);
@@ -3242,17 +3327,22 @@ class UnresolvedUsingTypenameDecl
32423327
/// \brief The source location of the 'typename' keyword
32433328
SourceLocation TypenameLocation;
32443329

3330+
/// \brief If this is a pack expansion, the location of the '...'.
3331+
SourceLocation EllipsisLoc;
3332+
32453333
/// \brief The nested-name-specifier that precedes the name.
32463334
NestedNameSpecifierLoc QualifierLoc;
32473335

32483336
UnresolvedUsingTypenameDecl(DeclContext *DC, SourceLocation UsingLoc,
32493337
SourceLocation TypenameLoc,
32503338
NestedNameSpecifierLoc QualifierLoc,
32513339
SourceLocation TargetNameLoc,
3252-
IdentifierInfo *TargetName)
3340+
IdentifierInfo *TargetName,
3341+
SourceLocation EllipsisLoc)
32533342
: TypeDecl(UnresolvedUsingTypename, DC, TargetNameLoc, TargetName,
32543343
UsingLoc),
3255-
TypenameLocation(TypenameLoc), QualifierLoc(QualifierLoc) { }
3344+
TypenameLocation(TypenameLoc), EllipsisLoc(EllipsisLoc),
3345+
QualifierLoc(QualifierLoc) { }
32563346

32573347
friend class ASTDeclReader;
32583348

@@ -3272,10 +3362,25 @@ class UnresolvedUsingTypenameDecl
32723362
return QualifierLoc.getNestedNameSpecifier();
32733363
}
32743364

3365+
DeclarationNameInfo getNameInfo() const {
3366+
return DeclarationNameInfo(getDeclName(), getLocation());
3367+
}
3368+
3369+
/// \brief Determine whether this is a pack expansion.
3370+
bool isPackExpansion() const {
3371+
return EllipsisLoc.isValid();
3372+
}
3373+
3374+
/// \brief Get the location of the ellipsis if this is a pack expansion.
3375+
SourceLocation getEllipsisLoc() const {
3376+
return EllipsisLoc;
3377+
}
3378+
32753379
static UnresolvedUsingTypenameDecl *
32763380
Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc,
32773381
SourceLocation TypenameLoc, NestedNameSpecifierLoc QualifierLoc,
3278-
SourceLocation TargetNameLoc, DeclarationName TargetName);
3382+
SourceLocation TargetNameLoc, DeclarationName TargetName,
3383+
SourceLocation EllipsisLoc);
32793384

32803385
static UnresolvedUsingTypenameDecl *
32813386
CreateDeserialized(ASTContext &C, unsigned ID);

Diff for: include/clang/AST/RecursiveASTVisitor.h

+2
Original file line numberDiff line numberDiff line change
@@ -1505,6 +1505,8 @@ DEF_TRAVERSE_DECL(UsingDecl, {
15051505
TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
15061506
})
15071507

1508+
DEF_TRAVERSE_DECL(UsingPackDecl, {})
1509+
15081510
DEF_TRAVERSE_DECL(UsingDirectiveDecl, {
15091511
TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
15101512
})

Diff for: include/clang/Basic/DeclNodes.td

+1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ def Named : Decl<1>;
6767
def TemplateTemplateParm : DDecl<Template>;
6868
def BuiltinTemplate : DDecl<Template>;
6969
def Using : DDecl<Named>;
70+
def UsingPack : DDecl<Named>;
7071
def UsingShadow : DDecl<Named>;
7172
def ConstructorUsingShadow : DDecl<UsingShadow>;
7273
def ObjCMethod : DDecl<Named>, DeclContext;

Diff for: include/clang/Basic/DiagnosticParseKinds.td

+7
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,8 @@ def err_alias_declaration_not_identifier : Error<
740740
"name defined in alias declaration must be an identifier">;
741741
def err_alias_declaration_specialization : Error<
742742
"%select{partial specialization|explicit specialization|explicit instantiation}0 of alias templates is not permitted">;
743+
def err_alias_declaration_pack_expansion : Error<
744+
"alias declaration cannot be a pack expansion">;
743745

744746
// C++1z using-declaration pack expansions
745747
def ext_multi_using_declaration : ExtWarn<
@@ -749,6 +751,11 @@ def warn_cxx1z_compat_multi_using_declaration : Warning<
749751
"use of multiple declarators in a single using declaration is "
750752
"incompatible with C++ standards before C++1z">,
751753
InGroup<CXXPre1zCompat>, DefaultIgnore;
754+
def ext_using_declaration_pack : ExtWarn<
755+
"pack expansion of using declaration is a C++1z extension">, InGroup<CXX1z>;
756+
def warn_cxx1z_compat_using_declaration_pack : Warning<
757+
"pack expansion using declaration is incompatible with C++ standards "
758+
"before C++1z">, InGroup<CXXPre1zCompat>, DefaultIgnore;
752759

753760
// C++11 override control
754761
def ext_override_control_keyword : ExtWarn<

Diff for: include/clang/Basic/DiagnosticSemaKinds.td

+5
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,8 @@ def err_using_decl_conflict : Error<
474474
def err_using_decl_conflict_reverse : Error<
475475
"declaration conflicts with target of using declaration already in scope">;
476476
def note_using_decl : Note<"%select{|previous }0using declaration">;
477+
def err_using_decl_redeclaration_expansion : Error<
478+
"using declaration pack expansion at block scope produces multiple values">;
477479

478480
def warn_access_decl_deprecated : Warning<
479481
"access declarations are deprecated; use using declarations instead">,
@@ -4155,6 +4157,9 @@ def err_variable_instantiates_to_function : Error<
41554157
def err_nested_name_spec_non_tag : Error<
41564158
"type %0 cannot be used prior to '::' because it has no members">;
41574159

4160+
def err_using_pack_expansion_empty : Error<
4161+
"%select{|member}0 using declaration %1 instantiates to an empty pack">;
4162+
41584163
// C++ Explicit Instantiation
41594164
def err_explicit_instantiation_duplicate : Error<
41604165
"duplicate explicit instantiation of %0">;

Diff for: include/clang/Parse/Parser.h

+2-4
Original file line numberDiff line numberDiff line change
@@ -2436,9 +2436,10 @@ class Parser : public CodeCompletionHandler {
24362436
CXXScopeSpec SS;
24372437
SourceLocation TemplateKWLoc;
24382438
UnqualifiedId Name;
2439+
SourceLocation EllipsisLoc;
24392440

24402441
void clear() {
2441-
TypenameLoc = TemplateKWLoc = SourceLocation();
2442+
TypenameLoc = TemplateKWLoc = EllipsisLoc = SourceLocation();
24422443
SS.clear();
24432444
Name.clear();
24442445
}
@@ -2450,9 +2451,6 @@ class Parser : public CodeCompletionHandler {
24502451
SourceLocation UsingLoc,
24512452
SourceLocation &DeclEnd,
24522453
AccessSpecifier AS = AS_none);
2453-
Decl *ParseAliasTemplate(const ParsedTemplateInfo &TemplateInfo,
2454-
SourceLocation &DeclEnd, AccessSpecifier AS,
2455-
ParsedAttributesWithRange &MisplacedAttrs1);
24562454
Decl *ParseAliasDeclarationAfterDeclarator(
24572455
const ParsedTemplateInfo &TemplateInfo, SourceLocation UsingLoc,
24582456
UsingDeclarator &D, SourceLocation &DeclEnd, AccessSpecifier AS,

Diff for: include/clang/Sema/Sema.h

+10-6
Original file line numberDiff line numberDiff line change
@@ -4324,12 +4324,15 @@ class Sema {
43244324

43254325
NamedDecl *BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
43264326
SourceLocation UsingLoc,
4327+
bool HasTypenameKeyword,
4328+
SourceLocation TypenameLoc,
43274329
CXXScopeSpec &SS,
43284330
DeclarationNameInfo NameInfo,
4331+
SourceLocation EllipsisLoc,
43294332
AttributeList *AttrList,
4330-
bool IsInstantiation,
4331-
bool HasTypenameKeyword,
4332-
SourceLocation TypenameLoc);
4333+
bool IsInstantiation);
4334+
NamedDecl *BuildUsingPackDecl(NamedDecl *InstantiatedFrom,
4335+
ArrayRef<NamedDecl *> Expansions);
43334336

43344337
bool CheckInheritingConstructorUsingDecl(UsingDecl *UD);
43354338

@@ -4343,10 +4346,11 @@ class Sema {
43434346
Decl *ActOnUsingDeclaration(Scope *CurScope,
43444347
AccessSpecifier AS,
43454348
SourceLocation UsingLoc,
4349+
SourceLocation TypenameLoc,
43464350
CXXScopeSpec &SS,
43474351
UnqualifiedId &Name,
4348-
AttributeList *AttrList,
4349-
SourceLocation TypenameLoc);
4352+
SourceLocation EllipsisLoc,
4353+
AttributeList *AttrList);
43504354
Decl *ActOnAliasDeclaration(Scope *CurScope,
43514355
AccessSpecifier AS,
43524356
MultiTemplateParamsArg TemplateParams,
@@ -6351,7 +6355,7 @@ class Sema {
63516355
///
63526356
/// \param SS The nested-name-specifier that will be traversed to find
63536357
/// unexpanded parameter packs.
6354-
void collectUnexpandedParameterPacks(CXXScopeSpec &SS,
6358+
void collectUnexpandedParameterPacks(NestedNameSpecifierLoc NNS,
63556359
SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
63566360

63576361
/// \brief Collect the set of unexpanded parameter packs within the given

Diff for: include/clang/Sema/Template.h

+5
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,11 @@ namespace clang {
515515
VarTemplateDecl *VarTemplate,
516516
VarTemplatePartialSpecializationDecl *PartialSpec);
517517
void InstantiateEnumDefinition(EnumDecl *Enum, EnumDecl *Pattern);
518+
519+
private:
520+
template<typename T>
521+
Decl *instantiateUnresolvedUsingDecl(T *D,
522+
bool InstantiatingPackElement = false);
518523
};
519524
}
520525

Diff for: include/clang/Serialization/ASTBitCodes.h

+2
Original file line numberDiff line numberDiff line change
@@ -1103,6 +1103,8 @@ namespace clang {
11031103
DECL_NAMESPACE_ALIAS,
11041104
/// \brief A UsingDecl record.
11051105
DECL_USING,
1106+
/// \brief A UsingPackDecl record.
1107+
DECL_USING_PACK,
11061108
/// \brief A UsingShadowDecl record.
11071109
DECL_USING_SHADOW,
11081110
/// \brief A ConstructorUsingShadowDecl record.

Diff for: lib/AST/DeclBase.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -651,18 +651,21 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
651651
case Typedef:
652652
case TypeAlias:
653653
case TypeAliasTemplate:
654-
case UnresolvedUsingTypename:
655654
case TemplateTypeParm:
656655
case ObjCTypeParam:
657656
return IDNS_Ordinary | IDNS_Type;
658657

658+
case UnresolvedUsingTypename:
659+
return IDNS_Ordinary | IDNS_Type | IDNS_Using;
660+
659661
case UsingShadow:
660662
return 0; // we'll actually overwrite this later
661663

662664
case UnresolvedUsingValue:
663665
return IDNS_Ordinary | IDNS_Using;
664666

665667
case Using:
668+
case UsingPack:
666669
return IDNS_Using;
667670

668671
case ObjCProtocol:

0 commit comments

Comments
 (0)