Skip to content

Commit

Permalink
Implement 'using-enum-declaration' with splices.
Browse files Browse the repository at this point in the history
To implement this, splits 'ActOnUsingEnumDeclaration' into two
overloads: One which acts on an identifier, and one which acts directly
on an already known type.

Closes issue #3.
  • Loading branch information
katzdm committed Mar 16, 2024
1 parent c25fdbd commit 704c44e
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 0 deletions.
5 changes: 5 additions & 0 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -4150,6 +4150,11 @@ class Sema final {
SourceLocation EnumLoc,
SourceLocation IdentLoc, IdentifierInfo &II,
CXXScopeSpec *SS = nullptr);
Decl *ActOnUsingEnumDeclaration(Scope *CurScope, AccessSpecifier AS,
SourceLocation UsingLoc,
SourceLocation EnumLoc,
SourceLocation IdentLoc, QualType EnumTy,
TypeSourceInfo *TSI);
Decl *ActOnAliasDeclaration(Scope *CurScope, AccessSpecifier AS,
MultiTemplateParamsArg TemplateParams,
SourceLocation UsingLoc, UnqualifiedId &Name,
Expand Down
26 changes: 26 additions & 0 deletions clang/lib/Parse/ParseDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,32 @@ Parser::DeclGroupPtrTy Parser::ParseUsingDeclaration(
return nullptr;
}

if (Tok.is(tok::annot_splice)) {
SourceLocation SpliceLoc = Tok.getLocation();
TypeResult TR = ParseCXXSpliceAsType(/*AllowDependent=*/true,
/*Complain=*/true);
if (TR.isInvalid()) {
SkipUntil(tok::semi);
return nullptr;
}
TypeSourceInfo *TSI;
QualType EnumTy = Actions.GetTypeFromParser(TR.get(), &TSI);
if (EnumTy.isNull()) {
SkipUntil(tok::semi);
return nullptr;
}

Decl *UED = Actions.ActOnUsingEnumDeclaration(getCurScope(), AS, UsingLoc,
UELoc, SpliceLoc, EnumTy,
TSI);
if (!UED) {
SkipUntil(tok::semi);
return nullptr;
}

return Actions.ConvertDeclToDeclGroup(UED);
}

if (!Tok.is(tok::identifier)) {
Diag(Tok.getLocation(), diag::err_using_enum_expect_identifier)
<< Tok.is(tok::kw_enum);
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/Sema/SemaDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12466,6 +12466,16 @@ Decl *Sema::ActOnUsingEnumDeclaration(Scope *S, AccessSpecifier AS,
return nullptr;
}

return ActOnUsingEnumDeclaration(S, AS, UsingLoc, EnumLoc, IdentLoc, EnumTy,
TSI);
}

Decl *Sema::ActOnUsingEnumDeclaration(Scope *S, AccessSpecifier AS,
SourceLocation UsingLoc,
SourceLocation EnumLoc,
SourceLocation IdentLoc,
QualType EnumTy,
TypeSourceInfo *TSI) {
auto *Enum = dyn_cast_if_present<EnumDecl>(EnumTy->getAsTagDecl());
if (!Enum) {
Diag(IdentLoc, diag::err_using_enum_not_enum) << EnumTy;
Expand Down
14 changes: 14 additions & 0 deletions clang/test/Reflection/splice-types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,20 @@ static_assert(static_cast<Enum>([:rEnumCls:]::B) == [:rEnum:]::B);
// Splicing of a dependent reflection of an enum class.
template <info R> consteval int bval() { return int([:R:]::B); }
static_assert(bval<^Enum>() == bval<^EnumCls>());

// using-enum-declaration with a splice.
namespace {
using enum [:rEnumCls:];
static_assert(int(C) == 2);
} // namespace

// using-enum-declaration with a qualified-id having a splice as the leading
// nested-name-specifier.
namespace {
constexpr auto rns = ^with_enum_types;
using enum [:rns:]::EnumCls;
static_assert(int(B) == 1);
} // namespace
} // namespace with_enum_types

// ===================
Expand Down

0 comments on commit 704c44e

Please sign in to comment.