diff options
author | Richard Smith <richard@metafoo.co.uk> | 2020-03-27 17:08:26 -0700 |
---|---|---|
committer | Richard Smith <richard@metafoo.co.uk> | 2020-03-27 17:11:04 -0700 |
commit | b3f6e3d6d64d77a9c840b8407b7e3c49b62b46dd (patch) | |
tree | e895b196f86f66c63f133bf648951ee78f75fec8 /clang/lib/Parse/ParseTentative.cpp | |
parent | 569e4f9bc99a755cc30f0102b29b1eefd4fa33b4 (diff) | |
download | llvm-b3f6e3d6d64d77a9c840b8407b7e3c49b62b46dd.zip llvm-b3f6e3d6d64d77a9c840b8407b7e3c49b62b46dd.tar.gz llvm-b3f6e3d6d64d77a9c840b8407b7e3c49b62b46dd.tar.bz2 |
Improve recovery from invalid template-ids.
Instead of bailing out of parsing when we encounter an invalid
template-name or template arguments in a template-id, produce an
annotation token describing the invalid construct.
This avoids duplicate errors and generally allows us to recover better.
In principle we should be able to extend this to store some kinds of
invalid template-id in the AST for tooling use, but that isn't handled
as part of this change.
Diffstat (limited to 'clang/lib/Parse/ParseTentative.cpp')
-rw-r--r-- | clang/lib/Parse/ParseTentative.cpp | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp index bca7d02..0c3824c 100644 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -984,10 +984,16 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract, NextToken().is(tok::kw_operator)))) && mayHaveIdentifier) { // declarator-id - if (Tok.is(tok::annot_cxxscope)) + if (Tok.is(tok::annot_cxxscope)) { + CXXScopeSpec SS; + Actions.RestoreNestedNameSpecifierAnnotation( + Tok.getAnnotationValue(), Tok.getAnnotationRange(), SS); + if (SS.isInvalid()) + return TPResult::Error; ConsumeAnnotationToken(); - else if (Tok.is(tok::identifier)) + } else if (Tok.is(tok::identifier)) { TentativelyDeclaredIdentifiers.push_back(Tok.getIdentifierInfo()); + } if (Tok.is(tok::kw_operator)) { if (TryParseOperatorId() == TPResult::Error) return TPResult::Error; @@ -1547,6 +1553,8 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, *InvalidAsDeclSpec = NextToken().is(tok::l_paren); return TPResult::Ambiguous; } + if (TemplateId->hasInvalidName()) + return TPResult::Error; if (IsPlaceholderSpecifier(TemplateId, /*Lookahead=*/0)) return TPResult::True; if (TemplateId->Kind != TNK_Type_template) @@ -1566,6 +1574,8 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, NextToken().is(tok::annot_template_id)) { TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(NextToken()); + if (TemplateId->hasInvalidName()) + return TPResult::Error; if (IsPlaceholderSpecifier(TemplateId, /*Lookahead=*/1)) return TPResult::True; } @@ -2012,17 +2022,14 @@ Parser::TryParseParameterDeclarationClause(bool *InvalidAsDeclaration, // (a) the previous parameter did, and // (b) this must be the first declaration of the function, so we can't // inherit any default arguments from elsewhere. - // If we see an ')', then we've reached the end of a - // parameter-declaration-clause, and the last param is missing its default - // argument. + // FIXME: If we reach a ')' without consuming any '>'s, then this must + // also be a function parameter (that's missing its default argument). if (VersusTemplateArgument) - return Tok.isOneOf(tok::equal, tok::r_paren) ? TPResult::True - : TPResult::False; + return Tok.is(tok::equal) ? TPResult::True : TPResult::False; if (Tok.is(tok::equal)) { // '=' assignment-expression // Parse through assignment-expression. - // FIXME: assignment-expression may contain an unparenthesized comma. if (!SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch)) return TPResult::Error; } |