OSDN Git Service

* cp-tree.def (LABEL_STMT): New tree node.
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 28 Aug 1999 21:46:30 +0000 (21:46 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 28 Aug 1999 21:46:30 +0000 (21:46 +0000)
(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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@28943 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/cp-tree.def
gcc/cp/decl.c
gcc/cp/dump.c
gcc/cp/parse.c
gcc/cp/parse.y
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/testsuite/g++.old-deja/g++.ext/label1.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.ext/label2.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/goto2.C [new file with mode: 0644]

index 0db3c90..06d6b06 100644 (file)
@@ -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
index acd09b5..e864c78 100644 (file)
@@ -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
index 0fc298f..350eb8e 100644 (file)
@@ -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)
     }
 }
 \f
-/* 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;
index 7d9a5b7..1241d41 100644 (file)
@@ -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)
index 0c300ca..7b413f3 100644 (file)
@@ -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
index 7f8c344..f93fa61 100644 (file)
@@ -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);
                    }
                }
        ;
index f5c72b0..bb34296 100644 (file)
@@ -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:
index b9457c0..382258b 100644 (file)
@@ -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 (file)
index 0000000..e7327b4
--- /dev/null
@@ -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 (file)
index 0000000..891b89b
--- /dev/null
@@ -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 (file)
index 0000000..a513486
--- /dev/null
@@ -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;
+}