summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog75
-rw-r--r--gcc/cp/class.c32
-rw-r--r--gcc/cp/cp-tree.def6
-rw-r--r--gcc/cp/decl.c42
-rw-r--r--gcc/cp/error.c6
-rw-r--r--gcc/cp/method.c3
-rw-r--r--gcc/cp/parse.y23
-rw-r--r--gcc/cp/pt.c37
-rw-r--r--gcc/cp/tree.c4
9 files changed, 192 insertions, 36 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 49b3e9a83f6..471bd9b2a1c 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,80 @@
+Fri Mar 1 13:09:33 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (instantiate_class_template): If we don't have a pattern
+ yet, that's OK.
+ (coerce_template_parms): If we see a local class, bail.
+
+ * decl.c (grok_reference_init): Make sure there's a type before
+ checking its code.
+
+ * pt.c (do_function_instantiation): Avoid crashing on invalid decls.
+ (push_template_decl): Ditto.
+
+ * parse.y (named_class_head): Set
+ CLASSTYPE_TEMPLATE_SPECIALIZATION here if we have basetypes.
+
+ * decl.c (xref_tag): Diagnose redeclaration of template
+ type-parameter name.
+
+ * error.c (dump_type): Handle anonymous template type parms.
+
+ * pt.c (instantiate_template): Use TYPE_MAIN_DECL instead of
+ TYPE_STUB_DECL.
+ (coerce_template_parms): Ditto.
+
+Thu Feb 29 16:26:01 1996 Mike Stump <mrs@cygnus.com>
+
+ * class.c (instantiate_type, case {ARRAY,INDIRECT}_REF,
+ case ADDR_EXPR): Don't modify rhs if a subinstantiation fails.
+
+Thu Feb 29 08:20:25 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (instantiate_template): Take the MAIN_VARIANT of the type
+ before trying to get its STUB_DECL.
+ (coerce_template_parms): Ditto.
+
+ * parse.y (template_type_parm): If they didn't use 'class',
+ pretend they did after giving an error.
+
+ * pt.c (coerce_template_parms): Diagnose use of local class.
+
+ * decl.c (grok_reference_init): Use instantiate_type.
+
+ * error.c (dump_expr): Handle TEMPLATE_DECLs.
+
+ * parse.y (named_class_head): Diagnose mismatching types and tags.
+
+ * decl.c (pushdecl): Type decls and class templates clash with
+ artificial type decls, not hide them.
+
+ * decl.c (redeclaration_error_message): Diagnose redefinition of
+ templates properly.
+ (duplicate_decls): Diagnose disallowed overloads for template
+ functions, too.
+
+ * decl.c (start_decl): Call complete_type before checking for a
+ destructor.
+
+ * pt.c (tsubst): Use tsubst_expr on the elts of a VEC.
+
+ * decl.c (xref_tag): A TEMPLATE_TYPE_PARM is a match.
+
Wed Feb 28 09:28:44 1996 Jason Merrill <jason@yorick.cygnus.com>
+ * decl.c (grok_op_properties): Don't check for operator++(int) in
+ a template.
+
+ * tree.c (perm_manip): Return a copy of variable and function
+ decls with external linkage.
+
+ * tree.def: Change some of the min tree codes to type "1".
+ * pt.c (uses_template_parms): Handle 'e's, return 1 for LOOKUP_EXPRs.
+ * method.c (build_overload_int): Emit something arbitrary for
+ anything but an INTEGER_CST if we're in a template.
+
+ * decl.c (cp_finish_decl): Call complete_type before deciding
+ whether or not to lay out the decl.
+
* lex.c (do_identifier): Check for DECL_INITIAL before using it.
Tue Feb 27 16:35:32 1996 Jason Merrill <jason@yorick.cygnus.com>
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 4bceaa16310..e5ce5baa224 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -4842,9 +4842,12 @@ root_lang_context_p ()
/* Type instantiation routines. */
-/* This function will instantiate the type of the expression given
- in RHS to match the type of LHSTYPE. If LHSTYPE is NULL_TREE,
- or other errors exist, the TREE_TYPE of RHS will be ERROR_MARK_NODE.
+/* This function will instantiate the type of the expression given in
+ RHS to match the type of LHSTYPE. If errors exist, then return
+ error_mark_node. If only complain is COMPLAIN is set. If we are
+ not complaining, never modify rhs, as overload resolution wants to
+ try many possible instantiations, in hopes that at least one will
+ work.
This function is used in build_modify_expr, convert_arguments,
build_c_cast, and compute_conversion_costs. */
@@ -4880,14 +4883,18 @@ instantiate_type (lhstype, rhs, complain)
case INDIRECT_REF:
case ARRAY_REF:
- TREE_TYPE (rhs) = lhstype;
- lhstype = build_pointer_type (lhstype);
- TREE_OPERAND (rhs, 0)
- = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain);
- if (TREE_OPERAND (rhs, 0) == error_mark_node)
- return error_mark_node;
+ {
+ tree new_rhs;
- return rhs;
+ new_rhs = instantiate_type (build_pointer_type (lhstype),
+ TREE_OPERAND (rhs, 0), complain);
+ if (new_rhs == error_mark_node)
+ return error_mark_node;
+
+ TREE_TYPE (rhs) = lhstype;
+ TREE_OPERAND (rhs, 0) = new_rhs;
+ return rhs;
+ }
case NOP_EXPR:
rhs = copy_node (TREE_OPERAND (rhs, 0));
@@ -5262,13 +5269,12 @@ instantiate_type (lhstype, rhs, complain)
error ("type for resolving address of overloaded function must be pointer type");
return error_mark_node;
}
- TREE_TYPE (rhs) = lhstype;
- lhstype = TREE_TYPE (lhstype);
{
- tree fn = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain);
+ tree fn = instantiate_type (TREE_TYPE (lhstype), TREE_OPERAND (rhs, 0), complain);
if (fn == error_mark_node)
return error_mark_node;
mark_addressable (fn);
+ TREE_TYPE (rhs) = lhstype;
TREE_OPERAND (rhs, 0) = fn;
TREE_CONSTANT (rhs) = staticp (fn);
}
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index 51edcb00a07..d965783188a 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -116,9 +116,9 @@ DEFTREECODE (USING_DECL, "using_decl", "d", 0)
DEFTREECODE (LOOKUP_EXPR, "lookup_expr", "e", 2)
DEFTREECODE (MODOP_EXPR, "modop_expr", "e", 3)
-DEFTREECODE (CAST_EXPR, "cast_expr", "e", 1)
-DEFTREECODE (REINTERPRET_CAST_EXPR, "reinterpret_cast_expr", "e", 1)
-DEFTREECODE (SIZEOF_EXPR, "sizeof_expr", "e", 1)
+DEFTREECODE (CAST_EXPR, "cast_expr", "1", 1)
+DEFTREECODE (REINTERPRET_CAST_EXPR, "reinterpret_cast_expr", "1", 1)
+DEFTREECODE (SIZEOF_EXPR, "sizeof_expr", "1", 1)
DEFTREECODE (ARROW_EXPR, "arrow_expr", "e", 1)
DEFTREECODE (DOTSTAR_EXPR, "dotstar_expr", "e", 2)
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 2dd92e56610..8d1d8cda336 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -2501,6 +2501,14 @@ duplicate_decls (newdecl, olddecl)
cp_error_at ("conflicts with previous declaration `%#D'",
olddecl);
}
+ else if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == FUNCTION_DECL
+ && TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == FUNCTION_DECL
+ && compparms (TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl))),
+ TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (newdecl))), 3))
+ {
+ cp_error ("new declaration `%#D'", newdecl);
+ cp_error_at ("ambiguates old declaration `%#D'", olddecl);
+ }
return 0;
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
@@ -3044,8 +3052,15 @@ pushdecl (x)
}
else if (TREE_CODE (t) != TREE_CODE (x))
{
- if ((TREE_CODE (t) == TYPE_DECL && DECL_ARTIFICIAL (t))
- || (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)))
+ if ((TREE_CODE (t) == TYPE_DECL && DECL_ARTIFICIAL (t)
+ && TREE_CODE (x) != TYPE_DECL
+ && ! (TREE_CODE (x) == TEMPLATE_DECL
+ && TREE_CODE (DECL_TEMPLATE_RESULT (x)) == TYPE_DECL))
+ || (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)
+ && TREE_CODE (t) != TYPE_DECL
+ && ! (TREE_CODE (t) == TEMPLATE_DECL
+ && (TREE_CODE (DECL_TEMPLATE_RESULT (t))
+ == TYPE_DECL))))
{
/* We do nothing special here, because C++ does such nasty
things with TYPE_DECLs. Instead, just let the TYPE_DECL
@@ -3714,7 +3729,12 @@ redeclaration_error_message (newdecl, olddecl)
}
else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
- if (DECL_INITIAL (olddecl) && DECL_INITIAL (newdecl))
+ if ((TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == FUNCTION_DECL
+ && DECL_INITIAL (DECL_TEMPLATE_RESULT (newdecl))
+ && DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl)))
+ || (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL
+ && TYPE_SIZE (TREE_TYPE (newdecl))
+ && TYPE_SIZE (TREE_TYPE (olddecl))))
return "redefinition of `%#D'";
return 0;
}
@@ -5737,7 +5757,7 @@ start_decl (declarator, declspecs, initialized, raises)
/* Don't lose if destructors must be executed at file-level. */
if (! current_template_parms && TREE_STATIC (decl)
- && TYPE_NEEDS_DESTRUCTOR (type)
+ && TYPE_NEEDS_DESTRUCTOR (complete_type (type))
&& !TREE_PERMANENT (decl))
{
push_obstacks (&permanent_obstack, &permanent_obstack);
@@ -6029,6 +6049,10 @@ grok_reference_init (decl, type, init, cleanupp)
return;
}
+ if (TREE_TYPE (init) && TREE_CODE (TREE_TYPE (init)) == UNKNOWN_TYPE)
+ /* decay_conversion is probably wrong for references to functions. */
+ init = decay_conversion (instantiate_type (TREE_TYPE (type), init, 1));
+
if (TREE_CODE (init) == TREE_LIST)
init = build_compound_expr (init);
@@ -6417,7 +6441,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
if (TREE_CODE (decl) == VAR_DECL)
{
if (DECL_SIZE (decl) == NULL_TREE
- && TYPE_SIZE (TREE_TYPE (decl)) != NULL_TREE)
+ && TYPE_SIZE (complete_type (TREE_TYPE (decl))) != NULL_TREE)
layout_decl (decl, 0);
if (TREE_STATIC (decl) && DECL_SIZE (decl) == NULL_TREE)
@@ -10152,6 +10176,7 @@ grok_op_properties (decl, virtualp, friendp)
{
if ((name == ansi_opname[(int) POSTINCREMENT_EXPR]
|| name == ansi_opname[(int) POSTDECREMENT_EXPR])
+ && ! current_template_parms
&& TREE_VALUE (TREE_CHAIN (argtypes)) != integer_type_node)
{
if (methodp)
@@ -10259,11 +10284,16 @@ xref_tag (code_type_node, name, binfo, globalize)
}
else
t = IDENTIFIER_TYPE_VALUE (name);
- if (t && TREE_CODE (t) != code)
+ if (t && TREE_CODE (t) != code && TREE_CODE (t) != TEMPLATE_TYPE_PARM)
t = NULL_TREE;
if (! globalize)
{
+ if (pedantic && t && TREE_CODE (t) == TEMPLATE_TYPE_PARM)
+ {
+ cp_pedwarn ("redeclaration of template type-parameter `%T'", name);
+ cp_pedwarn_at (" previously declared here", t);
+ }
/* If we know we are defining this tag, only look it up in this scope
* and don't try to find it as a type. */
if (t && TYPE_CONTEXT(t) && TREE_MANGLED (name))
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 3c1d9a2e959..99f72fba9df 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -209,7 +209,10 @@ dump_type (t, v)
break;
case TEMPLATE_TYPE_PARM:
- OB_PUTID (TYPE_IDENTIFIER (t));
+ if (TYPE_IDENTIFIER (t))
+ OB_PUTID (TYPE_IDENTIFIER (t));
+ else
+ OB_PUTS ("{anonymous template type parm}");
break;
/* This is not always necessary for pointers and such, but doing this
@@ -941,6 +944,7 @@ dump_expr (t, nop)
case FIELD_DECL:
case CONST_DECL:
case FUNCTION_DECL:
+ case TEMPLATE_DECL:
dump_decl (t, -1);
break;
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 5156121ffb7..6b45ff4008e 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -364,7 +364,8 @@ build_overload_int (value)
OB_PUTC ('_');
return;
}
- else if (uses_template_parms (value))
+ else if (current_template_parms
+ && TREE_CODE (value) != INTEGER_CST)
/* We don't ever want this output, but it's inconvenient not to
be able to build the string. This should cause assembler
errors we'll notice. */
diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y
index be782b7eb9e..c53bef3b6be 100644
--- a/gcc/cp/parse.y
+++ b/gcc/cp/parse.y
@@ -427,7 +427,10 @@ template_type_parm:
if (TREE_PURPOSE ($$) == signature_type_node)
sorry ("signature as template type parameter");
else if (TREE_PURPOSE ($$) != class_type_node)
- pedwarn ("template type parameters must use the keyword `class'");
+ {
+ pedwarn ("template type parameters must use the keyword `class'");
+ TREE_PURPOSE ($$) = class_type_node;
+ }
}
| aggr identifier
{ $$ = build_tree_list ($1, $2); goto ttpa; }
@@ -2129,8 +2132,24 @@ named_class_head:
| named_complex_class_head_sans_basetype maybe_base_class_list
{
$$ = TREE_TYPE ($1);
+ if (TREE_INT_CST_LOW (current_aggr) == union_type
+ && TREE_CODE ($$) != UNION_TYPE)
+ cp_pedwarn ("`union' tag used in declaring `%#T'", $$);
+ else if (TREE_CODE ($$) == UNION_TYPE
+ && TREE_INT_CST_LOW (current_aggr) != union_type)
+ cp_pedwarn ("non-`union' tag used in declaring `%#T'", $$);
if ($2)
- xref_basetypes (current_aggr, $1, $$, $2);
+ {
+ if (IS_AGGR_TYPE ($$) && CLASSTYPE_USE_TEMPLATE ($$))
+ {
+ if (CLASSTYPE_IMPLICIT_INSTANTIATION ($$)
+ && TYPE_SIZE ($$) == NULL_TREE)
+ SET_CLASSTYPE_TEMPLATE_SPECIALIZATION ($$);
+ else if (CLASSTYPE_TEMPLATE_INSTANTIATION ($$))
+ cp_error ("specialization after instantiation of `%T'", $$);
+ }
+ xref_basetypes (current_aggr, $1, $$, $2);
+ }
}
;
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 5a30c9a2301..02e2822144e 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -253,6 +253,8 @@ push_template_decl (decl)
CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (tmpl)) = info;
DECL_NAME (decl) = classtype_mangled_name (TREE_TYPE (decl));
}
+ else if (! DECL_LANG_SPECIFIC (decl))
+ cp_error ("template declaration of `%#D'", decl);
else
DECL_TEMPLATE_INFO (decl) = info;
}
@@ -352,12 +354,24 @@ coerce_template_parms (parms, arglist, in_decl)
continue;
}
if (is_type)
- val = groktypename (arg);
+ {
+ val = groktypename (arg);
+ if (! current_template_parms)
+ {
+ tree t = target_type (val);
+ if (IS_AGGR_TYPE (t)
+ && decl_function_context (TYPE_MAIN_DECL (t)))
+ {
+ cp_error ("type `%T' composed from a local class is not a valid template-argument", val);
+ return error_mark_node;
+ }
+ }
+ }
else
{
tree t = tsubst (TREE_TYPE (parm), &TREE_VEC_ELT (vec, 0),
TREE_VEC_LENGTH (vec), in_decl);
- if (current_template_parms && uses_template_parms (arg))
+ if (current_template_parms)
val = arg;
else
val = digest_init (t, arg, (tree *) 0);
@@ -844,6 +858,7 @@ uses_template_parms (t)
/* NOTREACHED */
return 0;
+ case LOOKUP_EXPR:
case TYPENAME_TYPE:
return 1;
@@ -857,7 +872,7 @@ uses_template_parms (t)
{
case '1':
case '2':
- case '3':
+ case 'e':
case '<':
{
int i;
@@ -980,11 +995,7 @@ instantiate_class_template (type)
pattern = TREE_TYPE (template);
if (TYPE_SIZE (pattern) == NULL_TREE)
- {
- cp_error_at ("no definition available for `%#D'", template);
- cp_error (" trying to instantiate `%#T'", type);
- return error_mark_node;
- }
+ return type;
TYPE_BEING_DEFINED (type) = 1;
@@ -1608,7 +1619,7 @@ tsubst (t, args, nargs, in_decl)
for (i = 0; i < len; i++)
{
- elts[i] = tsubst_copy (TREE_VEC_ELT (t, i), args, nargs, in_decl);
+ elts[i] = tsubst_expr (TREE_VEC_ELT (t, i), args, nargs, in_decl);
if (elts[i] != TREE_VEC_ELT (t, i))
need_new = 1;
}
@@ -2287,7 +2298,7 @@ instantiate_template (tmpl, targ_ptr)
if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
{
tree nt = target_type (t);
- if (IS_AGGR_TYPE (nt) && decl_function_context (TYPE_STUB_DECL (nt)))
+ if (IS_AGGR_TYPE (nt) && decl_function_context (TYPE_MAIN_DECL (nt)))
{
cp_error ("type `%T' composed from a local class is not a valid template-argument", t);
cp_error (" trying to instantiate `%D'", tmpl);
@@ -2696,6 +2707,12 @@ do_function_instantiation (declspecs, declarator, storage)
tree result = NULL_TREE;
int extern_p = 0;
+ if (! DECL_LANG_SPECIFIC (decl))
+ {
+ cp_error ("explicit instantiation of non-template `%#D'", decl);
+ return;
+ }
+
/* If we've already seen this template instance, use it. */
if (name = DECL_ASSEMBLER_NAME (decl),
fn = IDENTIFIER_GLOBAL_VALUE (name),
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index e5eb64749e5..8fbd59bcc9c 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1625,6 +1625,10 @@ perm_manip (t)
{
if (TREE_PERMANENT (t))
return t;
+ /* Support `void f () { extern int i; A<&i> a; }' */
+ if ((TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == FUNCTION_DECL)
+ && TREE_PUBLIC (t))
+ return copy_node (t);
return NULL_TREE;
}