public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* C++ PATCHes for core 1358, 1360, c++/50248 (constexpr, templates, default constructor)
@ 2011-09-05  4:29 Jason Merrill
  2011-09-05  5:04 ` Gabriel Dos Reis
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Jason Merrill @ 2011-09-05  4:29 UTC (permalink / raw)
  To: gcc-patches List

[-- Attachment #1: Type: text/plain, Size: 1207 bytes --]

At the Bloomington C++ meeting we discussed some issues with the 
constexpr specification that the clang team encountered while trying to 
implement it.  Among the issues was a problem that also came up recently 
for us as BZ 50248: if the constexpr-ness of a template instantiation 
depends on its body, we need to instantiate it in order to decide 
whether or not an implicitly-declared function that uses it is 
constexpr.  The resolution of DR 1358 is that an instantiation of a 
constexpr template is constexpr even if it can never produce a constant 
expression.

The second patch is related to DR 1360, where the clang team was 
complaining that deciding whether or not a class is literal requires the 
implicit declaration of the default constructor, which they would like 
to do lazily.  We seem to have agreed that it can be avoided in the 
cases where doing such is useful, but while looking at this I noticed a 
bug in our handling of this stuff: the function 
synthesized_default_constructor_is_constexpr was only right for trivial 
constructors.  So now I've renamed it accordingly, and force the 
implicit declaration for the non-trivial case.

Tested x86_64-pc-linux-gnu, applying to trunk.

[-- Attachment #2: core-1358.patch --]
[-- Type: text/x-patch, Size: 9483 bytes --]

commit 7efc1b17c6bf70cc2c4d12ce912c194f09f2ea17
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Aug 31 10:23:57 2011 -0400

    	PR c++/50248
    	Core 1358
    	* init.c (perform_member_init): Don't diagnose missing inits here.
    	(emit_mem_initializers): Or here.
    	* method.c (process_subob_fn): Don't instantiate constexpr ctors.
    	* semantics.c (cx_check_missing_mem_inits): New.
    	(explain_invalid_constexpr_fn): Call it.
    	(register_constexpr_fundef): Likewise.  Leave
    	DECL_DECLARED_CONSTEXPR_P set when the body is unsuitable.
    	(cxx_eval_call_expression): Adjust diagnostics.
    	(cxx_eval_constant_expression): Catch use of 'this' in a constructor.

diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 847f519..ff1884b 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -606,15 +606,6 @@ perform_member_init (tree member, tree init)
 
 	  core_type = strip_array_types (type);
 
-	  if (DECL_DECLARED_CONSTEXPR_P (current_function_decl)
-	      && !type_has_constexpr_default_constructor (core_type))
-	    {
-	      if (!DECL_TEMPLATE_INSTANTIATION (current_function_decl))
-		error ("uninitialized member %qD in %<constexpr%> constructor",
-		       member);
-	      DECL_DECLARED_CONSTEXPR_P (current_function_decl) = false;
-	    }
-
 	  if (CLASS_TYPE_P (core_type)
 	      && (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type)
 		  || CLASSTYPE_REF_FIELDS_NEED_INIT (core_type)))
@@ -962,16 +953,6 @@ emit_mem_initializers (tree mem_inits)
 			OPT_Wextra, "base class %q#T should be explicitly "
 			"initialized in the copy constructor",
 			BINFO_TYPE (subobject));
-
-	  if (DECL_DECLARED_CONSTEXPR_P (current_function_decl)
-	      && !(type_has_constexpr_default_constructor
-		   (BINFO_TYPE (subobject))))
-	    {
-	      if (!DECL_TEMPLATE_INSTANTIATION (current_function_decl))
-		error ("uninitialized base %qT in %<constexpr%> constructor",
-		       BINFO_TYPE (subobject));
-	      DECL_DECLARED_CONSTEXPR_P (current_function_decl) = false;
-	    }
 	}
 
       /* Initialize the base.  */
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 3d272a3..74a3bdb 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -952,23 +952,14 @@ process_subob_fn (tree fn, bool move_p, tree *spec_p, bool *trivial_p,
       goto bad;
     }
 
-  if (constexpr_p)
+  if (constexpr_p && !DECL_DECLARED_CONSTEXPR_P (fn))
     {
-      /* If this is a specialization of a constexpr template, we need to
-	 force the instantiation now so that we know whether or not it's
-	 really constexpr.  */
-      if (DECL_DECLARED_CONSTEXPR_P (fn) && DECL_TEMPLATE_INSTANTIATION (fn)
-	  && !DECL_TEMPLATE_INSTANTIATED (fn))
-	instantiate_decl (fn, /*defer_ok*/false, /*expl_class*/false);
-      if (!DECL_DECLARED_CONSTEXPR_P (fn))
+      *constexpr_p = false;
+      if (msg)
 	{
-	  *constexpr_p = false;
-	  if (msg)
-	    {
-	      inform (0, "defaulted constructor calls non-constexpr "
-		      "%q+D", fn);
-	      explain_invalid_constexpr_fn (fn);
-	    }
+	  inform (0, "defaulted constructor calls non-constexpr "
+		  "%q+D", fn);
+	  explain_invalid_constexpr_fn (fn);
 	}
     }
 
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index ce84062..fd96d70 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -5775,6 +5775,53 @@ massage_constexpr_body (tree fun, tree body)
   return body;
 }
 
+/* FUN is a constexpr constructor with massaged body BODY.  Return true
+   if some bases/fields are uninitialized, and complain if COMPLAIN.  */
+
+static bool
+cx_check_missing_mem_inits (tree fun, tree body, bool complain)
+{
+  bool bad;
+  tree field;
+  unsigned i, nelts;
+
+  if (TREE_CODE (body) != CONSTRUCTOR)
+    return false;
+
+  bad = false;
+  nelts = CONSTRUCTOR_NELTS (body);
+  field = TYPE_FIELDS (DECL_CONTEXT (fun));
+  for (i = 0; i <= nelts; ++i)
+    {
+      tree index;
+      if (i == nelts)
+	index = NULL_TREE;
+      else
+	{
+	  index = CONSTRUCTOR_ELT (body, i)->index;
+	  /* Skip base vtable inits.  */
+	  if (TREE_CODE (index) == COMPONENT_REF)
+	    continue;
+	}
+      for (; field != index; field = DECL_CHAIN (field))
+	{
+	  if (TREE_CODE (field) != FIELD_DECL
+	      || (DECL_C_BIT_FIELD (field) && !DECL_NAME (field)))
+	    continue;
+	  if (!complain)
+	    return true;
+	  error ("uninitialized member %qD in %<constexpr%> constructor",
+		 field);
+	  bad = true;
+	}
+      if (field == NULL_TREE)
+	break;
+      field = DECL_CHAIN (field);
+    }
+
+  return bad;
+}
+
 /* We are processing the definition of the constexpr function FUN.
    Check that its BODY fulfills the propriate requirements and
    enter it in the constexpr function definition table.
@@ -5797,12 +5844,15 @@ register_constexpr_fundef (tree fun, tree body)
 
   if (!potential_rvalue_constant_expression (body))
     {
-      DECL_DECLARED_CONSTEXPR_P (fun) = false;
       if (!DECL_TEMPLATE_INFO (fun))
 	require_potential_rvalue_constant_expression (body);
       return NULL;
     }
 
+  if (DECL_CONSTRUCTOR_P (fun)
+      && cx_check_missing_mem_inits (fun, body, !DECL_TEMPLATE_INFO (fun)))
+    return NULL;
+
   /* Create the constexpr function table if necessary.  */
   if (constexpr_fundef_table == NULL)
     constexpr_fundef_table = htab_create_ggc (101,
@@ -5842,8 +5892,7 @@ explain_invalid_constexpr_fn (tree fun)
 
   save_loc = input_location;
   input_location = DECL_SOURCE_LOCATION (fun);
-  inform (0, "%q+D is not constexpr because it does not satisfy the "
-	  "requirements:", fun);
+  inform (0, "%q+D is not usable as a constexpr function because:", fun);
   /* First check the declaration.  */
   if (is_valid_constexpr_fn (fun, true))
     {
@@ -5854,6 +5903,8 @@ explain_invalid_constexpr_fn (tree fun)
 	{
 	  body = massage_constexpr_body (fun, DECL_SAVED_TREE (fun));
 	  require_potential_rvalue_constant_expression (body);
+	  if (DECL_CONSTRUCTOR_P (fun))
+	    cx_check_missing_mem_inits (fun, body, true);
 	}
     }
   input_location = save_loc;
@@ -6203,7 +6254,16 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t,
       if (new_call.fundef == NULL || new_call.fundef->body == NULL)
         {
 	  if (!allow_non_constant)
-	    error_at (loc, "%qD used before its definition", fun);
+	    {
+	      if (DECL_SAVED_TREE (fun))
+		{
+		  /* The definition of fun was somehow unsuitable.  */
+		  error_at (loc, "%qD called in a constant expression", fun);
+		  explain_invalid_constexpr_fn (fun);
+		}
+	      else
+		error_at (loc, "%qD used before its definition", fun);
+	    }
 	  *non_constant_p = true;
           return t;
         }
@@ -7176,7 +7236,17 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
 
     case PARM_DECL:
       if (call && DECL_CONTEXT (t) == call->fundef->decl)
-	r = lookup_parameter_binding (call, t);
+	{
+	  if (DECL_ARTIFICIAL (t) && DECL_CONSTRUCTOR_P (DECL_CONTEXT (t)))
+	    {
+	      if (!allow_non_constant)
+		sorry ("use of the value of the object being constructed "
+		       "in a constant expression");
+	      *non_constant_p = true;
+	    }
+	  else
+	    r = lookup_parameter_binding (call, t);
+	}
       else if (addr)
 	/* Defer in case this is only used for its type.  */;
       else
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C
index 5124f7c..a6cf408 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C
@@ -14,7 +14,7 @@ struct s {
   int v;
 };
 
-constexpr s bang;		// { dg-error "" }
+constexpr s bang;		// { dg-message "" }
 
 struct R {
   int i,j;
@@ -33,7 +33,7 @@ struct T {
 
 constexpr T t1;
 // Ill-formed (diagnostic required)
-constexpr T t2(t1);		// { dg-error "" }
+constexpr T t2(t1);		// { dg-message "" }
 
 // Well-formed
 struct U {
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ex1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ex1.C
index 584a5a0..3df7956 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ex1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ex1.C
@@ -89,6 +89,6 @@ struct resource {
 };
 constexpr resource f(resource d)
 { return d; }                  // { dg-error "non-constexpr" }
-constexpr resource d = f(9);   // { dg-error "resource" }
+constexpr resource d = f(9);   // { dg-message "constexpr" }
 
 // 4.4 floating-point constant expressions
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-template1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-template1.C
new file mode 100644
index 0000000..8807723
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-template1.C
@@ -0,0 +1,27 @@
+// PR c++/50248, DR 1358
+// { dg-options -std=c++0x }
+
+template<class Elt, unsigned max>
+struct earray
+{
+    Elt elts[max];
+    earray() = default;
+    template<typename... Elt2>
+    constexpr earray(Elt2&& ... e): elts(0) { }
+};
+
+struct SessionData
+{
+    SessionData(SessionData&) = delete;
+    SessionData() = default;
+};
+
+struct MapSessionData : SessionData
+{
+    earray<short, 11> equip_index;
+};
+
+void test()
+{
+    MapSessionData *sd = new MapSessionData;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-template2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-template2.C
new file mode 100644
index 0000000..6786d16
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-template2.C
@@ -0,0 +1,12 @@
+// { dg-options -std=c++0x }
+
+template <class T> struct A
+{
+  T t;
+  constexpr A() { }		// { dg-error "uninitialized" }
+};
+
+int main()
+{
+  constexpr A<int> a;		// { dg-error "A()" }
+}

[-- Attachment #3: default-constexpr.patch --]
[-- Type: text/x-patch, Size: 5389 bytes --]

commit 2f4a14c2ce37bbba87e45977c1314ab7984baf72
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Aug 19 09:21:45 2011 -0400

    	* class.c (trivial_default_constructor_is_constexpr): Rename from
    	synthesized_default_constructor_is_constexpr.
    	(type_has_constexpr_default_constructor): Adjust.
    	(add_implicitly_declared_members): Call it instead.
    	(explain_non_literal_class): Explain about non-constexpr default ctor.
    	* cp-tree.h: Adjust.
    	* method.c (synthesized_method_walk): Adjust.
    	* semantics.c (explain_invalid_constexpr_fn): Handle defaulted
    	functions, too.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 2a4bc77..a4a7468 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -2726,7 +2726,8 @@ add_implicitly_declared_members (tree t,
       CLASSTYPE_LAZY_DEFAULT_CTOR (t) = 1;
       if (cxx_dialect >= cxx0x)
 	TYPE_HAS_CONSTEXPR_CTOR (t)
-	  = synthesized_default_constructor_is_constexpr (t);
+	  /* This might force the declaration.  */
+	  = type_has_constexpr_default_constructor (t);
     }
 
   /* [class.ctor]
@@ -4355,15 +4356,15 @@ type_has_user_provided_default_constructor (tree t)
   return false;
 }
 
-/* Returns true iff for class T, a synthesized default constructor
+/* Returns true iff for class T, a trivial synthesized default constructor
    would be constexpr.  */
 
 bool
-synthesized_default_constructor_is_constexpr (tree t)
+trivial_default_constructor_is_constexpr (tree t)
 {
-  /* A defaulted default constructor is constexpr
+  /* A defaulted trivial default constructor is constexpr
      if there is nothing to initialize.  */
-  /* FIXME adjust for non-static data member initializers.  */
+  gcc_assert (!TYPE_HAS_COMPLEX_DFLT (t));
   return is_really_empty_class (t);
 }
 
@@ -4381,7 +4382,12 @@ type_has_constexpr_default_constructor (tree t)
       return false;
     }
   if (CLASSTYPE_LAZY_DEFAULT_CTOR (t))
-    return synthesized_default_constructor_is_constexpr (t);
+    {
+      if (!TYPE_HAS_COMPLEX_DFLT (t))
+	return trivial_default_constructor_is_constexpr (t);
+      /* Non-trivial, we need to check subobject constructors.  */
+      lazily_declare_fn (sfk_constructor, t);
+    }
   fns = locate_ctor (t);
   return (fns && DECL_DECLARED_CONSTEXPR_P (fns));
 }
@@ -4608,9 +4614,14 @@ explain_non_literal_class (tree t)
   else if (CLASSTYPE_NON_AGGREGATE (t)
 	   && !TYPE_HAS_TRIVIAL_DFLT (t)
 	   && !TYPE_HAS_CONSTEXPR_CTOR (t))
-    inform (0, "  %q+T is not an aggregate, does not have a trivial "
-	    "default constructor, and has no constexpr constructor that "
-	    "is not a copy or move constructor", t);
+    {
+      inform (0, "  %q+T is not an aggregate, does not have a trivial "
+	      "default constructor, and has no constexpr constructor that "
+	      "is not a copy or move constructor", t);
+      if (TYPE_HAS_DEFAULT_CONSTRUCTOR (t)
+	  && !type_has_user_provided_default_constructor (t))
+	explain_invalid_constexpr_fn (locate_ctor (t));
+    }
   else
     {
       tree binfo, base_binfo, field; int i;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index d18599b..cf6c056 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4823,7 +4823,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 trivial_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 74a3bdb..5b24f8f 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1187,7 +1187,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
       && (!copy_arg_p || cxx_dialect < cxx0x))
     {
       if (constexpr_p && sfk == sfk_constructor)
-	*constexpr_p = synthesized_default_constructor_is_constexpr (ctype);
+	*constexpr_p = trivial_default_constructor_is_constexpr (ctype);
       return;
     }
 
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index fd96d70..bdc4cf2 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -5881,8 +5881,9 @@ explain_invalid_constexpr_fn (tree fun)
   static struct pointer_set_t *diagnosed;
   tree body;
   location_t save_loc;
-  /* Only diagnose instantiations of constexpr templates.  */
-  if (!is_instantiation_of_constexpr (fun))
+  /* Only diagnose defaulted functions or instantiations.  */
+  if (!DECL_DEFAULTED_FN (fun)
+      && !is_instantiation_of_constexpr (fun))
     return;
   if (diagnosed == NULL)
     diagnosed = pointer_set_create ();
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-default-ctor.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-default-ctor.C
new file mode 100644
index 0000000..d3868b5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-default-ctor.C
@@ -0,0 +1,12 @@
+// { dg-options -std=c++0x }
+
+struct A {
+  int i;
+  constexpr A():i(42) { };
+};
+struct B: A { };
+constexpr int f(B b) { return b.i; }
+
+struct C { C(); };	       // { dg-message "calls non-constexpr" }
+struct D: C { };	       // { dg-message "no constexpr constructor" }
+constexpr int g(D d) { return 42; } // { dg-error "invalid type" }

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: C++ PATCHes for core 1358, 1360, c++/50248 (constexpr, templates, default constructor)
  2011-09-05  4:29 C++ PATCHes for core 1358, 1360, c++/50248 (constexpr, templates, default constructor) Jason Merrill
@ 2011-09-05  5:04 ` Gabriel Dos Reis
  2011-09-05  6:18   ` Jason Merrill
  2011-09-05 19:07 ` H.J. Lu
  2011-09-06 18:16 ` Jason Merrill
  2 siblings, 1 reply; 8+ messages in thread
From: Gabriel Dos Reis @ 2011-09-05  5:04 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches List

On Sun, Sep 4, 2011 at 11:29 PM, Jason Merrill <jason@redhat.com> wrote:
> At the Bloomington C++ meeting we discussed some issues with the constexpr
> specification that the clang team encountered while trying to implement it.
>  Among the issues was a problem that also came up recently for us as BZ
> 50248: if the constexpr-ness of a template instantiation depends on its
> body, we need to instantiate it in order to decide whether or not an
> implicitly-declared function that uses it is constexpr.  The resolution of
> DR 1358 is that an instantiation of a constexpr template is constexpr even
> if it can never produce a constant expression.

I am lost: so no diagnostic is issued but the function is deemed constexpr?

-- Gaby

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: C++ PATCHes for core 1358, 1360, c++/50248 (constexpr, templates, default constructor)
  2011-09-05  5:04 ` Gabriel Dos Reis
