PATCH for miscellaneous improvements
Mark Mitchell
mark@markmitchell.com
Fri Aug 7 16:34:00 GMT 1998
This patch fixes a few small problems:
o We no longer allow the declaration of bitfields with function
type.
o The destruction of static data members whose destructors are
private is permitted.
o Crashes on certain programs making use of `typename' are avoided.
In addition, this patch improves the reporting of errors during
template instantiation. Previously many errors were reported at the
instantiation site, like:
template <class T>
struct S {
T* t;
};
template struct S<int&>; // ERROR: Cannnot form pointer to reference
Now, the error is associated with the declaration of `t'. (Of course,
the `instantiated from here' message still appears at the point of
instantiation.)
--
Mark Mitchell mark@markmitchell.com
Mark Mitchell Consulting http://www.markmitchell.com
1998-08-07 Mark Mitchell <mark@markmitchell.com>
* 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.
Index: testsuite/g++.old-deja/g++.other/dtor2.C
===================================================================
RCS file: dtor2.C
diff -N dtor2.C
*** /dev/null Mon Dec 31 20:00:00 1979
--- dtor2.C Fri Aug 7 16:26:22 1998
***************
*** 0 ****
--- 1,13 ----
+ // Build don't link:
+
+ class K {
+ public:
+ friend class C;
+
+ private:
+ static K qwe;
+ K();
+ ~K();
+ };
+
+ K K::qwe;
Index: testsuite/g++.old-deja/g++.bugs/900402_01.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.bugs/900402_01.C,v
retrieving revision 1.1.1.1
diff -c -p -r1.1.1.1 900402_01.C
*** 900402_01.C 1997/08/19 07:35:13 1.1.1.1
--- 900402_01.C 1998/08/07 22:24:57
***************
*** 9,15 ****
typedef void (func_type) ();
struct s {
! func_type f:32; // ERROR - XFAIL *-*-*
};
int main () { return 0; }
--- 9,15 ----
typedef void (func_type) ();
struct s {
! func_type f:32; // ERROR - bitified with function type
};
int main () { return 0; }
Index: testsuite/g++.old-deja/g++.law/visibility13.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.law/visibility13.C,v
retrieving revision 1.2
diff -c -p -r1.2 visibility13.C
*** visibility13.C 1997/11/13 09:36:10 1.2
--- visibility13.C 1998/08/07 22:25:01
***************
*** 14,20 ****
const int ArraySize = 12;
template <class Type>
! class Array {
friend class Array_RC;
public:
Array(const Type *ar, int sz) { init(ar,sz); }
--- 14,20 ----
const int ArraySize = 12;
template <class Type>
! class Array { // ERROR - .struct Array_RC redecl.*
friend class Array_RC;
public:
Array(const Type *ar, int sz) { init(ar,sz); }
*************** try_array( Array_RC<Type> &rc )
*** 97,103 ****
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.*
cout << "template Array_RC class" << endl;
try_array(iA);
--- 97,103 ----
main()
{
static int ia[10] = { 12, 7, 14, 9, 128, 17, 6, 3, 27, 5 };
! Array_RC<int> iA(ia, 10);// ERROR - instantiated from here
cout << "template Array_RC class" << endl;
try_array(iA);
Index: testsuite/g++.old-deja/g++.pt/friend23.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.pt/friend23.C,v
retrieving revision 1.1
diff -c -p -r1.1 friend23.C
*** friend23.C 1998/07/28 01:03:08 1.1
--- friend23.C 1998/08/07 22:25:02
***************
*** 2,10 ****
template <class T = int> // ERROR - original definition
struct S
! {
template <class U = int>
friend class S;
};
! template struct S<int>; // ERROR - redefinition of default arg
--- 2,10 ----
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 - instantiated from here
Index: testsuite/g++.old-deja/g++.pt/t05.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.pt/t05.C,v
retrieving revision 1.1.1.1
diff -c -p -r1.1.1.1 t05.C
*** t05.C 1997/08/19 07:35:47 1.1.1.1
--- t05.C 1998/08/07 22:25:02
***************
*** 1,9 ****
// Build don't link:
! template <class A> class B {
! A a;
public:
! B(A&aa); // ERROR -
~B();
};
! static B<int> b_int (3); // ERROR -
--- 1,9 ----
// Build don't link:
! template <class A> class B { // ERROR - candidates
! A a;
public:
! B(A&aa); // ERROR - near match
~B();
};
! static B<int> b_int (3); // ERROR - no matching function
Index: testsuite/g++.old-deja/g++.pt/typename8.C
===================================================================
RCS file: typename8.C
diff -N typename8.C
*** /dev/null Mon Dec 31 20:00:00 1979
--- typename8.C Fri Aug 7 15:25:02 1998
***************
*** 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;
+ }
Index: testsuite/g++.old-deja/g++.robertl/eb109.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.robertl/eb109.C,v
retrieving revision 1.2
diff -c -p -r1.2 eb109.C
*** eb109.C 1998/06/04 01:49:24 1.2
--- eb109.C 1998/08/07 22:25:02
*************** inline istream& operator>>(istream& is,
*** 17,23 ****
template<class VertexType, class EdgeType>
class Graph
! {
public:
// public type interface
typedef map<int, EdgeType > Successor;
--- 17,23 ----
template<class VertexType, class EdgeType>
class Graph
! { // ERROR - candidates
public:
// public type interface
typedef map<int, EdgeType > Successor;
Index: testsuite/g++.old-deja/g++.robertl/eb128.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.robertl/eb128.C,v
retrieving revision 1.1
diff -c -p -r1.1 eb128.C
*** eb128.C 1998/06/02 19:45:48 1.1
--- eb128.C 1998/08/07 22:25:02
***************
*** 1,11 ****
template<class T>
struct A {
! typedef T* iterator;
public:
A(){}
};
void f()
{
! A<int&> a; // ERROR - pointer to reference
}
--- 1,11 ----
template<class T>
struct A {
! typedef T* iterator; // ERROR - pointer to reference
public:
A(){}
};
void f()
{
! A<int&> a; // ERROR - instantiated from here
}
Index: cp/decl2.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl2.c,v
retrieving revision 1.110
diff -c -p -r1.110 decl2.c
*** decl2.c 1998/08/03 09:58:32 1.110
--- decl2.c 1998/08/07 22:26:03
*************** grokbitfield (declarator, declspecs, wid
*** 1845,1850 ****
--- 1845,1861 ----
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");
*************** do_dtors ()
*** 3001,3006 ****
--- 3012,3036 ----
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)
*************** do_dtors ()
*** 3015,3020 ****
--- 3045,3055 ----
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;
}
}
Index: cp/pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.174
diff -c -p -r1.174 pt.c
*** pt.c 1998/08/06 16:56:41 1.174
--- pt.c 1998/08/07 22:26:58
*************** static tree most_specialized_class PROTO
*** 122,127 ****
--- 122,129 ----
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
*************** pop_tinst_level ()
*** 3779,3784 ****
--- 3781,3791 ----
{
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;
*************** instantiate_class_template (type)
*** 4291,4297 ****
for (t = TYPE_FIELDS (pattern); t; t = TREE_CHAIN (t))
if (TREE_CODE (t) != CONST_DECL)
{
! tree r = tsubst (t, args, NULL_TREE);
if (TREE_CODE (r) == VAR_DECL)
{
pending_statics = perm_tree_cons (NULL_TREE, r, pending_statics);
--- 4298,4312 ----
for (t = TYPE_FIELDS (pattern); t; t = TREE_CHAIN (t))
if (TREE_CODE (t) != CONST_DECL)
{
! 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);
*************** tsubst_aggr_type (t, args, in_decl, ente
*** 4618,4822 ****
return tsubst (t, args, in_decl);
}
}
-
- /* 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);
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;
--- 4633,4667 ----
return tsubst (t, args, in_decl);
}
}
! /* 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_decl (t, args, type, in_decl)
! tree t;
! tree args;
! tree type;
tree in_decl;
{
! int saved_lineno;
! char* saved_filename;
! tree r;
! /* 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 TEMPLATE_DECL:
{
/* We can get here when processing a member template function
of a template class. */
tree decl = DECL_TEMPLATE_RESULT (t);
tree parms;
tree* new_parms;
*************** tsubst (t, args, in_decl)
*** 4841,4847 ****
spec = retrieve_specialization (t, full_args);
if (spec != NULL_TREE)
! return spec;
}
/* Make a new template decl. It will be similar to the
--- 4686,4695 ----
spec = retrieve_specialization (t, full_args);
if (spec != NULL_TREE)
! {
! r = spec;
! break;
! }
}
/* Make a new template decl. It will be similar to the
*************** tsubst (t, args, in_decl)
*** 4849,4908 ****
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;
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_CONTEXT (tmpl)
= tsubst_aggr_type (DECL_CONTEXT (t), args, in_decl,
/*entering_scope=*/1);
! DECL_CLASS_CONTEXT (tmpl)
= tsubst_aggr_type (DECL_CLASS_CONTEXT (t), args, in_decl,
/*entering_scope=*/1);
! DECL_TEMPLATE_INFO (tmpl) = 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);
}
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);
}
! SET_DECL_IMPLICIT_INSTANTIATION (tmpl);
! DECL_TEMPLATE_INSTANTIATIONS (tmpl) = NULL_TREE;
! DECL_TEMPLATE_SPECIALIZATIONS (tmpl) = 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)
= tsubst_template_parms (DECL_TEMPLATE_PARMS (t), args);
if (PRIMARY_TEMPLATE_P (t))
! DECL_PRIMARY_TEMPLATE (tmpl) = tmpl;
/* We don't partially instantiate partial specializations. */
if (TREE_CODE (decl) == TYPE_DECL)
! return tmpl;
for (spec = DECL_TEMPLATE_SPECIALIZATIONS (t);
spec != NULL_TREE;
--- 4697,4756 ----
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. */
! 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 (r) = new_decl;
! TREE_TYPE (r) = TREE_TYPE (new_decl);
! break;
}
! DECL_CONTEXT (r)
= tsubst_aggr_type (DECL_CONTEXT (t), args, in_decl,
/*entering_scope=*/1);
! DECL_CLASS_CONTEXT (r)
= tsubst_aggr_type (DECL_CLASS_CONTEXT (t), args, in_decl,
/*entering_scope=*/1);
! 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 (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 (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 (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 (r)
= tsubst_template_parms (DECL_TEMPLATE_PARMS (t), args);
if (PRIMARY_TEMPLATE_P (t))
! DECL_PRIMARY_TEMPLATE (r) = r;
/* We don't partially instantiate partial specializations. */
if (TREE_CODE (decl) == TYPE_DECL)
! break;
for (spec = DECL_TEMPLATE_SPECIALIZATIONS (t);
spec != NULL_TREE;
*************** tsubst (t, args, in_decl)
*** 4953,4972 ****
new_fn = tsubst (DECL_RESULT (most_general_template (fn)),
spec_args, in_decl);
DECL_TI_TEMPLATE (new_fn) = fn;
! register_specialization (new_fn, tmpl,
innermost_args (spec_args));
}
/* Record this partial instantiation. */
! register_specialization (tmpl, t,
! DECL_TI_ARGS (DECL_RESULT (tmpl)));
- return tmpl;
}
case FUNCTION_DECL:
{
- tree r = NULL_TREE;
tree ctx;
tree argvec;
tree gen_tmpl;
--- 4801,4819 ----
new_fn = tsubst (DECL_RESULT (most_general_template (fn)),
spec_args, in_decl);
DECL_TI_TEMPLATE (new_fn) = fn;
! register_specialization (new_fn, r,
innermost_args (spec_args));
}
/* Record this partial instantiation. */
! register_specialization (r, t,
! DECL_TI_ARGS (DECL_RESULT (r)));
}
+ break;
case FUNCTION_DECL:
{
tree ctx;
tree argvec;
tree gen_tmpl;
*************** tsubst (t, args, in_decl)
*** 4988,4994 ****
/* Check to see if we already have this specialization. */
spec = retrieve_specialization (gen_tmpl, argvec);
if (spec)
! return spec;
}
else
{
--- 4835,4844 ----
/* Check to see if we already have this specialization. */
spec = retrieve_specialization (gen_tmpl, argvec);
if (spec)
! {
! r = spec;
! break;
! }
}
else
{
*************** tsubst (t, args, in_decl)
*** 5113,5125 ****
== NULL_TREE))
SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r), r);
}
-
- return r;
}
case PARM_DECL:
{
! tree r = copy_node (t);
TREE_TYPE (r) = type;
if (TREE_CODE (DECL_INITIAL (r)) != TEMPLATE_PARM_INDEX)
DECL_INITIAL (r) = TREE_TYPE (r);
--- 4963,4974 ----
== NULL_TREE))
SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r), r);
}
}
+ break;
case PARM_DECL:
{
! r = copy_node (t);
TREE_TYPE (r) = type;
if (TREE_CODE (DECL_INITIAL (r)) != TEMPLATE_PARM_INDEX)
DECL_INITIAL (r) = TREE_TYPE (r);
*************** tsubst (t, args, in_decl)
*** 5135,5146 ****
#endif
if (TREE_CHAIN (t))
TREE_CHAIN (r) = tsubst (TREE_CHAIN (t), args, TREE_CHAIN (t));
- return r;
}
case FIELD_DECL:
{
! tree r = copy_node (t);
TREE_TYPE (r) = type;
copy_lang_decl (r);
#if 0
--- 4984,4995 ----
#endif
if (TREE_CHAIN (t))
TREE_CHAIN (r) = tsubst (TREE_CHAIN (t), args, TREE_CHAIN (t));
}
+ break;
case FIELD_DECL:
{
! r = copy_node (t);
TREE_TYPE (r) = type;
copy_lang_decl (r);
#if 0
*************** tsubst (t, args, in_decl)
*** 5150,5170 ****
TREE_CHAIN (r) = NULL_TREE;
if (TREE_CODE (type) == VOID_TYPE)
cp_error_at ("instantiation of `%D' as type void", r);
- return r;
}
case USING_DECL:
{
! tree r = copy_node (t);
DECL_INITIAL (r)
= tsubst_copy (DECL_INITIAL (t), args, in_decl);
TREE_CHAIN (r) = NULL_TREE;
- return r;
}
case VAR_DECL:
{
- tree r;
tree argvec;
tree gen_tmpl;
tree spec;
--- 4999,5018 ----
TREE_CHAIN (r) = NULL_TREE;
if (TREE_CODE (type) == VOID_TYPE)
cp_error_at ("instantiation of `%D' as type void", r);
}
+ break;
case USING_DECL:
{
! r = copy_node (t);
DECL_INITIAL (r)
= tsubst_copy (DECL_INITIAL (t), args, in_decl);
TREE_CHAIN (r) = NULL_TREE;
}
+ break;
case VAR_DECL:
{
tree argvec;
tree gen_tmpl;
tree spec;
*************** tsubst (t, args, in_decl)
*** 5183,5189 ****
spec = retrieve_specialization (gen_tmpl, argvec);
if (spec)
! return spec;
r = copy_node (t);
TREE_TYPE (r) = type;
--- 5031,5040 ----
spec = retrieve_specialization (gen_tmpl, argvec);
if (spec)
! {
! r = spec;
! break;
! }
r = copy_node (t);
TREE_TYPE (r) = type;
*************** tsubst (t, args, in_decl)
*** 5207,5226 ****
TREE_CHAIN (r) = NULL_TREE;
if (TREE_CODE (type) == VOID_TYPE)
cp_error_at ("instantiation of `%D' as type void", r);
- return r;
}
case TYPE_DECL:
if (t == TYPE_NAME (TREE_TYPE (t)))
! return TYPE_NAME (type);
{
! tree r = copy_node (t);
! TREE_TYPE (r) = type;
! DECL_CONTEXT (r) = current_class_type;
! TREE_CHAIN (r) = NULL_TREE;
return r;
! }
case TREE_LIST:
{
--- 5058,5284 ----
TREE_CHAIN (r) = NULL_TREE;
if (TREE_CODE (type) == VOID_TYPE)
cp_error_at ("instantiation of `%D' as type void", r);
}
+ break;
case TYPE_DECL:
if (t == TYPE_NAME (TREE_TYPE (t)))
! 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 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:
{
*************** tsubst (t, args, in_decl)
*** 5439,5444 ****
--- 5497,5515 ----
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),
Index: cp/typeck.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/typeck.c,v
retrieving revision 1.92
diff -c -p -r1.92 typeck.c
*** typeck.c 1998/08/03 22:11:25 1.92
--- typeck.c 1998/08/07 22:27:22
*************** target_type (type)
*** 80,86 ****
}
/* Do `exp = require_complete_type (exp);' to make sure exp
! does not have an incomplete type. (That includes void types.) */
tree
require_complete_type (value)
--- 80,88 ----
}
/* Do `exp = require_complete_type (exp);' to make sure exp
! 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)
*************** require_complete_type (value)
*** 120,132 ****
return require_complete_type (value);
}
! if (TYPE_SIZE (complete_type (type)))
return value;
else
! {
! incomplete_type_error (value, type);
! return error_mark_node;
! }
}
/* Try to complete TYPE, if it is incomplete. For example, if TYPE is
--- 122,131 ----
return require_complete_type (value);
}
! if (complete_type_or_else (type))
return value;
else
! return error_mark_node;
}
/* Try to complete TYPE, if it is incomplete. For example, if TYPE is
*************** complete_type_or_else (type)
*** 170,176 ****
tree type;
{
type = complete_type (type);
! if (type != error_mark_node && !TYPE_SIZE (type))
{
incomplete_type_error (NULL_TREE, type);
return NULL_TREE;
--- 169,178 ----
tree type;
{
type = complete_type (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;
cvs server: Diffing cp/inc
More information about the Gcc-patches
mailing list