Patchwork C++ PATCH to when constexpr violations are diagnosed

login
register
mail settings
Submitter Jason Merrill
Date Sept. 20, 2011, 7:35 p.m.
Message ID <4E78EB09.6080001@redhat.com>
Download mbox | patch
Permalink /patch/115628/
State New
Headers show

Comments

Jason Merrill - Sept. 20, 2011, 7:35 p.m.
For a normal function, we want a constexpr violation to be diagnosed 
immediately so that the programmer can fix it.  But for a template, we 
don't want to complain about a particular instantiation if other 
instantiations could be usable as constexpr functions.  I've gone 
through a couple of different checks to test this condition, but neither 
was quite right, so now I've actually added the condition I want to 
test: Is this function somehow generated by the compiler?  In that case, 
we let it pass and just complain if it gets used in a constant 
expression; otherwise, we complain immediately.

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

Patch

commit 4c572dcb57f6e6073ebf8155f2a9ea254c90bf0f
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Sep 15 17:20:39 2011 -0400

    	* cp-tree.h (DECL_TEMPLOID_INSTANTIATION): New.
    	(DECL_GENERATED_P): New.
    	* class.c (finalize_literal_type_property): Use them.
    	* semantics.c (is_instantiation_of_constexpr): Likewise.
    	(register_constexpr_fundef): Likewise.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index a4a7468..e398416 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -4581,7 +4581,7 @@  finalize_literal_type_property (tree t)
 	  && !DECL_CONSTRUCTOR_P (fn))
 	{
 	  DECL_DECLARED_CONSTEXPR_P (fn) = false;
-	  if (!DECL_TEMPLATE_INFO (fn))
+	  if (!DECL_GENERATED_P (fn))
 	    {
 	      error ("enclosing class of constexpr non-static member "
 		     "function %q+#D is not a literal type", fn);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 8e52e28..bcfc3b3 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3705,6 +3705,17 @@  more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
 #define DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION(DECL) \
   (DECL_TEMPLATE_INFO (DECL) && !DECL_USE_TEMPLATE (DECL))
 
+/* Nonzero if DECL is a function generated from a function 'temploid',
+   i.e. template, member of class template, or dependent friend.  */
+#define DECL_TEMPLOID_INSTANTIATION(DECL)		\
+  (DECL_TEMPLATE_INSTANTIATION (DECL)			\
+   || DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (DECL))
+
+/* Nonzero if DECL is either defined implicitly by the compiler or
+   generated from a temploid.  */
+#define DECL_GENERATED_P(DECL) \
+  (DECL_TEMPLOID_INSTANTIATION (DECL) || DECL_DEFAULTED_FN (DECL))
+
 /* Nonzero iff we are currently processing a declaration for an
    entity with its own template parameter list, and which is not a
    full specialization.  */
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index f782df9..150805f 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -3559,7 +3559,7 @@  emit_associated_thunks (tree fn)
 static inline bool
 is_instantiation_of_constexpr (tree fun)
 {
-  return (DECL_TEMPLATE_INFO (fun)
+  return (DECL_TEMPLOID_INSTANTIATION (fun)
 	  && DECL_DECLARED_CONSTEXPR_P (DECL_TEMPLATE_RESULT
 					(DECL_TI_TEMPLATE (fun))));
 }
@@ -5820,7 +5820,7 @@  register_constexpr_fundef (tree fun, tree body)
   constexpr_fundef entry;
   constexpr_fundef **slot;
 
-  if (!is_valid_constexpr_fn (fun, !DECL_TEMPLATE_INFO (fun)))
+  if (!is_valid_constexpr_fn (fun, !DECL_GENERATED_P (fun)))
     return NULL;
 
   body = massage_constexpr_body (fun, body);
@@ -5833,13 +5833,13 @@  register_constexpr_fundef (tree fun, tree body)
 
   if (!potential_rvalue_constant_expression (body))
     {
-      if (!DECL_TEMPLATE_INFO (fun))
+      if (!DECL_GENERATED_P (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)))
+      && cx_check_missing_mem_inits (fun, body, !DECL_GENERATED_P (fun)))
     return NULL;
 
   /* Create the constexpr function table if necessary.  */
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-generated1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-generated1.C
new file mode 100644
index 0000000..73ddc8f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-generated1.C
@@ -0,0 +1,21 @@ 
+// { dg-options -std=c++0x }
+
+template <class T> struct A
+{
+  constexpr T f ();
+};
+
+int g();
+
+// We should complain about this.
+template<> constexpr int A<int>::f()
+{ return g(); }			// { dg-error "non-constexpr" }
+
+// But not about this.
+struct B
+{
+  int i;
+  constexpr B(int i = g()):i(i) { }
+};
+struct C: B { };
+C c;