@ 2011-09-05  6:18   ` Jason Merrill
  0 siblings, 0 replies; 8+ messages in thread
From: Jason Merrill @ 2011-09-05  6:18 UTC (permalink / raw)
  To: Gabriel Dos Reis; +Cc: gcc-patches List

On 09/05/2011 01:04 AM, Gabriel Dos Reis wrote:
> On Sun, Sep 4, 2011 at 11:29 PM, Jason Merrill<jason@redhat.com>  wrote:
>> At the Bloomington C++ meeting we discussed some issues with the constexpr
>> specification that the clang team encountered while trying to implement it.
>>   Among the issues was a problem that also came up recently for us as BZ
>> 50248: if the constexpr-ness of a template instantiation depends on its
>> body, we need to instantiate it in order to decide whether or not an
>> implicitly-declared function that uses it is constexpr.  The resolution of
>> DR 1358 is that an instantiation of a constexpr template is constexpr even
>> if it can never produce a constant expression.
>
> I am lost: so no diagnostic is issued but the function is deemed constexpr?

For a template instantiation, correct.  If the function doesn't satisfy 
the constexpr requirements, we don't store it in the hash table and we 
complain about it if it's used in a constant expression.  We don't want 
a function to change constexpr status depending on whether it has been 
instantiated or not, so they should just stay constexpr.

Jason

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: C++ PATCHes for core 1358, 1360, c++/50248 (constexpr, templates, default constructor)
  2011-09-05  4:29 C++ PATCHes for core 1358, 1360, c++/50248 (constexpr, templates, default constructor) Jason Merrill
  2011-09-05  5:04 ` Gabriel Dos Reis
