diff options
| -rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 7 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 14 | ||||
| -rw-r--r-- | clang/test/Parser/recovery.cpp | 10 |
3 files changed, 25 insertions, 6 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 8fcfcb34be2..a17fd6dbee8 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -3648,11 +3648,12 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, // if a fixed underlying type is allowed. ColonProtectionRAIIObject X(*this, AllowFixedUnderlyingType); - if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), + CXXScopeSpec Spec; + if (ParseOptionalCXXScopeSpecifier(Spec, ParsedType(), /*EnteringContext=*/true)) return; - if (SS.isSet() && Tok.isNot(tok::identifier)) { + if (Spec.isSet() && Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected) << tok::identifier; if (Tok.isNot(tok::l_brace)) { // Has no name and is not a definition. @@ -3661,6 +3662,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, return; } } + + SS = Spec; } // Must have either 'enum name' or 'enum {...}'. diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 63baaefc2fc..0a88d202b8b 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1310,11 +1310,19 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // is a base-specifier-list. ColonProtectionRAIIObject X(*this); - if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), EnteringContext)) + CXXScopeSpec Spec; + bool HasValidSpec = true; + if (ParseOptionalCXXScopeSpecifier(Spec, ParsedType(), EnteringContext)) { DS.SetTypeSpecError(); - if (SS.isSet()) - if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id)) + HasValidSpec = false; + } + if (Spec.isSet()) + if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id)) { Diag(Tok, diag::err_expected) << tok::identifier; + HasValidSpec = false; + } + if (HasValidSpec) + SS = Spec; } TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams; diff --git a/clang/test/Parser/recovery.cpp b/clang/test/Parser/recovery.cpp index e53a361dca8..bca9ace89e2 100644 --- a/clang/test/Parser/recovery.cpp +++ b/clang/test/Parser/recovery.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -verify -std=c++11 %s +// RUN: %clang_cc1 -verify -std=c++11 -fms-extensions %s 8gi///===--- recovery.cpp ---===// // expected-error {{unqualified-id}} namespace Std { // expected-note {{here}} @@ -202,3 +202,11 @@ namespace pr15133 { struct S2 :: S3 :: public S2 { // expected-error{{'public' cannot be a part of nested name specifier; did you mean ':'?}} }; } + +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}} +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}} +} |

