OSDN Git Service

* cp-tree.def (TYPENAME_TYPE): Add to documentation.
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 15 Oct 1998 11:27:43 +0000 (11:27 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 15 Oct 1998 11:27:43 +0000 (11:27 +0000)
* cp-tree.h (TYPENAME_TYPE_FULLNAME): Document.
(build_typename_type): New function.
* decl.c (build_typename_type): Broken out from ...
(make_typename_type): Use it.
* search.c (lookup_field): Likewise.

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

gcc/cp/cp-tree.def
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/search.c
gcc/testsuite/g++.old-deja/g++.pt/typename14.C [new file with mode: 0644]

index 20a0117..2b24969 100644 (file)
@@ -143,7 +143,10 @@ DEFTREECODE (TEMPLATE_TYPE_PARM, "template_type_parm", 't', 0)
    The TYPE_FIELDS value will be a TEMPLATE_PARM_INDEX.  */
 DEFTREECODE (TEMPLATE_TEMPLATE_PARM, "template_template_parm", 't', 0)
 
-/* A type designated by 'typename T::t'. */
+/* A type designated by `typename T::t'.  TYPE_CONTEXT is `T',
+   TYPE_NAME is a TYPE_DECL for `t'.  If TREE_TYPE is present, this
+   type was generated by the implicit typename extension, and the
+   TREE_TYPE is a _TYPE from a baseclass of `T'.  */
 DEFTREECODE (TYPENAME_TYPE, "typename_type", 't', 0)
 
 /* A thunk is a stub function.
index 6632f8a..6a74d26 100644 (file)
@@ -1337,6 +1337,10 @@ struct lang_decl
    && !CLASSTYPE_USE_TEMPLATE (NODE) \
    && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE)))
 
+/* The name used by the user to name the typename type.  Typically,
+   this is an IDENTIFIER_NODE, and the same as the DECL_NAME on the
+   corresponding TYPE_DECL.  However, this may also be a
+   TEMPLATE_ID_EXPR if we had something like `typename X::Y<T>'.  */
 #define TYPENAME_TYPE_FULLNAME(NODE)   CLASSTYPE_SIZE (NODE)
 
 /* Nonzero in INTEGER_CST means that this int is negative by dint of
@@ -2543,6 +2547,7 @@ extern tree binding_for_name                    PROTO((tree, tree));
 extern tree namespace_binding                   PROTO((tree, tree));
 extern void set_namespace_binding               PROTO((tree, tree, tree));
 extern tree lookup_namespace_name              PROTO((tree, tree));
+extern tree build_typename_type                 PROTO((tree, tree, tree, tree));
 extern tree make_typename_type                 PROTO((tree, tree));
 extern tree lookup_name_nonclass               PROTO((tree));
 extern tree lookup_function_nonclass            PROTO((tree, tree));
index 8d9337f..8facd96 100644 (file)
@@ -4776,11 +4776,51 @@ lookup_namespace_name (namespace, name)
   return error_mark_node;
 }
 
+/* Build a TYPENAME_TYPE.  If the type is `typename T::t', CONTEXT is
+   the type of `T', NAME is the IDENTIFIER_NODE for `t'.  If BASE_TYPE
+   is non-NULL, this type is being created by the implicit typename
+   extension, and BASE_TYPE is a type named `t' in some base class of
+   `T' which depends on template parameters.  
+
+   Returns the new TYPENAME_TYPE.  */
+
+tree
+build_typename_type (context, name, fullname, base_type)
+     tree context;
+     tree name;
+     tree fullname;
+     tree base_type;
+{
+  tree t;
+  tree d;
+
+  if (processing_template_decl)
+    push_obstacks (&permanent_obstack, &permanent_obstack);
+
+  /* Build the TYPENAME_TYPE.  */
+  t = make_lang_type (TYPENAME_TYPE);
+  TYPE_CONTEXT (t) = FROB_CONTEXT (context);
+  TYPENAME_TYPE_FULLNAME (t) = fullname;
+  TREE_TYPE (t) = base_type;
+  CLASSTYPE_GOT_SEMICOLON (t) = 1;
+
+  /* Build the corresponding TYPE_DECL.  */
+  d = build_decl (TYPE_DECL, name, t);
+  TYPE_NAME (TREE_TYPE (d)) = d;
+  TYPE_STUB_DECL (TREE_TYPE (d)) = d;
+  DECL_CONTEXT (d) = FROB_CONTEXT (context);
+
+  if (processing_template_decl)
+    pop_obstacks ();
+
+  return t;
+}
+
 tree
 make_typename_type (context, name)
      tree context, name;
 {
-  tree t, d;
+  tree t;
   tree fullname;
 
   if (TREE_CODE_CLASS (TREE_CODE (name)) == 't')
@@ -4846,22 +4886,8 @@ make_typename_type (context, name)
          return TREE_TYPE (t);
        }
     }
-
-  if (processing_template_decl)
-    push_obstacks (&permanent_obstack, &permanent_obstack);
-  t = make_lang_type (TYPENAME_TYPE);
-  TYPENAME_TYPE_FULLNAME (t) = fullname;
-  d = build_decl (TYPE_DECL, name, t);
-  if (processing_template_decl)
-    pop_obstacks ();
-
-  TYPE_CONTEXT (t) = FROB_CONTEXT (context);
-  TYPE_NAME (TREE_TYPE (d)) = d;
-  TYPE_STUB_DECL (TREE_TYPE (d)) = d;
-  DECL_CONTEXT (d) = FROB_CONTEXT (context);
-  CLASSTYPE_GOT_SEMICOLON (t) = 1;
-
-  return t;
+  
+  return build_typename_type (context, name, fullname,  NULL_TREE);
 }
 
 /* Select the right _DECL from multiple choices. */
index be6cffc..50afeee 100644 (file)
@@ -1178,7 +1178,14 @@ lookup_field (xbasetype, name, protect, want_type)
       rval = error_mark_node;
     }
 
-  /* Do implicit typename stuff.  */
+  /* Do implicit typename stuff.  This code also handles out-of-class
+     definitions of nested classes whose enclosing class is a
+     template.  For example:
+    
+       template <class T> struct S { struct I { void f(); }; };
+       template <class T> void S<T>::I::f() {}
+
+     will come through here to handle `S<T>::I'.  */
   if (rval && TREE_CODE (rval) == TYPE_DECL
       && processing_template_decl
       && ! currently_open_class (BINFO_TYPE (rval_binfo))
@@ -1191,9 +1198,9 @@ lookup_field (xbasetype, name, protect, want_type)
                == current_class_type))
          break;
 
-      entry = make_typename_type (BINFO_TYPE (binfo), name);
-      TREE_TYPE (entry) = TREE_TYPE (rval);
-      rval = TYPE_MAIN_DECL (entry);
+      entry = build_typename_type (BINFO_TYPE (binfo), name,  name, 
+                                  TREE_TYPE (rval));
+      return TYPE_STUB_DECL (entry);
     }
 
   return rval;
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/typename14.C b/gcc/testsuite/g++.old-deja/g++.pt/typename14.C
new file mode 100644 (file)
index 0000000..7365b66
--- /dev/null
@@ -0,0 +1,15 @@
+// Build don't link:
+// Special g++ Options:
+
+template <class T>
+struct B {
+  typedef T X;
+};
+
+template <class T>
+struct S : public B<T>
+{
+  struct I {
+    void f(X x);
+  };
+};