summaryrefslogtreecommitdiffstats
path: root/clang/lib/Parse/ParseTentative.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2018-02-28 03:02:23 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2018-02-28 03:02:23 +0000
commit77a9c60aa670d262d9bc98fe327067a40c3c2afc (patch)
treef613992afcd3d40fb8756bcb0e00f0105e7b78d0 /clang/lib/Parse/ParseTentative.cpp
parentc1a40220b4f4983706a4509f0291bb8c2a24b8a1 (diff)
downloadbcm5719-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.cpp39
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;
OpenPOWER on IntegriCloud