decl2.c (decl_constant_var_p): New fn.
* decl2.c (decl_constant_var_p): New fn. (decl_maybe_constant_var_p): New fn. (mark_used): Rework instantiation of things needed for constant expressions. * cp-tree.h: Declare new fns. * pt.c (instantiate_decl): Handle cp_unevaluated_operand. (always_instantiate_p): Use decl_maybe_constant_var_p. (instantiate_decl): Don't defer constexpr functions. * repo.c (repo_emit_p): Use decl_maybe_constant_var_p. * semantics.c (finish_id_expression): Use decl_constant_var_p. Check for valid name in constant expr after mark_used. From-SVN: r166164
This commit is contained in:
parent
7bf8ca763d
commit
aef4a21519
|
@ -1,3 +1,17 @@
|
||||||
|
2010-11-01 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
|
* decl2.c (decl_constant_var_p): New fn.
|
||||||
|
(decl_maybe_constant_var_p): New fn.
|
||||||
|
(mark_used): Rework instantiation of things needed for constant
|
||||||
|
expressions.
|
||||||
|
* cp-tree.h: Declare new fns.
|
||||||
|
* pt.c (instantiate_decl): Handle cp_unevaluated_operand.
|
||||||
|
(always_instantiate_p): Use decl_maybe_constant_var_p.
|
||||||
|
(instantiate_decl): Don't defer constexpr functions.
|
||||||
|
* repo.c (repo_emit_p): Use decl_maybe_constant_var_p.
|
||||||
|
* semantics.c (finish_id_expression): Use decl_constant_var_p.
|
||||||
|
Check for valid name in constant expr after mark_used.
|
||||||
|
|
||||||
2010-10-31 Jason Merrill <jason@redhat.com>
|
2010-10-31 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
* class.c (is_really_empty_class): Work when type is not complete.
|
* class.c (is_really_empty_class): Work when type is not complete.
|
||||||
|
|
|
@ -4882,6 +4882,8 @@ extern void constrain_class_visibility (tree);
|
||||||
extern void import_export_decl (tree);
|
extern void import_export_decl (tree);
|
||||||
extern tree build_cleanup (tree);
|
extern tree build_cleanup (tree);
|
||||||
extern tree build_offset_ref_call_from_tree (tree, VEC(tree,gc) **);
|
extern tree build_offset_ref_call_from_tree (tree, VEC(tree,gc) **);
|
||||||
|
extern bool decl_constant_var_p (tree);
|
||||||
|
extern bool decl_maybe_constant_var_p (tree);
|
||||||
extern void check_default_args (tree);
|
extern void check_default_args (tree);
|
||||||
extern void mark_used (tree);
|
extern void mark_used (tree);
|
||||||
extern void finish_static_data_member_decl (tree, tree, bool, tree, int);
|
extern void finish_static_data_member_decl (tree, tree, bool, tree, int);
|
||||||
|
|
107
gcc/cp/decl2.c
107
gcc/cp/decl2.c
|
@ -3526,6 +3526,60 @@ decl_defined_p (tree decl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Nonzero for a VAR_DECL whose value can be used in a constant expression.
|
||||||
|
|
||||||
|
[expr.const]
|
||||||
|
|
||||||
|
An integral constant-expression can only involve ... const
|
||||||
|
variables of integral or enumeration types initialized with
|
||||||
|
constant expressions ...
|
||||||
|
|
||||||
|
C++0x also allows constexpr variables and temporaries initialized
|
||||||
|
with constant expressions. We handle the former here, but the latter
|
||||||
|
are just folded away in cxx_eval_constant_expression.
|
||||||
|
|
||||||
|
The standard does not require that the expression be non-volatile.
|
||||||
|
G++ implements the proposed correction in DR 457. */
|
||||||
|
|
||||||
|
bool
|
||||||
|
decl_constant_var_p (tree decl)
|
||||||
|
{
|
||||||
|
bool ret;
|
||||||
|
tree type = TREE_TYPE (decl);
|
||||||
|
if (TREE_CODE (decl) != VAR_DECL)
|
||||||
|
return false;
|
||||||
|
if (DECL_DECLARED_CONSTEXPR_P (decl))
|
||||||
|
ret = true;
|
||||||
|
else if (CP_TYPE_CONST_NON_VOLATILE_P (type)
|
||||||
|
&& INTEGRAL_OR_ENUMERATION_TYPE_P (type))
|
||||||
|
{
|
||||||
|
/* We don't know if a template static data member is initialized with
|
||||||
|
a constant expression until we instantiate its initializer. */
|
||||||
|
mark_used (decl);
|
||||||
|
ret = DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret = false;
|
||||||
|
|
||||||
|
gcc_assert (!ret || DECL_INITIAL (decl));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns true if DECL could be a symbolic constant variable, depending on
|
||||||
|
its initializer. */
|
||||||
|
|
||||||
|
bool
|
||||||
|
decl_maybe_constant_var_p (tree decl)
|
||||||
|
{
|
||||||
|
tree type = TREE_TYPE (decl);
|
||||||
|
if (TREE_CODE (decl) != VAR_DECL)
|
||||||
|
return false;
|
||||||
|
if (DECL_DECLARED_CONSTEXPR_P (decl))
|
||||||
|
return true;
|
||||||
|
return (CP_TYPE_CONST_NON_VOLATILE_P (type)
|
||||||
|
&& INTEGRAL_OR_ENUMERATION_TYPE_P (type));
|
||||||
|
}
|
||||||
|
|
||||||
/* Complain that DECL uses a type with no linkage but is never defined. */
|
/* Complain that DECL uses a type with no linkage but is never defined. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -4074,8 +4128,6 @@ possibly_inlined_p (tree decl)
|
||||||
void
|
void
|
||||||
mark_used (tree decl)
|
mark_used (tree decl)
|
||||||
{
|
{
|
||||||
HOST_WIDE_INT saved_processing_template_decl = 0;
|
|
||||||
|
|
||||||
/* If DECL is a BASELINK for a single function, then treat it just
|
/* If DECL is a BASELINK for a single function, then treat it just
|
||||||
like the DECL for the function. Otherwise, if the BASELINK is
|
like the DECL for the function. Otherwise, if the BASELINK is
|
||||||
for an overloaded function, we don't know which function was
|
for an overloaded function, we don't know which function was
|
||||||
|
@ -4113,9 +4165,6 @@ mark_used (tree decl)
|
||||||
error_at (DECL_SOURCE_LOCATION (decl), "declared here");
|
error_at (DECL_SOURCE_LOCATION (decl), "declared here");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* If we don't need a value, then we don't need to synthesize DECL. */
|
|
||||||
if (cp_unevaluated_operand != 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* We can only check DECL_ODR_USED on variables or functions with
|
/* We can only check DECL_ODR_USED on variables or functions with
|
||||||
DECL_LANG_SPECIFIC set, and these are also the only decls that we
|
DECL_LANG_SPECIFIC set, and these are also the only decls that we
|
||||||
|
@ -4139,31 +4188,39 @@ mark_used (tree decl)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Normally, we can wait until instantiation-time to synthesize
|
/* Normally, we can wait until instantiation-time to synthesize DECL.
|
||||||
DECL. However, if DECL is a static data member initialized with
|
However, if DECL is a static data member initialized with a constant
|
||||||
a constant, we need the value right now because a reference to
|
or a constexpr function, we need it right now because a reference to
|
||||||
such a data member is not value-dependent. */
|
such a data member or a call to such function is not value-dependent. */
|
||||||
if (TREE_CODE (decl) == VAR_DECL
|
if ((decl_maybe_constant_var_p (decl)
|
||||||
&& DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)
|
|| (TREE_CODE (decl) == FUNCTION_DECL
|
||||||
&& DECL_CLASS_SCOPE_P (decl))
|
&& DECL_DECLARED_CONSTEXPR_P (decl)))
|
||||||
|
&& !DECL_INITIAL (decl)
|
||||||
|
&& DECL_LANG_SPECIFIC (decl)
|
||||||
|
&& DECL_TEMPLATE_INSTANTIATION (decl))
|
||||||
{
|
{
|
||||||
/* Don't try to instantiate members of dependent types. We
|
/* Instantiating a function will result in garbage collection. We
|
||||||
cannot just use dependent_type_p here because this function
|
must treat this situation as if we were within the body of a
|
||||||
may be called from fold_non_dependent_expr, and then we may
|
function so as to avoid collecting live data only referenced from
|
||||||
see dependent types, even though processing_template_decl
|
the stack (such as overload resolution candidates). */
|
||||||
will not be set. */
|
++function_depth;
|
||||||
if (CLASSTYPE_TEMPLATE_INFO ((DECL_CONTEXT (decl)))
|
instantiate_decl (decl, /*defer_ok=*/false,
|
||||||
&& uses_template_parms (CLASSTYPE_TI_ARGS (DECL_CONTEXT (decl))))
|
/*expl_inst_class_mem_p=*/false);
|
||||||
return;
|
--function_depth;
|
||||||
/* Pretend that we are not in a template, even if we are, so
|
|
||||||
that the static data member initializer will be processed. */
|
|
||||||
saved_processing_template_decl = processing_template_decl;
|
|
||||||
processing_template_decl = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If we don't need a value, then we don't need to synthesize DECL. */
|
||||||
|
if (cp_unevaluated_operand != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
if (processing_template_decl)
|
if (processing_template_decl)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Check this too in case we're within fold_non_dependent_expr. */
|
||||||
|
if (DECL_TEMPLATE_INFO (decl)
|
||||||
|
&& uses_template_parms (DECL_TI_ARGS (decl)))
|
||||||
|
return;
|
||||||
|
|
||||||
DECL_ODR_USED (decl) = 1;
|
DECL_ODR_USED (decl) = 1;
|
||||||
if (DECL_CLONED_FUNCTION_P (decl))
|
if (DECL_CLONED_FUNCTION_P (decl))
|
||||||
DECL_ODR_USED (DECL_CLONED_FUNCTION (decl)) = 1;
|
DECL_ODR_USED (DECL_CLONED_FUNCTION (decl)) = 1;
|
||||||
|
@ -4233,8 +4290,6 @@ mark_used (tree decl)
|
||||||
need. Therefore, we always try to defer instantiation. */
|
need. Therefore, we always try to defer instantiation. */
|
||||||
instantiate_decl (decl, /*defer_ok=*/true,
|
instantiate_decl (decl, /*defer_ok=*/true,
|
||||||
/*expl_inst_class_mem_p=*/false);
|
/*expl_inst_class_mem_p=*/false);
|
||||||
|
|
||||||
processing_template_decl = saved_processing_template_decl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "gt-cp-decl2.h"
|
#include "gt-cp-decl2.h"
|
||||||
|
|
10
gcc/cp/pt.c
10
gcc/cp/pt.c
|
@ -16714,7 +16714,7 @@ always_instantiate_p (tree decl)
|
||||||
their initializers are available in integral constant
|
their initializers are available in integral constant
|
||||||
expressions. */
|
expressions. */
|
||||||
|| (TREE_CODE (decl) == VAR_DECL
|
|| (TREE_CODE (decl) == VAR_DECL
|
||||||
&& DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)));
|
&& decl_maybe_constant_var_p (decl)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Produce the definition of D, a _DECL generated from a template. If
|
/* Produce the definition of D, a _DECL generated from a template. If
|
||||||
|
@ -16750,7 +16750,8 @@ instantiate_decl (tree d, int defer_ok,
|
||||||
case that an expression refers to the value of the variable --
|
case that an expression refers to the value of the variable --
|
||||||
if the variable has a constant value the referring expression can
|
if the variable has a constant value the referring expression can
|
||||||
take advantage of that fact. */
|
take advantage of that fact. */
|
||||||
if (TREE_CODE (d) == VAR_DECL)
|
if (TREE_CODE (d) == VAR_DECL
|
||||||
|
|| DECL_DECLARED_CONSTEXPR_P (d))
|
||||||
defer_ok = 0;
|
defer_ok = 0;
|
||||||
|
|
||||||
/* Don't instantiate cloned functions. Instead, instantiate the
|
/* Don't instantiate cloned functions. Instead, instantiate the
|
||||||
|
@ -16926,6 +16927,11 @@ instantiate_decl (tree d, int defer_ok,
|
||||||
permerror (input_location, "explicit instantiation of %qD "
|
permerror (input_location, "explicit instantiation of %qD "
|
||||||
"but no definition available", d);
|
"but no definition available", d);
|
||||||
|
|
||||||
|
/* If we're in unevaluated context, we just wanted to get the
|
||||||
|
constant value; this isn't an odr use, so don't queue
|
||||||
|
a full instantiation. */
|
||||||
|
if (cp_unevaluated_operand != 0)
|
||||||
|
goto out;
|
||||||
/* ??? Historically, we have instantiated inline functions, even
|
/* ??? Historically, we have instantiated inline functions, even
|
||||||
when marked as "extern template". */
|
when marked as "extern template". */
|
||||||
if (!(external_p && TREE_CODE (d) == VAR_DECL))
|
if (!(external_p && TREE_CODE (d) == VAR_DECL))
|
||||||
|
|
|
@ -319,7 +319,7 @@ repo_emit_p (tree decl)
|
||||||
available. Still record them into *.rpo files, so if they
|
available. Still record them into *.rpo files, so if they
|
||||||
weren't actually emitted and collect2 requests them, they can
|
weren't actually emitted and collect2 requests them, they can
|
||||||
be provided. */
|
be provided. */
|
||||||
if (DECL_INTEGRAL_CONSTANT_VAR_P (decl)
|
if (decl_maybe_constant_var_p (decl)
|
||||||
&& DECL_CLASS_SCOPE_P (decl))
|
&& DECL_CLASS_SCOPE_P (decl))
|
||||||
ret = 2;
|
ret = 2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2826,7 +2826,7 @@ finish_id_expression (tree id_expression,
|
||||||
the complexity of the problem"
|
the complexity of the problem"
|
||||||
|
|
||||||
FIXME update for final resolution of core issue 696. */
|
FIXME update for final resolution of core issue 696. */
|
||||||
if (DECL_INTEGRAL_CONSTANT_VAR_P (decl))
|
if (decl_constant_var_p (decl))
|
||||||
return integral_constant_value (decl);
|
return integral_constant_value (decl);
|
||||||
|
|
||||||
if (TYPE_P (context))
|
if (TYPE_P (context))
|
||||||
|
@ -3077,21 +3077,6 @@ finish_id_expression (tree id_expression,
|
||||||
return id_expression;
|
return id_expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only certain kinds of names are allowed in constant
|
|
||||||
expression. Enumerators and template parameters have already
|
|
||||||
been handled above. */
|
|
||||||
if (integral_constant_expression_p
|
|
||||||
&& ! DECL_INTEGRAL_CONSTANT_VAR_P (decl)
|
|
||||||
&& ! builtin_valid_in_constant_expr_p (decl))
|
|
||||||
{
|
|
||||||
if (!allow_non_integral_constant_expression_p)
|
|
||||||
{
|
|
||||||
error ("%qD cannot appear in a constant-expression", decl);
|
|
||||||
return error_mark_node;
|
|
||||||
}
|
|
||||||
*non_integral_constant_expression_p = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TREE_CODE (decl) == NAMESPACE_DECL)
|
if (TREE_CODE (decl) == NAMESPACE_DECL)
|
||||||
{
|
{
|
||||||
error ("use of namespace %qD as expression", decl);
|
error ("use of namespace %qD as expression", decl);
|
||||||
|
@ -3118,6 +3103,21 @@ finish_id_expression (tree id_expression,
|
||||||
|| TREE_CODE (decl) == RESULT_DECL)
|
|| TREE_CODE (decl) == RESULT_DECL)
|
||||||
mark_used (decl);
|
mark_used (decl);
|
||||||
|
|
||||||
|
/* Only certain kinds of names are allowed in constant
|
||||||
|
expression. Enumerators and template parameters have already
|
||||||
|
been handled above. */
|
||||||
|
if (integral_constant_expression_p
|
||||||
|
&& ! decl_constant_var_p (decl)
|
||||||
|
&& ! builtin_valid_in_constant_expr_p (decl))
|
||||||
|
{
|
||||||
|
if (!allow_non_integral_constant_expression_p)
|
||||||
|
{
|
||||||
|
error ("%qD cannot appear in a constant-expression", decl);
|
||||||
|
return error_mark_node;
|
||||||
|
}
|
||||||
|
*non_integral_constant_expression_p = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (scope)
|
if (scope)
|
||||||
{
|
{
|
||||||
decl = (adjust_result_of_qualified_name_lookup
|
decl = (adjust_result_of_qualified_name_lookup
|
||||||
|
|
Loading…
Reference in New Issue