diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2018-02-28 03:02:23 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2018-02-28 03:02:23 +0000 |
commit | 77a9c60aa670d262d9bc98fe327067a40c3c2afc (patch) | |
tree | f613992afcd3d40fb8756bcb0e00f0105e7b78d0 /clang/lib/Parse/ParseTentative.cpp | |
parent | c1a40220b4f4983706a4509f0291bb8c2a24b8a1 (diff) | |
download | bcm5719-llvm-77a9c60aa670d262d9bc98fe327067a40c3c2afc.tar.gz bcm5719-llvm-77a9c60aa670d262d9bc98fe327067a40c3c2afc.zip |
Fix a couple of cases where we would fail to correctly parse deduced class template specialization types.
Specifically, we would not properly parse these types within template arguments
(for non-type template parameters), and in tentative parses. Fixing both of
these essentially requires that we parse deduced template specialization types
as types in all contexts, even in template argument lists -- in particular,
tentative parsing may look ahead and annotate a deduced template specialization
type before we figure out that we're actually supposed to treat the tokens as a
template-name. We deal with this by simply permitting deduced template
specialization types when parsing template arguments, and converting them to
template template arguments.
llvm-svn: 326299
Diffstat (limited to 'clang/lib/Parse/ParseTentative.cpp')
-rw-r--r-- | clang/lib/Parse/ParseTentative.cpp | 39 |
1 files changed, 31 insertions, 8 deletions
diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp index 10c084b66da..88c0e176b02 100644 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -1246,6 +1246,17 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, case ANK_TentativeDecl: return TPResult::False; case ANK_TemplateName: + // In C++17, this could be a type template for class template argument + // deduction. Try to form a type annotation for it. If we're in a + // template template argument, we'll undo this when checking the + // validity of the argument. + if (getLangOpts().CPlusPlus17) { + if (TryAnnotateTypeOrScopeToken()) + return TPResult::Error; + if (Tok.isNot(tok::identifier)) + break; + } + // A bare type template-name which can't be a template template // argument is an error, and was probably intended to be a type. return GreaterThanIsOperator ? TPResult::True : TPResult::False; @@ -1424,8 +1435,6 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, *HasMissingTypename = true; return TPResult::Ambiguous; } - - // FIXME: Fails to either revert or commit the tentative parse! } else { // Try to resolve the name. If it doesn't exist, assume it was // intended to name a type and keep disambiguating. @@ -1435,19 +1444,33 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, case ANK_TentativeDecl: return TPResult::False; case ANK_TemplateName: + // In C++17, this could be a type template for class template + // argument deduction. + if (getLangOpts().CPlusPlus17) { + if (TryAnnotateTypeOrScopeToken()) + return TPResult::Error; + if (Tok.isNot(tok::identifier)) + break; + } + // A bare type template-name which can't be a template template // argument is an error, and was probably intended to be a type. - return GreaterThanIsOperator ? TPResult::True : TPResult::False; + // In C++17, this could be class template argument deduction. + return (getLangOpts().CPlusPlus17 || GreaterThanIsOperator) + ? TPResult::True + : TPResult::False; case ANK_Unresolved: return HasMissingTypename ? TPResult::Ambiguous : TPResult::False; case ANK_Success: - // Annotated it, check again. - assert(Tok.isNot(tok::annot_cxxscope) || - NextToken().isNot(tok::identifier)); - return isCXXDeclarationSpecifier(BracedCastResult, - HasMissingTypename); + break; } + + // Annotated it, check again. + assert(Tok.isNot(tok::annot_cxxscope) || + NextToken().isNot(tok::identifier)); + return isCXXDeclarationSpecifier(BracedCastResult, + HasMissingTypename); } } return TPResult::False; |