parser.c (struct cp_parser): Update comment for greater_than_is_operator_p.
2007-03-28 Douglas Gregor <doug.gregor@gmail.com> * parser.c (struct cp_parser): Update comment for greater_than_is_operator_p. (cp_parser_primary_expression): In C++0x mode, a cast operator can be terminated with a `>>' token when !GREATER_THAN_IS_OPERATOR_P. (TOKEN_PRECEDENCE): In C++0x mode, `>>' is treated like `>' when !GREATER_THAN_IS_OPERATOR_P. (cp_parser_binary_expression): When -Wc++0x-compat, warn about `>>' operators that will become two `>' tokens in C++0x. (cp_parser_parameter_declaration): Treat `>>' like `>' in C++0x mode, allowing it to terminate default arguments. (cp_parser_enclosed_template_argument_list): In C++0x mode, treat `>>' like two consecutive `>' tokens. (cp_parser_skip_to_end_of_template_parameter_list): Ditto. (cp_parser_next_token_ends_template_argument_p): In C++0x, `>>' ends a template argument. 2007-03-28 Douglas Gregor <doug.gregor@gmail.com> * g++.dg/cpp0x/bracket1.C: New. * g++.dg/cpp0x/bracket2.C: New. * g++.dg/cpp0x/bracket3.C: New. * g++.dg/cpp0x/bracket4.C: New. From-SVN: r123302
This commit is contained in:
parent
a646adedf0
commit
a2ca1ab2e9
@ -1,3 +1,21 @@
|
||||
2007-03-28 Douglas Gregor <doug.gregor@gmail.com>
|
||||
|
||||
* parser.c (struct cp_parser): Update comment for
|
||||
greater_than_is_operator_p.
|
||||
(cp_parser_primary_expression): In C++0x mode, a cast operator can
|
||||
be terminated with a `>>' token when !GREATER_THAN_IS_OPERATOR_P.
|
||||
(TOKEN_PRECEDENCE): In C++0x mode, `>>' is treated like `>' when
|
||||
!GREATER_THAN_IS_OPERATOR_P.
|
||||
(cp_parser_binary_expression): When -Wc++0x-compat, warn about
|
||||
`>>' operators that will become two `>' tokens in C++0x.
|
||||
(cp_parser_parameter_declaration): Treat `>>' like `>' in C++0x
|
||||
mode, allowing it to terminate default arguments.
|
||||
(cp_parser_enclosed_template_argument_list): In C++0x mode, treat
|
||||
`>>' like two consecutive `>' tokens.
|
||||
(cp_parser_skip_to_end_of_template_parameter_list): Ditto.
|
||||
(cp_parser_next_token_ends_template_argument_p): In C++0x, `>>'
|
||||
ends a template argument.
|
||||
|
||||
2007-03-28 Douglas Gregor <doug.gregor@gmail.com>
|
||||
|
||||
* decl.c (redeclaration_error_message): Complain when redeclaring
|
||||
|
@ -1400,7 +1400,9 @@ typedef struct cp_parser GTY(())
|
||||
|
||||
/* TRUE if the `>' token should be interpreted as the greater-than
|
||||
operator. FALSE if it is the end of a template-id or
|
||||
template-parameter-list. */
|
||||
template-parameter-list. In C++0x mode, this flag also applies to
|
||||
`>>' tokens, which are viewed as two consecutive `>' tokens when
|
||||
this flag is FALSE. */
|
||||
bool greater_than_is_operator_p;
|
||||
|
||||
/* TRUE if default arguments are allowed within a parameter list
|
||||
@ -3027,6 +3029,11 @@ cp_parser_primary_expression (cp_parser *parser,
|
||||
&& next_token->type != CPP_CLOSE_SQUARE
|
||||
/* The closing ">" in a template-argument-list. */
|
||||
&& (next_token->type != CPP_GREATER
|
||||
|| parser->greater_than_is_operator_p)
|
||||
/* C++0x only: A ">>" treated like two ">" tokens,
|
||||
in a template-argument-list. */
|
||||
&& (next_token->type != CPP_RSHIFT
|
||||
|| !flag_cpp0x
|
||||
|| parser->greater_than_is_operator_p))
|
||||
cast_p = false;
|
||||
}
|
||||
@ -5792,10 +5799,12 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p)
|
||||
The binops_by_token map is used to get the tree codes for each <token> type.
|
||||
binary-expressions are associated according to a precedence table. */
|
||||
|
||||
#define TOKEN_PRECEDENCE(token) \
|
||||
((token->type == CPP_GREATER && !parser->greater_than_is_operator_p) \
|
||||
? PREC_NOT_OPERATOR \
|
||||
: binops_by_token[token->type].prec)
|
||||
#define TOKEN_PRECEDENCE(token) \
|
||||
(((token->type == CPP_GREATER \
|
||||
|| (flag_cpp0x && token->type == CPP_RSHIFT)) \
|
||||
&& !parser->greater_than_is_operator_p) \
|
||||
? PREC_NOT_OPERATOR \
|
||||
: binops_by_token[token->type].prec)
|
||||
|
||||
static tree
|
||||
cp_parser_binary_expression (cp_parser* parser, bool cast_p)
|
||||
@ -5817,6 +5826,17 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p)
|
||||
/* Get an operator token. */
|
||||
token = cp_lexer_peek_token (parser->lexer);
|
||||
|
||||
if (warn_cxx0x_compat
|
||||
&& token->type == CPP_RSHIFT
|
||||
&& !parser->greater_than_is_operator_p)
|
||||
{
|
||||
warning (OPT_Wc__0x_compat,
|
||||
"%H%<>>%> operator will be treated as two right angle brackets in C++0x",
|
||||
&token->location);
|
||||
warning (OPT_Wc__0x_compat,
|
||||
"suggest parentheses around %<>>%> expression");
|
||||
}
|
||||
|
||||
new_prec = TOKEN_PRECEDENCE (token);
|
||||
|
||||
/* Popping an entry off the stack means we completed a subexpression:
|
||||
@ -13015,6 +13035,13 @@ cp_parser_parameter_declaration (cp_parser *parser,
|
||||
++depth;
|
||||
break;
|
||||
|
||||
case CPP_RSHIFT:
|
||||
if (!flag_cpp0x)
|
||||
break;
|
||||
/* Fall through for C++0x, which treats the `>>'
|
||||
operator like two `>' tokens in certain
|
||||
cases. */
|
||||
|
||||
case CPP_GREATER:
|
||||
/* If we see a non-nested `>', and `>' is not an
|
||||
operator, then it marks the end of the default
|
||||
@ -16536,7 +16563,8 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
|
||||
saved_skip_evaluation = skip_evaluation;
|
||||
skip_evaluation = false;
|
||||
/* Parse the template-argument-list itself. */
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_GREATER))
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_GREATER)
|
||||
|| cp_lexer_next_token_is (parser->lexer, CPP_RSHIFT))
|
||||
arguments = NULL_TREE;
|
||||
else
|
||||
arguments = cp_parser_template_argument_list (parser);
|
||||
@ -16544,7 +16572,28 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
|
||||
a '>>' instead, it's probably just a typo. */
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_RSHIFT))
|
||||
{
|
||||
if (!saved_greater_than_is_operator_p)
|
||||
if (flag_cpp0x)
|
||||
{
|
||||
/* In C++0x, a `>>' in a template argument list or cast
|
||||
expression is considered to be two separate `>'
|
||||
tokens. So, change the current token to a `>', but don't
|
||||
consume it: it will be consumed later when the outer
|
||||
template argument list (or cast expression) is parsed.
|
||||
Note that this replacement of `>' for `>>' is necessary
|
||||
even if we are parsing tentatively: in the tentative
|
||||
case, after calling
|
||||
cp_parser_enclosed_template_argument_list we will always
|
||||
throw away all of the template arguments and the first
|
||||
closing `>', either because the template argument list
|
||||
was erroneous or because we are replacing those tokens
|
||||
with a CPP_TEMPLATE_ID token. The second `>' (which will
|
||||
not have been thrown away) is needed either to close an
|
||||
outer template argument list or to complete a new-style
|
||||
cast. */
|
||||
cp_token *token = cp_lexer_peek_token (parser->lexer);
|
||||
token->type = CPP_GREATER;
|
||||
}
|
||||
else if (!saved_greater_than_is_operator_p)
|
||||
{
|
||||
/* If we're in a nested template argument list, the '>>' has
|
||||
to be a typo for '> >'. We emit the error message, but we
|
||||
@ -16557,8 +16606,6 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
|
||||
"within a nested template argument list",
|
||||
&token->location);
|
||||
|
||||
/* ??? Proper recovery should terminate two levels of
|
||||
template argument list here. */
|
||||
token->type = CPP_GREATER;
|
||||
}
|
||||
else
|
||||
@ -17054,6 +17101,23 @@ cp_parser_skip_to_end_of_template_parameter_list (cp_parser* parser)
|
||||
++level;
|
||||
break;
|
||||
|
||||
case CPP_RSHIFT:
|
||||
if (!flag_cpp0x)
|
||||
/* C++0x views the `>>' operator as two `>' tokens, but
|
||||
C++98 does not. */
|
||||
break;
|
||||
else if (!nesting_depth && level-- == 0)
|
||||
{
|
||||
/* We've hit a `>>' where the first `>' closes the
|
||||
template argument list, and the second `>' is
|
||||
spurious. Just consume the `>>' and stop; we've
|
||||
already produced at least one error. */
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
return;
|
||||
}
|
||||
/* Fall through for C++0x, so we handle the second `>' in
|
||||
the `>>'. */
|
||||
|
||||
case CPP_GREATER:
|
||||
if (!nesting_depth && level-- == 0)
|
||||
{
|
||||
@ -17148,8 +17212,8 @@ cp_parser_next_token_starts_class_definition_p (cp_parser *parser)
|
||||
return (token->type == CPP_OPEN_BRACE || token->type == CPP_COLON);
|
||||
}
|
||||
|
||||
/* Returns TRUE iff the next token is the "," or ">" ending a
|
||||
template-argument. */
|
||||
/* Returns TRUE iff the next token is the "," or ">" (or `>>', in
|
||||
C++0x) ending a template-argument. */
|
||||
|
||||
static bool
|
||||
cp_parser_next_token_ends_template_argument_p (cp_parser *parser)
|
||||
@ -17159,7 +17223,8 @@ cp_parser_next_token_ends_template_argument_p (cp_parser *parser)
|
||||
token = cp_lexer_peek_token (parser->lexer);
|
||||
return (token->type == CPP_COMMA
|
||||
|| token->type == CPP_GREATER
|
||||
|| token->type == CPP_ELLIPSIS);
|
||||
|| token->type == CPP_ELLIPSIS
|
||||
|| (flag_cpp0x && token->type == CPP_RSHIFT));
|
||||
}
|
||||
|
||||
/* Returns TRUE iff the n-th token is a "<", or the n-th is a "[" and the
|
||||
|
@ -1,3 +1,10 @@
|
||||
2007-03-28 Douglas Gregor <doug.gregor@gmail.com>
|
||||
|
||||
* g++.dg/cpp0x/bracket1.C: New.
|
||||
* g++.dg/cpp0x/bracket2.C: New.
|
||||
* g++.dg/cpp0x/bracket3.C: New.
|
||||
* g++.dg/cpp0x/bracket4.C: New.
|
||||
|
||||
2007-03-28 Douglas Gregor <doug.gregor@gmail.com>
|
||||
|
||||
* g++.dg/cpp0x/temp_default1.C: New.
|
||||
|
16
gcc/testsuite/g++.dg/cpp0x/bracket1.C
Normal file
16
gcc/testsuite/g++.dg/cpp0x/bracket1.C
Normal file
@ -0,0 +1,16 @@
|
||||
// { dg-do "compile" }
|
||||
// { dg-options "-std=gnu++0x" }
|
||||
|
||||
template<typename T>
|
||||
struct list {};
|
||||
|
||||
template<typename T>
|
||||
struct vector {
|
||||
operator T() const;
|
||||
};
|
||||
|
||||
void f()
|
||||
{
|
||||
vector<vector<int>> v;
|
||||
const vector<int> vi = static_cast<vector<int>>(v);
|
||||
}
|
11
gcc/testsuite/g++.dg/cpp0x/bracket2.C
Normal file
11
gcc/testsuite/g++.dg/cpp0x/bracket2.C
Normal file
@ -0,0 +1,11 @@
|
||||
// { dg-do "compile" }
|
||||
// { dg-options "-std=gnu++0x" }
|
||||
|
||||
template<int i> class X { /* ... */ };
|
||||
X< 1>2 > x1; // // { dg-error "numeric constant" }
|
||||
X<(1>2)> x2; // Okay.
|
||||
|
||||
template<class T> class Y { /* ... */ };
|
||||
Y<X<1>> x3; // Okay, same as "Y<X<1> > x3;".
|
||||
Y<X<6>>1>> x4; // { dg-error "numeric constant" }
|
||||
Y<X<(6>>1)>> x5; // Okay
|
5
gcc/testsuite/g++.dg/cpp0x/bracket3.C
Normal file
5
gcc/testsuite/g++.dg/cpp0x/bracket3.C
Normal file
@ -0,0 +1,5 @@
|
||||
// { dg-options "-std=c++98 -Wc++0x-compat" }
|
||||
|
||||
template<int N> struct X {};
|
||||
|
||||
X<1 >> 2> x; // { dg-warning "will be treated as|suggest parentheses" }
|
27
gcc/testsuite/g++.dg/cpp0x/bracket4.C
Normal file
27
gcc/testsuite/g++.dg/cpp0x/bracket4.C
Normal file
@ -0,0 +1,27 @@
|
||||
// { dg-do "compile" }
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
template<typename T>
|
||||
struct vector {
|
||||
};
|
||||
|
||||
struct X {
|
||||
template<typename T>
|
||||
struct tmpl {
|
||||
operator T() const;
|
||||
};
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
void g()
|
||||
{
|
||||
T::template tmpl<vector<int>>() + 2;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void operator+(vector<T>, int);
|
||||
|
||||
void f()
|
||||
{
|
||||
vector<vector<int>>() + 2;
|
||||
}
|
Loading…
Reference in New Issue
Block a user