+1999-05-25 Mark Mitchell <mark@codesourcery.com>
+
+ * class.c (finish_vtbls): Copy BINFO_VIRTUALs before using it to
+ intialize a vtable.
+
+ * cp-tree.h (NAMESPACE_LEVEL): Reformat.
+ (lang_decl_flags): Document MEMFUNC_POINTER_TO. Save four bytes
+ by combining TEMPLATE_INFO and LEVEL into a single union.
+ (DECL_TEMPLATE_INFO): Reformat.
+ (DECL_SAVED_TREE): Document.
+ (DECL_TEMPLATE_INJECT): Remove.
+ * class.c (finish_struct): Remove code to deal with
+ DECL_TEMPLATE_INJECT.
+
+ * decl.c (maybe_process_template_type_declaration): Handle all new
+ types in templates uniformly.
+ * method.c (bulid_overload_identifier): Use CP_DECL_CONTEXT, not
+ DECL_CONTEXT.
+ * pt.c (lookup_template_class): Inject template instantiations of
+ forward-declarations.
+ (instantiate_class_template): Remove code processing
+ DECL_TEMPLATE_INJECT.
+
+ * pt.c (lookup_template_class): Tweak lookup to find member
+ templates.
+
+ * pt.c (tsubst_expr, case ASM_STMT): Don't tsubst into
+ ASM_CV_QUAL.
+ * semantics.c (finish_asm_stmt): Make strings permanent if they're
+ used in a template.
+
1999-05-25 Jason Merrill <jason@yorick.cygnus.com>
* typeck.c (casts_away_constness, casts_away_constness_r): Strip both
decl = BINFO_VTABLE (binfo);
context = DECL_CONTEXT (decl);
DECL_CONTEXT (decl) = 0;
- if (DECL_INITIAL (decl) != BINFO_VIRTUALS (binfo))
- DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE,
- BINFO_VIRTUALS (binfo));
+
+ /* We make a copy here in case we need to replace pure
+ virtual functions with __pure_virtual. We don't want to
+ mess up BINFO_VIRTUALS when we do this. */
+ DECL_INITIAL (decl) = copy_list (BINFO_VIRTUALS (binfo));
+ DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE,
+ DECL_INITIAL (decl));
+
cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0, 0);
DECL_CONTEXT (decl) = context;
}
if (processing_template_decl)
{
- tree d = getdecls ();
- for (; d; d = TREE_CHAIN (d))
- {
- /* If this is the decl for the class or one of the template
- parms, we've seen all the injected decls. */
- if ((TREE_CODE (d) == TYPE_DECL
- && (TREE_TYPE (d) == t
- || TREE_CODE (TREE_TYPE (d)) == TEMPLATE_TYPE_PARM
- || TREE_CODE (TREE_TYPE (d)) == TEMPLATE_TEMPLATE_PARM))
- || TREE_CODE (d) == CONST_DECL)
- break;
- /* Don't inject cache decls. */
- else if (IDENTIFIER_TEMPLATE (DECL_NAME (d)))
- continue;
- DECL_TEMPLATE_INJECT (CLASSTYPE_TI_TEMPLATE (t))
- = tree_cons (NULL_TREE, d,
- DECL_TEMPLATE_INJECT (CLASSTYPE_TI_TEMPLATE (t)));
- }
finish_struct_methods (t);
TYPE_SIZE (t) = integer_zero_node;
}
&& TREE_VALUE (TYPE_RAISES_EXCEPTIONS (NODE)) == NULL_TREE)
/* The binding level associated with the namespace. */
-#define NAMESPACE_LEVEL(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.level)
+#define NAMESPACE_LEVEL(NODE) \
+ (DECL_LANG_SPECIFIC(NODE)->decl_flags.u.level)
\f
/* If a DECL has DECL_LANG_SPECIFIC, it is either a lang_decl_flags or
tree access;
tree context;
+
+ /* In a template FUNCTION_DECL, this is DECL_SAVED_TREE.
+ In a non-template FUNCTION_DECL, this is DECL_MEMFUNC_POINTER_TO.
+ In a FIELD_DECL, this is DECL_MEMFUNC_POINTING_TO. */
tree memfunc_pointer_to;
- tree template_info;
- struct binding_level *level;
+
+ union {
+ /* In a FUNCTION_DECL, this is DECL_TEMPLATE_INFO. */
+ tree template_info;
+
+ /* In a NAMESPACE_DECL, this is NAMESPACE_LEVEL. */
+ struct binding_level *level;
+ } u;
};
struct lang_decl
#define DECL_MEMFUNC_POINTING_TO(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.memfunc_pointer_to)
/* For a VAR_DECL or FUNCTION_DECL: template-specific information. */
-#define DECL_TEMPLATE_INFO(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.template_info)
+#define DECL_TEMPLATE_INFO(NODE) \
+ (DECL_LANG_SPECIFIC(NODE)->decl_flags.u.template_info)
/* Template information for a RECORD_TYPE or UNION_TYPE. */
#define CLASSTYPE_TEMPLATE_INFO(NODE) (TYPE_LANG_SPECIFIC(NODE)->template_info)
the class definition is complete. */
#define TEMPLATE_PARMS_FOR_INLINE(NODE) TREE_LANG_FLAG_1 (NODE)
+/* In a template FUNCTION_DECL, the tree structure that will be
+ substituted into to obtain instantiations. */
#define DECL_SAVED_TREE(NODE) DECL_MEMFUNC_POINTER_TO (NODE)
+
#define COMPOUND_STMT_NO_SCOPE(NODE) TREE_LANG_FLAG_0 (NODE)
#define NEW_EXPR_USE_GLOBAL(NODE) TREE_LANG_FLAG_0 (NODE)
#define DELETE_EXPR_USE_GLOBAL(NODE) TREE_LANG_FLAG_0 (NODE)
This list is not used for static variable templates. */
#define DECL_TEMPLATE_SPECIALIZATIONS(NODE) DECL_SIZE(NODE)
-#define DECL_TEMPLATE_INJECT(NODE) DECL_INITIAL(NODE)
/* Nonzero for a DECL which is actually a template parameter. */
#define DECL_TEMPLATE_PARM_P(NODE) \
|| TREE_CODE (type) == ENUMERAL_TYPE, 0);
- if (/* If !GLOBALIZE then we are looking at a definition.
- It may not be a primary template. (For example, in:
-
- template <class T>
- struct S1 { class S2 {}; }
-
- we have to push_template_decl for S2.) */
- (processing_template_decl && !globalize)
- /* If we are declaring a friend template class, we will
- have GLOBALIZE set, since something like:
-
- template <class T>
- struct S1 {
- template <class U>
- friend class S2;
- };
-
- declares S2 to be at global scope. */
- || PROCESSING_REAL_TEMPLATE_DECL_P ())
+ if (processing_template_decl)
{
/* This may change after the call to
push_template_decl_real, but we want the original value. */
&& CLASS_TYPE_P (TREE_TYPE (name))
&& CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name))
&& (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (TREE_TYPE (name)))
- || (TREE_CODE (DECL_CONTEXT (CLASSTYPE_TI_TEMPLATE
- (TREE_TYPE (name))))
+ || (TREE_CODE (CP_DECL_CONTEXT (CLASSTYPE_TI_TEMPLATE
+ (TREE_TYPE (name))))
== FUNCTION_DECL)))
{
/* NAME is the TYPE_DECL for a template specialization. */
{
if (context)
push_decl_namespace (context);
- if (current_class_type != NULL_TREE)
- template =
- maybe_get_template_decl_from_type_decl
- (IDENTIFIER_CLASS_VALUE (d1));
- if (template == NULL_TREE)
- template = lookup_name_nonclass (d1);
+ template = lookup_name (d1, /*prefer_type=*/0);
+ template = maybe_get_template_decl_from_type_decl (template);
if (context)
pop_decl_namespace ();
}
if (found)
found = TREE_VALUE (found);
}
-
+
if (found)
{
pop_momentary ();
return found;
}
- /* Since we didn't find the type, we'll have to create it.
- Since we'll be saving this type on the
- DECL_TEMPLATE_INSTANTIATIONS list, it must be permanent. */
- push_obstacks (&permanent_obstack, &permanent_obstack);
-
/* This type is a "partial instantiation" if any of the template
arguments still inolve template parameters. Note that we set
IS_PARTIAL_INSTANTIATION for partial specializations as
well. */
is_partial_instantiation = uses_template_parms (arglist);
+ if (!is_partial_instantiation
+ && !PRIMARY_TEMPLATE_P (template)
+ && TREE_CODE (CP_DECL_CONTEXT (template)) == NAMESPACE_DECL)
+ {
+ pop_momentary ();
+ found = xref_tag_from_type (TREE_TYPE (template),
+ DECL_NAME (template),
+ /*globalize=*/1);
+ return found;
+ }
+
+ /* Since we didn't find the type, we'll have to create it.
+ Since we'll be saving this type on the
+ DECL_TEMPLATE_INSTANTIATIONS list, it must be permanent. */
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+
/* Create the type. */
if (TREE_CODE (template_type) == ENUMERAL_TYPE)
{
--processing_template_decl;
}
- /* This does injection for friend functions. */
- if (!processing_template_decl)
- {
- t = tsubst (DECL_TEMPLATE_INJECT (template), args,
- /*complain=*/1, NULL_TREE);
-
- for (; t; t = TREE_CHAIN (t))
- {
- tree d = TREE_VALUE (t);
-
- if (TREE_CODE (d) == TYPE_DECL)
- /* Already injected. */;
- else
- pushdecl (d);
- }
- }
-
for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t))
if (TREE_CODE (t) == FIELD_DECL)
{
case ASM_STMT:
lineno = TREE_COMPLEXITY (t);
- finish_asm_stmt (tsubst_expr (ASM_CV_QUAL (t), args, complain, in_decl),
+ finish_asm_stmt (ASM_CV_QUAL (t),
tsubst_expr (ASM_STRING (t), args, complain, in_decl),
tsubst_expr (ASM_OUTPUTS (t), args, complain, in_decl),
tsubst_expr (ASM_INPUTS (t), args, complain, in_decl),
void
finish_asm_stmt (cv_qualifier, string, output_operands,
- input_operands, clobbers)
+ input_operands, clobbers)
tree cv_qualifier;
tree string;
tree output_operands;
tree clobbers;
{
if (TREE_CHAIN (string))
- string = combine_strings (string);
+ {
+ if (processing_template_decl)
+ {
+ /* We need to build the combined string on the permanent
+ obstack so that we can use it during instantiations. */
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+ }
+
+ string = combine_strings (string);
+
+ if (processing_template_decl)
+ pop_obstacks ();
+ }
if (processing_template_decl)
{
--- /dev/null
+// Build don't link:
+// Origin: "Weidmann, Nicholas" <nicholas.weidmann@swx.ch>
+// Skip if not target: i?86-*-linux*
+
+template<int i> int foo(int v)
+{
+ __asm__ __volatile__("addl %1, %0" : "=a" (v) : "b" (i));
+
+ return v;
+}
+
+int bar(int i)
+{
+ return foo<123>(i);
+}
+
--- /dev/null
+// Build don't link:
+// Origin: "Weidmann, Nicholas" <nicholas.weidmann@swx.ch>
+// Skip if not target: i?86-*-linux*
+
+typedef void (function_ptr)(int);
+
+void foo(int)
+{
+}
+
+template<function_ptr ptr> void doit(int i)
+{
+ __asm__("pushl %0\n\t"
+ "call *%1\n\t"
+ "popl %0"
+ :
+ : "a" (i), "b" (ptr));
+}
+
+void bar()
+{
+ doit<foo>(123);
+}
--- /dev/null
+// Build don't link:
+// Origin: Mark Mitchell <mark@codesourcery.com>
+
+template <int I>
+struct S {
+ struct T* x;
+};
+
+template struct S<2>;
+
+T* t;
--- /dev/null
+// Build don't link:
+// Origin: Mark Mitchell <mark@codesourcery.com>
+// Special g++ Options: -Wno-non-template-friend
+
+template<int I>
+class C {
+ friend void f(struct X *);
+};
+
+template class C<0>;
+
+class D {
+ friend void f(struct X*);
+};
+
--- /dev/null
+// Build don't link:
+// Origin: <Corey Kosak> kosak@cs.cmu.edu
+
+struct moo {
+ template<bool x> struct cow {};
+
+ template<bool x>
+ struct moo2 {
+ void func(cow<x> &c) { }
+ };
+};