Revert "Improve error recovery around colon."
This reverts commit r212957. It broke the self-host on code like this from LLVM's option library: for (auto Arg: filtered(Id0, Id1, Id2)) llvm-svn: 212965
This commit is contained in:
parent
86f6934e27
commit
c582f0137e
|
@ -2715,16 +2715,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||||
// typedef-name
|
// typedef-name
|
||||||
case tok::kw_decltype:
|
case tok::kw_decltype:
|
||||||
case tok::identifier: {
|
case tok::identifier: {
|
||||||
// This identifier can only be a typedef name if we haven't already seen
|
|
||||||
// a type-specifier. Without this check we misparse:
|
|
||||||
// typedef int X; struct Y { short X; }; as 'short int'.
|
|
||||||
if (DS.hasTypeSpecifier())
|
|
||||||
goto DoneWithDeclSpec;
|
|
||||||
|
|
||||||
// In C++, check to see if this is a scope specifier like foo::bar::, if
|
// In C++, check to see if this is a scope specifier like foo::bar::, if
|
||||||
// so handle it as such. This is important for ctor parsing.
|
// so handle it as such. This is important for ctor parsing.
|
||||||
if (getLangOpts().CPlusPlus) {
|
if (getLangOpts().CPlusPlus) {
|
||||||
if (TryAnnotateCXXScopeToken(EnteringContext)) {
|
if (TryAnnotateCXXScopeToken(EnteringContext)) {
|
||||||
|
if (!DS.hasTypeSpecifier())
|
||||||
DS.SetTypeSpecError();
|
DS.SetTypeSpecError();
|
||||||
goto DoneWithDeclSpec;
|
goto DoneWithDeclSpec;
|
||||||
}
|
}
|
||||||
|
@ -2732,6 +2727,12 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This identifier can only be a typedef name if we haven't already seen
|
||||||
|
// a type-specifier. Without this check we misparse:
|
||||||
|
// typedef int X; struct Y { short X; }; as 'short int'.
|
||||||
|
if (DS.hasTypeSpecifier())
|
||||||
|
goto DoneWithDeclSpec;
|
||||||
|
|
||||||
// Check for need to substitute AltiVec keyword tokens.
|
// Check for need to substitute AltiVec keyword tokens.
|
||||||
if (TryAltiVecToken(DS, Loc, PrevSpec, DiagID, isInvalid))
|
if (TryAltiVecToken(DS, Loc, PrevSpec, DiagID, isInvalid))
|
||||||
break;
|
break;
|
||||||
|
@ -4528,9 +4529,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
|
||||||
// Member pointers get special handling, since there's no place for the
|
// Member pointers get special handling, since there's no place for the
|
||||||
// scope spec in the generic path below.
|
// scope spec in the generic path below.
|
||||||
if (getLangOpts().CPlusPlus &&
|
if (getLangOpts().CPlusPlus &&
|
||||||
(Tok.is(tok::coloncolon) ||
|
(Tok.is(tok::coloncolon) || Tok.is(tok::identifier) ||
|
||||||
(Tok.is(tok::identifier) &&
|
|
||||||
(NextToken().is(tok::coloncolon) || NextToken().is(tok::less))) ||
|
|
||||||
Tok.is(tok::annot_cxxscope))) {
|
Tok.is(tok::annot_cxxscope))) {
|
||||||
bool EnteringContext = D.getContext() == Declarator::FileContext ||
|
bool EnteringContext = D.getContext() == Declarator::FileContext ||
|
||||||
D.getContext() == Declarator::MemberContext;
|
D.getContext() == Declarator::MemberContext;
|
||||||
|
@ -4723,11 +4722,6 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
|
||||||
DeclaratorScopeObj DeclScopeObj(*this, D.getCXXScopeSpec());
|
DeclaratorScopeObj DeclScopeObj(*this, D.getCXXScopeSpec());
|
||||||
|
|
||||||
if (getLangOpts().CPlusPlus && D.mayHaveIdentifier()) {
|
if (getLangOpts().CPlusPlus && D.mayHaveIdentifier()) {
|
||||||
// Don't parse FOO:BAR as if it were a typo for FOO::BAR inside a class, in
|
|
||||||
// this context it is a bitfield.
|
|
||||||
ColonProtectionRAIIObject X(*this,
|
|
||||||
D.getContext() == Declarator::MemberContext);
|
|
||||||
|
|
||||||
// ParseDeclaratorInternal might already have parsed the scope.
|
// ParseDeclaratorInternal might already have parsed the scope.
|
||||||
if (D.getCXXScopeSpec().isEmpty()) {
|
if (D.getCXXScopeSpec().isEmpty()) {
|
||||||
bool EnteringContext = D.getContext() == Declarator::FileContext ||
|
bool EnteringContext = D.getContext() == Declarator::FileContext ||
|
||||||
|
|
|
@ -1239,8 +1239,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
|
||||||
// Parse the (optional) nested-name-specifier.
|
// Parse the (optional) nested-name-specifier.
|
||||||
CXXScopeSpec &SS = DS.getTypeSpecScope();
|
CXXScopeSpec &SS = DS.getTypeSpecScope();
|
||||||
if (getLangOpts().CPlusPlus) {
|
if (getLangOpts().CPlusPlus) {
|
||||||
// "FOO : BAR" is not a potential typo for "FOO::BAR". In this context it
|
// "FOO : BAR" is not a potential typo for "FOO::BAR".
|
||||||
// is a base-specifier-list.
|
|
||||||
ColonProtectionRAIIObject X(*this);
|
ColonProtectionRAIIObject X(*this);
|
||||||
|
|
||||||
if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), EnteringContext))
|
if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), EnteringContext))
|
||||||
|
@ -1927,8 +1926,14 @@ void Parser::ParseCXXMemberDeclaratorBeforeInitializer(
|
||||||
// declarator pure-specifier[opt]
|
// declarator pure-specifier[opt]
|
||||||
// declarator brace-or-equal-initializer[opt]
|
// declarator brace-or-equal-initializer[opt]
|
||||||
// identifier[opt] ':' constant-expression
|
// identifier[opt] ':' constant-expression
|
||||||
if (Tok.isNot(tok::colon))
|
if (Tok.isNot(tok::colon)) {
|
||||||
|
// Don't parse FOO:BAR as if it were a typo for FOO::BAR, in this context it
|
||||||
|
// is a bitfield.
|
||||||
|
// FIXME: This should only apply when parsing the id-expression (see
|
||||||
|
// PR18587).
|
||||||
|
ColonProtectionRAIIObject X(*this);
|
||||||
ParseDeclarator(DeclaratorInfo);
|
ParseDeclarator(DeclaratorInfo);
|
||||||
|
}
|
||||||
|
|
||||||
if (!DeclaratorInfo.isFunctionDeclarator() && TryConsumeToken(tok::colon)) {
|
if (!DeclaratorInfo.isFunctionDeclarator() && TryConsumeToken(tok::colon)) {
|
||||||
BitfieldSize = ParseConstantExpression();
|
BitfieldSize = ParseConstantExpression();
|
||||||
|
@ -2010,14 +2015,6 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turn on colon protection early, while parsing declspec, although there is
|
|
||||||
// nothing to protect there. It prevents from false errors if error recovery
|
|
||||||
// incorrectly determines where the declspec ends, as in the example:
|
|
||||||
// struct A { enum class B { C }; };
|
|
||||||
// const int C = 4;
|
|
||||||
// struct D { A::B : C; };
|
|
||||||
ColonProtectionRAIIObject X(*this);
|
|
||||||
|
|
||||||
// Access declarations.
|
// Access declarations.
|
||||||
bool MalformedTypeSpec = false;
|
bool MalformedTypeSpec = false;
|
||||||
if (!TemplateInfo.Kind &&
|
if (!TemplateInfo.Kind &&
|
||||||
|
@ -2131,11 +2128,13 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
|
||||||
if (MalformedTypeSpec)
|
if (MalformedTypeSpec)
|
||||||
DS.SetTypeSpecError();
|
DS.SetTypeSpecError();
|
||||||
|
|
||||||
|
{
|
||||||
|
// Don't parse FOO:BAR as if it were a typo for FOO::BAR, in this context it
|
||||||
|
// is a bitfield.
|
||||||
|
ColonProtectionRAIIObject X(*this);
|
||||||
ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class,
|
ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class,
|
||||||
&CommonLateParsedAttrs);
|
&CommonLateParsedAttrs);
|
||||||
|
}
|
||||||
// Turn off colon protection that was set for declspec.
|
|
||||||
X.restore();
|
|
||||||
|
|
||||||
// If we had a free-standing type definition with a missing semicolon, we
|
// If we had a free-standing type definition with a missing semicolon, we
|
||||||
// may get this far before the problem becomes obvious.
|
// may get this far before the problem becomes obvious.
|
||||||
|
|
|
@ -16,15 +16,3 @@ struct Y {
|
||||||
enum E : int(2);
|
enum E : int(2);
|
||||||
enum E : Z(); // expected-error{{integral constant expression must have integral or unscoped enumeration type, not 'Z'}}
|
enum E : Z(); // expected-error{{integral constant expression must have integral or unscoped enumeration type, not 'Z'}}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace pr18587 {
|
|
||||||
struct A {
|
|
||||||
enum class B {
|
|
||||||
C
|
|
||||||
};
|
|
||||||
};
|
|
||||||
const int C = 4;
|
|
||||||
struct D {
|
|
||||||
A::B : C;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
|
@ -311,102 +311,3 @@ namespace N {
|
||||||
|
|
||||||
namespace TypedefNamespace { typedef int F; };
|
namespace TypedefNamespace { typedef int F; };
|
||||||
TypedefNamespace::F::NonexistentName BadNNSWithCXXScopeSpec; // expected-error {{'F' (aka 'int') is not a class, namespace, or scoped enumeration}}
|
TypedefNamespace::F::NonexistentName BadNNSWithCXXScopeSpec; // expected-error {{'F' (aka 'int') is not a class, namespace, or scoped enumeration}}
|
||||||
|
|
||||||
namespace PR18587 {
|
|
||||||
|
|
||||||
struct C1 {
|
|
||||||
int a, b, c;
|
|
||||||
typedef int C2;
|
|
||||||
struct B1 {
|
|
||||||
struct B2 {
|
|
||||||
int a, b, c;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
struct C2 { static const unsigned N1 = 1; };
|
|
||||||
struct B1 {
|
|
||||||
enum E1 { B2 = 2 };
|
|
||||||
static const int B3 = 3;
|
|
||||||
};
|
|
||||||
const int N1 = 2;
|
|
||||||
|
|
||||||
// Function declarators
|
|
||||||
struct S1a { int f(C1::C2); };
|
|
||||||
struct S1b { int f(C1:C2); }; // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
|
|
||||||
|
|
||||||
struct S2a {
|
|
||||||
C1::C2 f(C1::C2);
|
|
||||||
};
|
|
||||||
struct S2c {
|
|
||||||
C1::C2 f(C1:C2); // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct S3a {
|
|
||||||
int f(C1::C2), C2 : N1;
|
|
||||||
int g : B1::B2;
|
|
||||||
};
|
|
||||||
struct S3b {
|
|
||||||
int g : B1:B2; // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Inside square brackets
|
|
||||||
struct S4a {
|
|
||||||
int f[C2::N1];
|
|
||||||
};
|
|
||||||
struct S4b {
|
|
||||||
int f[C2:N1]; // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct S5a {
|
|
||||||
int f(int xx[B1::B3 ? C2::N1 : B1::B2]);
|
|
||||||
};
|
|
||||||
struct S5b {
|
|
||||||
int f(int xx[B1::B3 ? C2::N1 : B1:B2]); // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
|
|
||||||
};
|
|
||||||
struct S5c {
|
|
||||||
int f(int xx[B1:B3 ? C2::N1 : B1::B2]); // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Bit fields
|
|
||||||
struct S6a {
|
|
||||||
C1::C2 m1 : B1::B2;
|
|
||||||
};
|
|
||||||
struct S6c {
|
|
||||||
C1::C2 m1 : B1:B2; // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
|
|
||||||
};
|
|
||||||
struct S6d {
|
|
||||||
int C2:N1;
|
|
||||||
};
|
|
||||||
struct S6e {
|
|
||||||
static const int N = 3;
|
|
||||||
B1::E1 : N;
|
|
||||||
};
|
|
||||||
struct S6g {
|
|
||||||
C1::C2 : B1:B2; // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
|
|
||||||
B1::E1 : B1:B2; // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Template parameters
|
|
||||||
template <int N> struct T1 {
|
|
||||||
int a,b,c;
|
|
||||||
static const unsigned N1 = N;
|
|
||||||
typedef unsigned C1;
|
|
||||||
};
|
|
||||||
T1<C2::N1> var_1a;
|
|
||||||
T1<C2:N1> var_1b; // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
|
|
||||||
template<int N> int F() {}
|
|
||||||
int (*X1)() = (B1::B2 ? F<1> : F<2>);
|
|
||||||
int (*X2)() = (B1:B2 ? F<1> : F<2>); // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
|
|
||||||
|
|
||||||
// Bit fields + templates
|
|
||||||
struct S7a {
|
|
||||||
T1<B1::B2>::C1 m1 : T1<B1::B2>::N1;
|
|
||||||
};
|
|
||||||
struct S7b {
|
|
||||||
T1<B1:B2>::C1 m1 : T1<B1::B2>::N1; // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
|
|
||||||
};
|
|
||||||
struct S7c {
|
|
||||||
T1<B1::B2>::C1 m1 : T1<B1:B2>::N1; // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue