aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@markmitchell.com>1998-08-07 16:33:34 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>1998-08-07 16:33:34 +0000
commitae58fa02be510bc8a7bb014a5f3f511594848d22 (patch)
treed092a56e00a569bdd8d9357a8f77fb52cca950e7 /gcc
parent523633872ac859b97c453f3c7356201f934e3478 (diff)
downloadgcc-ae58fa02be510bc8a7bb014a5f3f511594848d22.zip
gcc-ae58fa02be510bc8a7bb014a5f3f511594848d22.tar.gz
gcc-ae58fa02be510bc8a7bb014a5f3f511594848d22.tar.bz2
typeck.c (require_complete_type): Use complete_type_or_else.
* typeck.c (require_complete_type): Use complete_type_or_else. (complete_type_or_else): Always return NULL_TREE on failure, as documented. * pt.c (tsubst_aggr_type): Prototype. (tsubst_decl): New function, split out from tsubst. Set input_filename and lineno as appropriate. (pop_tinst_level): Restore the file and line number saved in push_tinst_level. (instantiate_class_template): Set input_filename and lineno as appropriate. (tsubst): Move _DECL processing to tsubst_decl. Make sure the context for a TYPENAME_TYPE is complete. * decl2.c (grokbitfield): Issue errors on bitfields declared with function type. (do_dtors): As in do_ctors, pretend to be a member of the same class as a static data member while generating a call to its destructor. From-SVN: r21627
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog22
-rw-r--r--gcc/cp/decl2.c35
-rw-r--r--gcc/cp/pt.c541
-rw-r--r--gcc/cp/typeck.c16
-rw-r--r--gcc/testsuite/g++.old-deja/g++.bugs/900402_01.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.law/visibility13.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/dtor2.C13
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/friend23.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/t05.C8
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/typename8.C27
-rw-r--r--gcc/testsuite/g++.old-deja/g++.robertl/eb109.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.robertl/eb128.C4
12 files changed, 423 insertions, 255 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index f1957d8..4a1c42a 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,6 +1,26 @@
1998-08-07 Mark Mitchell <mark@markmitchell.com>
- * cvt.c (cp_convert_to_pointer): Handle a NULL pointer
+ * typeck.c (require_complete_type): Use complete_type_or_else.
+ (complete_type_or_else): Always return NULL_TREE on failure, as
+ documented.
+
+ * pt.c (tsubst_aggr_type): Prototype.
+ (tsubst_decl): New function, split out from tsubst. Set
+ input_filename and lineno as appropriate.
+ (pop_tinst_level): Restore the file and line number saved in
+ push_tinst_level.
+ (instantiate_class_template): Set input_filename and lineno as
+ appropriate.
+ (tsubst): Move _DECL processing to tsubst_decl. Make sure the
+ context for a TYPENAME_TYPE is complete.
+
+ * decl2.c (grokbitfield): Issue errors on bitfields declared with
+ function type.
+ (do_dtors): As in do_ctors, pretend to be a member of the same
+ class as a static data member while generating a call to its
+ destructor.
+
+ * cvt.c (cp_convert_to_pointer): Handle NULL pointer
conversions, even in complex virtual base class hierarchies.
1998-08-06 Mark Mitchell <mark@markmitchell.com>
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 998b346..d8bc74f 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -1845,6 +1845,17 @@ grokbitfield (declarator, declspecs, width)
return NULL_TREE;
}
+ /* Usually, finish_struct_1 catches bitifields with invalid types.
+ But, in the case of bitfields with function type, we confuse
+ ourselves into thinking they are member functions, so we must
+ check here. */
+ if (TREE_CODE (value) == FUNCTION_DECL)
+ {
+ cp_error ("cannot declare bitfield `%D' with funcion type",
+ DECL_NAME (value));
+ return NULL_TREE;
+ }
+
if (IS_SIGNATURE (current_class_type))
{
error ("field declaration not allowed in signature");
@@ -3001,6 +3012,25 @@ do_dtors ()
if (! current_function_decl)
start_objects ('D');
+ /* Because of:
+
+ [class.access.spec]
+
+ Access control for implicit calls to the constructors,
+ the conversion functions, or the destructor called to
+ create and destroy a static data member is per- formed as
+ if these calls appeared in the scope of the member's
+ class.
+
+ we must convince enforce_access to let us access the
+ DECL. */
+ if (member_p (decl))
+ {
+ DECL_CLASS_CONTEXT (current_function_decl)
+ = DECL_CONTEXT (decl);
+ DECL_STATIC_FUNCTION_P (current_function_decl) = 1;
+ }
+
temp = build_cleanup (decl);
if (protect)
@@ -3015,6 +3045,11 @@ do_dtors ()
if (protect)
expand_end_cond ();
+
+ /* Now that we're done with DECL we don't need to pretend to
+ be a member of its class any longer. */
+ DECL_CLASS_CONTEXT (current_function_decl) = NULL_TREE;
+ DECL_STATIC_FUNCTION_P (current_function_decl) = 0;
}
}
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 3071f1e..f664caa 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -122,6 +122,8 @@ static tree most_specialized_class PROTO((tree, tree));
static tree most_general_template PROTO((tree));
static void set_mangled_name_for_template_decl PROTO((tree));
static int template_class_depth_real PROTO((tree, int));
+static tree tsubst_aggr_type PROTO((tree, tree, tree, int));
+static tree tsubst_decl PROTO((tree, tree, tree, tree));
/* We use TREE_VECs to hold template arguments. If there is only one
level of template arguments, then the TREE_VEC contains the
@@ -3779,6 +3781,11 @@ pop_tinst_level ()
{
struct tinst_level *old = current_tinst_level;
+ /* Restore the filename and line number stashed away when we started
+ this instantiation. */
+ lineno = old->line;
+ input_filename = old->file;
+
current_tinst_level = old->next;
old->next = free_tinst_level;
free_tinst_level = old;
@@ -4291,7 +4298,15 @@ instantiate_class_template (type)
for (t = TYPE_FIELDS (pattern); t; t = TREE_CHAIN (t))
if (TREE_CODE (t) != CONST_DECL)
{
- tree r = tsubst (t, args, NULL_TREE);
+ tree r;
+
+ /* The the file and line for this declaration, to assist in
+ error message reporting. Since we called push_tinst_level
+ above, we don't need to restore these. */
+ lineno = DECL_SOURCE_LINE (t);
+ input_filename = DECL_SOURCE_FILE (t);
+
+ r = tsubst (t, args, NULL_TREE);
if (TREE_CODE (r) == VAR_DECL)
{
pending_statics = perm_tree_cons (NULL_TREE, r, pending_statics);
@@ -4619,204 +4634,34 @@ tsubst_aggr_type (t, args, in_decl, entering_scope)
}
}
-/* Take the tree structure T and replace template parameters used therein
- with the argument vector ARGS. IN_DECL is an associated decl for
- diagnostics.
-
- tsubst is used for dealing with types, decls and the like; for
- expressions, use tsubst_expr or tsubst_copy. */
+/* Substitute the ARGS into the T, which is a _DECL. TYPE is the
+ (already computed) substitution of ARGS into TREE_TYPE (T), if
+ appropriate. Return the result of the substitution. IN_DECL is as
+ for tsubst. */
tree
-tsubst (t, args, in_decl)
- tree t, args;
+tsubst_decl (t, args, type, in_decl)
+ tree t;
+ tree args;
+ tree type;
tree in_decl;
{
- tree type;
-
- if (t == NULL_TREE || t == error_mark_node
- || t == integer_type_node
- || t == void_type_node
- || t == char_type_node
- || TREE_CODE (t) == NAMESPACE_DECL)
- return t;
-
- if (TREE_CODE (t) == IDENTIFIER_NODE)
- type = IDENTIFIER_TYPE_VALUE (t);
- else
- type = TREE_TYPE (t);
- if (type == unknown_type_node)
- my_friendly_abort (42);
+ int saved_lineno;
+ char* saved_filename;
+ tree r;
- if (type && TREE_CODE (t) != FUNCTION_DECL
- && TREE_CODE (t) != TYPENAME_TYPE
- && TREE_CODE (t) != TEMPLATE_DECL
- && TREE_CODE (t) != IDENTIFIER_NODE)
- type = tsubst (type, args, in_decl);
+ /* Set the filename and linenumber to improve error-reporting. */
+ saved_lineno = lineno;
+ saved_filename = input_filename;
+ lineno = DECL_SOURCE_LINE (t);
+ input_filename = DECL_SOURCE_FILE (t);
switch (TREE_CODE (t))
{
- case RECORD_TYPE:
- case UNION_TYPE:
- case ENUMERAL_TYPE:
- return tsubst_aggr_type (t, args, in_decl, /*entering_scope=*/0);
-
- case ERROR_MARK:
- case IDENTIFIER_NODE:
- case OP_IDENTIFIER:
- case VOID_TYPE:
- case REAL_TYPE:
- case COMPLEX_TYPE:
- case BOOLEAN_TYPE:
- case INTEGER_CST:
- case REAL_CST:
- case STRING_CST:
- case NAMESPACE_DECL:
- return t;
-
- case INTEGER_TYPE:
- if (t == integer_type_node)
- return t;
-
- if (TREE_CODE (TYPE_MIN_VALUE (t)) == INTEGER_CST
- && TREE_CODE (TYPE_MAX_VALUE (t)) == INTEGER_CST)
- return t;
-
- {
- tree max = TREE_OPERAND (TYPE_MAX_VALUE (t), 0);
- max = tsubst_expr (max, args, in_decl);
- if (processing_template_decl)
- {
- tree itype = make_node (INTEGER_TYPE);
- TYPE_MIN_VALUE (itype) = size_zero_node;
- TYPE_MAX_VALUE (itype) = build_min (MINUS_EXPR, sizetype, max,
- integer_one_node);
- return itype;
- }
-
- max = fold (build_binary_op (MINUS_EXPR, max, integer_one_node, 1));
- return build_index_2_type (size_zero_node, max);
- }
-
- case TEMPLATE_TYPE_PARM:
- case TEMPLATE_TEMPLATE_PARM:
- case TEMPLATE_PARM_INDEX:
- {
- int idx;
- int level;
- int levels;
- tree r = NULL_TREE;
-
- if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
- || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
- {
- idx = TEMPLATE_TYPE_IDX (t);
- level = TEMPLATE_TYPE_LEVEL (t);
- }
- else
- {
- idx = TEMPLATE_PARM_IDX (t);
- level = TEMPLATE_PARM_LEVEL (t);
- }
-
- if (TREE_VEC_LENGTH (args) > 0)
- {
- tree arg = NULL_TREE;
-
- levels = TMPL_ARGS_DEPTH (args);
- if (level <= levels)
- arg = TMPL_ARG (args, level, idx);
-
- if (arg != NULL_TREE)
- {
- if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
- {
- my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (arg))
- == 't', 0);
- return cp_build_type_variant
- (arg, TYPE_READONLY (arg) || TYPE_READONLY (t),
- TYPE_VOLATILE (arg) || TYPE_VOLATILE (t));
- }
- else if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
- {
- if (CLASSTYPE_TEMPLATE_INFO (t))
- {
- /* We are processing a type constructed from
- a template template parameter */
- tree argvec = tsubst (CLASSTYPE_TI_ARGS (t),
- args, in_decl);
- tree r;
-
- /* We can get a TEMPLATE_TEMPLATE_PARM here when
- we are resolving nested-types in the signature of
- a member function templates.
- Otherwise ARG is a TEMPLATE_DECL and is the real
- template to be instantiated. */
- if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
- arg = TYPE_NAME (arg);
-
- r = lookup_template_class (DECL_NAME (arg),
- argvec, in_decl,
- DECL_CONTEXT (arg),
- /*entering_scope=*/0);
- return cp_build_type_variant (r, TYPE_READONLY (t),
- TYPE_VOLATILE (t));
- }
- else
- /* We are processing a template argument list. */
- return arg;
- }
- else
- return arg;
- }
- }
-
- if (level == 1)
- /* This can happen during the attempted tsubst'ing in
- unify. This means that we don't yet have any information
- about the template parameter in question. */
- return t;
-
- /* If we get here, we must have been looking at a parm for a
- more deeply nested template. Make a new version of this
- template parameter, but with a lower level. */
- switch (TREE_CODE (t))
- {
- case TEMPLATE_TYPE_PARM:
- case TEMPLATE_TEMPLATE_PARM:
- r = copy_node (t);
- TEMPLATE_TYPE_PARM_INDEX (r)
- = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
- r, levels);
- TYPE_STUB_DECL (r) = TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r);
- TYPE_MAIN_VARIANT (r) = r;
- TYPE_POINTER_TO (r) = NULL_TREE;
- TYPE_REFERENCE_TO (r) = NULL_TREE;
-
- if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM
- && CLASSTYPE_TEMPLATE_INFO (t))
- {
- tree argvec = tsubst (CLASSTYPE_TI_ARGS (t), args, in_decl);
- CLASSTYPE_TEMPLATE_INFO (r)
- = perm_tree_cons (TYPE_NAME (t), argvec, NULL_TREE);
- }
- break;
-
- case TEMPLATE_PARM_INDEX:
- r = reduce_template_parm_level (t, type, levels);
- break;
-
- default:
- my_friendly_abort (0);
- }
-
- return r;
- }
-
case TEMPLATE_DECL:
{
/* We can get here when processing a member template function
of a template class. */
- tree tmpl;
tree decl = DECL_TEMPLATE_RESULT (t);
tree parms;
tree* new_parms;
@@ -4841,7 +4686,10 @@ tsubst (t, args, in_decl)
spec = retrieve_specialization (t, full_args);
if (spec != NULL_TREE)
- return spec;
+ {
+ r = spec;
+ break;
+ }
}
/* Make a new template decl. It will be similar to the
@@ -4849,60 +4697,60 @@ tsubst (t, args, in_decl)
We also create a new function declaration, which is just
like the old one, but points to this new template, rather
than the old one. */
- tmpl = copy_node (t);
- copy_lang_decl (tmpl);
- my_friendly_assert (DECL_LANG_SPECIFIC (tmpl) != 0, 0);
- TREE_CHAIN (tmpl) = NULL_TREE;
+ r = copy_node (t);
+ copy_lang_decl (r);
+ my_friendly_assert (DECL_LANG_SPECIFIC (r) != 0, 0);
+ TREE_CHAIN (r) = NULL_TREE;
if (is_template_template_parm)
{
tree new_decl = tsubst (decl, args, in_decl);
- DECL_RESULT (tmpl) = new_decl;
- TREE_TYPE (tmpl) = TREE_TYPE (new_decl);
- return tmpl;
+ DECL_RESULT (r) = new_decl;
+ TREE_TYPE (r) = TREE_TYPE (new_decl);
+ break;
}
- DECL_CONTEXT (tmpl)
+ DECL_CONTEXT (r)
= tsubst_aggr_type (DECL_CONTEXT (t), args, in_decl,
/*entering_scope=*/1);
- DECL_CLASS_CONTEXT (tmpl)
+ DECL_CLASS_CONTEXT (r)
= tsubst_aggr_type (DECL_CLASS_CONTEXT (t), args, in_decl,
/*entering_scope=*/1);
- DECL_TEMPLATE_INFO (tmpl) = build_tree_list (t, args);
+ DECL_TEMPLATE_INFO (r) = build_tree_list (t, args);
if (TREE_CODE (decl) == TYPE_DECL)
{
tree new_type = tsubst (TREE_TYPE (t), args, in_decl);
- TREE_TYPE (tmpl) = new_type;
- CLASSTYPE_TI_TEMPLATE (new_type) = tmpl;
- DECL_RESULT (tmpl) = TYPE_MAIN_DECL (new_type);
- DECL_TI_ARGS (tmpl) = CLASSTYPE_TI_ARGS (new_type);
+ TREE_TYPE (r) = new_type;
+ CLASSTYPE_TI_TEMPLATE (new_type) = r;
+ DECL_RESULT (r) = TYPE_MAIN_DECL (new_type);
+ DECL_TI_ARGS (r) = CLASSTYPE_TI_ARGS (new_type);
}
else
{
tree new_decl = tsubst (decl, args, in_decl);
- DECL_RESULT (tmpl) = new_decl;
- DECL_TI_TEMPLATE (new_decl) = tmpl;
- TREE_TYPE (tmpl) = TREE_TYPE (new_decl);
- DECL_TI_ARGS (tmpl) = DECL_TI_ARGS (new_decl);
+ DECL_RESULT (r) = new_decl;
+ DECL_TI_TEMPLATE (new_decl) = r;
+ TREE_TYPE (r) = TREE_TYPE (new_decl);
+ DECL_TI_ARGS (r) = DECL_TI_ARGS (new_decl);
}
- SET_DECL_IMPLICIT_INSTANTIATION (tmpl);
- DECL_TEMPLATE_INSTANTIATIONS (tmpl) = NULL_TREE;
- DECL_TEMPLATE_SPECIALIZATIONS (tmpl) = NULL_TREE;
+ SET_DECL_IMPLICIT_INSTANTIATION (r);
+ DECL_TEMPLATE_INSTANTIATIONS (r) = NULL_TREE;
+ DECL_TEMPLATE_SPECIALIZATIONS (r) = NULL_TREE;
/* The template parameters for this new template are all the
template parameters for the old template, except the
outermost level of parameters. */
- DECL_TEMPLATE_PARMS (tmpl)
+ DECL_TEMPLATE_PARMS (r)
= tsubst_template_parms (DECL_TEMPLATE_PARMS (t), args);
if (PRIMARY_TEMPLATE_P (t))
- DECL_PRIMARY_TEMPLATE (tmpl) = tmpl;
+ DECL_PRIMARY_TEMPLATE (r) = r;
/* We don't partially instantiate partial specializations. */
if (TREE_CODE (decl) == TYPE_DECL)
- return tmpl;
+ break;
for (spec = DECL_TEMPLATE_SPECIALIZATIONS (t);
spec != NULL_TREE;
@@ -4953,20 +4801,19 @@ tsubst (t, args, in_decl)
new_fn = tsubst (DECL_RESULT (most_general_template (fn)),
spec_args, in_decl);
DECL_TI_TEMPLATE (new_fn) = fn;
- register_specialization (new_fn, tmpl,
+ register_specialization (new_fn, r,
innermost_args (spec_args));
}
/* Record this partial instantiation. */
- register_specialization (tmpl, t,
- DECL_TI_ARGS (DECL_RESULT (tmpl)));
+ register_specialization (r, t,
+ DECL_TI_ARGS (DECL_RESULT (r)));
- return tmpl;
}
+ break;
case FUNCTION_DECL:
{
- tree r = NULL_TREE;
tree ctx;
tree argvec;
tree gen_tmpl;
@@ -4988,7 +4835,10 @@ tsubst (t, args, in_decl)
/* Check to see if we already have this specialization. */
spec = retrieve_specialization (gen_tmpl, argvec);
if (spec)
- return spec;
+ {
+ r = spec;
+ break;
+ }
}
else
{
@@ -5113,13 +4963,12 @@ tsubst (t, args, in_decl)
== NULL_TREE))
SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r), r);
}
-
- return r;
}
+ break;
case PARM_DECL:
{
- tree r = copy_node (t);
+ r = copy_node (t);
TREE_TYPE (r) = type;
if (TREE_CODE (DECL_INITIAL (r)) != TEMPLATE_PARM_INDEX)
DECL_INITIAL (r) = TREE_TYPE (r);
@@ -5135,12 +4984,12 @@ tsubst (t, args, in_decl)
#endif
if (TREE_CHAIN (t))
TREE_CHAIN (r) = tsubst (TREE_CHAIN (t), args, TREE_CHAIN (t));
- return r;
}
+ break;
case FIELD_DECL:
{
- tree r = copy_node (t);
+ r = copy_node (t);
TREE_TYPE (r) = type;
copy_lang_decl (r);
#if 0
@@ -5150,21 +4999,20 @@ tsubst (t, args, in_decl)
TREE_CHAIN (r) = NULL_TREE;
if (TREE_CODE (type) == VOID_TYPE)
cp_error_at ("instantiation of `%D' as type void", r);
- return r;
}
+ break;
case USING_DECL:
{
- tree r = copy_node (t);
+ r = copy_node (t);
DECL_INITIAL (r)
= tsubst_copy (DECL_INITIAL (t), args, in_decl);
TREE_CHAIN (r) = NULL_TREE;
- return r;
}
+ break;
case VAR_DECL:
{
- tree r;
tree argvec;
tree gen_tmpl;
tree spec;
@@ -5183,7 +5031,10 @@ tsubst (t, args, in_decl)
spec = retrieve_specialization (gen_tmpl, argvec);
if (spec)
- return spec;
+ {
+ r = spec;
+ break;
+ }
r = copy_node (t);
TREE_TYPE (r) = type;
@@ -5207,20 +5058,227 @@ tsubst (t, args, in_decl)
TREE_CHAIN (r) = NULL_TREE;
if (TREE_CODE (type) == VOID_TYPE)
cp_error_at ("instantiation of `%D' as type void", r);
- return r;
}
+ break;
case TYPE_DECL:
if (t == TYPE_NAME (TREE_TYPE (t)))
- return TYPE_NAME (type);
+ r = TYPE_NAME (type);
+ else
+ {
+ r = copy_node (t);
+ TREE_TYPE (r) = type;
+ DECL_CONTEXT (r) = current_class_type;
+ TREE_CHAIN (r) = NULL_TREE;
+ }
+ break;
+
+ default:
+ my_friendly_abort (0);
+ }
+
+ /* Restore the file and line information. */
+ lineno = saved_lineno;
+ input_filename = saved_filename;
+
+ return r;
+}
+
+
+/* Take the tree structure T and replace template parameters used therein
+ with the argument vector ARGS. IN_DECL is an associated decl for
+ diagnostics.
+
+ tsubst is used for dealing with types, decls and the like; for
+ expressions, use tsubst_expr or tsubst_copy. */
+
+tree
+tsubst (t, args, in_decl)
+ tree t, args;
+ tree in_decl;
+{
+ tree type;
+
+ if (t == NULL_TREE || t == error_mark_node
+ || t == integer_type_node
+ || t == void_type_node
+ || t == char_type_node
+ || TREE_CODE (t) == NAMESPACE_DECL)
+ return t;
+
+ if (TREE_CODE (t) == IDENTIFIER_NODE)
+ type = IDENTIFIER_TYPE_VALUE (t);
+ else
+ type = TREE_TYPE (t);
+ if (type == unknown_type_node)
+ my_friendly_abort (42);
+
+ if (type && TREE_CODE (t) != FUNCTION_DECL
+ && TREE_CODE (t) != TYPENAME_TYPE
+ && TREE_CODE (t) != TEMPLATE_DECL
+ && TREE_CODE (t) != IDENTIFIER_NODE)
+ type = tsubst (type, args, in_decl);
+
+ if (TREE_CODE_CLASS (TREE_CODE (t)) == 'd')
+ return tsubst_decl (t, args, type, in_decl);
+
+ switch (TREE_CODE (t))
+ {
+ case RECORD_TYPE:
+ case UNION_TYPE:
+ case ENUMERAL_TYPE:
+ return tsubst_aggr_type (t, args, in_decl, /*entering_scope=*/0);
+
+ case ERROR_MARK:
+ case IDENTIFIER_NODE:
+ case OP_IDENTIFIER:
+ case VOID_TYPE:
+ case REAL_TYPE:
+ case COMPLEX_TYPE:
+ case BOOLEAN_TYPE:
+ case INTEGER_CST:
+ case REAL_CST:
+ case STRING_CST:
+ return t;
+
+ case INTEGER_TYPE:
+ if (t == integer_type_node)
+ return t;
+
+ if (TREE_CODE (TYPE_MIN_VALUE (t)) == INTEGER_CST
+ && TREE_CODE (TYPE_MAX_VALUE (t)) == INTEGER_CST)
+ return t;
{
- tree r = copy_node (t);
- TREE_TYPE (r) = type;
- DECL_CONTEXT (r) = current_class_type;
- TREE_CHAIN (r) = NULL_TREE;
+ tree max = TREE_OPERAND (TYPE_MAX_VALUE (t), 0);
+ max = tsubst_expr (max, args, in_decl);
+ if (processing_template_decl)
+ {
+ tree itype = make_node (INTEGER_TYPE);
+ TYPE_MIN_VALUE (itype) = size_zero_node;
+ TYPE_MAX_VALUE (itype) = build_min (MINUS_EXPR, sizetype, max,
+ integer_one_node);
+ return itype;
+ }
+
+ max = fold (build_binary_op (MINUS_EXPR, max, integer_one_node, 1));
+ return build_index_2_type (size_zero_node, max);
+ }
+
+ case TEMPLATE_TYPE_PARM:
+ case TEMPLATE_TEMPLATE_PARM:
+ case TEMPLATE_PARM_INDEX:
+ {
+ int idx;
+ int level;
+ int levels;
+ tree r = NULL_TREE;
+
+ if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
+ || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
+ {
+ idx = TEMPLATE_TYPE_IDX (t);
+ level = TEMPLATE_TYPE_LEVEL (t);
+ }
+ else
+ {
+ idx = TEMPLATE_PARM_IDX (t);
+ level = TEMPLATE_PARM_LEVEL (t);
+ }
+
+ if (TREE_VEC_LENGTH (args) > 0)
+ {
+ tree arg = NULL_TREE;
+
+ levels = TMPL_ARGS_DEPTH (args);
+ if (level <= levels)
+ arg = TMPL_ARG (args, level, idx);
+
+ if (arg != NULL_TREE)
+ {
+ if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
+ {
+ my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (arg))
+ == 't', 0);
+ return cp_build_type_variant
+ (arg, TYPE_READONLY (arg) || TYPE_READONLY (t),
+ TYPE_VOLATILE (arg) || TYPE_VOLATILE (t));
+ }
+ else if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
+ {
+ if (CLASSTYPE_TEMPLATE_INFO (t))
+ {
+ /* We are processing a type constructed from
+ a template template parameter */
+ tree argvec = tsubst (CLASSTYPE_TI_ARGS (t),
+ args, in_decl);
+ tree r;
+
+ /* We can get a TEMPLATE_TEMPLATE_PARM here when
+ we are resolving nested-types in the signature of
+ a member function templates.
+ Otherwise ARG is a TEMPLATE_DECL and is the real
+ template to be instantiated. */
+ if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
+ arg = TYPE_NAME (arg);
+
+ r = lookup_template_class (DECL_NAME (arg),
+ argvec, in_decl,
+ DECL_CONTEXT (arg),
+ /*entering_scope=*/0);
+ return cp_build_type_variant (r, TYPE_READONLY (t),
+ TYPE_VOLATILE (t));
+ }
+ else
+ /* We are processing a template argument list. */
+ return arg;
+ }
+ else
+ return arg;
+ }
+ }
+
+ if (level == 1)
+ /* This can happen during the attempted tsubst'ing in
+ unify. This means that we don't yet have any information
+ about the template parameter in question. */
+ return t;
+
+ /* If we get here, we must have been looking at a parm for a
+ more deeply nested template. Make a new version of this
+ template parameter, but with a lower level. */
+ switch (TREE_CODE (t))
+ {
+ case TEMPLATE_TYPE_PARM:
+ case TEMPLATE_TEMPLATE_PARM:
+ r = copy_node (t);
+ TEMPLATE_TYPE_PARM_INDEX (r)
+ = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
+ r, levels);
+ TYPE_STUB_DECL (r) = TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r);
+ TYPE_MAIN_VARIANT (r) = r;
+ TYPE_POINTER_TO (r) = NULL_TREE;
+ TYPE_REFERENCE_TO (r) = NULL_TREE;
+
+ if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM
+ && CLASSTYPE_TEMPLATE_INFO (t))
+ {
+ tree argvec = tsubst (CLASSTYPE_TI_ARGS (t), args, in_decl);
+ CLASSTYPE_TEMPLATE_INFO (r)
+ = perm_tree_cons (TYPE_NAME (t), argvec, NULL_TREE);
+ }
+ break;
+
+ case TEMPLATE_PARM_INDEX:
+ r = reduce_template_parm_level (t, type, levels);
+ break;
+
+ default:
+ my_friendly_abort (0);
+ }
+
return r;
- }
+ }
case TREE_LIST:
{
@@ -5439,6 +5497,19 @@ tsubst (t, args, in_decl)
tree ctx = tsubst_aggr_type (TYPE_CONTEXT (t), args, in_decl,
/*entering_scope=*/1);
tree f = tsubst_copy (TYPENAME_TYPE_FULLNAME (t), args, in_decl);
+
+ /* Normally, make_typename_type does not require that the CTX
+ have complete type in order to allow things like:
+
+ template <class T> struct S { typename S<T>::X Y; };
+
+ But, such constructs have already been resolved by this
+ point, so here CTX really should have complete type, unless
+ it's a partial instantiation. */
+ if (!uses_template_parms (ctx)
+ && !complete_type_or_else (ctx))
+ return error_mark_node;
+
f = make_typename_type (ctx, f);
return cp_build_type_variant
(f, TYPE_READONLY (f) || TYPE_READONLY (t),
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 3e4fd0a..008a315 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -80,7 +80,9 @@ target_type (type)
}
/* Do `exp = require_complete_type (exp);' to make sure exp
- does not have an incomplete type. (That includes void types.) */
+ does not have an incomplete type. (That includes void types.)
+ Returns the error_mark_node if the VALUE does not have
+ complete type when this function returns. */
tree
require_complete_type (value)
@@ -120,13 +122,10 @@ require_complete_type (value)
return require_complete_type (value);
}
- if (TYPE_SIZE (complete_type (type)))
+ if (complete_type_or_else (type))
return value;
else
- {
- incomplete_type_error (value, type);
- return error_mark_node;
- }
+ return error_mark_node;
}
/* Try to complete TYPE, if it is incomplete. For example, if TYPE is
@@ -170,7 +169,10 @@ complete_type_or_else (type)
tree type;
{
type = complete_type (type);
- if (type != error_mark_node && !TYPE_SIZE (type))
+ if (type == error_mark_node)
+ /* We already issued an error. */
+ return NULL_TREE;
+ else if (!TYPE_SIZE (type))
{
incomplete_type_error (NULL_TREE, type);
return NULL_TREE;
diff --git a/gcc/testsuite/g++.old-deja/g++.bugs/900402_01.C b/gcc/testsuite/g++.old-deja/g++.bugs/900402_01.C
index 4e636b5..946e6d1 100644
--- a/gcc/testsuite/g++.old-deja/g++.bugs/900402_01.C
+++ b/gcc/testsuite/g++.old-deja/g++.bugs/900402_01.C
@@ -9,7 +9,7 @@
typedef void (func_type) ();
struct s {
- func_type f:32; // ERROR - XFAIL *-*-*
+ func_type f:32; // ERROR - bitified with function type
};
int main () { return 0; }
diff --git a/gcc/testsuite/g++.old-deja/g++.law/visibility13.C b/gcc/testsuite/g++.old-deja/g++.law/visibility13.C
index 6e53fc7..8bd6a85 100644
--- a/gcc/testsuite/g++.old-deja/g++.law/visibility13.C
+++ b/gcc/testsuite/g++.old-deja/g++.law/visibility13.C
@@ -14,7 +14,7 @@
const int ArraySize = 12;
template <class Type>
-class Array {
+class Array { // ERROR - .struct Array_RC redecl.*
friend class Array_RC;
public:
Array(const Type *ar, int sz) { init(ar,sz); }
@@ -97,7 +97,7 @@ try_array( Array_RC<Type> &rc )
main()
{
static int ia[10] = { 12, 7, 14, 9, 128, 17, 6, 3, 27, 5 };
- Array_RC<int> iA(ia, 10);// ERROR - .struct Array_RC redecl.*
+ Array_RC<int> iA(ia, 10);// ERROR - instantiated from here
cout << "template Array_RC class" << endl;
try_array(iA);
diff --git a/gcc/testsuite/g++.old-deja/g++.other/dtor2.C b/gcc/testsuite/g++.old-deja/g++.other/dtor2.C
new file mode 100644
index 0000000..201068c
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.other/dtor2.C
@@ -0,0 +1,13 @@
+// Build don't link:
+
+class K {
+public:
+ friend class C;
+
+private:
+ static K qwe;
+ K();
+ ~K();
+};
+
+K K::qwe;
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/friend23.C b/gcc/testsuite/g++.old-deja/g++.pt/friend23.C
index efb24b1..21065f1 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/friend23.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/friend23.C
@@ -2,9 +2,9 @@
template <class T = int> // ERROR - original definition
struct S
-{
+{ // ERROR - redefinition of default arg
template <class U = int>
friend class S;
};
-template struct S<int>; // ERROR - redefinition of default arg
+template struct S<int>; // ERROR - instantiated from here
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/t05.C b/gcc/testsuite/g++.old-deja/g++.pt/t05.C
index 888f1de..6dab744 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/t05.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/t05.C
@@ -1,9 +1,9 @@
// Build don't link:
-template <class A> class B {
- A a;
+template <class A> class B { // ERROR - candidates
+ A a;
public:
- B(A&aa); // ERROR -
+ B(A&aa); // ERROR - near match
~B();
};
-static B<int> b_int (3); // ERROR -
+static B<int> b_int (3); // ERROR - no matching function
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/typename8.C b/gcc/testsuite/g++.old-deja/g++.pt/typename8.C
new file mode 100644
index 0000000..d2eb4ce
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.pt/typename8.C
@@ -0,0 +1,27 @@
+// Build don't link:
+
+template < class T > class A
+{
+public:
+ typedef typename T::myT anotherT; // ERROR - undefined type
+
+ anotherT t; // ERROR - undefined type
+
+ A(anotherT _t) { // ERROR - undefined type
+ t=_t;
+ }
+
+ anotherT getT() {
+ return t;
+ }
+};
+
+class B : public A< B >
+{
+public:
+ typedef int myT;
+};
+
+int main() {
+ B b;
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.robertl/eb109.C b/gcc/testsuite/g++.old-deja/g++.robertl/eb109.C
index dd9e0e5..9414154 100644
--- a/gcc/testsuite/g++.old-deja/g++.robertl/eb109.C
+++ b/gcc/testsuite/g++.old-deja/g++.robertl/eb109.C
@@ -17,7 +17,7 @@ inline istream& operator>>(istream& is, Empty& ) { return is;}
template<class VertexType, class EdgeType>
class Graph
-{
+{ // ERROR - candidates
public:
// public type interface
typedef map<int, EdgeType > Successor;
diff --git a/gcc/testsuite/g++.old-deja/g++.robertl/eb128.C b/gcc/testsuite/g++.old-deja/g++.robertl/eb128.C
index ae4fc66..d056e39 100644
--- a/gcc/testsuite/g++.old-deja/g++.robertl/eb128.C
+++ b/gcc/testsuite/g++.old-deja/g++.robertl/eb128.C
@@ -1,11 +1,11 @@
template<class T>
struct A {
- typedef T* iterator;
+ typedef T* iterator; // ERROR - pointer to reference
public:
A(){}
};
void f()
{
- A<int&> a; // ERROR - pointer to reference
+ A<int&> a; // ERROR - instantiated from here
}