diff options
author | Jason Merrill <jason@redhat.com> | 2010-11-01 21:30:39 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2010-11-01 21:30:39 -0400 |
commit | aef4a21519866e460d2baa161a402164af67547d (patch) | |
tree | 78573089ef14591417c470516d19451c94823b25 /gcc/cp/decl2.c | |
parent | 7bf8ca763de168f22d2b65662a83e47b56d187e8 (diff) | |
download | gcc-aef4a21519866e460d2baa161a402164af67547d.tar.gz |
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/decl2.c')
-rw-r--r-- | gcc/cp/decl2.c | 107 |
1 files changed, 81 insertions, 26 deletions
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 13fa5f69890..3f492bbc9e7 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" |