diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-02-10 00:53:15 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-02-10 00:53:15 +0000 |
commit | 97f34576d4a50a24f4154b85bcff9e29b240e8ac (patch) | |
tree | c507dc5a4c8cc7807d7a3d59474cb18a46c68365 /clang/lib | |
parent | 85e0f66250637165a815ef78ab4b3fe102d75c8b (diff) | |
download | bcm5719-llvm-97f34576d4a50a24f4154b85bcff9e29b240e8ac.tar.gz bcm5719-llvm-97f34576d4a50a24f4154b85bcff9e29b240e8ac.zip |
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.
llvm-svn: 64189
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Parse/ParseTemplate.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Parse/ParseTentative.cpp | 37 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 4 |
3 files changed, 29 insertions, 14 deletions
diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index f860058117b..25aea352242 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -456,7 +456,7 @@ void *Parser::ParseTemplateArgument(bool &ArgIsType) { // the corresponding template-parameter. // // Therefore, we initially try to parse a type-id. - if (isTypeIdInParens()) { + if (isCXXTypeId(TypeIdAsTemplateArgument)) { ArgIsType = true; return ParseTypeName(); } diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp index 445dd8b6eff..06c136df918 100644 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -270,16 +270,24 @@ bool Parser::isCXXConditionDeclaration() { 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 @@ bool Parser::isCXXTypeIdInParens() { 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(); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 1a2da846429..ecbc860d1df 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -458,7 +458,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // is an expression. Diag(ArgExpr->getSourceRange().getBegin(), diag::err_template_arg_must_be_type); - Diag((*Param)->getLocation(), diag::note_template_parameter_here); + Diag((*Param)->getLocation(), diag::note_template_param_here); Invalid = true; } else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*Param)) { @@ -484,7 +484,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, << ArgType; else Diag(ArgLoc, diag::err_template_arg_must_be_expr); - Diag((*Param)->getLocation(), diag::note_template_parameter_here); + Diag((*Param)->getLocation(), diag::note_template_param_here); Invalid = true; } else { // Check template template parameters. |