aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorZack Weinberg <zack@gcc.gnu.org>2004-09-06 17:38:18 +0000
committerZack Weinberg <zack@gcc.gnu.org>2004-09-06 17:38:18 +0000
commitff4eb0b5ff4c7607e1ff7e0be67f4a0c09caa326 (patch)
tree076d3a2ac346783bfed885fdb4b84add325e5754 /gcc/cp
parent8a57cd3d5e63ab1e0ec1127ec548d535993b71c4 (diff)
downloadgcc-ff4eb0b5ff4c7607e1ff7e0be67f4a0c09caa326.zip
gcc-ff4eb0b5ff4c7607e1ff7e0be67f4a0c09caa326.tar.gz
gcc-ff4eb0b5ff4c7607e1ff7e0be67f4a0c09caa326.tar.bz2
decl.c (build_enumerator): Use add_double and int_fits_type_p instead of cp_build_binary_op...
cp: * decl.c (build_enumerator): Use add_double and int_fits_type_p instead of cp_build_binary_op, to avoid creating short-lived trees. * parser.c (cp_parse_type_specifier <RID_ENUM>): Use two-token lookahead instead of backtracking. Move some code to avoid a conditional branch. (cp_parser_enum_specifier): Avoid duplication of effort with caller. Use cp_lexer_next_token_is/cp_lexer_next_token_is_not as appropriate. (cp_parser_enumerator_list, cp_parser_enumerator_definition): Use cp_lexer_next_token_is/cp_lexer_next_token_is_not as appropriate. testsuite: * g++.old-deja/g++.other/enum2.C: Move dg-error markers to reflect changed line numbering of diagnostics. From-SVN: r87121
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog22
-rw-r--r--gcc/cp/decl.c23
-rw-r--r--gcc/cp/parser.c95
3 files changed, 81 insertions, 59 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 32a1b7e..fd9b97d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,15 @@
+2004-09-06 Zack Weinberg <zack@codesourcery.com>
+
+ * decl.c (build_enumerator): Use add_double and int_fits_type_p
+ instead of cp_build_binary_op, to avoid creating short-lived trees.
+ * parser.c (cp_parse_type_specifier <RID_ENUM>): Use two-token
+ lookahead instead of backtracking. Move some code to avoid a
+ conditional branch.
+ (cp_parser_enum_specifier): Avoid duplication of effort with caller.
+ Use cp_lexer_next_token_is/cp_lexer_next_token_is_not as appropriate.
+ (cp_parser_enumerator_list, cp_parser_enumerator_definition):
+ Use cp_lexer_next_token_is/cp_lexer_next_token_is_not as appropriate.
+
2004-09-04 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
* decl.c (grok_declarator): Remove a redundant semicolon.
@@ -17,7 +29,7 @@
define a stub macro that expands to NULL.
(cp_lexer_new_main): Only set debugging_p if ENABLE_CHECKING set.
(cp_lexer_new_from_tokens): Likewise.
-
+
2004-09-03 Jan Hubicka <jh@suse.cz>
* decl.c (finish_function): Clean out pointers we no longer need.
@@ -36,7 +48,7 @@
* cp-tree.h (DECL_CONSTRUCTION_VTABLE_P): New macro.
* class.c (build_ctor_vtbl_group): Set DECL_CONSTRUCTION_VTABLE_P.
- * decl2.c (determine_visibility): Honor
+ * decl2.c (determine_visibility): Honor
TARGET_CXX_EXPORT_CLASS_DATA.
* class.c (key_method): Rename to ...
@@ -76,7 +88,7 @@
LANG_HOOKS_ATTRIBUTE_TABLE, LANG_HOOKS_TREE_INLINING_WALK_SUBTREES,
LANG_HOOKS_TREE_INLINING_CANNOT_INLINE_TREE_FN,
LANG_HOOKS_TREE_INLINING_ADD_PENDING_FN_DECLS,
- LANG_HOOKS_TREE_INLINING_AUTO_VAR_IN_FN_P,
+ LANG_HOOKS_TREE_INLINING_AUTO_VAR_IN_FN_P,
LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P,
LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P,
LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN,
@@ -95,7 +107,7 @@
* cp-tree.h (cp_finish_file): New prototype.
* decl.c: Do not include gtype-cp.h.
* decl2.c (finish_file): Rename to cp_finish_file.
-
+
2004-08-31 Richard Henderson <rth@redhat.com>
PR c++/17221
@@ -403,7 +415,7 @@
build_dynamic_cast_1, ptr_initializer, ptm_initializer,
get_pseudo_ti_init): Likewise.
* search.c (get_dynamic_cast_base_type): Likewise.
-
+
2004-08-25 Zack Weinberg <zack@codesourcery.com>
* class.c, search.c: Remove references to DWARF_DEBUG.
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 607b907..5cb43d2 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -9520,18 +9520,25 @@ build_enumerator (tree name, tree value, tree enumtype)
/* Default based on previous value. */
if (value == NULL_TREE)
{
- tree prev_value;
-
if (TYPE_VALUES (enumtype))
{
- /* The next value is the previous value ... */
+ HOST_WIDE_INT hi;
+ unsigned HOST_WIDE_INT lo;
+ tree prev_value;
+ bool overflowed;
+
+ /* The next value is the previous value plus one. We can
+ safely assume that the previous value is an INTEGER_CST.
+ add_double doesn't know the type of the target expression,
+ so we must check with int_fits_type_p as well. */
prev_value = DECL_INITIAL (TREE_VALUE (TYPE_VALUES (enumtype)));
- /* ... plus one. */
- value = cp_build_binary_op (PLUS_EXPR,
- prev_value,
- integer_one_node);
+ overflowed = add_double (TREE_INT_CST_LOW (prev_value),
+ TREE_INT_CST_HIGH (prev_value),
+ 1, 0, &lo, &hi);
+ value = build_int_cst_wide (TREE_TYPE (prev_value), lo, hi);
+ overflowed |= !int_fits_type_p (value, TREE_TYPE (prev_value));
- if (tree_int_cst_lt (value, prev_value))
+ if (overflowed)
error ("overflow in enumeration values at `%D'", name);
}
else
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 45eb20a..6d56f97 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -9265,21 +9265,36 @@ cp_parser_type_specifier (cp_parser* parser,
keyword = token->keyword;
switch (keyword)
{
+ case RID_ENUM:
+ /* 'enum' [identifier] '{' introduces an enum-specifier;
+ 'enum' <anything else> introduces an elaborated-type-specifier. */
+ if (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_OPEN_BRACE
+ || (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_NAME
+ && cp_lexer_peek_nth_token (parser->lexer, 3)->type
+ == CPP_OPEN_BRACE))
+ {
+ type_spec = cp_parser_enum_specifier (parser);
+ if (declares_class_or_enum)
+ *declares_class_or_enum = 2;
+ if (decl_specs)
+ cp_parser_set_decl_spec_type (decl_specs,
+ type_spec,
+ /*user_defined_p=*/true);
+ return type_spec;
+ }
+ else
+ goto elaborated_type_specifier;
+
/* Any of these indicate either a class-specifier, or an
elaborated-type-specifier. */
case RID_CLASS:
case RID_STRUCT:
case RID_UNION:
- case RID_ENUM:
/* Parse tentatively so that we can back up if we don't find a
- class-specifier or enum-specifier. */
+ class-specifier. */
cp_parser_parse_tentatively (parser);
- /* Look for the class-specifier or enum-specifier. */
- if (keyword == RID_ENUM)
- type_spec = cp_parser_enum_specifier (parser);
- else
- type_spec = cp_parser_class_specifier (parser);
-
+ /* Look for the class-specifier. */
+ type_spec = cp_parser_class_specifier (parser);
/* If that worked, we're done. */
if (cp_parser_parse_definitely (parser))
{
@@ -9293,7 +9308,12 @@ cp_parser_type_specifier (cp_parser* parser,
}
/* Fall through. */
+ elaborated_type_specifier:
+ /* We're declaring (not defining) a class or enum. */
+ if (declares_class_or_enum)
+ *declares_class_or_enum = 1;
+ /* Fall through. */
case RID_TYPENAME:
/* Look for an elaborated-type-specifier. */
type_spec
@@ -9301,10 +9321,6 @@ cp_parser_type_specifier (cp_parser* parser,
(parser,
decl_specs && decl_specs->specs[(int) ds_friend],
is_declaration));
- /* We're declaring a class or enum -- unless we're using
- `typename'. */
- if (declares_class_or_enum && keyword != RID_TYPENAME)
- *declares_class_or_enum = 1;
if (decl_specs)
cp_parser_set_decl_spec_type (decl_specs,
type_spec,
@@ -9906,40 +9922,33 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
static tree
cp_parser_enum_specifier (cp_parser* parser)
{
- cp_token *token;
- tree identifier = NULL_TREE;
+ tree identifier;
tree type;
- /* Look for the `enum' keyword. */
- if (!cp_parser_require_keyword (parser, RID_ENUM, "`enum'"))
- return error_mark_node;
- /* Peek at the next token. */
- token = cp_lexer_peek_token (parser->lexer);
+ /* Caller guarantees that the current token is 'enum', an identifier
+ possibly follows, and the token after that is an opening brace.
+ If we don't have an identifier, fabricate an anonymous name for
+ the enumeration being defined. */
+ cp_lexer_consume_token (parser->lexer);
- /* See if it is an identifier. */
- if (token->type == CPP_NAME)
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
identifier = cp_parser_identifier (parser);
+ else
+ identifier = make_anon_name ();
- /* Look for the `{'. */
- if (!cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"))
- return error_mark_node;
-
- /* At this point, we're going ahead with the enum-specifier, even
- if some other problem occurs. */
- cp_parser_commit_to_tentative_parse (parser);
+ cp_lexer_consume_token (parser->lexer);
/* Issue an error message if type-definitions are forbidden here. */
cp_parser_check_type_definition (parser);
/* Create the new type. */
- type = start_enum (identifier ? identifier : make_anon_name ());
+ type = start_enum (identifier);
- /* Peek at the next token. */
- token = cp_lexer_peek_token (parser->lexer);
- /* If it's not a `}', then there are some enumerators. */
- if (token->type != CPP_CLOSE_BRACE)
+ /* If the next token is not '}', then there are some enumerators. */
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_BRACE))
cp_parser_enumerator_list (parser, type);
- /* Look for the `}'. */
+
+ /* Consume the final '}'. */
cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
/* Finish up the enumeration. */
@@ -9960,15 +9969,12 @@ cp_parser_enumerator_list (cp_parser* parser, tree type)
{
while (true)
{
- cp_token *token;
-
/* Parse an enumerator-definition. */
cp_parser_enumerator_definition (parser, type);
- /* Peek at the next token. */
- token = cp_lexer_peek_token (parser->lexer);
- /* If it's not a `,', then we've reached the end of the
- list. */
- if (token->type != CPP_COMMA)
+
+ /* If the next token is not a ',', we've reached the end of
+ the list. */
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
break;
/* Otherwise, consume the `,' and keep going. */
cp_lexer_consume_token (parser->lexer);
@@ -9995,7 +10001,6 @@ cp_parser_enumerator_list (cp_parser* parser, tree type)
static void
cp_parser_enumerator_definition (cp_parser* parser, tree type)
{
- cp_token *token;
tree identifier;
tree value;
@@ -10004,10 +10009,8 @@ cp_parser_enumerator_definition (cp_parser* parser, tree type)
if (identifier == error_mark_node)
return;
- /* Peek at the next token. */
- token = cp_lexer_peek_token (parser->lexer);
- /* If it's an `=', then there's an explicit value. */
- if (token->type == CPP_EQ)
+ /* If the next token is an '=', then there is an explicit value. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
{
/* Consume the `=' token. */
cp_lexer_consume_token (parser->lexer);