forked from OSchip/llvm-project
[Clang] Avoid crashes when parsing using enum declarations
In Parser::ParseUsingDeclaration(...) when we call ParseEnumSpecifier(...) it is not calling SetTypeSpecError() on DS when it detects an error. That means that DS is left set to TST_unspecified. When we then pass DS into Sema::ActOnUsingEnumDeclaration(...) we hit an llvm_unreachable(...) since it expects it to be one of three states TST_error, TST_enum or TST_typename. This fixes https://github.com/llvm/llvm-project/issues/57347 Differential Revision: https://reviews.llvm.org/D132695
This commit is contained in:
parent
44a06b51b2
commit
aa7ce60536
|
@ -4647,6 +4647,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
|
|||
|
||||
if (Spec.isSet() && Tok.isNot(tok::identifier)) {
|
||||
Diag(Tok, diag::err_expected) << tok::identifier;
|
||||
DS.SetTypeSpecError();
|
||||
if (Tok.isNot(tok::l_brace)) {
|
||||
// Has no name and is not a definition.
|
||||
// Skip the rest of this declarator, up until the comma or semicolon.
|
||||
|
@ -4663,6 +4664,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
|
|||
Tok.isNot(tok::colon)) {
|
||||
Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_brace;
|
||||
|
||||
DS.SetTypeSpecError();
|
||||
// Skip the rest of this declarator, up until the comma or semicolon.
|
||||
SkipUntil(tok::comma, StopAtSemi);
|
||||
return;
|
||||
|
@ -4838,6 +4840,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
|
|||
if (!Name && TUK != Sema::TUK_Definition) {
|
||||
Diag(Tok, diag::err_enumerator_unnamed_no_def);
|
||||
|
||||
DS.SetTypeSpecError();
|
||||
// Skip the rest of this declarator, up until the comma or semicolon.
|
||||
SkipUntil(tok::comma, StopAtSemi);
|
||||
return;
|
||||
|
|
|
@ -4,4 +4,4 @@
|
|||
// will necessarily be ill-formed as a trailing return type for a function
|
||||
// definition), and recover with a "type cannot be defined in a trailing return
|
||||
// type" error.
|
||||
auto j() -> enum { e3 }; // expected-error{{unnamed enumeration must be a definition}} expected-error {{expected a type}}
|
||||
auto j() -> enum { e3 }; // expected-error{{unnamed enumeration must be a definition}}
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace dr301 { // dr301: yes
|
|||
typename T::template operator+<int> a; // expected-error {{typename specifier refers to a non-type template}} expected-error +{{}}
|
||||
// FIXME: This shouldn't say (null).
|
||||
class T::template operator+<int> b; // expected-error {{identifier followed by '<' indicates a class template specialization but (null) refers to a function template}}
|
||||
enum T::template operator+<int> c; // expected-error {{expected identifier}} expected-error {{does not declare anything}}
|
||||
enum T::template operator+<int> c; // expected-error {{expected identifier}}
|
||||
enum T::template operator+<int>::E d; // expected-error {{qualified name refers into a specialization of function template 'T::template operator +'}} expected-error {{forward reference}}
|
||||
enum T::template X<int>::E e;
|
||||
T::template operator+<int>::foobar(); // expected-error {{qualified name refers into a specialization of function template 'T::template operator +'}}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
// RUN: %clang_cc1 -std=c++20 -verify %s
|
||||
|
||||
namespace GH57347 {
|
||||
namespace A {}
|
||||
|
||||
void f() {
|
||||
using enum A::+; // expected-error {{expected identifier}}
|
||||
using enum; // expected-error {{expected identifier or '{'}}
|
||||
using enum class; // expected-error {{expected identifier or '{'}}
|
||||
using enum : blah; // expected-error {{unknown type name 'blah'}} expected-error {{unnamed enumeration must be a definition}}
|
||||
}
|
||||
}
|
|
@ -209,7 +209,7 @@ namespace pr15133 {
|
|||
namespace InvalidEmptyNames {
|
||||
// These shouldn't crash, the diagnostics aren't important.
|
||||
struct ::, struct ::; // expected-error 2 {{expected identifier}} expected-error 2 {{declaration of anonymous struct must be a definition}} expected-warning {{declaration does not declare anything}}
|
||||
enum ::, enum ::; // expected-error 2 {{expected identifier}} expected-warning {{declaration does not declare anything}}
|
||||
enum ::, enum ::; // expected-error 2 {{expected identifier}}
|
||||
struct ::__super, struct ::__super; // expected-error 2 {{expected identifier}} expected-error 2 {{expected '::' after '__super'}}
|
||||
struct ::template foo, struct ::template bar; // expected-error 2 {{expected identifier}} expected-error 2 {{declaration of anonymous struct must be a definition}} expected-warning {{declaration does not declare anything}}
|
||||
struct ::foo struct::; // expected-error {{no struct named 'foo' in the global namespace}} expected-error {{expected identifier}} expected-error {{declaration of anonymous struct must be a definition}}
|
||||
|
|
|
@ -160,7 +160,7 @@ struct EnumRedeclStruct {
|
|||
} e;
|
||||
};
|
||||
|
||||
enum struct GH42372_1 { // expected-error {{expected identifier or '{'}} expected-warning {{declaration does not declare anything}}
|
||||
enum struct GH42372_1 { // expected-error {{expected identifier or '{'}}
|
||||
One
|
||||
};
|
||||
|
||||
|
|
|
@ -432,7 +432,7 @@ namespace nested_name {
|
|||
a<int>::b c; // expected-error {{qualified name refers into a specialization of variable template 'a'}}
|
||||
|
||||
class a<int> {}; // expected-error {{identifier followed by '<' indicates a class template specialization but 'a' refers to a variable template}}
|
||||
enum a<int> {}; // expected-error {{expected identifier or '{'}} expected-warning {{does not declare anything}}
|
||||
enum a<int> {}; // expected-error {{expected identifier or '{'}}
|
||||
}
|
||||
|
||||
namespace PR18530 {
|
||||
|
|
|
@ -114,8 +114,7 @@ enum : long {
|
|||
long_enum_val = 10000
|
||||
};
|
||||
|
||||
enum : long x; // expected-error{{unnamed enumeration must be a definition}} \
|
||||
// expected-warning{{declaration does not declare anything}}
|
||||
enum : long x; // expected-error{{unnamed enumeration must be a definition}}
|
||||
|
||||
void PR9333() {
|
||||
enum class scoped_enum { yes, no, maybe };
|
||||
|
|
Loading…
Reference in New Issue