diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a463df6d813..917457b1804 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,31 @@ +2004-01-26 Mark Mitchell + + * class.c (add_method): Just check processing_template_decl to + determine whether or not we are within a template. + * decl2.c (maybe_retrofit_in_chrg): Likewise. + * init.c (decl_constant_value): Check the type of the declaration, + not TREE_READONLY. + * name-lookup.c (maybe_push_to_top_level): Rename to ... + (push_to_top_level): ... this. + * name-lookup.h (maybe_push_to_top_level): Do not declare it. + * pt.c (push_template_decl_real): Reorder condition for speed. + (convert_template_argument): Use dependency-checking functions in + place of uses_template_parms. + (lookup_template_class): Avoid calling uses_template_parms more + than once. + (uses_template_parms): Reimplement, using dependency-checking + functions. + (instantiate_class_template): Use push_to_top_level, not + maybe_push_to_top_level. + (type_unification_real): Simplify. + (type_dependent_expression_p): Handle OFFSET_REFs and + TEMPLATE_DECLs. + (any_dependent_template_arguments_p): Handle multiple levels of + template argument. + * semantics.c (expand_or_defer_fn): Do not check + uses_template_parms for template instantiations. + * typeck.c (comptypes): Avoid calling cp_type_quals. + 2004-01-25 Mark Mitchell PR c++/13833 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 7d82bd7c7e8..d97f85046e5 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -866,7 +866,7 @@ add_method (tree type, tree method, int error_p) } } - if (template_class_depth (type)) + if (processing_template_decl) /* TYPE is a template class. Don't issue any errors now; wait until instantiation time to complain. */ ; diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index f192491cf1d..7bcbc605ea1 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -229,7 +229,7 @@ maybe_retrofit_in_chrg (tree fn) /* When processing templates we can't know, in general, whether or not we're going to have virtual baseclasses. */ - if (uses_template_parms (fn)) + if (processing_template_decl) return; /* We don't need an in-charge parameter for constructors that don't diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 3aec7d64120..6f361b082b3 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -1610,8 +1610,12 @@ decl_constant_value (tree decl) TREE_OPERAND (decl, 0), d1, d2); } - if (TREE_READONLY_DECL_P (decl) - && ! TREE_THIS_VOLATILE (decl) + if (DECL_P (decl) + && (/* Enumeration constants are constant. */ + TREE_CODE (decl) == CONST_DECL + /* And so are variables with a 'const' type -- unless they + are also 'volatile'. */ + || CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl))) && DECL_INITIAL (decl) && DECL_INITIAL (decl) != error_mark_node /* This is invalid if initial value is not constant. diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 4893e5ebda0..14f7b76bdcd 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -4688,7 +4688,7 @@ store_bindings (tree names, cxx_saved_binding *old_bindings) } void -maybe_push_to_top_level (int pseudo) +push_to_top_level (void) { struct saved_scope *s; struct cp_binding_level *b; @@ -4723,7 +4723,7 @@ maybe_push_to_top_level (int pseudo) inserted into namespace level, finish_file wouldn't find them when doing pending instantiations. Therefore, don't stop at namespace level, but continue until :: . */ - if (global_scope_p (b) || (pseudo && b->kind == sk_template_parms)) + if (global_scope_p (b)) break; old_bindings = store_bindings (b->names, old_bindings); @@ -4751,12 +4751,6 @@ maybe_push_to_top_level (int pseudo) timevar_pop (TV_NAME_LOOKUP); } -void -push_to_top_level (void) -{ - maybe_push_to_top_level (0); -} - void pop_from_top_level (void) { diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h index d2fe5946a06..c986fbc9707 100644 --- a/gcc/cp/name-lookup.h +++ b/gcc/cp/name-lookup.h @@ -264,7 +264,6 @@ extern void print_binding_stack (void); extern void print_binding_level (cxx_scope *); extern void push_to_top_level (void); extern void pop_from_top_level (void); -extern void maybe_push_to_top_level (int); extern void pop_everything (void); extern void keep_next_level (bool); extern bool is_ancestor (tree, tree); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index a9ab858ff96..ba296c700e9 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -2909,10 +2909,10 @@ push_template_decl_real (tree decl, int is_friend) else tmpl = DECL_TI_TEMPLATE (decl); - if (is_member_template (tmpl) - && DECL_FUNCTION_TEMPLATE_P (tmpl) + if (DECL_FUNCTION_TEMPLATE_P (tmpl) && DECL_TEMPLATE_INFO (decl) && DECL_TI_ARGS (decl) - && DECL_TEMPLATE_SPECIALIZATION (decl)) + && DECL_TEMPLATE_SPECIALIZATION (decl) + && is_member_template (tmpl)) { tree new_tmpl; @@ -4275,11 +4275,7 @@ lookup_template_class (tree d1, template, complain, /*require_all_args=*/1); - if (arglist == error_mark_node - || (!uses_template_parms (INNERMOST_TEMPLATE_ARGS (arglist)) - && check_instantiated_args (template, - INNERMOST_TEMPLATE_ARGS (arglist), - complain))) + if (arglist == error_mark_node) /* We were unable to bind the arguments. */ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node); @@ -4340,6 +4336,14 @@ lookup_template_class (tree d1, well. */ is_partial_instantiation = uses_template_parms (arglist); + /* If the deduced arguments are invalid, then the binding + failed. */ + if (!is_partial_instantiation + && check_instantiated_args (template, + INNERMOST_TEMPLATE_ARGS (arglist), + complain)) + POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node); + if (!is_partial_instantiation && !PRIMARY_TEMPLATE_P (template) && TREE_CODE (CP_DECL_CONTEXT (template)) == NAMESPACE_DECL) @@ -4717,7 +4721,34 @@ for_each_template_parm (tree t, tree_fn_t fn, void* data, htab_t visited) int uses_template_parms (tree t) { - return for_each_template_parm (t, 0, 0, NULL); + bool dependent_p; + int saved_processing_template_decl; + + saved_processing_template_decl = processing_template_decl; + if (!saved_processing_template_decl) + processing_template_decl = 1; + if (TYPE_P (t)) + dependent_p = dependent_type_p (t); + else if (TREE_CODE (t) == TREE_VEC) + dependent_p = any_dependent_template_arguments_p (t); + else if (TREE_CODE (t) == TREE_LIST) + dependent_p = (uses_template_parms (TREE_VALUE (t)) + || uses_template_parms (TREE_CHAIN (t))); + else if (DECL_P (t) + || EXPR_P (t) + || TREE_CODE (t) == TEMPLATE_PARM_INDEX + || TREE_CODE (t) == OVERLOAD + || TREE_CODE (t) == BASELINK + || TREE_CODE_CLASS (TREE_CODE (t)) == 'c') + dependent_p = (type_dependent_expression_p (t) + || value_dependent_expression_p (t)); + else if (t == error_mark_node) + dependent_p = false; + else + abort (); + processing_template_decl = saved_processing_template_decl; + + return dependent_p; } /* Returns true if T depends on any template parameter with level LEVEL. */ @@ -5229,7 +5260,7 @@ instantiate_class_template (tree type) it now. */ push_deferring_access_checks (dk_no_deferred); - maybe_push_to_top_level (uses_template_parms (type)); + push_to_top_level (); if (t) { @@ -8952,17 +8983,14 @@ type_unification_real (tree tparms, corresponds with a function parameter that contains only non-deducible template parameters and explicitly specified template parameters. */ - if (! uses_template_parms (parm)) + if (!uses_template_parms (parm)) { tree type; if (!TYPE_P (arg)) type = TREE_TYPE (arg); else - { - type = arg; - arg = NULL_TREE; - } + type = arg; if (strict == DEDUCE_EXACT || strict == DEDUCE_ORDER) { @@ -11767,11 +11795,16 @@ type_dependent_expression_p (tree expression) (INNERMOST_TEMPLATE_ARGS (DECL_TI_ARGS (expression))))) return true; + if (TREE_CODE (expression) == TEMPLATE_DECL + && !DECL_TEMPLATE_TEMPLATE_PARM_P (expression)) + return false; + if (TREE_TYPE (expression) == unknown_type_node) { if (TREE_CODE (expression) == ADDR_EXPR) return type_dependent_expression_p (TREE_OPERAND (expression, 0)); - if (TREE_CODE (expression) == COMPONENT_REF) + if (TREE_CODE (expression) == COMPONENT_REF + || TREE_CODE (expression) == OFFSET_REF) { if (type_dependent_expression_p (TREE_OPERAND (expression, 0))) return true; @@ -11847,13 +11880,18 @@ bool any_dependent_template_arguments_p (tree args) { int i; - + int j; + if (!args) return false; - for (i = 0; i < TREE_VEC_LENGTH (args); ++i) - if (dependent_template_arg_p (TREE_VEC_ELT (args, i))) - return true; + for (i = 0; i < TMPL_ARGS_DEPTH (args); ++i) + { + tree level = TMPL_ARGS_LEVEL (args, i + 1); + for (j = 0; j < TREE_VEC_LENGTH (level); ++j) + if (dependent_template_arg_p (TREE_VEC_ELT (level, j))) + return true; + } return false; } diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 3cf4e08fca6..69364d8f673 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2930,14 +2930,8 @@ void expand_or_defer_fn (tree fn) { /* When the parser calls us after finishing the body of a template - function, we don't really want to expand the body. When we're - processing an in-class definition of an inline function, - PROCESSING_TEMPLATE_DECL will no longer be set here, so we have - to look at the function itself. */ - if (processing_template_decl - || (DECL_LANG_SPECIFIC (fn) - && DECL_TEMPLATE_INFO (fn) - && uses_template_parms (DECL_TI_ARGS (fn)))) + function, we don't really want to expand the body. */ + if (processing_template_decl) { /* Normally, collection only occurs in rest_of_compilation. So, if we don't collect here, we never collect junk generated diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index a1403d6a734..b2dfe647a6b 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -963,8 +963,10 @@ comptypes (tree t1, tree t2, int strict) if (TREE_CODE (t1) != TREE_CODE (t2)) return false; - /* Qualifiers must match. */ - if (cp_type_quals (t1) != cp_type_quals (t2)) + /* Qualifiers must match. For array types, we will check when we + recur on the array element types. */ + if (TREE_CODE (t1) != ARRAY_TYPE + && TYPE_QUALS (t1) != TYPE_QUALS (t2)) return false; if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2)) return false; @@ -973,7 +975,8 @@ comptypes (tree t1, tree t2, int strict) definition. Note that we already checked for equality of the type qualifiers (just above). */ - if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2)) + if (TREE_CODE (t1) != ARRAY_TYPE + && TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2)) return true; if (!(*targetm.comp_type_attributes) (t1, t2))