Teach the type-id/expression disambiguator about different
disambiguation contexts, so that we properly parse template arguments
such as
A<int()>
as type-ids rather than as expressions. Since this can be confusing
(especially when the template parameter is a non-type template
parameter), we try to give a friendly error message.
Almost, eliminate a redundant error message (that should have been a
note) and add some ultra-basic checks for non-type template
arguments.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64189 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
index 445dd8b..06c136d 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -270,16 +270,24 @@
return TPR == TPResult::True();
}
-/// isCXXTypeIdInParens - Assumes that a '(' was parsed and now we want to
-/// know whether the parens contain an expression or a type-id.
-/// Returns true for a type-id and false for an expression.
-/// If during the disambiguation process a parsing error is encountered,
-/// the function returns true to let the declaration parsing code handle it.
-///
-/// type-id:
-/// type-specifier-seq abstract-declarator[opt]
-///
-bool Parser::isCXXTypeIdInParens() {
+ /// \brief Determine whether the next set of tokens contains a type-id.
+ ///
+ /// The context parameter states what context we're parsing right
+ /// now, which affects how this routine copes with the token
+ /// following the type-id. If the context is TypeIdInParens, we have
+ /// already parsed the '(' and we will cease lookahead when we hit
+ /// the corresponding ')'. If the context is
+ /// TypeIdAsTemplateArgument, we've already parsed the '<' or ','
+ /// before this template argument, and will cease lookahead when we
+ /// hit a '>', '>>' (in C++0x), or ','. Returns true for a type-id
+ /// and false for an expression. If during the disambiguation
+ /// process a parsing error is encountered, the function returns
+ /// true to let the declaration parsing code handle it.
+ ///
+ /// type-id:
+ /// type-specifier-seq abstract-declarator[opt]
+ ///
+bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context) {
// C++ 8.2p2:
// The ambiguity arising from the similarity between a function-style cast and
@@ -318,7 +326,14 @@
if (TPR == TPResult::Ambiguous()) {
// We are supposed to be inside parens, so if after the abstract declarator
// we encounter a ')' this is a type-id, otherwise it's an expression.
- if (Tok.is(tok::r_paren))
+ if (Context == TypeIdInParens && Tok.is(tok::r_paren))
+ TPR = TPResult::True();
+ // We are supposed to be inside a template argument, so if after
+ // the abstract declarator we encounter a '>', '>>' (in C++0x), or
+ // ',', this is a type-id. Otherwise, it's an expression.
+ else if (Context == TypeIdAsTemplateArgument &&
+ (Tok.is(tok::greater) || Tok.is(tok::comma) ||
+ (getLang().CPlusPlus0x && Tok.is(tok::greatergreater))))
TPR = TPResult::True();
else
TPR = TPResult::False();