aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>1999-08-28 21:46:30 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>1999-08-28 21:46:30 +0000
commitacef433b61b5e8001133d37e66250c2f0ab2a042 (patch)
tree8ab9e1dd5159729ad69d044ceacb1739bfbc9532 /gcc
parent79101920008a32754f6cfc9074fc13d5fc50c473 (diff)
downloadgcc-acef433b61b5e8001133d37e66250c2f0ab2a042.zip
gcc-acef433b61b5e8001133d37e66250c2f0ab2a042.tar.gz
gcc-acef433b61b5e8001133d37e66250c2f0ab2a042.tar.bz2
cp-tree.def (LABEL_STMT): New tree node.
* cp-tree.def (LABEL_STMT): New tree node. (LABEL_STMT_LABEL): New macro. (shadow_label): Remove. (declare_local_label): New function. (finish_label_decl): Likewise. * decl.c (make_label_decl): New function, split out from lookup_label. (shadowed_labels): Remove. (binding_level): Add shadowed_labels. (clear_binding_level): Remove. (push_binding_level): Just bzero the new binding level. (pushlevel): Fix indentation. (pop_label): New function. (pop_labels): Likewise, split out from poplevel. (poplevel): Pop local labels. Use pop_labels. (maybe_push_to_top_level): Don't clear shadowed_labels. (lookup_label): Use make_label_decl. (shadow_label): Remove. (declare_local_label): New function. (define_label): Simplify. (start_function): Don't clear shadowed_labels. (cp_function): Remove shadowed_labels. (push_cp_function_context): Don't save shadowed_labels. (pop_cp_function_context): Don't restore it. * dump.c (dequeue_and_dump): Handle LABEL_STMT. * parse.y (label_decl): Use finish_label_decl. * pt.c (tsubst_expr): Handle LABEL_STMTs, and local label declarations. * semantics.c (finish_label_stmt): Add a LABEL_STMT when building_stmt_tree. (finish_label_decl): New function. (expand_stmt): Handle LABEL_STMTs and local label declarations. From-SVN: r28943
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog35
-rw-r--r--gcc/cp/cp-tree.def1
-rw-r--r--gcc/cp/decl.c269
-rw-r--r--gcc/cp/dump.c7
-rw-r--r--gcc/cp/parse.c335
-rw-r--r--gcc/cp/parse.y9
-rw-r--r--gcc/cp/pt.c30
-rw-r--r--gcc/cp/semantics.c54
-rw-r--r--gcc/testsuite/g++.old-deja/g++.ext/label1.C27
-rw-r--r--gcc/testsuite/g++.old-deja/g++.ext/label2.C34
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/goto2.C17
11 files changed, 490 insertions, 328 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 0db3c902..06d6b06 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,38 @@
+1999-08-28 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.def (LABEL_STMT): New tree node.
+ (LABEL_STMT_LABEL): New macro.
+ (shadow_label): Remove.
+ (declare_local_label): New function.
+ (finish_label_decl): Likewise.
+ * decl.c (make_label_decl): New function, split out from
+ lookup_label.
+ (shadowed_labels): Remove.
+ (binding_level): Add shadowed_labels.
+ (clear_binding_level): Remove.
+ (push_binding_level): Just bzero the new binding level.
+ (pushlevel): Fix indentation.
+ (pop_label): New function.
+ (pop_labels): Likewise, split out from poplevel.
+ (poplevel): Pop local labels. Use pop_labels.
+ (maybe_push_to_top_level): Don't clear shadowed_labels.
+ (lookup_label): Use make_label_decl.
+ (shadow_label): Remove.
+ (declare_local_label): New function.
+ (define_label): Simplify.
+ (start_function): Don't clear shadowed_labels.
+ (cp_function): Remove shadowed_labels.
+ (push_cp_function_context): Don't save shadowed_labels.
+ (pop_cp_function_context): Don't restore it.
+ * dump.c (dequeue_and_dump): Handle LABEL_STMT.
+ * parse.y (label_decl): Use finish_label_decl.
+ * pt.c (tsubst_expr): Handle LABEL_STMTs, and local label
+ declarations.
+ * semantics.c (finish_label_stmt): Add a LABEL_STMT when
+ building_stmt_tree.
+ (finish_label_decl): New function.
+ (expand_stmt): Handle LABEL_STMTs and local label declarations.
+
1999-08-26 Mark Mitchell <mark@codesourcery.com>
* decl.c (lookup_label): Build labels on the permanent obstack
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index acd09b5..e864c78 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -228,6 +228,7 @@ DEFTREECODE (BREAK_STMT, "break_stmt", 'e', 0)
DEFTREECODE (CONTINUE_STMT, "continue_stmt", 'e', 0)
DEFTREECODE (SWITCH_STMT, "switch_stmt", 'e', 2)
DEFTREECODE (GOTO_STMT, "goto_stmt", 'e', 1)
+DEFTREECODE (LABEL_STMT, "label_stmt", 'e', 1)
DEFTREECODE (ASM_STMT, "asm_stmt", 'e', 5)
/* A SUBOBJECT statement marks the point at which a sub-object is
fully constructed. After this point, the SUBOBJECT_CLEANUP must be
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 0fc298f..350eb8e 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -190,6 +190,9 @@ static void warn_about_implicit_typename_lookup PROTO((tree, tree));
static int walk_namespaces_r PROTO((tree, walk_namespaces_fn, void *));
static int walk_globals_r PROTO((tree, void *));
static void add_decl_to_level PROTO((tree, struct binding_level *));
+static tree make_label_decl PROTO((tree, int));
+static void pop_label PROTO((tree));
+static void pop_labels PROTO((tree));
#if defined (DEBUG_CP_BINDING_LEVELS)
static void indent PROTO((void));
@@ -419,14 +422,11 @@ static tree current_function_parm_tags;
/* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
that have names. Here so we can clear out their names' definitions
- at the end of the function. */
+ at the end of the function. The TREE_VALUE is a LABEL_DECL; the
+ TREE_PURPOSE is the previous binding of the label. */
static tree named_labels;
-/* A list of LABEL_DECLs from outer contexts that are currently shadowed. */
-
-static tree shadowed_labels;
-
/* The FUNCTION_DECL for the function currently being compiled,
or 0 if between functions. */
tree current_function_decl;
@@ -587,6 +587,11 @@ struct binding_level
is used for all binding levels. */
tree type_shadowed;
+ /* A TREE_LIST. Each TREE_VALUE is the LABEL_DECL for a local
+ label in this scope. The TREE_PURPOSE is the previous value of
+ the IDENTIFIER_LABEL VALUE. */
+ tree shadowed_labels;
+
/* For each level (except not the global one),
a chain of BLOCK nodes for all the levels
that were entered and exited one level down. */
@@ -669,10 +674,6 @@ static struct binding_level *free_binding_level;
static struct binding_level *global_binding_level;
-/* Binding level structures are initialized by copying this one. */
-
-static struct binding_level clear_binding_level;
-
/* Nonzero means unconditionally make a BLOCK for the next level pushed. */
static int keep_next_level_flag;
@@ -700,7 +701,7 @@ push_binding_level (newlevel, tag_transparent, keep)
{
/* Add this level to the front of the chain (stack) of levels that
are active. */
- *newlevel = clear_binding_level;
+ bzero ((char*) newlevel, sizeof (struct binding_level));
newlevel->level_chain = current_binding_level;
current_binding_level = newlevel;
newlevel->tag_transparent = tag_transparent;
@@ -967,9 +968,7 @@ pushlevel (tag_transparent)
free_binding_level = free_binding_level->level_chain;
}
else
- {
- newlevel = make_binding_level ();
- }
+ newlevel = make_binding_level ();
push_binding_level (newlevel, tag_transparent, keep_next_level_flag);
GNU_xref_start_scope ((HOST_WIDE_INT) newlevel);
@@ -1277,6 +1276,51 @@ pop_binding (id, decl)
}
}
+/* When a label goes out of scope, check to see if that label was used
+ in a valid manner, and issue any appropriate warnings or errors. */
+
+static void
+pop_label (link)
+ tree link;
+{
+ tree label = TREE_VALUE (link);
+
+ if (DECL_INITIAL (label) == NULL_TREE)
+ {
+ cp_error_at ("label `%D' used but not defined", label);
+ /* Avoid crashing later. */
+ define_label (input_filename, 1, DECL_NAME (label));
+ }
+ else if (warn_unused && !TREE_USED (label))
+ cp_warning_at ("label `%D' defined but not used", label);
+
+ SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (label), TREE_PURPOSE (link));
+}
+
+/* At the end of a function, all labels declared within the fucntion
+ go out of scope. BLOCK is the top-level block for the
+ function. */
+
+static void
+pop_labels (block)
+ tree block;
+{
+ tree link;
+
+ /* Clear out the definitions of all label names, since their scopes
+ end here. */
+ for (link = named_labels; link; link = TREE_CHAIN (link))
+ {
+ pop_label (link);
+ /* Put the labels into the "variables" of the top-level block,
+ so debugger can see them. */
+ TREE_CHAIN (TREE_VALUE (link)) = BLOCK_VARS (block);
+ BLOCK_VARS (block) = TREE_VALUE (link);
+ }
+
+ named_labels = NULL_TREE;
+}
+
/* Exit a binding level.
Pop the level off, and restore the state of the identifier-decl mappings
that were in effect when this level was entered.
@@ -1512,7 +1556,13 @@ poplevel (keep, reverse, functionbody)
for (link = current_binding_level->type_shadowed;
link; link = TREE_CHAIN (link))
SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link), TREE_VALUE (link));
-
+
+ /* Restore the IDENTIFIER_LABEL_VALUEs for local labels. */
+ for (link = current_binding_level->shadowed_labels;
+ link;
+ link = TREE_CHAIN (link))
+ pop_label (link);
+
/* There may be OVERLOADs (wrapped in TREE_LISTs) on the BLOCK_VARs
list if a `using' declaration put them there. The debugging
back-ends won't understand OVERLOAD, so we remove them here.
@@ -1534,40 +1584,13 @@ poplevel (keep, reverse, functionbody)
/* If the level being exited is the top level of a function,
check over all the labels. */
-
if (functionbody)
{
- /* If this is the top level block of a function,
- the vars are the function's parameters.
- Don't leave them in the BLOCK because they are
- found in the FUNCTION_DECL instead. */
-
+ /* Since this is the top level block of a function, the vars are
+ the function's parameters. Don't leave them in the BLOCK
+ because they are found in the FUNCTION_DECL instead. */
BLOCK_VARS (block) = 0;
-
- /* Clear out the definitions of all label names,
- since their scopes end here. */
-
- for (link = named_labels; link; link = TREE_CHAIN (link))
- {
- register tree label = TREE_VALUE (link);
-
- if (DECL_INITIAL (label) == NULL_TREE)
- {
- cp_error_at ("label `%D' used but not defined", label);
- /* Avoid crashing later. */
- define_label (input_filename, 1, DECL_NAME (label));
- }
- else if (warn_unused && !TREE_USED (label))
- cp_warning_at ("label `%D' defined but not used", label);
- SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (label), NULL_TREE);
-
- /* Put the labels into the "variables" of the
- top-level block, so debugger can see them. */
- TREE_CHAIN (label) = BLOCK_VARS (block);
- BLOCK_VARS (block) = label;
- }
-
- named_labels = NULL_TREE;
+ pop_labels (block);
}
/* Any uses of undefined labels now operate under constraints
@@ -2547,7 +2570,6 @@ maybe_push_to_top_level (pseudo)
current_lang_name = lang_name_cplusplus;
strict_prototype = strict_prototypes_lang_cplusplus;
named_labels = NULL_TREE;
- shadowed_labels = NULL_TREE;
previous_class_type = previous_class_values = NULL_TREE;
class_cache_firstobj = 0;
processing_specialization = 0;
@@ -4784,25 +4806,40 @@ redeclaration_error_message (newdecl, olddecl)
}
}
-/* Get the LABEL_DECL corresponding to identifier ID as a label.
- Create one if none exists so far for the current function.
- This function is called for both label definitions and label references. */
+/* Create a new label, named ID. */
-tree
-lookup_label (id)
+static tree
+make_label_decl (id, local_p)
tree id;
+ int local_p;
{
- register tree decl = IDENTIFIER_LABEL_VALUE (id);
+ tree decl;
- if (current_function_decl == NULL_TREE)
- {
- error ("label `%s' referenced outside of any function",
- IDENTIFIER_POINTER (id));
- return NULL_TREE;
- }
+ if (building_stmt_tree ())
+ push_permanent_obstack ();
+ decl = build_decl (LABEL_DECL, id, void_type_node);
+ if (building_stmt_tree ())
+ pop_obstacks ();
+ else
+ /* Make sure every label has an rtx. */
+ label_rtx (decl);
+
+ DECL_CONTEXT (decl) = current_function_decl;
+ DECL_MODE (decl) = VOIDmode;
+ C_DECLARED_LABEL_FLAG (decl) = local_p;
- if ((decl == NULL_TREE
- || DECL_SOURCE_LINE (decl) == 0)
+ /* Say where one reference is to the label, for the sake of the
+ error if it is not defined. */
+ DECL_SOURCE_LINE (decl) = lineno;
+ DECL_SOURCE_FILE (decl) = input_filename;
+
+ /* Record the fact that this identifier is bound to this label. */
+ SET_IDENTIFIER_LABEL_VALUE (id, decl);
+
+ /* Record this label on the list of used labels so that we can check
+ at the end of the function to see whether or not the label was
+ actually defined. */
+ if ((named_label_uses == NULL || named_label_uses->label_decl != decl)
&& (named_label_uses == NULL
|| named_label_uses->names_in_scope != current_binding_level->names
|| named_label_uses->label_decl != decl))
@@ -4819,64 +4856,65 @@ lookup_label (id)
named_label_uses = new_ent;
}
- /* Use a label already defined or ref'd with this name. */
- if (decl != NULL_TREE)
- {
- /* But not if it is inherited and wasn't declared to be inheritable. */
- if (DECL_CONTEXT (decl) != current_function_decl
- && ! C_DECLARED_LABEL_FLAG (decl))
- return shadow_label (id);
- return decl;
- }
-
- if (building_stmt_tree ())
- push_permanent_obstack ();
- decl = build_decl (LABEL_DECL, id, void_type_node);
- if (building_stmt_tree ())
- pop_obstacks ();
- else
- /* Make sure every label has an rtx. */
- label_rtx (decl);
-
- /* A label not explicitly declared must be local to where it's ref'd. */
- DECL_CONTEXT (decl) = current_function_decl;
+ return decl;
+}
- DECL_MODE (decl) = VOIDmode;
+/* Look for a label named ID in the current function. If one cannot
+ be found, create one. (We keep track of used, but undefined,
+ labels, and complain about them at the end of a function.) */
- /* Say where one reference is to the label,
- for the sake of the error if it is not defined. */
- DECL_SOURCE_LINE (decl) = lineno;
- DECL_SOURCE_FILE (decl) = input_filename;
+tree
+lookup_label (id)
+ tree id;
+{
+ tree decl;
- SET_IDENTIFIER_LABEL_VALUE (id, decl);
+ /* You can't use labels at global scope. */
+ if (current_function_decl == NULL_TREE)
+ {
+ error ("label `%s' referenced outside of any function",
+ IDENTIFIER_POINTER (id));
+ return NULL_TREE;
+ }
+
+ /* See if we've already got this label. */
+ decl = IDENTIFIER_LABEL_VALUE (id);
+ if (decl != NULL_TREE && DECL_CONTEXT (decl) == current_function_decl)
+ return decl;
- named_labels = tree_cons (NULL_TREE, decl, named_labels);
- named_label_uses->label_decl = decl;
+ /* Record this label on the list of labels used in this function.
+ We do this before calling make_label_decl so that we get the
+ IDENTIFIER_LABEL_VALUE before the new label is declared. */
+ named_labels = tree_cons (IDENTIFIER_LABEL_VALUE (id), NULL_TREE,
+ named_labels);
+ /* We need a new label. */
+ decl = make_label_decl (id, /*local_p=*/0);
+ /* Now fill in the information we didn't have before. */
+ TREE_VALUE (named_labels) = decl;
return decl;
}
-/* Make a label named NAME in the current function,
- shadowing silently any that may be inherited from containing functions
- or containing scopes.
-
- Note that valid use, if the label being shadowed
- comes from another scope in the same function,
- requires calling declare_nonlocal_label right away. */
+/* Declare a local label named ID. */
tree
-shadow_label (name)
- tree name;
+declare_local_label (id)
+ tree id;
{
- register tree decl = IDENTIFIER_LABEL_VALUE (name);
-
- if (decl != NULL_TREE)
- {
- shadowed_labels = tree_cons (NULL_TREE, decl, shadowed_labels);
- SET_IDENTIFIER_LABEL_VALUE (name, NULL_TREE);
- }
+ tree decl;
- return lookup_label (name);
+ /* Add a new entry to the SHADOWED_LABELS list so that when we leave
+ this scope we can restore the old value of
+ IDENTIFIER_TYPE_VALUE. */
+ current_binding_level->shadowed_labels
+ = tree_cons (IDENTIFIER_LABEL_VALUE (id), NULL_TREE,
+ current_binding_level->shadowed_labels);
+ /* Look for the label. */
+ decl = make_label_decl (id, /*local_p=*/1);
+ /* Now fill in the information we didn't have before. */
+ TREE_VALUE (current_binding_level->shadowed_labels) = decl;
+
+ return decl;
}
/* Define a label, specifying the location in the source file.
@@ -4895,14 +4933,6 @@ define_label (filename, line, name)
own new (temporary) binding contour. */
current_binding_level->more_cleanups_ok = 0;
- /* If label with this name is known from an outer context, shadow it. */
- if (decl != NULL_TREE && DECL_CONTEXT (decl) != current_function_decl)
- {
- shadowed_labels = tree_cons (NULL_TREE, decl, shadowed_labels);
- SET_IDENTIFIER_LABEL_VALUE (name, NULL_TREE);
- decl = lookup_label (name);
- }
-
if (name == get_identifier ("wchar_t"))
cp_pedwarn ("label named wchar_t");
@@ -12815,7 +12845,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
current_function_returns_value = 0;
current_function_returns_null = 0;
named_labels = 0;
- shadowed_labels = 0;
current_function_assigns_this = 0;
current_function_just_assigned_this = 0;
current_function_parms_stored = 0;
@@ -14385,7 +14414,6 @@ struct cp_function
int temp_name_counter;
tree named_labels;
struct named_label_list *named_label_uses;
- tree shadowed_labels;
tree ctor_label;
tree dtor_label;
rtx last_dtor_insn;
@@ -14427,7 +14455,6 @@ push_cp_function_context (context)
p->named_labels = named_labels;
p->named_label_uses = named_label_uses;
- p->shadowed_labels = shadowed_labels;
p->returns_value = current_function_returns_value;
p->returns_null = current_function_returns_null;
p->binding_level = current_binding_level;
@@ -14468,13 +14495,6 @@ pop_cp_function_context (context)
tree context;
{
struct cp_function *p = cp_function_chain;
- tree link;
-
- /* Bring back all the labels that were shadowed. */
- for (link = shadowed_labels; link; link = TREE_CHAIN (link))
- if (DECL_NAME (TREE_VALUE (link)) != 0)
- SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)),
- TREE_VALUE (link));
pop_function_context_from (context);
@@ -14482,7 +14502,6 @@ pop_cp_function_context (context)
named_labels = p->named_labels;
named_label_uses = p->named_label_uses;
- shadowed_labels = p->shadowed_labels;
current_function_returns_value = p->returns_value;
current_function_returns_null = p->returns_null;
current_binding_level = p->binding_level;
diff --git a/gcc/cp/dump.c b/gcc/cp/dump.c
index 7d9a5b7..1241d41 100644
--- a/gcc/cp/dump.c
+++ b/gcc/cp/dump.c
@@ -731,6 +731,13 @@ dequeue_and_dump (di)
dump_next_stmt (di, t);
break;
+ case LABEL_STMT:
+ dump_stmt (di, t);
+ if (dump_children_p)
+ dump_child ("labl", LABEL_STMT_LABEL (t));
+ dump_next_stmt (di, t);
+ break;
+
case RETURN_STMT:
dump_stmt (di, t);
if (dump_children_p)
diff --git a/gcc/cp/parse.c b/gcc/cp/parse.c
index 0c300ca..7b413f3 100644
--- a/gcc/cp/parse.c
+++ b/gcc/cp/parse.c
@@ -714,23 +714,23 @@ static const short yyrline[] = { 0,
3090, 3092, 3094, 3096, 3098, 3100, 3102, 3104, 3108, 3112,
3116, 3120, 3122, 3124, 3126, 3128, 3130, 3132, 3134, 3136,
3144, 3146, 3147, 3148, 3151, 3157, 3159, 3164, 3166, 3169,
- 3183, 3186, 3189, 3193, 3196, 3203, 3205, 3208, 3210, 3212,
- 3215, 3218, 3221, 3224, 3226, 3229, 3233, 3235, 3241, 3243,
- 3244, 3246, 3251, 3253, 3255, 3257, 3259, 3262, 3263, 3265,
- 3268, 3269, 3272, 3272, 3275, 3275, 3278, 3278, 3280, 3282,
- 3284, 3286, 3292, 3298, 3301, 3304, 3310, 3312, 3314, 3318,
- 3320, 3321, 3322, 3324, 3327, 3330, 3333, 3339, 3343, 3345,
- 3348, 3350, 3353, 3357, 3359, 3362, 3364, 3367, 3384, 3390,
- 3393, 3395, 3397, 3401, 3404, 3405, 3413, 3417, 3421, 3424,
- 3425, 3431, 3434, 3437, 3439, 3443, 3448, 3451, 3461, 3466,
- 3467, 3474, 3477, 3480, 3482, 3485, 3487, 3497, 3511, 3515,
- 3518, 3520, 3524, 3528, 3531, 3534, 3536, 3540, 3542, 3549,
- 3556, 3559, 3563, 3567, 3571, 3577, 3581, 3586, 3588, 3591,
- 3596, 3602, 3613, 3616, 3618, 3622, 3630, 3633, 3637, 3640,
- 3642, 3644, 3650, 3655, 3658, 3660, 3662, 3664, 3666, 3668,
- 3670, 3672, 3674, 3676, 3678, 3680, 3682, 3684, 3686, 3688,
- 3690, 3692, 3694, 3696, 3698, 3700, 3702, 3704, 3706, 3708,
- 3710, 3712, 3714, 3716, 3718, 3720, 3723, 3725
+ 3182, 3185, 3188, 3192, 3195, 3202, 3204, 3207, 3209, 3211,
+ 3214, 3217, 3220, 3223, 3225, 3228, 3232, 3234, 3240, 3242,
+ 3243, 3245, 3250, 3252, 3254, 3256, 3258, 3261, 3262, 3264,
+ 3267, 3268, 3271, 3271, 3274, 3274, 3277, 3277, 3279, 3281,
+ 3283, 3285, 3291, 3297, 3300, 3303, 3309, 3311, 3313, 3317,
+ 3319, 3320, 3321, 3323, 3326, 3329, 3332, 3338, 3342, 3344,
+ 3347, 3349, 3352, 3356, 3358, 3361, 3363, 3366, 3383, 3389,
+ 3392, 3394, 3396, 3400, 3403, 3404, 3412, 3416, 3420, 3423,
+ 3424, 3430, 3433, 3436, 3438, 3442, 3447, 3450, 3460, 3465,
+ 3466, 3473, 3476, 3479, 3481, 3484, 3486, 3496, 3510, 3514,
+ 3517, 3519, 3523, 3527, 3530, 3533, 3535, 3539, 3541, 3548,
+ 3555, 3558, 3562, 3566, 3570, 3576, 3580, 3585, 3587, 3590,
+ 3595, 3601, 3612, 3615, 3617, 3621, 3629, 3632, 3636, 3639,
+ 3641, 3643, 3649, 3654, 3657, 3659, 3661, 3663, 3665, 3667,
+ 3669, 3671, 3673, 3675, 3677, 3679, 3681, 3683, 3685, 3687,
+ 3689, 3691, 3693, 3695, 3697, 3699, 3701, 3703, 3705, 3707,
+ 3709, 3711, 3713, 3715, 3717, 3719, 3722, 3724
};
#endif
@@ -7489,191 +7489,190 @@ case 707:
break;}
case 710:
#line 3171 "parse.y"
-{ tree link;
- for (link = yyvsp[-1].ttype; link; link = TREE_CHAIN (link))
+{
+ while (yyvsp[-1].ttype)
{
- tree label = shadow_label (TREE_VALUE (link));
- C_DECLARED_LABEL_FLAG (label) = 1;
- declare_nonlocal_label (label);
+ finish_label_decl (TREE_VALUE (yyvsp[-1].ttype));
+ yyvsp[-1].ttype = TREE_CHAIN (yyvsp[-1].ttype);
}
;
break;}
case 711:
-#line 3185 "parse.y"
+#line 3184 "parse.y"
{;
break;}
case 713:
-#line 3191 "parse.y"
+#line 3190 "parse.y"
{ yyval.ttype = begin_compound_stmt (0); ;
break;}
case 714:
-#line 3193 "parse.y"
+#line 3192 "parse.y"
{ yyval.ttype = finish_compound_stmt (0, yyvsp[-1].ttype); ;
break;}
case 715:
-#line 3198 "parse.y"
+#line 3197 "parse.y"
{
yyval.ttype = begin_if_stmt ();
cond_stmt_keyword = "if";
;
break;}
case 716:
-#line 3203 "parse.y"
+#line 3202 "parse.y"
{ finish_if_stmt_cond (yyvsp[0].ttype, yyvsp[-1].ttype); ;
break;}
case 717:
-#line 3205 "parse.y"
+#line 3204 "parse.y"
{ yyval.ttype = finish_then_clause (yyvsp[-3].ttype); ;
break;}
case 719:
-#line 3210 "parse.y"
+#line 3209 "parse.y"
{ yyval.ttype = begin_compound_stmt (0); ;
break;}
case 720:
-#line 3212 "parse.y"
+#line 3211 "parse.y"
{ yyval.ttype = finish_compound_stmt (0, yyvsp[-1].ttype); ;
break;}
case 721:
-#line 3217 "parse.y"
+#line 3216 "parse.y"
{;
break;}
case 723:
-#line 3223 "parse.y"
+#line 3222 "parse.y"
{ finish_stmt (); ;
break;}
case 724:
-#line 3225 "parse.y"
+#line 3224 "parse.y"
{ finish_expr_stmt (yyvsp[-1].ttype); ;
break;}
case 725:
-#line 3227 "parse.y"
+#line 3226 "parse.y"
{ begin_else_clause (); ;
break;}
case 726:
-#line 3229 "parse.y"
+#line 3228 "parse.y"
{
finish_else_clause (yyvsp[-3].ttype);
finish_if_stmt ();
;
break;}
case 727:
-#line 3234 "parse.y"
+#line 3233 "parse.y"
{ finish_if_stmt (); ;
break;}
case 728:
-#line 3236 "parse.y"
+#line 3235 "parse.y"
{
yyval.ttype = begin_while_stmt ();
cond_stmt_keyword = "while";
;
break;}
case 729:
-#line 3241 "parse.y"
+#line 3240 "parse.y"
{ finish_while_stmt_cond (yyvsp[0].ttype, yyvsp[-1].ttype); ;
break;}
case 730:
-#line 3243 "parse.y"
+#line 3242 "parse.y"
{ finish_while_stmt (yyvsp[-3].ttype); ;
break;}
case 731:
-#line 3245 "parse.y"
+#line 3244 "parse.y"
{ yyval.ttype = begin_do_stmt (); ;
break;}
case 732:
-#line 3247 "parse.y"
+#line 3246 "parse.y"
{
finish_do_body (yyvsp[-2].ttype);
cond_stmt_keyword = "do";
;
break;}
case 733:
-#line 3252 "parse.y"
+#line 3251 "parse.y"
{ finish_do_stmt (yyvsp[-1].ttype, yyvsp[-5].ttype); ;
break;}
case 734:
-#line 3254 "parse.y"
+#line 3253 "parse.y"
{ yyval.ttype = begin_for_stmt (); ;
break;}
case 735:
-#line 3256 "parse.y"
+#line 3255 "parse.y"
{ finish_for_init_stmt (yyvsp[-2].ttype); ;
break;}
case 736:
-#line 3258 "parse.y"
+#line 3257 "parse.y"
{ finish_for_cond (yyvsp[-1].ttype, yyvsp[-5].ttype); ;
break;}
case 737:
-#line 3260 "parse.y"
+#line 3259 "parse.y"
{ finish_for_expr (yyvsp[-1].ttype, yyvsp[-8].ttype); ;
break;}
case 738:
-#line 3262 "parse.y"
+#line 3261 "parse.y"
{ finish_for_stmt (yyvsp[-3].ttype, yyvsp[-10].ttype); ;
break;}
case 739:
-#line 3264 "parse.y"
+#line 3263 "parse.y"
{ begin_switch_stmt (); ;
break;}
case 740:
-#line 3266 "parse.y"
+#line 3265 "parse.y"
{ yyval.ttype = finish_switch_cond (yyvsp[-1].ttype); ;
break;}
case 741:
-#line 3268 "parse.y"
+#line 3267 "parse.y"
{ finish_switch_stmt (yyvsp[-3].ttype, yyvsp[-1].ttype); ;
break;}
case 742:
-#line 3270 "parse.y"
+#line 3269 "parse.y"
{ finish_case_label (yyvsp[-1].ttype, NULL_TREE); ;
break;}
case 744:
-#line 3273 "parse.y"
+#line 3272 "parse.y"
{ finish_case_label (yyvsp[-3].ttype, yyvsp[-1].ttype); ;
break;}
case 746:
-#line 3276 "parse.y"
+#line 3275 "parse.y"
{ finish_case_label (NULL_TREE, NULL_TREE); ;
break;}
case 748:
-#line 3279 "parse.y"
+#line 3278 "parse.y"
{ finish_break_stmt (); ;
break;}
case 749:
-#line 3281 "parse.y"
+#line 3280 "parse.y"
{ finish_continue_stmt (); ;
break;}
case 750:
-#line 3283 "parse.y"
+#line 3282 "parse.y"
{ finish_return_stmt (NULL_TREE); ;
break;}
case 751:
-#line 3285 "parse.y"
+#line 3284 "parse.y"
{ finish_return_stmt (yyvsp[-1].ttype); ;
break;}
case 752:
-#line 3287 "parse.y"
+#line 3286 "parse.y"
{
finish_asm_stmt (yyvsp[-4].ttype, yyvsp[-2].ttype, NULL_TREE, NULL_TREE,
NULL_TREE);
;
break;}
case 753:
-#line 3293 "parse.y"
+#line 3292 "parse.y"
{
finish_asm_stmt (yyvsp[-6].ttype, yyvsp[-4].ttype, yyvsp[-2].ttype, NULL_TREE,
NULL_TREE);
;
break;}
case 754:
-#line 3299 "parse.y"
+#line 3298 "parse.y"
{ finish_asm_stmt (yyvsp[-8].ttype, yyvsp[-6].ttype, yyvsp[-4].ttype, yyvsp[-2].ttype, NULL_TREE); ;
break;}
case 755:
-#line 3303 "parse.y"
+#line 3302 "parse.y"
{ finish_asm_stmt (yyvsp[-10].ttype, yyvsp[-8].ttype, yyvsp[-6].ttype, yyvsp[-4].ttype, yyvsp[-2].ttype); ;
break;}
case 756:
-#line 3305 "parse.y"
+#line 3304 "parse.y"
{
if (pedantic)
pedwarn ("ANSI C++ forbids computed gotos");
@@ -7681,173 +7680,173 @@ case 756:
;
break;}
case 757:
-#line 3311 "parse.y"
+#line 3310 "parse.y"
{ finish_goto_stmt (yyvsp[-1].ttype); ;
break;}
case 758:
-#line 3313 "parse.y"
+#line 3312 "parse.y"
{ finish_stmt (); ;
break;}
case 759:
-#line 3315 "parse.y"
+#line 3314 "parse.y"
{ error ("label must be followed by statement");
yyungetc ('}', 0);
finish_stmt (); ;
break;}
case 760:
-#line 3319 "parse.y"
+#line 3318 "parse.y"
{ finish_stmt (); ;
break;}
case 763:
-#line 3323 "parse.y"
+#line 3322 "parse.y"
{ do_local_using_decl (yyvsp[0].ttype); ;
break;}
case 765:
-#line 3329 "parse.y"
+#line 3328 "parse.y"
{ yyval.ttype = begin_function_try_block (); ;
break;}
case 766:
-#line 3331 "parse.y"
+#line 3330 "parse.y"
{ finish_function_try_block (yyvsp[-2].ttype); ;
break;}
case 767:
-#line 3333 "parse.y"
+#line 3332 "parse.y"
{
finish_function_handler_sequence (yyvsp[-4].ttype);
yyval.itype = yyvsp[-3].itype;
;
break;}
case 768:
-#line 3341 "parse.y"
+#line 3340 "parse.y"
{ yyval.ttype = begin_try_block (); ;
break;}
case 769:
-#line 3343 "parse.y"
+#line 3342 "parse.y"
{ finish_try_block (yyvsp[-1].ttype); ;
break;}
case 770:
-#line 3345 "parse.y"
+#line 3344 "parse.y"
{ finish_handler_sequence (yyvsp[-3].ttype); ;
break;}
case 773:
-#line 3355 "parse.y"
+#line 3354 "parse.y"
{ yyval.ttype = begin_handler(); ;
break;}
case 774:
-#line 3357 "parse.y"
+#line 3356 "parse.y"
{ finish_handler_parms (yyvsp[-1].ttype); ;
break;}
case 775:
-#line 3359 "parse.y"
+#line 3358 "parse.y"
{ finish_handler (yyvsp[-3].ttype); ;
break;}
case 778:
-#line 3369 "parse.y"
+#line 3368 "parse.y"
{ expand_start_catch_block (NULL_TREE, NULL_TREE); ;
break;}
case 779:
-#line 3385 "parse.y"
+#line 3384 "parse.y"
{ check_for_new_type ("inside exception declarations", yyvsp[-1].ftype);
expand_start_catch_block (TREE_PURPOSE (yyvsp[-1].ftype.t),
TREE_VALUE (yyvsp[-1].ftype.t)); ;
break;}
case 780:
-#line 3392 "parse.y"
+#line 3391 "parse.y"
{ finish_label_stmt (yyvsp[-1].ttype); ;
break;}
case 781:
-#line 3394 "parse.y"
+#line 3393 "parse.y"
{ finish_label_stmt (yyvsp[-1].ttype); ;
break;}
case 782:
-#line 3396 "parse.y"
+#line 3395 "parse.y"
{ finish_label_stmt (yyvsp[-1].ttype); ;
break;}
case 783:
-#line 3398 "parse.y"
+#line 3397 "parse.y"
{ finish_label_stmt (yyvsp[-1].ttype); ;
break;}
case 784:
-#line 3403 "parse.y"
+#line 3402 "parse.y"
{ finish_expr_stmt (yyvsp[-1].ttype); ;
break;}
case 786:
-#line 3406 "parse.y"
+#line 3405 "parse.y"
{ if (pedantic)
pedwarn ("ANSI C++ forbids compound statements inside for initializations");
;
break;}
case 787:
-#line 3415 "parse.y"
+#line 3414 "parse.y"
{ emit_line_note (input_filename, lineno);
yyval.ttype = NULL_TREE; ;
break;}
case 788:
-#line 3418 "parse.y"
+#line 3417 "parse.y"
{ emit_line_note (input_filename, lineno); ;
break;}
case 789:
-#line 3423 "parse.y"
+#line 3422 "parse.y"
{ yyval.ttype = NULL_TREE; ;
break;}
case 791:
-#line 3426 "parse.y"
+#line 3425 "parse.y"
{ yyval.ttype = NULL_TREE; ;
break;}
case 792:
-#line 3433 "parse.y"
+#line 3432 "parse.y"
{ yyval.ttype = NULL_TREE; ;
break;}
case 795:
-#line 3440 "parse.y"
+#line 3439 "parse.y"
{ yyval.ttype = chainon (yyval.ttype, yyvsp[0].ttype); ;
break;}
case 796:
-#line 3445 "parse.y"
+#line 3444 "parse.y"
{ yyval.ttype = build_tree_list (yyval.ttype, yyvsp[-1].ttype); ;
break;}
case 797:
-#line 3450 "parse.y"
+#line 3449 "parse.y"
{ yyval.ttype = tree_cons (NULL_TREE, yyval.ttype, NULL_TREE); ;
break;}
case 798:
-#line 3452 "parse.y"
+#line 3451 "parse.y"
{ yyval.ttype = tree_cons (NULL_TREE, yyvsp[0].ttype, yyval.ttype); ;
break;}
case 799:
-#line 3463 "parse.y"
+#line 3462 "parse.y"
{
yyval.ttype = empty_parms();
;
break;}
case 801:
-#line 3468 "parse.y"
+#line 3467 "parse.y"
{ yyval.ttype = finish_parmlist (build_tree_list (NULL_TREE, yyvsp[0].ftype.t), 0);
check_for_new_type ("inside parameter list", yyvsp[0].ftype); ;
break;}
case 802:
-#line 3476 "parse.y"
+#line 3475 "parse.y"
{ yyval.ttype = finish_parmlist (yyval.ttype, 0); ;
break;}
case 803:
-#line 3478 "parse.y"
+#line 3477 "parse.y"
{ yyval.ttype = finish_parmlist (yyvsp[-1].ttype, 1); ;
break;}
case 804:
-#line 3481 "parse.y"
+#line 3480 "parse.y"
{ yyval.ttype = finish_parmlist (yyvsp[-1].ttype, 1); ;
break;}
case 805:
-#line 3483 "parse.y"
+#line 3482 "parse.y"
{ yyval.ttype = finish_parmlist (build_tree_list (NULL_TREE,
yyvsp[-1].ftype.t), 1); ;
break;}
case 806:
-#line 3486 "parse.y"
+#line 3485 "parse.y"
{ yyval.ttype = finish_parmlist (NULL_TREE, 1); ;
break;}
case 807:
-#line 3488 "parse.y"
+#line 3487 "parse.y"
{
/* This helps us recover from really nasty
parse errors, for example, a missing right
@@ -7859,7 +7858,7 @@ case 807:
;
break;}
case 808:
-#line 3498 "parse.y"
+#line 3497 "parse.y"
{
/* This helps us recover from really nasty
parse errors, for example, a missing right
@@ -7872,99 +7871,99 @@ case 808:
;
break;}
case 809:
-#line 3513 "parse.y"
+#line 3512 "parse.y"
{ maybe_snarf_defarg (); ;
break;}
case 810:
-#line 3515 "parse.y"
+#line 3514 "parse.y"
{ yyval.ttype = yyvsp[0].ttype; ;
break;}
case 813:
-#line 3526 "parse.y"
+#line 3525 "parse.y"
{ check_for_new_type ("in a parameter list", yyvsp[0].ftype);
yyval.ttype = build_tree_list (NULL_TREE, yyvsp[0].ftype.t); ;
break;}
case 814:
-#line 3529 "parse.y"
+#line 3528 "parse.y"
{ check_for_new_type ("in a parameter list", yyvsp[-1].ftype);
yyval.ttype = build_tree_list (yyvsp[0].ttype, yyvsp[-1].ftype.t); ;
break;}
case 815:
-#line 3532 "parse.y"
+#line 3531 "parse.y"
{ check_for_new_type ("in a parameter list", yyvsp[0].ftype);
yyval.ttype = chainon (yyval.ttype, yyvsp[0].ftype.t); ;
break;}
case 816:
-#line 3535 "parse.y"
+#line 3534 "parse.y"
{ yyval.ttype = chainon (yyval.ttype, build_tree_list (NULL_TREE, yyvsp[0].ttype)); ;
break;}
case 817:
-#line 3537 "parse.y"
+#line 3536 "parse.y"
{ yyval.ttype = chainon (yyval.ttype, build_tree_list (yyvsp[0].ttype, yyvsp[-2].ttype)); ;
break;}
case 819:
-#line 3543 "parse.y"
+#line 3542 "parse.y"
{ check_for_new_type ("in a parameter list", yyvsp[-1].ftype);
yyval.ttype = build_tree_list (NULL_TREE, yyvsp[-1].ftype.t); ;
break;}
case 820:
-#line 3553 "parse.y"
+#line 3552 "parse.y"
{ tree specs = strip_attrs (yyvsp[-1].ftype.t);
yyval.ftype.new_type_flag = yyvsp[-1].ftype.new_type_flag;
yyval.ftype.t = build_tree_list (specs, yyvsp[0].ttype); ;
break;}
case 821:
-#line 3557 "parse.y"
+#line 3556 "parse.y"
{ yyval.ftype.t = build_tree_list (yyvsp[-1].ftype.t, yyvsp[0].ttype);
yyval.ftype.new_type_flag = yyvsp[-1].ftype.new_type_flag; ;
break;}
case 822:
-#line 3560 "parse.y"
+#line 3559 "parse.y"
{ yyval.ftype.t = build_tree_list (build_decl_list (NULL_TREE, yyvsp[-1].ftype.t),
yyvsp[0].ttype);
yyval.ftype.new_type_flag = yyvsp[-1].ftype.new_type_flag; ;
break;}
case 823:
-#line 3564 "parse.y"
+#line 3563 "parse.y"
{ tree specs = strip_attrs (yyvsp[-1].ftype.t);
yyval.ftype.t = build_tree_list (specs, yyvsp[0].ttype);
yyval.ftype.new_type_flag = yyvsp[-1].ftype.new_type_flag; ;
break;}
case 824:
-#line 3568 "parse.y"
+#line 3567 "parse.y"
{ tree specs = strip_attrs (yyvsp[0].ftype.t);
yyval.ftype.t = build_tree_list (specs, NULL_TREE);
yyval.ftype.new_type_flag = yyvsp[0].ftype.new_type_flag; ;
break;}
case 825:
-#line 3572 "parse.y"
+#line 3571 "parse.y"
{ tree specs = strip_attrs (yyvsp[-1].ttype);
yyval.ftype.t = build_tree_list (specs, yyvsp[0].ttype);
yyval.ftype.new_type_flag = 0; ;
break;}
case 826:
-#line 3579 "parse.y"
+#line 3578 "parse.y"
{ yyval.ftype.t = build_tree_list (NULL_TREE, yyvsp[0].ftype.t);
yyval.ftype.new_type_flag = yyvsp[0].ftype.new_type_flag; ;
break;}
case 827:
-#line 3582 "parse.y"
+#line 3581 "parse.y"
{ yyval.ftype.t = build_tree_list (yyvsp[0].ttype, yyvsp[-1].ftype.t);
yyval.ftype.new_type_flag = yyvsp[-1].ftype.new_type_flag; ;
break;}
case 830:
-#line 3593 "parse.y"
+#line 3592 "parse.y"
{ see_typename (); ;
break;}
case 831:
-#line 3598 "parse.y"
+#line 3597 "parse.y"
{
error ("type specifier omitted for parameter");
yyval.ttype = build_tree_list (integer_type_node, NULL_TREE);
;
break;}
case 832:
-#line 3603 "parse.y"
+#line 3602 "parse.y"
{
error ("type specifier omitted for parameter");
if (TREE_CODE (yyval.ttype) == SCOPE_REF
@@ -7975,192 +7974,192 @@ case 832:
;
break;}
case 833:
-#line 3615 "parse.y"
+#line 3614 "parse.y"
{ yyval.ttype = NULL_TREE; ;
break;}
case 834:
-#line 3617 "parse.y"
+#line 3616 "parse.y"
{ yyval.ttype = yyvsp[-1].ttype; ;
break;}
case 835:
-#line 3619 "parse.y"
+#line 3618 "parse.y"
{ yyval.ttype = empty_except_spec; ;
break;}
case 836:
-#line 3624 "parse.y"
+#line 3623 "parse.y"
{
check_for_new_type ("exception specifier", yyvsp[0].ftype);
yyval.ttype = groktypename (yyvsp[0].ftype.t);
;
break;}
case 837:
-#line 3632 "parse.y"
+#line 3631 "parse.y"
{ yyval.ttype = add_exception_specifier (NULL_TREE, yyvsp[0].ttype, 1); ;
break;}
case 838:
-#line 3634 "parse.y"
+#line 3633 "parse.y"
{ yyval.ttype = add_exception_specifier (yyvsp[-2].ttype, yyvsp[0].ttype, 1); ;
break;}
case 839:
-#line 3639 "parse.y"
+#line 3638 "parse.y"
{ yyval.ttype = NULL_TREE; ;
break;}
case 840:
-#line 3641 "parse.y"
+#line 3640 "parse.y"
{ yyval.ttype = make_pointer_declarator (yyvsp[-1].ttype, yyvsp[0].ttype); ;
break;}
case 841:
-#line 3643 "parse.y"
+#line 3642 "parse.y"
{ yyval.ttype = make_reference_declarator (yyvsp[-1].ttype, yyvsp[0].ttype); ;
break;}
case 842:
-#line 3645 "parse.y"
+#line 3644 "parse.y"
{ tree arg = make_pointer_declarator (yyvsp[-1].ttype, yyvsp[0].ttype);
yyval.ttype = build_parse_node (SCOPE_REF, yyvsp[-2].ttype, arg);
;
break;}
case 843:
-#line 3652 "parse.y"
+#line 3651 "parse.y"
{ got_scope = NULL_TREE; ;
break;}
case 844:
-#line 3657 "parse.y"
+#line 3656 "parse.y"
{ yyval.ttype = ansi_opname[MULT_EXPR]; ;
break;}
case 845:
-#line 3659 "parse.y"
+#line 3658 "parse.y"
{ yyval.ttype = ansi_opname[TRUNC_DIV_EXPR]; ;
break;}
case 846:
-#line 3661 "parse.y"
+#line 3660 "parse.y"
{ yyval.ttype = ansi_opname[TRUNC_MOD_EXPR]; ;
break;}
case 847:
-#line 3663 "parse.y"
+#line 3662 "parse.y"
{ yyval.ttype = ansi_opname[PLUS_EXPR]; ;
break;}
case 848:
-#line 3665 "parse.y"
+#line 3664 "parse.y"
{ yyval.ttype = ansi_opname[MINUS_EXPR]; ;
break;}
case 849:
-#line 3667 "parse.y"
+#line 3666 "parse.y"
{ yyval.ttype = ansi_opname[BIT_AND_EXPR]; ;
break;}
case 850:
-#line 3669 "parse.y"
+#line 3668 "parse.y"
{ yyval.ttype = ansi_opname[BIT_IOR_EXPR]; ;
break;}
case 851:
-#line 3671 "parse.y"
+#line 3670 "parse.y"
{ yyval.ttype = ansi_opname[BIT_XOR_EXPR]; ;
break;}
case 852:
-#line 3673 "parse.y"
+#line 3672 "parse.y"
{ yyval.ttype = ansi_opname[BIT_NOT_EXPR]; ;
break;}
case 853:
-#line 3675 "parse.y"
+#line 3674 "parse.y"
{ yyval.ttype = ansi_opname[COMPOUND_EXPR]; ;
break;}
case 854:
-#line 3677 "parse.y"
+#line 3676 "parse.y"
{ yyval.ttype = ansi_opname[yyvsp[0].code]; ;
break;}
case 855:
-#line 3679 "parse.y"
+#line 3678 "parse.y"
{ yyval.ttype = ansi_opname[LT_EXPR]; ;
break;}
case 856:
-#line 3681 "parse.y"
+#line 3680 "parse.y"
{ yyval.ttype = ansi_opname[GT_EXPR]; ;
break;}
case 857:
-#line 3683 "parse.y"
+#line 3682 "parse.y"
{ yyval.ttype = ansi_opname[yyvsp[0].code]; ;
break;}
case 858:
-#line 3685 "parse.y"
+#line 3684 "parse.y"
{ yyval.ttype = ansi_assopname[yyvsp[0].code]; ;
break;}
case 859:
-#line 3687 "parse.y"
+#line 3686 "parse.y"
{ yyval.ttype = ansi_opname [MODIFY_EXPR]; ;
break;}
case 860:
-#line 3689 "parse.y"
+#line 3688 "parse.y"
{ yyval.ttype = ansi_opname[yyvsp[0].code]; ;
break;}
case 861:
-#line 3691 "parse.y"
+#line 3690 "parse.y"
{ yyval.ttype = ansi_opname[yyvsp[0].code]; ;
break;}
case 862:
-#line 3693 "parse.y"
+#line 3692 "parse.y"
{ yyval.ttype = ansi_opname[POSTINCREMENT_EXPR]; ;
break;}
case 863:
-#line 3695 "parse.y"
+#line 3694 "parse.y"
{ yyval.ttype = ansi_opname[PREDECREMENT_EXPR]; ;
break;}
case 864:
-#line 3697 "parse.y"
+#line 3696 "parse.y"
{ yyval.ttype = ansi_opname[TRUTH_ANDIF_EXPR]; ;
break;}
case 865:
-#line 3699 "parse.y"
+#line 3698 "parse.y"
{ yyval.ttype = ansi_opname[TRUTH_ORIF_EXPR]; ;
break;}
case 866:
-#line 3701 "parse.y"
+#line 3700 "parse.y"
{ yyval.ttype = ansi_opname[TRUTH_NOT_EXPR]; ;
break;}
case 867:
-#line 3703 "parse.y"
+#line 3702 "parse.y"
{ yyval.ttype = ansi_opname[COND_EXPR]; ;
break;}
case 868:
-#line 3705 "parse.y"
+#line 3704 "parse.y"
{ yyval.ttype = ansi_opname[yyvsp[0].code]; ;
break;}
case 869:
-#line 3707 "parse.y"
+#line 3706 "parse.y"
{ yyval.ttype = ansi_opname[COMPONENT_REF]; ;
break;}
case 870:
-#line 3709 "parse.y"
+#line 3708 "parse.y"
{ yyval.ttype = ansi_opname[MEMBER_REF]; ;
break;}
case 871:
-#line 3711 "parse.y"
+#line 3710 "parse.y"
{ yyval.ttype = ansi_opname[CALL_EXPR]; ;
break;}
case 872:
-#line 3713 "parse.y"
+#line 3712 "parse.y"
{ yyval.ttype = ansi_opname[ARRAY_REF]; ;
break;}
case 873:
-#line 3715 "parse.y"
+#line 3714 "parse.y"
{ yyval.ttype = ansi_opname[NEW_EXPR]; ;
break;}
case 874:
-#line 3717 "parse.y"
+#line 3716 "parse.y"
{ yyval.ttype = ansi_opname[DELETE_EXPR]; ;
break;}
case 875:
-#line 3719 "parse.y"
+#line 3718 "parse.y"
{ yyval.ttype = ansi_opname[VEC_NEW_EXPR]; ;
break;}
case 876:
-#line 3721 "parse.y"
+#line 3720 "parse.y"
{ yyval.ttype = ansi_opname[VEC_DELETE_EXPR]; ;
break;}
case 877:
-#line 3724 "parse.y"
+#line 3723 "parse.y"
{ yyval.ttype = grokoptypename (yyvsp[-1].ftype.t, yyvsp[0].ttype); ;
break;}
case 878:
-#line 3726 "parse.y"
+#line 3725 "parse.y"
{ yyval.ttype = ansi_opname[ERROR_MARK]; ;
break;}
}
@@ -8385,7 +8384,7 @@ yyerrhandle:
}
return 1;
}
-#line 3729 "parse.y"
+#line 3728 "parse.y"
#ifdef SPEW_DEBUG
diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y
index 7f8c344..f93fa61 100644
--- a/gcc/cp/parse.y
+++ b/gcc/cp/parse.y
@@ -3168,12 +3168,11 @@ label_decls:
label_decl:
LABEL identifiers_or_typenames ';'
- { tree link;
- for (link = $2; link; link = TREE_CHAIN (link))
+ {
+ while ($2)
{
- tree label = shadow_label (TREE_VALUE (link));
- C_DECLARED_LABEL_FLAG (label) = 1;
- declare_nonlocal_label (label);
+ finish_label_decl (TREE_VALUE ($2));
+ $2 = TREE_CHAIN ($2);
}
}
;
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index f5c72b0..bb34296 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -7264,18 +7264,23 @@ tsubst_expr (t, args, complain, in_decl)
lineno = STMT_LINENO (t);
decl = DECL_STMT_DECL (t);
- init = DECL_INITIAL (decl);
- decl = tsubst (decl, args, complain, in_decl);
- init = tsubst_expr (init, args, complain, in_decl);
- DECL_INITIAL (decl) = init;
- /* By marking the declaration as instantiated, we avoid trying
+ if (TREE_CODE (decl) == LABEL_DECL)
+ finish_label_decl (DECL_NAME (decl));
+ else
+ {
+ init = DECL_INITIAL (decl);
+ decl = tsubst (decl, args, complain, in_decl);
+ init = tsubst_expr (init, args, complain, in_decl);
+ DECL_INITIAL (decl) = init;
+ /* By marking the declaration as instantiated, we avoid trying
to instantiate it. Since instantiate_decl can't handle
local variables, and since we've already done all that
needs to be done, that's the right thing to do. */
- if (TREE_CODE (decl) == VAR_DECL)
- DECL_TEMPLATE_INSTANTIATED (decl) = 1;
- maybe_push_decl (decl);
- add_decl_stmt (decl);
+ if (TREE_CODE (decl) == VAR_DECL)
+ DECL_TEMPLATE_INSTANTIATED (decl) = 1;
+ maybe_push_decl (decl);
+ add_decl_stmt (decl);
+ }
resume_momentary (i);
return decl;
}
@@ -7392,10 +7397,9 @@ tsubst_expr (t, args, complain, in_decl)
tsubst_expr (CASE_HIGH (t), args, complain, in_decl));
break;
- case LABEL_DECL:
- lineno = DECL_SOURCE_LINE (t);
- input_filename = DECL_SOURCE_FILE (t);
- finish_label_stmt (DECL_NAME (t));
+ case LABEL_STMT:
+ lineno = STMT_LINENO (t);
+ finish_label_stmt (DECL_NAME (LABEL_STMT_LABEL (t)));
break;
case GOTO_STMT:
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index b9457c0..382258b 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -919,11 +919,24 @@ finish_label_stmt (name)
tree decl = define_label (input_filename, lineno, name);
if (building_stmt_tree ())
- add_tree (decl);
+ add_tree (build_min_nt (LABEL_STMT, decl));
else if (decl)
expand_label (decl);
}
+/* Finish a series of declarations for local labels. G++ allows users
+ to declare "local" labels, i.e., labels with scope. This extension
+ is useful when writing code involving statement-expressions. */
+
+void
+finish_label_decl (name)
+ tree name;
+{
+ tree decl = declare_local_label (name);
+ if (building_stmt_tree ())
+ add_decl_stmt (decl);
+}
+
/* Create a declaration statement for the declaration given by the
DECL. */
@@ -2019,17 +2032,22 @@ expand_stmt (t)
lineno = STMT_LINENO (t);
emit_line_note (input_filename, lineno);
decl = DECL_STMT_DECL (t);
- /* We need to clear DECL_CONTEXT so that maybe_push_decl
- will push it into the current scope. */
- if (DECL_CONTEXT (decl) == current_function_decl)
- DECL_CONTEXT (decl) = NULL_TREE;
- /* If we marked this variable as dead when we processed it
- before, we must undo that now. The variable has been
- resuscitated. */
- if (TREE_CODE (decl) == VAR_DECL)
- DECL_DEAD_FOR_LOCAL (decl) = 0;
- maybe_push_decl (decl);
- cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0, 0);
+ if (TREE_CODE (decl) == LABEL_DECL)
+ finish_label_decl (DECL_NAME (decl));
+ else
+ {
+ /* We need to clear DECL_CONTEXT so that maybe_push_decl
+ will push it into the current scope. */
+ if (DECL_CONTEXT (decl) == current_function_decl)
+ DECL_CONTEXT (decl) = NULL_TREE;
+ /* If we marked this variable as dead when we processed it
+ before, we must undo that now. The variable has been
+ resuscitated. */
+ if (TREE_CODE (decl) == VAR_DECL)
+ DECL_DEAD_FOR_LOCAL (decl) = 0;
+ maybe_push_decl (decl);
+ cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0, 0);
+ }
resume_momentary (i);
}
break;
@@ -2119,15 +2137,17 @@ expand_stmt (t)
finish_case_label (CASE_LOW (t), CASE_HIGH (t));
break;
- case LABEL_DECL:
- input_filename = DECL_SOURCE_FILE (t);
- lineno = DECL_SOURCE_LINE (t);
- finish_label_stmt (DECL_NAME (t));
+ case LABEL_STMT:
+ lineno = STMT_LINENO (t);
+ finish_label_stmt (DECL_NAME (LABEL_STMT_LABEL (t)));
break;
case GOTO_STMT:
lineno = STMT_LINENO (t);
- finish_goto_stmt (GOTO_DESTINATION (t));
+ if (TREE_CODE (GOTO_DESTINATION (t)) == LABEL_DECL)
+ finish_goto_stmt (DECL_NAME (GOTO_DESTINATION (t)));
+ else
+ finish_goto_stmt (GOTO_DESTINATION (t));
break;
case ASM_STMT:
diff --git a/gcc/testsuite/g++.old-deja/g++.ext/label1.C b/gcc/testsuite/g++.old-deja/g++.ext/label1.C
new file mode 100644
index 0000000..e7327b4
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.ext/label1.C
@@ -0,0 +1,27 @@
+// Origin: Mark Mitchell <mark@codesourcery.com>
+// Special g++ Options:
+
+int main ()
+{
+ int i = 0;
+ int j = 0;
+ int k = 0;
+
+ l:
+ if (j)
+ return 0;
+ ({
+ __label__ l;
+ k = 0;
+ l:
+ if (++k <= 2)
+ goto l;
+ ++i;});
+ if (i > 1 || k != 3)
+ return 1;
+ else
+ {
+ j = 1;
+ goto l;
+ }
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.ext/label2.C b/gcc/testsuite/g++.old-deja/g++.ext/label2.C
new file mode 100644
index 0000000..891b89b
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.ext/label2.C
@@ -0,0 +1,34 @@
+// Origin: Mark Mitchell <mark@codesourcery.com>
+// Special g++ Options:
+
+template <class T>
+int f ()
+{
+ int i = 0;
+ int j = 0;
+ int k = 0;
+
+ l:
+ if (j)
+ return 0;
+ ({
+ __label__ l;
+ k = 0;
+ l:
+ if (++k <= 2)
+ goto l;
+ ++i;});
+ if (i > 1 || k != 3)
+ return 1;
+ else
+ {
+ j = 1;
+ goto l;
+ }
+}
+
+int main ()
+{
+ return f<double>();
+}
+
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/goto2.C b/gcc/testsuite/g++.old-deja/g++.pt/goto2.C
new file mode 100644
index 0000000..a513486
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.pt/goto2.C
@@ -0,0 +1,17 @@
+// Build don't link:
+// Origin: Mark Mitchell <mark@codesourcery.com>
+
+int i = 1;
+
+template <class T> void test()
+{
+ goto lab;
+ lab:
+ --i;
+}
+
+int main ()
+{
+ test<int>();
+ return i;
+}