Patchwork C++ PATCHes for core 1358, 1360, c++/50248 (constexpr, templates, default constructor)

login
register
mail settings
Submitter Jason Merrill
Date Sept. 6, 2011, 9:32 p.m.
Message ID <4E66916A.5040500@redhat.com>
Download mbox | patch
Permalink /patch/113671/
State New
Headers show

Comments

Jason Merrill - Sept. 6, 2011, 9:32 p.m.
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.

Patch

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" }