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.
&& !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
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));
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')
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. */
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))
== 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;
--- /dev/null
+// 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);
+ };
+};