Recover properly if a class member declaration starts with a scope specifier

or template-id which can't be parsed.

llvm-svn: 156468
This commit is contained in:
Richard Smith 2012-05-09 08:23:23 +00:00
parent 28540adfcf
commit 45855df4c6
4 changed files with 14 additions and 10 deletions

View File

@ -1704,12 +1704,16 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
}
// Access declarations.
bool MalformedTypeSpec = false;
if (!TemplateInfo.Kind &&
(Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) &&
!TryAnnotateCXXScopeToken() &&
Tok.is(tok::annot_cxxscope)) {
bool isAccessDecl = false;
if (NextToken().is(tok::identifier))
(Tok.is(tok::identifier) || Tok.is(tok::coloncolon))) {
if (TryAnnotateCXXScopeToken())
MalformedTypeSpec = true;
bool isAccessDecl;
if (Tok.isNot(tok::annot_cxxscope))
isAccessDecl = false;
else if (NextToken().is(tok::identifier))
isAccessDecl = GetLookAheadToken(2).is(tok::semi);
else
isAccessDecl = NextToken().is(tok::kw_operator);
@ -1806,6 +1810,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// Parse the common declaration-specifiers piece.
ParsingDeclSpec DS(*this, TemplateDiags);
DS.takeAttributesFrom(attrs);
if (MalformedTypeSpec)
DS.SetTypeSpecError();
ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class,
&CommonLateParsedAttrs);

View File

@ -1420,8 +1420,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) {
/// TryAnnotateScopeToken - Like TryAnnotateTypeOrScopeToken but only
/// annotates C++ scope specifiers and template-ids. This returns
/// true if the token was annotated or there was an error that could not be
/// recovered from.
/// true if there was an error that could not be recovered from.
///
/// Note that this routine emits an error if you call it with ::new or ::delete
/// as the current tokens, so only call it in contexts where these are invalid.

View File

@ -28,7 +28,7 @@ template<> struct T<2> { template<int C, int D> using B = int; };
const int C = 0, D = 0;
struct S {
int as[] = { decltype(x)::B<C, D>(0) }; // expected-error {{array bound cannot be deduced from an in-class initializer}}
T<sizeof(as) / sizeof(int)> x; // expected-error {{requires a type specifier}}
T<sizeof(as) / sizeof(int)> x;
// test that we handle invalid array bound deductions without crashing when the declarator name is itself invalid
operator int[](){}; // expected-error {{'operator int' cannot be the name of a variable or data member}} \
// expected-error {{array bound cannot be deduced from an in-class initializer}}

View File

@ -32,8 +32,7 @@ namespace PR6031 {
template <class TT>
struct FI2
{
C<typename FI2::type> a; // expected-error{{no type named 'type' in 'FI2<TT>'}} \
// expected-error{{C++ requires a type specifier for all declarations}}
C<typename FI2::type> a; // expected-error{{no type named 'type' in 'FI2<TT>'}}
};
template<typename T>