#include "config.h"
#include "system.h"
#include "obstack.h"
-
#include "tree.h"
#include "flags.h"
#include "cp-tree.h"
+#include "tree-inline.h"
#include "decl.h"
#include "parse.h"
#include "lex.h"
#define UNIFY_ALLOW_OUTER_LEVEL 16
#define UNIFY_ALLOW_OUTER_MORE_CV_QUAL 32
#define UNIFY_ALLOW_OUTER_LESS_CV_QUAL 64
+#define UNIFY_ALLOW_MAX_CORRECTION 128
#define GTB_VIA_VIRTUAL 1 /* The base class we are examining is
virtual, or a base class of a virtual
Here, S<int>::f is a non-template, but S<int> is a
template class. If FN has the same type as DECL, we
might be in business. */
+
+ if (!DECL_TEMPLATE_INFO (fn))
+ /* Its enclosing class is an explicit specialization
+ of a template class. This is not a candidate. */
+ continue;
+
if (!same_type_p (TREE_TYPE (TREE_TYPE (decl)),
TREE_TYPE (TREE_TYPE (fn))))
/* The return types differ. */
my_friendly_assert (TREE_CODE (TREE_PURPOSE (parm)) == TREE_LIST, 260);
/* is a const-param */
parm = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm),
- PARM, 0, NULL_TREE);
+ PARM, 0, NULL);
/* [temp.param]
parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
+ /* Consider an example where a template template parameter declared as
+
+ template <class T, class U = std::allocator<T> > class TT
+
+ The template parameter level of T and U are one level larger than
+ of TT. To proper process the default argument of U, say when an
+ instantiation `TT<int>' is seen, we need to build the full
+ arguments containing {int} as the innermost level. Outer levels
+ can be obtained from `current_template_args ()'. */
+
+ if (processing_template_decl)
+ arglist = add_to_template_args (current_template_args (), arglist);
+
arglist2 = coerce_template_parms (parmlist, arglist, template,
complain, /*require_all_args=*/1);
if (arglist2 == error_mark_node)
TYPE_HAS_NEW_OPERATOR (type) = TYPE_HAS_NEW_OPERATOR (pattern);
TYPE_HAS_ARRAY_NEW_OPERATOR (type) = TYPE_HAS_ARRAY_NEW_OPERATOR (pattern);
TYPE_GETS_DELETE (type) = TYPE_GETS_DELETE (pattern);
- TYPE_VEC_DELETE_TAKES_SIZE (type) = TYPE_VEC_DELETE_TAKES_SIZE (pattern);
TYPE_HAS_ASSIGN_REF (type) = TYPE_HAS_ASSIGN_REF (pattern);
TYPE_HAS_CONST_ASSIGN_REF (type) = TYPE_HAS_CONST_ASSIGN_REF (pattern);
TYPE_HAS_ABSTRACT_ASSIGN_REF (type) = TYPE_HAS_ABSTRACT_ASSIGN_REF (pattern);
maybe_fold_nontype_arg (arg)
tree arg;
{
- /* If we're not in a template, ARG is already as simple as it's going to
- get, and trying to reprocess the trees will break. */
- if (! processing_template_decl)
- return arg;
-
- if (!TYPE_P (arg) && !uses_template_parms (arg))
+ if (arg && !TYPE_P (arg) && !uses_template_parms (arg))
{
/* Sometimes, one of the args was an expression involving a
template constant parameter, like N - 1. Now that we've
fool build_expr_from_tree() into building an actual
tree. */
- int saved_processing_template_decl = processing_template_decl;
- processing_template_decl = 0;
- arg = fold (build_expr_from_tree (arg));
- processing_template_decl = saved_processing_template_decl;
+ /* If the TREE_TYPE of ARG is not NULL_TREE, ARG is already
+ as simple as it's going to get, and trying to reprocess
+ the trees will break. */
+ if (!TREE_TYPE (arg))
+ {
+ int saved_processing_template_decl = processing_template_decl;
+ processing_template_decl = 0;
+ arg = build_expr_from_tree (arg);
+ processing_template_decl = saved_processing_template_decl;
+ }
+
+ arg = fold (arg);
}
return arg;
}
TREE_VALUE (TREE_VEC_ELT (TREE_VALUE (parms), i));
TREE_VEC_ELT (new_vec, i)
- = build_tree_list (tsubst (default_value, args, complain,
- NULL_TREE),
+ = build_tree_list (maybe_fold_nontype_arg (
+ tsubst_expr (default_value, args, complain,
+ NULL_TREE)),
tsubst (parm_decl, args, complain,
NULL_TREE));
}
/* For __PRETTY_FUNCTION__ we have to adjust the initializer. */
if (DECL_PRETTY_FUNCTION_P (r))
{
- const char *name = (*decl_printable_name)
+ const char *const name = (*decl_printable_name)
(current_function_decl, 2);
DECL_INITIAL (r) = cp_fname_init (name);
TREE_TYPE (r) = TREE_TYPE (DECL_INITIAL (r));
case ERROR_MARK:
case IDENTIFIER_NODE:
- case OP_IDENTIFIER:
case VOID_TYPE:
case REAL_TYPE:
case COMPLEX_TYPE:
}
else
{
- r = copy_node (t);
+ r = copy_type (t);
TEMPLATE_TYPE_PARM_INDEX (r)
= reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
r, levels);
int complain;
tree in_decl;
{
- tree stmt;
+ tree stmt, tmp;
if (t == NULL_TREE || t == error_mark_node)
return t;
if (processing_template_decl)
return tsubst_copy (t, args, complain, in_decl);
+ if (!statement_code_p (TREE_CODE (t)))
+ return build_expr_from_tree (tsubst_copy (t, args, complain, in_decl));
+
switch (TREE_CODE (t))
{
case RETURN_INIT:
finish_named_return_value
(TREE_OPERAND (t, 0),
tsubst_expr (TREE_OPERAND (t, 1), args, /*complain=*/1, in_decl));
- tsubst_expr (TREE_CHAIN (t), args, complain, in_decl);
break;
case CTOR_INITIALIZER:
base_init_list
= tsubst_initializer_list (TREE_OPERAND (t, 1), args);
setup_vtbl_ptr (member_init_list, base_init_list);
- tsubst_expr (TREE_CHAIN (t), args, complain, in_decl);
break;
}
cp_finish_decl (decl, init, NULL_TREE, 0);
}
}
- return decl;
+
+ /* A DECL_STMT can also be used as an expression, in the condition
+ clause of a if/for/while construct. If we aren't followed by
+ another statement, return our decl. */
+ if (TREE_CHAIN (t) == NULL_TREE)
+ return decl;
}
+ break;
case FOR_STMT:
{
- tree tmp;
prep_stmt (t);
stmt = begin_for_stmt ();
- for (tmp = FOR_INIT_STMT (t); tmp; tmp = TREE_CHAIN (tmp))
- tsubst_expr (tmp, args, complain, in_decl);
+ tsubst_expr (FOR_INIT_STMT (t), args, complain, in_decl);
finish_for_init_stmt (stmt);
finish_for_cond (tsubst_expr (FOR_COND (t), args,
complain, in_decl),
case IF_STMT:
{
- tree tmp;
-
prep_stmt (t);
stmt = begin_if_stmt ();
finish_if_stmt_cond (tsubst_expr (IF_COND (t),
case COMPOUND_STMT:
{
- tree substmt;
-
prep_stmt (t);
stmt = begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t));
- for (substmt = COMPOUND_BODY (t);
- substmt != NULL_TREE;
- substmt = TREE_CHAIN (substmt))
- tsubst_expr (substmt, args, complain, in_decl);
- return finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t), stmt);
+ tsubst_expr (COMPOUND_BODY (t), args, complain, in_decl);
+ finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t), stmt);
}
break;
case GOTO_STMT:
prep_stmt (t);
- t = GOTO_DESTINATION (t);
- if (TREE_CODE (t) != LABEL_DECL)
+ tmp = GOTO_DESTINATION (t);
+ if (TREE_CODE (tmp) != LABEL_DECL)
/* Computed goto's must be tsubst'd into. On the other hand,
non-computed gotos must not be; the identifier in question
will have no binding. */
- t = tsubst_expr (t, args, complain, in_decl);
+ tmp = tsubst_expr (tmp, args, complain, in_decl);
else
- t = DECL_NAME (t);
- finish_goto_stmt (t);
+ tmp = DECL_NAME (tmp);
+ finish_goto_stmt (tmp);
break;
case ASM_STMT:
}
else
{
- tree handler;
-
if (FN_TRY_BLOCK_P (t))
stmt = begin_function_try_block ();
else
else
finish_try_block (stmt);
- handler = TRY_HANDLERS (t);
- for (; handler; handler = TREE_CHAIN (handler))
- tsubst_expr (handler, args, complain, in_decl);
+ tsubst_expr (TRY_HANDLERS (t), args, complain, in_decl);
if (FN_TRY_BLOCK_P (t))
finish_function_handler_sequence (stmt);
else
case TAG_DEFN:
prep_stmt (t);
- t = TREE_TYPE (t);
- tsubst (t, args, complain, NULL_TREE);
+ tsubst (TREE_TYPE (t), args, complain, NULL_TREE);
break;
+ case CTOR_STMT:
+ add_stmt (copy_node (t));
+ break;
+
default:
- return build_expr_from_tree (tsubst_copy (t, args, complain, in_decl));
+ abort ();
}
- return NULL_TREE;
+
+ return tsubst_expr (TREE_CHAIN (t), args, complain, in_decl);
}
/* TMPL is a TEMPLATE_DECL for a cloned constructor or destructor.
qualified at this point.
UNIFY_ALLOW_OUTER_LESS_CV_QUAL:
This is the outermost level of a deduction, and PARM can be less CV
- qualified at this point. */
+ qualified at this point.
+ UNIFY_ALLOW_MAX_CORRECTION:
+ This is an INTEGER_TYPE's maximum value. Used if the range may
+ have been derived from a size specification, such as an array size.
+ If the size was given by a nontype template parameter N, the maximum
+ value will have the form N-1. The flag says that we can (and indeed
+ must) unify N with (ARG + 1), an exception to the normal rules on
+ folding PARM. */
static int
unify (tparms, targs, parm, arg, strict)
strict &= ~UNIFY_ALLOW_DERIVED;
strict &= ~UNIFY_ALLOW_OUTER_MORE_CV_QUAL;
strict &= ~UNIFY_ALLOW_OUTER_LESS_CV_QUAL;
+ strict &= ~UNIFY_ALLOW_MAX_CORRECTION;
switch (TREE_CODE (parm))
{
return 1;
if (TYPE_MAX_VALUE (parm) && TYPE_MAX_VALUE (arg)
&& unify (tparms, targs, TYPE_MAX_VALUE (parm),
- TYPE_MAX_VALUE (arg), UNIFY_ALLOW_INTEGER))
+ TYPE_MAX_VALUE (arg),
+ UNIFY_ALLOW_INTEGER | UNIFY_ALLOW_MAX_CORRECTION))
return 1;
}
/* We have already checked cv-qualification at the top of the
return 1;
case MINUS_EXPR:
- if (TREE_CODE (TREE_OPERAND (parm, 1)) == INTEGER_CST)
+ if (tree_int_cst_equal (TREE_OPERAND (parm, 1), integer_one_node)
+ && (strict_in & UNIFY_ALLOW_MAX_CORRECTION))
{
/* We handle this case specially, since it comes up with
arrays. In particular, something like:
do_decl_instantiation (declspecs, declarator, storage)
tree declspecs, declarator, storage;
{
- tree decl = grokdeclarator (declarator, declspecs, NORMAL, 0, NULL_TREE);
+ tree decl = grokdeclarator (declarator, declspecs, NORMAL, 0, NULL);
tree result = NULL_TREE;
int extern_p = 0;
/* Reject all external templates except inline functions. */
else if (DECL_INTERFACE_KNOWN (d)
&& ! DECL_NOT_REALLY_EXTERN (d)
- && ! (TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d)))
+ && ! (TREE_CODE (d) == FUNCTION_DECL
+ && DECL_INLINE (d)))
goto out;
/* Defer all other templates, unless we have been explicitly
forbidden from doing so. We restore the source position here