r212965 - Revert "Improve error recovery around colon."
Reid Kleckner
reid at kleckner.net
Mon Jul 14 11:19:58 PDT 2014
Author: rnk
Date: Mon Jul 14 13:19:58 2014
New Revision: 212965
URL: http://llvm.org/viewvc/llvm-project?rev=212965&view=rev
Log:
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))
Modified:
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/ParseDeclCXX.cpp
cfe/trunk/test/SemaCXX/enum-bitfield.cpp
cfe/trunk/test/SemaCXX/nested-name-spec.cpp
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=212965&r1=212964&r2=212965&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Mon Jul 14 13:19:58 2014
@@ -2715,23 +2715,24 @@ void Parser::ParseDeclarationSpecifiers(
// typedef-name
case tok::kw_decltype:
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
// so handle it as such. This is important for ctor parsing.
if (getLangOpts().CPlusPlus) {
if (TryAnnotateCXXScopeToken(EnteringContext)) {
- DS.SetTypeSpecError();
+ if (!DS.hasTypeSpecifier())
+ DS.SetTypeSpecError();
goto DoneWithDeclSpec;
}
if (!Tok.is(tok::identifier))
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.
if (TryAltiVecToken(DS, Loc, PrevSpec, DiagID, isInvalid))
break;
@@ -4528,9 +4529,7 @@ void Parser::ParseDeclaratorInternal(Dec
// Member pointers get special handling, since there's no place for the
// scope spec in the generic path below.
if (getLangOpts().CPlusPlus &&
- (Tok.is(tok::coloncolon) ||
- (Tok.is(tok::identifier) &&
- (NextToken().is(tok::coloncolon) || NextToken().is(tok::less))) ||
+ (Tok.is(tok::coloncolon) || Tok.is(tok::identifier) ||
Tok.is(tok::annot_cxxscope))) {
bool EnteringContext = D.getContext() == Declarator::FileContext ||
D.getContext() == Declarator::MemberContext;
@@ -4723,11 +4722,6 @@ void Parser::ParseDirectDeclarator(Decla
DeclaratorScopeObj DeclScopeObj(*this, D.getCXXScopeSpec());
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.
if (D.getCXXScopeSpec().isEmpty()) {
bool EnteringContext = D.getContext() == Declarator::FileContext ||
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=212965&r1=212964&r2=212965&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Mon Jul 14 13:19:58 2014
@@ -1239,8 +1239,7 @@ void Parser::ParseClassSpecifier(tok::To
// Parse the (optional) nested-name-specifier.
CXXScopeSpec &SS = DS.getTypeSpecScope();
if (getLangOpts().CPlusPlus) {
- // "FOO : BAR" is not a potential typo for "FOO::BAR". In this context it
- // is a base-specifier-list.
+ // "FOO : BAR" is not a potential typo for "FOO::BAR".
ColonProtectionRAIIObject X(*this);
if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), EnteringContext))
@@ -1927,8 +1926,14 @@ void Parser::ParseCXXMemberDeclaratorBef
// declarator pure-specifier[opt]
// declarator brace-or-equal-initializer[opt]
// 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);
+ }
if (!DeclaratorInfo.isFunctionDeclarator() && TryConsumeToken(tok::colon)) {
BitfieldSize = ParseConstantExpression();
@@ -2010,14 +2015,6 @@ void Parser::ParseCXXClassMemberDeclarat
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.
bool MalformedTypeSpec = false;
if (!TemplateInfo.Kind &&
@@ -2131,11 +2128,13 @@ void Parser::ParseCXXClassMemberDeclarat
if (MalformedTypeSpec)
DS.SetTypeSpecError();
- ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class,
- &CommonLateParsedAttrs);
-
- // Turn off colon protection that was set for declspec.
- X.restore();
+ {
+ // 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,
+ &CommonLateParsedAttrs);
+ }
// If we had a free-standing type definition with a missing semicolon, we
// may get this far before the problem becomes obvious.
Modified: cfe/trunk/test/SemaCXX/enum-bitfield.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/enum-bitfield.cpp?rev=212965&r1=212964&r2=212965&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/enum-bitfield.cpp (original)
+++ cfe/trunk/test/SemaCXX/enum-bitfield.cpp Mon Jul 14 13:19:58 2014
@@ -16,15 +16,3 @@ struct Y {
enum E : int(2);
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;
-};
-}
Modified: cfe/trunk/test/SemaCXX/nested-name-spec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/nested-name-spec.cpp?rev=212965&r1=212964&r2=212965&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/nested-name-spec.cpp (original)
+++ cfe/trunk/test/SemaCXX/nested-name-spec.cpp Mon Jul 14 13:19:58 2014
@@ -311,102 +311,3 @@ namespace N {
namespace TypedefNamespace { typedef int F; };
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 '::'?}}
-};
-
-}
More information about the cfe-commits
mailing list