diff options
author | Serge Pavlov <sepavloff@gmail.com> | 2014-07-16 05:16:52 +0000 |
---|---|---|
committer | Serge Pavlov <sepavloff@gmail.com> | 2014-07-16 05:16:52 +0000 |
commit | 458ea76041ba41d61869543939274ebe296ac85a (patch) | |
tree | 5b19ed6faa88e6037a159ded2985a608cf3da919 /clang/lib/Parse/ParseDecl.cpp | |
parent | c68237bc2c7283f9cc62593b3dd8e30562014400 (diff) | |
download | bcm5719-llvm-458ea76041ba41d61869543939274ebe296ac85a.tar.gz bcm5719-llvm-458ea76041ba41d61869543939274ebe296ac85a.zip |
Improve error recovery around colon.
Recognize additional cases, when '::' is mistyped as ':'.
This is a fix to RP18587 - colons have too much protection in member-declarations
Review is tracked by http://reviews.llvm.org/D3653.
This is an attempt to recommit the fix, initially committed as r212957 but then
reverted in r212965 as it broke self-build. In the updated patch ParseDirectDeclarator
turns on colon protection in for context as well.
llvm-svn: 213120
Diffstat (limited to 'clang/lib/Parse/ParseDecl.cpp')
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 09f78e5a755..a8fab8396b9 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -2715,24 +2715,23 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // 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)) { - if (!DS.hasTypeSpecifier()) - DS.SetTypeSpecError(); + 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; @@ -4529,7 +4528,9 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // 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) || + (Tok.is(tok::coloncolon) || + (Tok.is(tok::identifier) && + (NextToken().is(tok::coloncolon) || NextToken().is(tok::less))) || Tok.is(tok::annot_cxxscope))) { bool EnteringContext = D.getContext() == Declarator::FileContext || D.getContext() == Declarator::MemberContext; @@ -4722,6 +4723,14 @@ void Parser::ParseDirectDeclarator(Declarator &D) { 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. Also in range-based for statement colon + // may delimit for-range-declaration. + ColonProtectionRAIIObject X(*this, + D.getContext() == Declarator::MemberContext || + (D.getContext() == Declarator::ForContext && + getLangOpts().CPlusPlus11)); + // ParseDeclaratorInternal might already have parsed the scope. if (D.getCXXScopeSpec().isEmpty()) { bool EnteringContext = D.getContext() == Declarator::FileContext || |