[gnu.g++.bug] g++ bug 12298901 - scope of class-nested typedefs

rfg@ICS.UCI.EDU (12/31/89)

In recent versions of g++ (1.36.0, 1.36.1, 1.36.2-) typedefs which are
nested within class declarations are given a scope which is local to
the class declaration itself.  This causes examples like the following
to get compile-time errors:

---------------------------------------------------------------------------
struct foo {

    typedef foo* foo_p;
    void member (foo_p);
};

void foo::member (foo_p p) // ERROR: `foo_ptr' undeclared, outside of functions
{
}
---------------------------------------------------------------------------

Such errors illustrate two separate problems with g++.

First, it is obvious that g++ does not extend the scope of `member' entities
(including, in this case, `member typedefs') to the formal parameter lists of
member function definitions which occur outside of the class declaration
itself.  This is a shame because this fact also makes it illegal to write
clever default parameter expressions as illustrated in the following example:

---------------------------------------------------------------------------
struct foo {

	int i;
	void member (int);
};

void foo::member (int arg = i) // ERROR: `i' undeclared, outside of functions
{
}
---------------------------------------------------------------------------

The second (and far more serious) problem is that by treating nested typedefs
as local to the classes in which they are nested, g++ is deviating unnecessarily
from the behavior of Cfront 2.0 (which gives class-nested typedefs global
scope).  Thus, the first example above compiles without error using Cfront 2.0,
but gets errors using recent editions of g++.

The fix is simply to have g++ give class-nested typedefs global scope.  The
following short patch implements this change.  (Your line numbers may vary.)

Note that it may *someday* be a good idea to treat class-local typedefs as
being local to the classes in which they are nested, but that should not
happen yet because (a) the C++ community should first embrace and bless such
a change, and (b) if typedefs can be local to a class, then the extension of
the scope of class-local entities to the formal parameter lists of class member
functions should also be implemented at the same time (in order to prevent
bogus errors on examples like the first one shown above).

// rfg

*** cplus-decl2.c-	Thu Dec  7 12:54:18 1989
--- cplus-decl2.c	Sat Dec 30 11:41:33 1989
***************
*** 372,378 ****
      {
        TREE_NONLOCAL (value) = 1;
!       CLASSTYPE_LOCAL_TYPEDECLS (current_class_type) = 1;
!       pushdecl_class_level (value);
!       return value;
      }
  
--- 372,377 ----
      {
        TREE_NONLOCAL (value) = 1;
!       pushdecl_top_level (value);
!       return void_type_node;
      }