-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang] Implement CWG2877 "Type-only lookup for using-enum-declarator" #95399
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a7b6a8b
38fd3ff
40ad680
d6868d3
c19bc28
2cc8a66
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -692,7 +692,7 @@ bool Parser::ParseUsingDeclarator(DeclaratorContext Context, | |
/// using-enum-declaration: [C++20, dcl.enum] | ||
/// 'using' elaborated-enum-specifier ; | ||
/// The terminal name of the elaborated-enum-specifier undergoes | ||
/// ordinary lookup | ||
/// type-only lookup | ||
/// | ||
/// elaborated-enum-specifier: | ||
/// 'enum' nested-name-specifier[opt] identifier | ||
|
@@ -724,7 +724,7 @@ Parser::DeclGroupPtrTy Parser::ParseUsingDeclaration( | |
/*ObectHasErrors=*/false, | ||
/*EnteringConttext=*/false, | ||
/*MayBePseudoDestructor=*/nullptr, | ||
/*IsTypename=*/false, | ||
/*IsTypename=*/true, | ||
/*IdentifierInfo=*/nullptr, | ||
/*OnlyNamespace=*/false, | ||
/*InUsingDeclaration=*/true)) { | ||
|
@@ -738,16 +738,49 @@ Parser::DeclGroupPtrTy Parser::ParseUsingDeclaration( | |
return nullptr; | ||
} | ||
|
||
if (!Tok.is(tok::identifier)) { | ||
Decl *UED = nullptr; | ||
|
||
// FIXME: identifier and annot_template_id handling is very similar to | ||
// ParseBaseTypeSpecifier. It should be factored out into a function. | ||
if (Tok.is(tok::identifier)) { | ||
IdentifierInfo *IdentInfo = Tok.getIdentifierInfo(); | ||
SourceLocation IdentLoc = ConsumeToken(); | ||
|
||
ParsedType Type = Actions.getTypeName( | ||
*IdentInfo, IdentLoc, getCurScope(), &SS, /*isClassName=*/true, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note that |
||
/*HasTrailingDot=*/false, | ||
/*ObjectType=*/nullptr, /*IsCtorOrDtorName=*/false, | ||
/*WantNontrivialTypeSourceInfo=*/true); | ||
|
||
UED = Actions.ActOnUsingEnumDeclaration( | ||
getCurScope(), AS, UsingLoc, UELoc, IdentLoc, *IdentInfo, Type, &SS); | ||
} else if (Tok.is(tok::annot_template_id)) { | ||
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); | ||
|
||
if (TemplateId->mightBeType()) { | ||
AnnotateTemplateIdTokenAsType(SS, ImplicitTypenameContext::No, | ||
/*IsClassName=*/true); | ||
|
||
assert(Tok.is(tok::annot_typename) && "template-id -> type failed"); | ||
TypeResult Type = getTypeAnnotation(Tok); | ||
SourceRange Loc = Tok.getAnnotationRange(); | ||
ConsumeAnnotationToken(); | ||
|
||
UED = Actions.ActOnUsingEnumDeclaration(getCurScope(), AS, UsingLoc, | ||
UELoc, Loc, *TemplateId->Name, | ||
Type.get(), &SS); | ||
} else { | ||
Diag(Tok.getLocation(), diag::err_using_enum_not_enum) | ||
<< TemplateId->Name->getName() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This leads to suboptimal diagnostic when e.g. variable template is put after There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't do it for base specifier, so i think this is fine (I suspect improvements would be a bit difficult, maybe by calling There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Looks like |
||
<< SourceRange(TemplateId->TemplateNameLoc, TemplateId->RAngleLoc); | ||
} | ||
} else { | ||
Diag(Tok.getLocation(), diag::err_using_enum_expect_identifier) | ||
<< Tok.is(tok::kw_enum); | ||
SkipUntil(tok::semi); | ||
return nullptr; | ||
} | ||
IdentifierInfo *IdentInfo = Tok.getIdentifierInfo(); | ||
SourceLocation IdentLoc = ConsumeToken(); | ||
Decl *UED = Actions.ActOnUsingEnumDeclaration( | ||
getCurScope(), AS, UsingLoc, UELoc, IdentLoc, *IdentInfo, &SS); | ||
|
||
if (!UED) { | ||
SkipUntil(tok::semi); | ||
return nullptr; | ||
|
@@ -1403,6 +1436,8 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, | |
} | ||
|
||
// Check whether we have a template-id that names a type. | ||
// FIXME: identifier and annot_template_id handling in ParseUsingDeclaration | ||
// work very similarly. It should be refactored into a separate function. | ||
if (Tok.is(tok::annot_template_id)) { | ||
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); | ||
if (TemplateId->mightBeType()) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -148,13 +148,10 @@ template <int I> struct C { | |
enum class D { d, | ||
e, | ||
f }; | ||
using enum D; | ||
|
||
static constexpr int W = int(f) + I; | ||
using enum D; // expected-error {{using-enum cannot name a dependent type}} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like we always got this wrong, did this fix just fall out of the implementation? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. I first implemented the DR, ran the tests, and this one failed. Then I realized that this test was incorrect. |
||
}; | ||
|
||
static_assert(C<2>::V == 4); | ||
static_assert(C<20>::W == 22); | ||
|
||
} // namespace Seven | ||
|
||
|
@@ -241,6 +238,13 @@ TPLa<int> a; | |
|
||
} // namespace Thirteen | ||
|
||
namespace Fourteen { | ||
template<typename T> | ||
int A = T(); | ||
|
||
using enum A<int>; // expected-error {{A is not an enumerated type}} | ||
} // namespace Fourteen | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. If you look at the rest of the file, you'll see tests |
||
|
||
namespace GH58057 { | ||
struct Wrap { | ||
enum Things { | ||
|
Uh oh!
There was an error while loading. Please reload this page.