Patchwork C++0x constexpr patch #6: fix for constexpr setting on implicit default constructor with --disable-checking

login
register
mail settings
Submitter Jason Merrill
Date Nov. 1, 2010, 2:07 a.m.
Message ID <4CCE20F0.10405@redhat.com>
Download mbox | patch
Permalink /patch/69747/
State New
Headers show

Comments

Jason Merrill - Nov. 1, 2010, 2:07 a.m.
bkoz pointed out to me that we were getting failures in the library when 
the compiler was built with --disable-checking; this was because the 
code to shortcut synthesized_method_walk for trivial functions wasn't 
handling constexpr properly.  This patch fixes that and also avoids 
having to declare the implicit default constructor in order to set 
TYPE_HAS_CONSTEXPR_CTOR properly.

Tested x86_64-pc-linux-gnu, applied to trunk.
commit a37983dd24e7aa00813ba55be29ebf02c0f05e34
Author: Jason Merrill <jason@redhat.com>
Date:   Sun Oct 31 17:14:38 2010 -0400

    	* class.c (is_really_empty_class): Work when type is not complete.
    	(synthesized_default_constructor_is_constexpr): New.
    	(add_implicitly_declared_members): Use it.
    	(type_has_constexpr_default_constructor): Likewise.
    	* cp-tree.h: Declare it.
    	* method.c (synthesized_method_walk): Use it.

Patch

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 50afc48..1c9fac1 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -2671,20 +2671,10 @@  add_implicitly_declared_members (tree t,
   if (! TYPE_HAS_USER_CONSTRUCTOR (t))
     {
       TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 1;
-      if (TYPE_HAS_TRIVIAL_DFLT (t))
-	{
-	  /* A trivial default constructor is constexpr
-	     if there is nothing to initialize.  */
-	  if (cxx_dialect >= cxx0x && is_really_empty_class (t))
-	    TYPE_HAS_CONSTEXPR_CTOR (t) = 1;
-	  CLASSTYPE_LAZY_DEFAULT_CTOR (t) = 1;
-	}
-      else if (cxx_dialect >= cxx0x)
-	/* We need to go ahead and declare this to set
-	   TYPE_HAS_CONSTEXPR_CTOR.  */
-	lazily_declare_fn (sfk_constructor, t);
-      else
-	CLASSTYPE_LAZY_DEFAULT_CTOR (t) = 1;
+      CLASSTYPE_LAZY_DEFAULT_CTOR (t) = 1;
+      if (cxx_dialect >= cxx0x)
+	TYPE_HAS_CONSTEXPR_CTOR (t)
+	  = synthesized_default_constructor_is_constexpr (t);
     }
 
   /* [class.ctor]
@@ -4337,6 +4327,18 @@  type_has_user_provided_default_constructor (tree t)
   return false;
 }
 
+/* Returns true iff for class T, a synthesized default constructor
+   would be constexpr.  */
+
+bool
+synthesized_default_constructor_is_constexpr (tree t)
+{
+  /* A defaulted default constructor is constexpr
+     if there is nothing to initialize.  */
+  /* FIXME adjust for non-static data member initializers.  */
+  return is_really_empty_class (t);
+}
+
 /* Returns true iff class T has a constexpr default constructor.  */
 
 bool
@@ -4346,6 +4348,8 @@  type_has_constexpr_default_constructor (tree t)
 
   if (!CLASS_TYPE_P (t))
     return false;
+  if (CLASSTYPE_LAZY_DEFAULT_CTOR (t))
+    return synthesized_default_constructor_is_constexpr (t);
   fns = get_default_ctor (t);
   return (fns && DECL_DECLARED_CONSTEXPR_P (fns));
 }
@@ -6824,13 +6828,11 @@  contains_empty_class_p (tree type)
 }
 
 /* Returns true if TYPE contains no actual data, just various
-   possible combinations of empty classes.  */
+   possible combinations of empty classes and possibly a vptr.  */
 
 bool
 is_really_empty_class (tree type)
 {
-  if (is_empty_class (type))
-    return true;
   if (CLASS_TYPE_P (type))
     {
       tree field;
@@ -6838,6 +6840,11 @@  is_really_empty_class (tree type)
       tree base_binfo;
       int i;
 
+      /* CLASSTYPE_EMPTY_P isn't set properly until the class is actually laid
+	 out, but we'd like to be able to check this before then.  */
+      if (COMPLETE_TYPE_P (type) && is_empty_class (type))
+	return true;
+
       for (binfo = TYPE_BINFO (type), i = 0;
 	   BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
 	if (!is_really_empty_class (BINFO_TYPE (base_binfo)))
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 7595b6f..e5ea232 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4722,6 +4722,7 @@  extern tree in_class_defaulted_default_constructor (tree);
 extern bool user_provided_p			(tree);
 extern bool type_has_user_provided_constructor  (tree);
 extern bool type_has_user_provided_default_constructor (tree);
+extern bool synthesized_default_constructor_is_constexpr (tree);
 extern bool type_has_constexpr_default_constructor (tree);
 extern bool type_has_virtual_destructor		(tree);
 extern bool type_has_move_constructor		(tree);
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 6687c75..ca5964e 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1157,7 +1157,11 @@  synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
      methods in C++0x.  */
   if (expected_trivial
       && (!copy_arg_p || cxx_dialect < cxx0x))
-    return;
+    {
+      if (constexpr_p && sfk == sfk_constructor)
+	*constexpr_p = synthesized_default_constructor_is_constexpr (ctype);
+      return;
+    }
 #endif
 
   ++cp_unevaluated_operand;