Commit 9baa27a9 by Mark Mitchell Committed by Mark Mitchell

re PR c++/13969 (static const value rejected as template parameter)

	PR c++/13969
	* g++.dg/template/static6.C: New test.

	PR c++/13969
	* cp-tree.h (fold_non_dependent_expr): New function.
	* parser.c (cp_parser_fold_non_dependent_expr): Remove.
	(cp_parser_template_argument): Use fold_non_dependent_expr.
	(cp_parser_direct_declarator): Likewise.
	* pt.c (fold_non_dependent_expr): New function.
	(convert_nontype_argument): Use it.
	(tsubst_qualified_id): Simplify.
	(tsubst_copy_and_build): Likewise.

From-SVN: r77260
parent 772fec9a
2004-02-04 Mark Mitchell <mark@codesourcery.com>
PR c++/13969
* cp-tree.h (fold_non_dependent_expr): New function.
* parser.c (cp_parser_fold_non_dependent_expr): Remove.
(cp_parser_template_argument): Use fold_non_dependent_expr.
(cp_parser_direct_declarator): Likewise.
* pt.c (fold_non_dependent_expr): New function.
(convert_nontype_argument): Use it.
(tsubst_qualified_id): Simplify.
(tsubst_copy_and_build): Likewise.
2004-02-04 Mark Mitchell <mark@codesourcery.com>
* decl.c (cxx_push_function_context): Do not set
current_function_is_thunk.
* method.c (use_thunk): Set CALL_FROM_THUNK on the call to the
......
......@@ -3927,6 +3927,7 @@ extern tree template_for_substitution (tree);
extern tree build_non_dependent_expr (tree);
extern tree build_non_dependent_args (tree);
extern bool reregister_specialization (tree, tree, tree);
extern tree fold_non_dependent_expr (tree);
/* in repo.c */
extern void repo_template_used (tree);
......
......@@ -1669,8 +1669,6 @@ static tree cp_parser_sizeof_operand
(cp_parser *, enum rid);
static bool cp_parser_declares_only_class_p
(cp_parser *);
static tree cp_parser_fold_non_dependent_expr
(tree);
static bool cp_parser_friend_p
(tree);
static cp_token *cp_parser_require
......@@ -8411,7 +8409,7 @@ cp_parser_template_argument (cp_parser* parser)
argument = cp_parser_constant_expression (parser,
/*allow_non_constant_p=*/false,
/*non_constant_p=*/NULL);
argument = cp_parser_fold_non_dependent_expr (argument);
argument = fold_non_dependent_expr (argument);
if (!maybe_type_id)
return argument;
if (!cp_parser_next_token_ends_template_argument_p (parser))
......@@ -10417,7 +10415,7 @@ cp_parser_direct_declarator (cp_parser* parser,
/*allow_non_constant=*/true,
&non_constant_p);
if (!non_constant_p)
bounds = cp_parser_fold_non_dependent_expr (bounds);
bounds = fold_non_dependent_expr (bounds);
}
else
bounds = NULL_TREE;
......@@ -14734,37 +14732,6 @@ cp_parser_declares_only_class_p (cp_parser *parser)
|| cp_lexer_next_token_is (parser->lexer, CPP_COMMA));
}
/* Simplify EXPR if it is a non-dependent expression. Returns the
(possibly simplified) expression. */
static tree
cp_parser_fold_non_dependent_expr (tree expr)
{
/* If we're in a template, but EXPR isn't value dependent, simplify
it. We're supposed to treat:
template <typename T> void f(T[1 + 1]);
template <typename T> void f(T[2]);
as two declarations of the same function, for example. */
if (processing_template_decl
&& !type_dependent_expression_p (expr)
&& !value_dependent_expression_p (expr))
{
HOST_WIDE_INT saved_processing_template_decl;
saved_processing_template_decl = processing_template_decl;
processing_template_decl = 0;
expr = tsubst_copy_and_build (expr,
/*args=*/NULL_TREE,
tf_error,
/*in_decl=*/NULL_TREE,
/*function_p=*/false);
processing_template_decl = saved_processing_template_decl;
}
return expr;
}
/* DECL_SPECIFIERS is the representation of a decl-specifier-seq.
Returns TRUE iff `friend' appears among the DECL_SPECIFIERS. */
......
......@@ -3099,20 +3099,60 @@ redeclare_class_template (tree type, tree parms)
}
}
/* Simplify EXPR if it is a non-dependent expression. Returns the
(possibly simplified) expression. */
tree
fold_non_dependent_expr (tree expr)
{
/* If we're in a template, but EXPR isn't value dependent, simplify
it. We're supposed to treat:
template <typename T> void f(T[1 + 1]);
template <typename T> void f(T[2]);
as two declarations of the same function, for example. */
if (processing_template_decl
&& !type_dependent_expression_p (expr)
&& !value_dependent_expression_p (expr))
{
HOST_WIDE_INT saved_processing_template_decl;
saved_processing_template_decl = processing_template_decl;
processing_template_decl = 0;
expr = tsubst_copy_and_build (expr,
/*args=*/NULL_TREE,
tf_error,
/*in_decl=*/NULL_TREE,
/*function_p=*/false);
processing_template_decl = saved_processing_template_decl;
}
return expr;
}
/* Attempt to convert the non-type template parameter EXPR to the
indicated TYPE. If the conversion is successful, return the
converted value. If the conversion is unsuccessful, return
NULL_TREE if we issued an error message, or error_mark_node if we
did not. We issue error messages for out-and-out bad template
parameters, but not simply because the conversion failed, since we
might be just trying to do argument deduction. By the time this
function is called, neither TYPE nor EXPR may make use of template
parameters. */
might be just trying to do argument deduction. Both TYPE and EXPR
must be non-dependent. */
static tree
convert_nontype_argument (tree type, tree expr)
{
tree expr_type = TREE_TYPE (expr);
tree expr_type;
/* If we are in a template, EXPR may be non-dependent, but still
have a syntactic, rather than semantic, form. For example, EXPR
might be a SCOPE_REF, rather than the VAR_DECL to which the
SCOPE_REF refers. Preserving the qualifying scope is necessary
so that access checking can be performed when the template is
instantiated -- but here we need the resolved form so that we can
convert the argument. */
expr = fold_non_dependent_expr (expr);
expr_type = TREE_TYPE (expr);
/* A template-argument for a non-type, non-template
template-parameter shall be one of:
......@@ -3136,12 +3176,31 @@ convert_nontype_argument (tree type, tree expr)
--a pointer to member expressed as described in _expr.unary.op_. */
/* An integral constant-expression can include const variables or
enumerators. Simplify things by folding them to their values,
. enumerators. Simplify things by folding them to their values,
unless we're about to bind the declaration to a reference
parameter. */
if (INTEGRAL_TYPE_P (expr_type)
&& TREE_CODE (type) != REFERENCE_TYPE)
expr = decl_constant_value (expr);
if (INTEGRAL_TYPE_P (expr_type) && TREE_CODE (type) != REFERENCE_TYPE)
while (true)
{
tree const_expr = decl_constant_value (expr);
/* In a template, the initializer for a VAR_DECL may not be
marked as TREE_CONSTANT, in which case decl_constant_value
will not return the initializer. Handle that special case
here. */
if (expr == const_expr
&& TREE_CODE (expr) == VAR_DECL
&& DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (expr)
&& CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (expr))
/* DECL_INITIAL can be NULL if we are processing a
variable initialized to an expression involving itself.
We know it is initialized to a constant -- but not what
constant, yet. */
&& DECL_INITIAL (expr))
const_expr = DECL_INITIAL (expr);
if (expr == const_expr)
break;
expr = fold_non_dependent_expr (const_expr);
}
if (is_overloaded_fn (expr))
/* OK for now. We'll check that it has external linkage later.
......@@ -7279,11 +7338,7 @@ tsubst_qualified_id (tree qualified_id, tree args,
/* Remember that there was a reference to this entity. */
if (DECL_P (expr))
{
mark_used (expr);
if (!args && TREE_CODE (expr) == VAR_DECL)
expr = DECL_INITIAL (expr);
}
mark_used (expr);
if (is_template)
expr = lookup_template_function (expr, template_args);
......@@ -8485,11 +8540,6 @@ tsubst_copy_and_build (tree t,
case VAR_DECL:
if (args)
t = tsubst_copy (t, args, complain, in_decl);
else
/* If there are no ARGS, then we are evaluating a
non-dependent expression. If the expression is
non-dependent, the variable must be a constant. */
t = DECL_INITIAL (t);
return convert_from_reference (t);
case VA_ARG_EXPR:
......
2004-02-04 Mark Mitchell <mark@codesourcery.com>
PR c++/13969
* g++.dg/template/static6.C: New test.
2004-02-04 Ian Lance Taylor <ian@wasabisystems.com>
* gcc.dg/arm-mmx-1.c: Don't look for ldmfd if -mthumb.
......
// PR c++/13969
struct B {
static const int N=10;
};
template <int> struct X {};
template <typename> struct S {
static const int N = B::N;
X<N> x;
};
template class S<float>;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment