]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
decl2.c (decl_constant_var_p): New fn.
authorJason Merrill <jason@redhat.com>
Tue, 2 Nov 2010 01:30:39 +0000 (21:30 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 2 Nov 2010 01:30:39 +0000 (21:30 -0400)
* 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

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl2.c
gcc/cp/pt.c
gcc/cp/repo.c
gcc/cp/semantics.c

index 6462e11cb3f94e0baab77795c5fca63dfaa39df3..264683949cbd25fc04ea401d14a6ae679fa6a6e1 100644 (file)
@@ -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.
index e5ea232a94c94eaa4c6b2d2cfe243665d4955001..bc4eb46e7f09d20e8838b74fd5600432f14a7c57 100644 (file)
@@ -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);
index 13fa5f698903d98c09136d94be0538a4d10d4fb2..3f492bbc9e7dc1a9284e88cc5db6503587052644 100644 (file)
@@ -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"
index 8a6d451a69e0ed0e85942b8b9d20f6d0cab85921..0047aaeb6fb830214cb5b5bbb8597b4d21c1a6a1 100644 (file)
@@ -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))
index 22d58af0f84abc035ee4b45ec0d4b09b3ccab239..357dcd976508fbdf9cc0ca95f20fb07ccf5bb1a9 100644 (file)
@@ -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;
     }
index 592696346cd42a4f4f4f9d602d15442c8f73d20e..ad26abb0930f01a02f03ca23bb39186f4cd7b5a6 100644 (file)
@@ -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