@ 2011-09-05 19:07 ` H.J. Lu
  2012-06-15  3:41   ` H.J. Lu
  2011-09-06 18:16 ` Jason Merrill
  2 siblings, 1 reply; 8+ messages in thread
From: H.J. Lu @ 2011-09-05 19:07 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches List

On Sun, Sep 4, 2011 at 9:29 PM, Jason Merrill <jason@redhat.com> wrote:
> At the Bloomington C++ meeting we discussed some issues with the constexpr
> specification that the clang team encountered while trying to implement it.
>  Among the issues was a problem that also came up recently for us as BZ
> 50248: if the constexpr-ness of a template instantiation depends on its
> body, we need to instantiate it in order to decide whether or not an
> implicitly-declared function that uses it is constexpr.  The resolution of
> DR 1358 is that an instantiation of a constexpr template is constexpr even
> if it can never produce a constant expression.
>
> The second patch is related to DR 1360, where the clang team was complaining
> that deciding whether or not a class is literal requires the implicit
> declaration of the default constructor, which they would like to do lazily.
>  We seem to have agreed that it can be avoided in the cases where doing such
> is useful, but while looking at this I noticed a bug in our handling of this
> stuff: the function synthesized_default_constructor_is_constexpr was only
> right for trivial constructors.  So now I've renamed it accordingly, and
> force the implicit declaration for the non-trivial case.
>
> Tested x86_64-pc-linux-gnu, applying to trunk.
>

This caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50296

-- 
H.J.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: C++ PATCHes for core 1358, 1360, c++/50248 (constexpr, templates, default constructor)
  2011-09-05  4:29 C++ PATCHes for core 1358, 1360, c++/50248 (constexpr, templates, default constructor) Jason Merrill
  2011-09-05  5:04 ` Gabriel Dos Reis
  2011-09-05 19:07 ` H.J. Lu
@ 2011-09-06 18:16 ` Jason Merrill
  2011-09-06 20:29   ` Dodji Seketeli
  2 siblings, 1 reply; 8+ messages in thread
From: Jason Merrill @ 2011-09-06 18:16 UTC (permalink / raw)
  To: gcc-patches List

[-- Attachment #1: Type: text/plain, Size: 269 bytes --]

A followup: non-literal argument types shouldn't change the constexpr 
flag either, and we shouldn't crash when a constructor initializes bases 
as well as members (50296).  I'm not sure how my testing missed that bug...

Tested x86_64-pc-linux-gnu, applying to trunk.

[-- Attachment #2: zad.patch --]
[-- Type: text/x-patch, Size: 3288 bytes --]

commit 26e458d541a3b04512ab88cfab866703e868e728
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Jul 14 23:56:59 2011 -0400

    zadditional_options

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 0fded4e..e12791d 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -5019,7 +5019,7 @@ check_p_subdirs=$(wordlist 1,$(words $(check_$*_parallelize)),$(check_p_numbers)
 
 # For parallelized check-% targets, this decides whether parallelization
 # is desirable (if -jN is used and RUNTESTFLAGS doesn't contain anything
-# but optional --target_board or --tool_opts arguments).  If it is desirable,
+# but optional --target_board or --zadditional_options arguments).  If desirable,
 # recursive make is run with check-parallel-$lang{,1,2,3,4,5} etc. goals,
 # which can be executed in parallel, as they are run in separate directories.
 # check-parallel-$lang{1,2,3,4,5} etc. goals invoke runtest with the longest
@@ -5036,7 +5036,7 @@ check_p_subdirs=$(wordlist 1,$(words $(check_$*_parallelize)),$(check_p_numbers)
 # to lang_checks_parallelized variable and define check_$lang_parallelize
 # variable (see above check_gcc_parallelize description).
 $(lang_checks_parallelized): check-% : site.exp
-	@if [ -z "$(filter-out --target_board=%,$(filter-out --tool_opts%,$(RUNTESTFLAGS)))" ] \
+	@if [ -z "$(filter-out --target_board=%,$(filter-out --zadditional_options%,$(RUNTESTFLAGS)))" ] \
 	    && [ "$(filter -j, $(MFLAGS))" = "-j" ]; then \
 	  $(MAKE) TESTSUITEDIR="$(TESTSUITEDIR)" RUNTESTFLAGS="$(RUNTESTFLAGS)" \
 	    check-parallel-$* \
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index b9251a4..8353376 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -151,7 +151,7 @@ c++.srcman: doc/g++.1
 check-c++ : check-g++
 # Run the testsute in C++0x mode.
 check-c++0x:
-	$(MAKE) RUNTESTFLAGS="$(RUNTESTFLAGS) --tool_opts=-std=gnu++0x" \
+	$(MAKE) RUNTESTFLAGS="$(RUNTESTFLAGS) --zadditional_options,-std=gnu++0x" \
 	  TESTSUITEDIR="$(TESTSUITEDIR).c++0x" check-g++
 check-c++-subtargets : check-g++-subtargets
 # List of targets that can use the generic check- rule and its // variant.
diff --git a/gcc/testsuite/lib/g++.exp b/gcc/testsuite/lib/g++.exp
index 81c4398..562f6f0 100644
--- a/gcc/testsuite/lib/g++.exp
+++ b/gcc/testsuite/lib/g++.exp
@@ -307,3 +307,33 @@ proc g++_target_compile { source dest type options } {
 
     return $result
 }
+
+#
+# ${tool}_option_help
+#
+# The initial 'z' is there because runtest.exp treats --a* as --all.
+# This shouldn't be necessary at all; it should be entirely redundant with
+# --tool_opts, except that --tool_opts currently breaks multilib.  Patch at
+# http://lists.gnu.org/archive/html/dejagnu/2002-10/msg00007.html
+
+proc ${tool}_option_help { } {
+    send_user " --zadditional_options,OPTIONS\t\tUse OPTIONS to compile the testcase files. OPTIONS should be comma-separated.\n"
+}
+
+#
+# ${tool}_option_proc
+#
+
+proc ${tool}_option_proc { option } {
+    if [regexp "^--zadditional_options," $option] {
+	global gpp_compile_options
+	regsub "^--zadditional_options," $option "" option
+	foreach x [split $option ","] {
+	    lappend gpp_compile_options "additional_flags=$x"
+	}
+	verbose -log "gpp_compile_options set to $gpp_compile_options"
+	return 1
+    } else {
+	return 0
+    }
+}

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: C++ PATCHes for core 1358, 1360, c++/50248 (constexpr, templates, default constructor)
  2011-09-06 18:16 ` Jason Merrill
