forked from OSchip/llvm-project
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:
parent
28540adfcf
commit
45855df4c6
|
@ -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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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}}
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue