From: gs4t@kelvin.seas.virginia.edu (Gnanasekaran  Swaminathan)
Subject: Fix for class local enum bug
Organization: GNUs Not Usenet
Distribution: gnu
Date: Wed, 30 Dec 1992 17:57:38 GMT

A patch that fixes the following two bugs in gcc-2.3.3 follows:

Bug1: gcc2.3.3 does not let member functions of nested classes
      to define its own local classes and enum.
		
Bug2: gcc2.3.3 does not define a class local enum as soon as it is
      supposed to be defined. See ARM p114 for details.
     
example:
struct A {
  struct B {
    int f() {
      enum { a=1, b=3 }; // Bug1. fails without the patch
      struct C { int j; }; // Bug1. fails without the patch
      return a*b;
    }
  };
  enum { a = 3, b = a*4 }; // Bug2. fails without the patch
};

ChangeLog:

Wed Dec 30 22:22:32 EST 1992 Gnanasekaran Swaminathan (gs4t@virginia.edu)

	* cp-decl.c (lookup_nested_type): Next context is RECORD_TYPE
	in case of local classes in member functions of nested classes.
	So, get the type decl from TREE_CHAIN (context) as the next context.
	(classlocal_enum_decls): A new static variable is introduced.
	(start_enum): Tag of enumtype is made addressable as soon as one is
	pushed. (build_enumerator): A class local enumerator is declared
	as soon as the name and its initializer are seen (cf. ARM p114).
	(grok_enum_decls): Cleaned up as most of its code are moved to
	build_enumerator now.

*** cp-decl.c.orig	Mon Dec 28 18:33:18 1992
--- cp-decl.c	Wed Dec 30 22:08:12 1992
***************
*** 3753,3756 ****
--- 3753,3758 ----
  	      return TREE_VALUE (match);
  	    context = DECL_CONTEXT (context);
+ 	    if (context && TREE_CODE (context) == RECORD_TYPE)
+ 		context = TREE_CHAIN (context);
  	  }
  	  break;
***************
*** 9390,9393 ****
--- 9392,9397 ----
  }
  
+ static tree classlocal_enum_decls = NULL_TREE;
+ 
  /* Begin compiling the definition of an enumeration type.
     NAME is its name (or null if anonymous).
***************
*** 9415,9420 ****
--- 9419,9429 ----
        enumtype = make_node (ENUMERAL_TYPE);
        pushtag (name, enumtype);
+ 
+       if (current_class_type != NULL_TREE)
+ 	  TREE_ADDRESSABLE (b->tags) = 1;
      }
  
+   classlocal_enum_decls = NULL_TREE;
+ 
    if (TYPE_VALUES (enumtype) != 0)
      {
***************
*** 9588,9591 ****
--- 9597,9614 ----
      }
  
+   if (current_class_type != NULL_TREE)
+     {
+       /* class local enum declaration */
+       decl = build_lang_field_decl (CONST_DECL, name, integer_type_node);
+       DECL_INITIAL (decl) = value;
+       TREE_READONLY (decl) = 1;
+       pushdecl_class_level (decl);
+ 
+       /* chain the decl in the tree classlocal_enum_decls
+ 	 See grok_enum_decls () where it is used and reset. */
+       TREE_CHAIN (decl) = classlocal_enum_decls;
+       classlocal_enum_decls = decl;
+     }
+ 
    /* Set basis for default for next value.  */
    enum_next_value = build_binary_op_nodefault (PLUS_EXPR, value,
***************
*** 9601,9634 ****
       tree type, decl;
  {
!   struct binding_level *b = class_binding_level;
!   tree tag = NULL_TREE;
!   tree values;
  
!   while (b)
!     {
!       tag = value_member (type, b->tags);
!       if (tag)
! 	break;
!       b = b->level_chain;
!     }
  
!   if (b == 0 || (b != class_binding_level) || TREE_ADDRESSABLE (tag))
      return decl;
!   else
!     TREE_ADDRESSABLE (tag) = 1;
! 
!   values = TYPE_VALUES (type);
!   while (values)
      {
!       /* Create a declaration for the enum value name.  */
!       tree next = build_lang_field_decl (CONST_DECL, TREE_PURPOSE (values), type);
!       TREE_READONLY (next) = 1;
!       DECL_INITIAL (next) = TREE_VALUE (values);
!       TREE_CHAIN (next) = decl;
!       decl = next;
!       pushdecl_class_level (decl);
!       values = TREE_CHAIN (values);
      }
!   return decl;
  }
  
--- 9624,9646 ----
       tree type, decl;
  {
!   tree d, ret;
  
!   d = ret = classlocal_enum_decls;
!   classlocal_enum_decls = NULL_TREE;
  
!   if (d == 0)
      return decl;
!   
!   for (;;)
      {
!       TREE_TYPE (d) = type;
!       if (TREE_CHAIN (d) == NULL_TREE)
! 	{
! 	  TREE_CHAIN (d) = decl;
! 	  break;
!         }
!       d = TREE_CHAIN (d);
      }
!   return ret;
  }
  

Newsgroups: gnu.g++.bug