PR c++/62129
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 22 Aug 2014 16:58:25 +0000 (16:58 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 22 Aug 2014 16:58:25 +0000 (16:58 +0000)
* class.c (outermost_open_class): New.
* cp-tree.h: Declare it.
* decl.c (maybe_register_incomplete_var): Use it.
(complete_vars): Handle any constant variable.
* expr.c (cplus_expand_constant): Handle CONSTRUCTOR.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@214333 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/expr.c
gcc/testsuite/g++.dg/cpp0x/constexpr-ptrmem3.C [new file with mode: 0644]

index 8505e9c..8102054 100644 (file)
@@ -1,3 +1,12 @@
+2014-08-22  Jason Merrill  <jason@redhat.com>
+
+       PR c++/62129
+       * class.c (outermost_open_class): New.
+       * cp-tree.h: Declare it.
+       * decl.c (maybe_register_incomplete_var): Use it.
+       (complete_vars): Handle any constant variable.
+       * expr.c (cplus_expand_constant): Handle CONSTRUCTOR.
+
 2014-08-22  Igor Zamyatin  <igor.zamyatin@intel.com>
 
        PR other/62008
index c7ecf70..fd22930 100644 (file)
@@ -7132,6 +7132,27 @@ currently_open_derived_class (tree t)
   return NULL_TREE;
 }
 
+/* Return the outermost enclosing class type that is still open, or
+   NULL_TREE.  */
+
+tree
+outermost_open_class (void)
+{
+  if (!current_class_type)
+    return NULL_TREE;
+  tree r = NULL_TREE;
+  for (int i = current_class_depth; i > 0; --i)
+    {
+      if (current_class_stack[i].hidden)
+       break;
+      tree t = current_class_stack[i].type;
+      if (!TYPE_BEING_DEFINED (t))
+       break;
+      r = t;
+    }
+  return r;
+}
+
 /* Returns the innermost class type which is not a lambda closure type.  */
 
 tree
index 64049c4..34373b7 100644 (file)
@@ -5154,6 +5154,7 @@ extern void resort_type_method_vec                (void *, void *,
 extern bool add_method                         (tree, tree, tree);
 extern bool currently_open_class               (tree);
 extern tree currently_open_derived_class       (tree);
+extern tree outermost_open_class               (void);
 extern tree current_nonlambda_class_type       (void);
 extern tree finish_struct                      (tree, tree);
 extern void finish_struct_1                    (tree);
index cc54cca..2e4e7f8 100644 (file)
@@ -14311,8 +14311,8 @@ grokmethod (cp_decl_specifier_seq *declspecs,
 /* VAR is a VAR_DECL.  If its type is incomplete, remember VAR so that
    we can lay it out later, when and if its type becomes complete.
 
-   Also handle constexpr pointer to member variables where the initializer
-   is an unlowered PTRMEM_CST because the class isn't complete yet.  */
+   Also handle constexpr variables where the initializer involves
+   an unlowered PTRMEM_CST because the class isn't complete yet.  */
 
 void
 maybe_register_incomplete_var (tree var)
@@ -14337,12 +14337,13 @@ maybe_register_incomplete_var (tree var)
          incomplete_var iv = {var, inner_type};
          vec_safe_push (incomplete_vars, iv);
        }
-      else if (TYPE_PTRMEM_P (inner_type)
-              && DECL_INITIAL (var)
-              && TREE_CODE (DECL_INITIAL (var)) == PTRMEM_CST)
+      else if (!(DECL_LANG_SPECIFIC (var) && DECL_TEMPLATE_INFO (var))
+              && decl_constant_var_p (var)
+              && (TYPE_PTRMEM_P (inner_type) || CLASS_TYPE_P (inner_type)))
        {
-         tree context = TYPE_PTRMEM_CLASS_TYPE (inner_type);
-         gcc_assert (TYPE_BEING_DEFINED (context));
+         /* When the outermost open class is complete we can resolve any
+            pointers-to-members.  */
+         tree context = outermost_open_class ();
          incomplete_var iv = {var, context};
          vec_safe_push (incomplete_vars, iv);
        }
@@ -14366,7 +14367,7 @@ complete_vars (tree type)
          tree var = iv->decl;
          tree type = TREE_TYPE (var);
 
-         if (TYPE_PTRMEM_P (type))
+         if (decl_constant_var_p (var))
            DECL_INITIAL (var) = cplus_expand_constant (DECL_INITIAL (var));
          else
            {
index a62e0f9..99f8006 100644 (file)
@@ -74,6 +74,14 @@ cplus_expand_constant (tree cst)
       }
       break;
 
+    case CONSTRUCTOR:
+      {
+       constructor_elt *elt;
+       unsigned HOST_WIDE_INT idx;
+       FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (cst), idx, elt)
+         elt->value = cplus_expand_constant (elt->value);
+      }
+
     default:
       /* There's nothing to do.  */
       break;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrmem3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrmem3.C
new file mode 100644 (file)
index 0000000..c5e2101
--- /dev/null
@@ -0,0 +1,16 @@
+// PR c++/62129
+// { dg-do compile { target c++11 } }
+
+class Evaluator
+{
+  int MakeChangelist ();
+  typedef int (Evaluator::*fac_t)();
+  struct CreatorEntry
+  {
+    const char *type;
+    fac_t factory;
+  };
+  static constexpr CreatorEntry kCreators[] = { "", &Evaluator::MakeChangelist };
+};
+
+constexpr Evaluator::CreatorEntry Evaluator::kCreators[];