@ 2011-09-06 20:29   ` Dodji Seketeli
  2011-09-06 21:32     ` Jason Merrill
  0 siblings, 1 reply; 8+ messages in thread
From: Dodji Seketeli @ 2011-09-06 20:29 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches List

Jason Merrill <jason@redhat.com> a écrit:

> A followup: non-literal argument types shouldn't change the constexpr
> flag either, and we shouldn't crash when a constructor initializes
> bases as well as members (50296).  I'm not sure how my testing missed
> that bug...
>
> Tested x86_64-pc-linux-gnu, applying to trunk.
> commit 26e458d541a3b04512ab88cfab866703e868e728
> Author: Jason Merrill <jason@redhat.com>
> Date:   Thu Jul 14 23:56:59 2011 -0400
>
>     zadditional_options

I fail to see what the patch below has to do with the cover letter you
wrote above.  Am I missing something?

>
> diff --git a/gcc/Makefile.in b/gcc/Makefile.in
> index 0fded4e..e12791d 100644
> --- a/gcc/Makefile.in
> +++ b/gcc/Makefile.in
> @@ -5019,7 +5019,7 @@ check_p_subdirs=$(wordlist 1,$(words $(check_$*_parallelize)),$(check_p_numbers)
>  
>  # For parallelized check-% targets, this decides whether parallelization
>  # is desirable (if -jN is used and RUNTESTFLAGS doesn't contain anything
> -# but optional --target_board or --tool_opts arguments).  If it is desirable,
> +# but optional --target_board or --zadditional_options arguments).  If desirable,
>  # recursive make is run with check-parallel-$lang{,1,2,3,4,5} etc. goals,
>  # which can be executed in parallel, as they are run in separate directories.
>  # check-parallel-$lang{1,2,3,4,5} etc. goals invoke runtest with the longest
> @@ -5036,7 +5036,7 @@ check_p_subdirs=$(wordlist 1,$(words $(check_$*_parallelize)),$(check_p_numbers)
>  # to lang_checks_parallelized variable and define check_$lang_parallelize
>  # variable (see above check_gcc_parallelize description).
>  $(lang_checks_parallelized): check-% : site.exp
> -	@if [ -z "$(filter-out --target_board=%,$(filter-out --tool_opts%,$(RUNTESTFLAGS)))" ] \
> +	@if [ -z "$(filter-out --target_board=%,$(filter-out --zadditional_options%,$(RUNTESTFLAGS)))" ] \
>  	    && [ "$(filter -j, $(MFLAGS))" = "-j" ]; then \
>  	  $(MAKE) TESTSUITEDIR="$(TESTSUITEDIR)" RUNTESTFLAGS="$(RUNTESTFLAGS)" \
>  	    check-parallel-$* \
> diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
> index b9251a4..8353376 100644
> --- a/gcc/cp/Make-lang.in
> +++ b/gcc/cp/Make-lang.in
> @@ -151,7 +151,7 @@ c++.srcman: doc/g++.1
>  check-c++ : check-g++
>  # Run the testsute in C++0x mode.
>  check-c++0x:
> -	$(MAKE) RUNTESTFLAGS="$(RUNTESTFLAGS) --tool_opts=-std=gnu++0x" \
> +	$(MAKE) RUNTESTFLAGS="$(RUNTESTFLAGS) --zadditional_options,-std=gnu++0x" \
>  	  TESTSUITEDIR="$(TESTSUITEDIR).c++0x" check-g++
>  check-c++-subtargets : check-g++-subtargets
>  # List of targets that can use the generic check- rule and its // variant.
> diff --git a/gcc/testsuite/lib/g++.exp b/gcc/testsuite/lib/g++.exp
> index 81c4398..562f6f0 100644
> --- a/gcc/testsuite/lib/g++.exp
> +++ b/gcc/testsuite/lib/g++.exp
> @@ -307,3 +307,33 @@ proc g++_target_compile { source dest type options } {
>  
>      return $result
>  }
> +
> +#
> +# ${tool}_option_help
> +#
> +# The initial 'z' is there because runtest.exp treats --a* as --all.
> +# This shouldn't be necessary at all; it should be entirely redundant with
> +# --tool_opts, except that --tool_opts currently breaks multilib.  Patch at
> +# http://lists.gnu.org/archive/html/dejagnu/2002-10/msg00007.html
> +
> +proc ${tool}_option_help { } {
> +    send_user " --zadditional_options,OPTIONS\t\tUse OPTIONS to compile the testcase files. OPTIONS should be comma-separated.\n"
> +}
> +
> +#
> +# ${tool}_option_proc
> +#
> +
> +proc ${tool}_option_proc { option } {
> +    if [regexp "^--zadditional_options," $option] {
> +	global gpp_compile_options
> +	regsub "^--zadditional_options," $option "" option
> +	foreach x [split $option ","] {
> +	    lappend gpp_compile_options "additional_flags=$x"
> +	}
> +	verbose -log "gpp_compile_options set to $gpp_compile_options"
> +	return 1
> +    } else {
> +	return 0
> +    }
> +}

-- 
		Dodji

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: C++ PATCHes for core 1358, 1360, c++/50248 (constexpr, templates, default constructor)
  2011-09-06 20:29   ` Dodji Seketeli
@ 2011-09-06 21:32     ` Jason Merrill
  0 siblings, 0 replies; 8+ messages in thread
From: Jason Merrill @ 2011-09-06 21:32 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: gcc-patches List

[-- Attachment #1: Type: text/plain, Size: 792 bytes --]

On 09/06/2011 04:21 PM, Dodji Seketeli wrote:
> Jason Merrill<jason@redhat.com>  a écrit:
>
>> A followup: non-literal argument types shouldn't change the constexpr
>> flag either, and we shouldn't crash when a constructor initializes
>> bases as well as members (50296).  I'm not sure how my testing missed
>> that bug...
>>
>> Tested x86_64-pc-linux-gnu, applying to trunk.
>> commit 26e458d541a3b04512ab88cfab866703e868e728
>> Author: Jason Merrill<jason@redhat.com>
>> Date:   Thu Jul 14 23:56:59 2011 -0400
>>
>>      zadditional_options
>
> I fail to see what the patch below has to do with the cover letter you
> wrote above.  Am I missing something?

Hmm, Thunderbird has wanted to attach that patch for a while and finally 
managed to sneak it past me.  Here's the proper patch.


[-- Attachment #2: constexpr-mem.patch --]
[-- Type: text/x-patch, Size: 5302 bytes --]

commit b7cc1c044d3a529340dc17599d58bef1dac8333a
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Sep 5 12:24:44 2011 -0400

    	PR c++/50296
    	* semantics.c (register_constexpr_fundef): Call is_valid_constexpr_fn.
    	(cx_check_missing_mem_inits): Handle bases and empty trivial members.
    	(validate_constexpr_fundecl): Remove.
    	* decl.c (start_preparsed_function): Don't call it.
    	* cp-tree.h: Don't declare it.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index cf6c056..ae4cd07 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5367,7 +5367,6 @@ extern void finish_handler_parms		(tree, tree);
 extern void finish_handler			(tree);
 extern void finish_cleanup			(tree, tree);
 extern bool literal_type_p (tree);
-extern tree validate_constexpr_fundecl (tree);
 extern tree register_constexpr_fundef (tree, tree);
 extern bool check_constexpr_ctor_body (tree, tree);
 extern tree ensure_literal_type_for_constexpr_object (tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 39a0b0e..eed4535 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -12659,10 +12659,6 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
 	maybe_apply_pragma_weak (decl1);
     }
 
-  /* constexpr functions must have literal argument types and
-     literal return type.  */
-  validate_constexpr_fundecl (decl1);
-
   /* Reset this in case the call to pushdecl changed it.  */
   current_function_decl = decl1;
 
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index bdc4cf2..f782df9 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -5485,7 +5485,6 @@ is_valid_constexpr_fn (tree fun, bool complain)
 	    }
 	}
 
-      /* Check this again here for cxx_eval_call_expression.  */
       if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fun)
 	  && !CLASSTYPE_LITERAL_P (DECL_CONTEXT (fun)))
 	{
@@ -5502,29 +5501,6 @@ is_valid_constexpr_fn (tree fun, bool complain)
   return ret;
 }
 
