aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2010-11-01 21:30:39 -0400
committerJason Merrill <jason@gcc.gnu.org>2010-11-01 21:30:39 -0400
commitaef4a21519866e460d2baa161a402164af67547d (patch)
tree78573089ef14591417c470516d19451c94823b25 /gcc/cp
parent7bf8ca763de168f22d2b65662a83e47b56d187e8 (diff)
downloadgcc-aef4a21519866e460d2baa161a402164af67547d.zip
gcc-aef4a21519866e460d2baa161a402164af67547d.tar.gz
gcc-aef4a21519866e460d2baa161a402164af67547d.tar.bz2
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
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog14
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/decl2.c107
-rw-r--r--gcc/cp/pt.c10
-rw-r--r--gcc/cp/repo.c2
-rw-r--r--gcc/cp/semantics.c32
6 files changed, 122 insertions, 45 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6462e11..2646839 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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>
* class.c (is_really_empty_class): Work when type is not complete.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index e5ea232..bc4eb46 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4882,6 +4882,8 @@ extern void constrain_class_visibility (tree);
extern void import_export_decl (tree);
extern tree build_cleanup (tree);
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 mark_used (tree);
extern void finish_static_data_member_decl (tree, tree, bool, tree, int);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 13fa5f6..3f492bb 100644
--- a/gcc/cp/decl2.c
+++ b/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. */
static void
@@ -4074,8 +4128,6 @@ possibly_inlined_p (tree decl)
void
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
like the DECL for the function. Otherwise, if the BASELINK is
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");
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
DECL_LANG_SPECIFIC set, and these are also the only decls that we
@@ -4139,31 +4188,39 @@ mark_used (tree decl)
return;
}
- /* Normally, we can wait until instantiation-time to synthesize
- DECL. However, if DECL is a static data member initialized with
- a constant, we need the value right now because a reference to
- such a data member is not value-dependent. */
- if (TREE_CODE (decl) == VAR_DECL
- && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)
- && DECL_CLASS_SCOPE_P (decl))
+ /* Normally, we can wait until instantiation-time to synthesize DECL.
+ However, if DECL is a static data member initialized with a constant
+ or a constexpr function, we need it right now because a reference to
+ such a data member or a call to such function is not value-dependent. */
+ if ((decl_maybe_constant_var_p (decl)
+ || (TREE_CODE (decl) == FUNCTION_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
- cannot just use dependent_type_p here because this function
- may be called from fold_non_dependent_expr, and then we may
- see dependent types, even though processing_template_decl
- will not be set. */
- if (CLASSTYPE_TEMPLATE_INFO ((DECL_CONTEXT (decl)))
- && uses_template_parms (CLASSTYPE_TI_ARGS (DECL_CONTEXT (decl))))
- return;
- /* 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;
+ /* Instantiating a function will result in garbage collection. We
+ must treat this situation as if we were within the body of a
+ function so as to avoid collecting live data only referenced from
+ the stack (such as overload resolution candidates). */
+ ++function_depth;
+ instantiate_decl (decl, /*defer_ok=*/false,
+ /*expl_inst_class_mem_p=*/false);
+ --function_depth;
}
+ /* 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)
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;
if (DECL_CLONED_FUNCTION_P (decl))
DECL_ODR_USED (DECL_CLONED_FUNCTION (decl)) = 1;
@@ -4233,8 +4290,6 @@ mark_used (tree decl)
need. Therefore, we always try to defer instantiation. */
instantiate_decl (decl, /*defer_ok=*/true,
/*expl_inst_class_mem_p=*/false);
-
- processing_template_decl = saved_processing_template_decl;
}
#include "gt-cp-decl2.h"
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 8a6d451..0047aae 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -16714,7 +16714,7 @@ always_instantiate_p (tree decl)
their initializers are available in integral constant
expressions. */
|| (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
@@ -16750,7 +16750,8 @@ instantiate_decl (tree d, int defer_ok,
case that an expression refers to the value of the variable --
if the variable has a constant value the referring expression can
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;
/* 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 "
"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
when marked as "extern template". */
if (!(external_p && TREE_CODE (d) == VAR_DECL))
diff --git a/gcc/cp/repo.c b/gcc/cp/repo.c
index 22d58af..357dcd9 100644
--- a/gcc/cp/repo.c
+++ b/gcc/cp/repo.c
@@ -319,7 +319,7 @@ repo_emit_p (tree decl)
available. Still record them into *.rpo files, so if they
weren't actually emitted and collect2 requests them, they can
be provided. */
- if (DECL_INTEGRAL_CONSTANT_VAR_P (decl)
+ if (decl_maybe_constant_var_p (decl)
&& DECL_CLASS_SCOPE_P (decl))
ret = 2;
}
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 5926963..ad26abb 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2826,7 +2826,7 @@ finish_id_expression (tree id_expression,
the complexity of the problem"
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);
if (TYPE_P (context))
@@ -3077,21 +3077,6 @@ finish_id_expression (tree 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)
{
error ("use of namespace %qD as expression", decl);
@@ -3118,6 +3103,21 @@ finish_id_expression (tree id_expression,
|| TREE_CODE (decl) == RESULT_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)
{
decl = (adjust_result_of_qualified_name_lookup