-/* Return non-null if FUN certainly designates a valid constexpr function
-   declaration.  Otherwise return NULL.  Issue appropriate diagnostics
-   if necessary.  Note that we only check the declaration, not the body
-   of the function.  */
-
-tree
-validate_constexpr_fundecl (tree fun)
-{
-  if (processing_template_decl || !DECL_DECLARED_CONSTEXPR_P (fun))
-    return NULL;
-  else if (DECL_CLONED_FUNCTION_P (fun))
-    /* We already checked the original function.  */
-    return fun;
-
-  if (!is_valid_constexpr_fn (fun, !DECL_TEMPLATE_INFO (fun)))
-    {
-      DECL_DECLARED_CONSTEXPR_P (fun) = false;
-      return NULL;
-    }
-
-  return fun;
-}
-
 /* Subroutine of  build_constexpr_constructor_member_initializers.
    The expression tree T represents a data member initialization
    in a (constexpr) constructor definition.  Build a pairing of
@@ -5799,17 +5775,27 @@ cx_check_missing_mem_inits (tree fun, tree body, bool complain)
       else
 	{
 	  index = CONSTRUCTOR_ELT (body, i)->index;
-	  /* Skip base vtable inits.  */
-	  if (TREE_CODE (index) == COMPONENT_REF)
+	  /* Skip base and vtable inits.  */
+	  if (TREE_CODE (index) != FIELD_DECL)
 	    continue;
 	}
       for (; field != index; field = DECL_CHAIN (field))
 	{
+	  tree ftype;
 	  if (TREE_CODE (field) != FIELD_DECL
 	      || (DECL_C_BIT_FIELD (field) && !DECL_NAME (field)))
 	    continue;
 	  if (!complain)
 	    return true;
+	  ftype = strip_array_types (TREE_TYPE (field));
+	  if (type_has_constexpr_default_constructor (ftype))
+	    {
+	      /* It's OK to skip a member with a trivial constexpr ctor.
+	         A constexpr ctor that isn't trivial should have been
+	         added in by now.  */
+	      gcc_checking_assert (!TYPE_HAS_COMPLEX_DFLT (ftype));
+	      continue;
+	    }
 	  error ("uninitialized member %qD in %<constexpr%> constructor",
 		 field);
 	  bad = true;
@@ -5834,6 +5820,9 @@ register_constexpr_fundef (tree fun, tree body)
   constexpr_fundef entry;
   constexpr_fundef **slot;
 
+  if (!is_valid_constexpr_fn (fun, !DECL_TEMPLATE_INFO (fun)))
+    return NULL;
+
   body = massage_constexpr_body (fun, body);
   if (body == NULL_TREE || body == error_mark_node)
     {
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C
index 44e6bc7..cbd4983 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C
@@ -17,4 +17,4 @@ constexpr int b = A<B>().f();	// { dg-error "non-constexpr function" }
 
 template <class T>
 constexpr int f (T t) { return 42; } // { dg-error "parameter" }
-constexpr int x = f(B());	     // { dg-error "constexpr function" }
+constexpr int x = f(B());	     // { dg-error "constexpr" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-friend.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-friend.C
index 1831a2b..57782cf 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-friend.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-friend.C
@@ -19,5 +19,5 @@ struct C
 
 constexpr int i = f(C<int>());
 constexpr int j = C<int>().m(C<int>());
-constexpr int k = C<double>().m(A()); // { dg-error "non-constexpr function" }
-constexpr int l = g(C<double>(),A()); // { dg-error "non-constexpr function" }
+constexpr int k = C<double>().m(A()); // { dg-error "constexpr" }
+constexpr int l = g(C<double>(),A()); // { dg-error "constexpr" }

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: C++ PATCHes for core 1358, 1360, c++/50248 (constexpr, templates, default constructor)
  2011-09-05 19:07 ` H.J. Lu
@ 2012-06-15  3:41   ` H.J. Lu
  0 siblings, 0 replies; 8+ messages in thread
From: H.J. Lu @ 2012-06-15  3:41 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches List

On Mon, Sep 5, 2011 at 12:07 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Sun, Sep 4, 2011 at 9:29 PM, Jason Merrill <jason@redhat.com> wrote:
>> At the Bloomington C++ meeting we discussed some issues with the constexpr
>> specification that the clang team encountered while trying to implement it.
>>  Among the issues was a problem that also came up recently for us as BZ
>> 50248: if the constexpr-ness of a template instantiation depends on its
>> body, we need to instantiate it in order to decide whether or not an
>> implicitly-declared function that uses it is constexpr.  The resolution of
>> DR 1358 is that an instantiation of a constexpr template is constexpr even
>> if it can never produce a constant expression.
>>
>> The second patch is related to DR 1360, where the clang team was complaining
>> that deciding whether or not a class is literal requires the implicit
>> declaration of the default constructor, which they would like to do lazily.
>>  We seem to have agreed that it can be avoided in the cases where doing such
>> is useful, but while looking at this I noticed a bug in our handling of this
>> stuff: the function synthesized_default_constructor_is_constexpr was only
>> right for trivial constructors.  So now I've renamed it accordingly, and
>> force the implicit declaration for the non-trivial case.
>>
>> Tested x86_64-pc-linux-gnu, applying to trunk.
>>
>
> This caused:
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50296
>

This also caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53202

-- 
H.J.

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2012-06-15  3:06 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-05  4:29 C++ PATCHes for core 1358, 1360, c++/50248 (constexpr, templates, default constructor) Jason Merrill
2011-09-05  5:04 ` Gabriel Dos Reis
2011-09-05  6:18   ` Jason Merrill
2011-09-05 19:07 ` H.J. Lu
2012-06-15  3:41   ` H.J. Lu
2011-09-06 18:16 ` Jason Merrill
2011-09-06 20:29   ` Dodji Seketeli
2011-09-06 21:32     ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).