public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* C++ PATCH to deal with trivial but non-callable [cd]tors
@ 2013-10-23 19:14 Jason Merrill
  2013-10-23 19:16 ` Paolo Carlini
  2013-10-25 19:04 ` Eric Botcazou
  0 siblings, 2 replies; 11+ messages in thread
From: Jason Merrill @ 2013-10-23 19:14 UTC (permalink / raw)
  To: gcc-patches List

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

Late in the C++11 process it was decided that a constructor or 
destructor can be trivial but not callable; as a result, everywhere that 
assumed that a call to a trivial function didn't need any processing 
needed to be updated.  This patch does that.

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


[-- Attachment #2: trivial-deleted.patch --]
[-- Type: text/x-patch, Size: 44874 bytes --]

commit cbc14ce6b840e6311b8c580564f8c836f8dc18ae
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Oct 22 16:38:01 2013 -0400

    	In C++11 a trivial [cd]tor might not be callable.
    	* class.c (user_provided_p): A function deleted on its declation
    	in the class is not user-provided.
    	(type_build_ctor_call): Also force a ctor call if we
    	might have a deleted or private trivial ctor.
    	(type_build_dtor_call): New.
    	(deduce_noexcept_on_destructors): Remove obsolete code.
    	* cp-tree.h: Declare type_build_dtor_call.
    	* decl.c (expand_static_init): Make sure trivial dtors are callable.
    	(cxx_maybe_build_cleanup): Likewise.
    	* except.c (build_throw): Likewise.
    	* init.c (build_value_init): Handle trivial but not callable ctors.
    	(perform_target_ctor): Make sure trivial dtor is callable.
    	(perform_member_init): Likewise.
    	(expand_cleanup_for_base): Likewise.
    	(build_vec_delete_1): Likewise.
    	(build_delete): Likewise.
    	(push_base_cleanups): Likewise.
    	(build_new_1): Avoid redundant error.
    	* method.c (synthesized_method_walk): Can't ever exit early in C++11.
    	Always process the subobject destructor.
    	* semantics.c (finish_compound_literal): Make sure trivial dtor is
    	callable.
    	* typeck2.c (split_nonconstant_init): Likewise.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 3ed73b8..cd90140 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -9273,6 +9273,9 @@ set_up_extended_ref_temp (tree decl, tree expr, vec<tree, va_gc> **cleanups,
 	    static_aggregates = tree_cons (NULL_TREE, var,
 					   static_aggregates);
 	}
+      else
+	/* Check whether the dtor is callable.  */
+	cxx_maybe_build_cleanup (var, tf_warning_or_error);
     }
 
   *initp = init;
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index c587e55..43f90d7 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -4674,15 +4674,8 @@ deduce_noexcept_on_destructors (tree t)
   if (!CLASSTYPE_METHOD_VEC (t))
     return;
 
-  bool saved_nontrivial_dtor = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t);
-
-  /* Avoid early exit from synthesized_method_walk (c++/57645).  */
-  TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = true;
-
   for (tree fns = CLASSTYPE_DESTRUCTORS (t); fns; fns = OVL_NEXT (fns))
     deduce_noexcept_on_destructor (OVL_CURRENT (fns));
-
-  TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = saved_nontrivial_dtor;
 }
 
 /* Subroutine of set_one_vmethod_tm_attributes.  Search base classes
@@ -4884,7 +4877,8 @@ user_provided_p (tree fn)
     return true;
   else
     return (!DECL_ARTIFICIAL (fn)
-	    && !DECL_DEFAULTED_IN_CLASS_P (fn));
+	    && !(DECL_INITIALIZED_IN_CLASS_P (fn)
+		 && (DECL_DEFAULTED_FN (fn) || DECL_DELETED_FN (fn))));
 }
 
 /* Returns true iff class T has a user-provided constructor.  */
@@ -5149,7 +5143,7 @@ type_has_user_declared_move_assign (tree t)
 }
 
 /* Nonzero if we need to build up a constructor call when initializing an
-   object of this class, either because it has a user-provided constructor
+   object of this class, either because it has a user-declared constructor
    or because it doesn't have a default constructor (so we need to give an
    error if no initializer is provided).  Use TYPE_NEEDS_CONSTRUCTING when
    what you care about is whether or not an object can be produced by a
@@ -5165,8 +5159,46 @@ type_build_ctor_call (tree t)
   if (TYPE_NEEDS_CONSTRUCTING (t))
     return true;
   inner = strip_array_types (t);
-  return (CLASS_TYPE_P (inner) && !TYPE_HAS_DEFAULT_CONSTRUCTOR (inner)
-	  && !ANON_AGGR_TYPE_P (inner));
+  if (!CLASS_TYPE_P (inner) || ANON_AGGR_TYPE_P (inner))
+    return false;
+  if (!TYPE_HAS_DEFAULT_CONSTRUCTOR (inner))
+    return true;
+  /* A user-declared constructor might be private, and a constructor might
+     be trivial but deleted.  */
+  for (tree fns = lookup_fnfields_slot (inner, complete_ctor_identifier);
+       fns; fns = OVL_NEXT (fns))
+    {
+      tree fn = OVL_CURRENT (fns);
+      if (!DECL_ARTIFICIAL (fn)
+	  || DECL_DELETED_FN (fn))
+	return true;
+    }
+  return false;
+}
+
+/* Like type_build_ctor_call, but for destructors.  */
+
+bool
+type_build_dtor_call (tree t)
+{
+  tree inner;
+  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t))
+    return true;
+  inner = strip_array_types (t);
+  if (!CLASS_TYPE_P (inner) || ANON_AGGR_TYPE_P (inner)
+      || !COMPLETE_TYPE_P (inner))
+    return false;
+  /* A user-declared destructor might be private, and a destructor might
+     be trivial but deleted.  */
+  for (tree fns = lookup_fnfields_slot (inner, complete_dtor_identifier);
+       fns; fns = OVL_NEXT (fns))
+    {
+      tree fn = OVL_CURRENT (fns);
+      if (!DECL_ARTIFICIAL (fn)
+	  || DECL_DELETED_FN (fn))
+	return true;
+    }
+  return false;
 }
 
 /* Remove all zero-width bit-fields from T.  */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index b1347e2..507b389 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5115,6 +5115,7 @@ extern bool type_has_move_assign		(tree);
 extern bool type_has_user_declared_move_constructor (tree);
 extern bool type_has_user_declared_move_assign(tree);
 extern bool type_build_ctor_call		(tree);
+extern bool type_build_dtor_call		(tree);
 extern void explain_non_literal_class		(tree);
 extern void defaulted_late_check		(tree);
 extern bool defaultable_fn_check		(tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index fe8fe4e..1e92f2a 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6897,7 +6897,11 @@ expand_static_init (tree decl, tree init)
   /* Some variables require no dynamic initialization.  */
   if (!init
       && TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
-    return;
+    {
+      /* Make sure the destructor is callable.  */
+      cxx_maybe_build_cleanup (decl, tf_warning_or_error);
+      return;
+    }
 
   if (DECL_THREAD_LOCAL_P (decl) && DECL_GNU_TLS_P (decl)
       && !DECL_FUNCTION_SCOPE_P (decl))
@@ -14296,7 +14300,7 @@ cxx_maybe_build_cleanup (tree decl, tsubst_flags_t complain)
     }
   /* Handle ordinary C++ destructors.  */
   type = TREE_TYPE (decl);
-  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+  if (type_build_dtor_call (type))
     {
       int flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
       bool has_vbases = (TREE_CODE (type) == RECORD_TYPE
@@ -14317,6 +14321,8 @@ cxx_maybe_build_cleanup (tree decl, tsubst_flags_t complain)
 			   sfk_complete_destructor, flags, 0, complain);
       if (call == error_mark_node)
 	cleanup = error_mark_node;
+      else if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
+	/* Discard the call.  */;
       else if (cleanup)
 	cleanup = cp_build_compound_expr (cleanup, call, complain);
       else
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index c76d944..daac0fd 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -868,17 +868,21 @@ build_throw (tree exp)
 
       throw_type = build_eh_type_type (prepare_eh_type (TREE_TYPE (object)));
 
-      if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (object)))
+      cleanup = NULL_TREE;
+      if (type_build_dtor_call (TREE_TYPE (object)))
 	{
-	  cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
+	  tree fn = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
 				     complete_dtor_identifier, 0);
-	  cleanup = BASELINK_FUNCTIONS (cleanup);
-	  mark_used (cleanup);
-	  cxx_mark_addressable (cleanup);
-	  /* Pretend it's a normal function.  */
-	  cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup);
+	  fn = BASELINK_FUNCTIONS (fn);
+	  mark_used (fn);
+	  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (object)))
+	    {
+	      cxx_mark_addressable (fn);
+	      /* Pretend it's a normal function.  */
+	      cleanup = build1 (ADDR_EXPR, cleanup_type, fn);
+	    }
 	}
-      else
+      if (cleanup == NULL_TREE)
 	cleanup = build_int_cst (cleanup_type, 0);
 
       /* ??? Indicate that this function call throws throw_type.  */
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index d18dc5e..78ea986 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -312,60 +312,55 @@ build_value_init (tree type, tsubst_flags_t complain)
 
      To value-initialize an object of type T means:
 
-     - if T is a class type (clause 9) with a user-provided constructor
-       (12.1), then the default constructor for T is called (and the
-       initialization is ill-formed if T has no accessible default
-       constructor);
+     - if T is a class type (clause 9) with either no default constructor
+       (12.1) or a default constructor that is user-provided or deleted,
+       then then the object is default-initialized;
 
-     - if T is a non-union class type without a user-provided constructor,
-       then every non-static data member and base-class component of T is
-       value-initialized;92)
+     - if T is a (possibly cv-qualified) class type without a user-provided
+       or deleted default constructor, then the object is zero-initialized
+       and the semantic constraints for default-initialization are checked,
+       and if T has a non-trivial default constructor, the object is
+       default-initialized;
 
      - if T is an array type, then each element is value-initialized;
 
      - otherwise, the object is zero-initialized.
 
      A program that calls for default-initialization or
-     value-initialization of an entity of reference type is ill-formed.
-
-     92) Value-initialization for such a class object may be implemented by
-     zero-initializing the object and then calling the default
-     constructor.  */
+     value-initialization of an entity of reference type is ill-formed.  */
 
   /* The AGGR_INIT_EXPR tweaking below breaks in templates.  */
   gcc_assert (!processing_template_decl
 	      || (SCALAR_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE));
 
-  if (CLASS_TYPE_P (type))
+  if (type_build_ctor_call (type))
     {
-      /* Instead of the above, only consider the user-providedness of the
-	 default constructor itself so value-initializing a class with an
-	 explicitly defaulted default constructor and another user-provided
-	 constructor works properly (c++std-core-19883).  */
-      if (type_has_user_provided_default_constructor (type)
-	  || (!TYPE_HAS_DEFAULT_CONSTRUCTOR (type)
-	      && type_has_user_provided_constructor (type)))
-	return build_aggr_init_expr
-	  (type,
-	   build_special_member_call (NULL_TREE, complete_ctor_identifier,
-				      NULL, type, LOOKUP_NORMAL,
-				      complain));
+      tree ctor = build_aggr_init_expr
+	(type,
+	 build_special_member_call (NULL_TREE, complete_ctor_identifier,
+				    NULL, type, LOOKUP_NORMAL,
+				    complain));
+      if (ctor == error_mark_node
+	  || type_has_user_provided_default_constructor (type))
+	return ctor;
       else if (TYPE_HAS_COMPLEX_DFLT (type))
 	{
 	  /* This is a class that needs constructing, but doesn't have
 	     a user-provided constructor.  So we need to zero-initialize
 	     the object and then call the implicitly defined ctor.
 	     This will be handled in simplify_aggr_init_expr.  */
-	  tree ctor = build_special_member_call
-	    (NULL_TREE, complete_ctor_identifier,
-	     NULL, type, LOOKUP_NORMAL, complain);
-	  ctor = build_aggr_init_expr (type, ctor);
-	  if (ctor != error_mark_node)
-	    AGGR_INIT_ZERO_FIRST (ctor) = 1;
+	  AGGR_INIT_ZERO_FIRST (ctor) = 1;
 	  return ctor;
 	}
     }
-  return build_value_init_noctor (type, complain);
+
+  /* Discard any access checking during subobject initialization;
+     the checks are implied by the call to the ctor which we have
+     verified is OK (cpp0x/defaulted46.C).  */
+  push_deferring_access_checks (dk_deferred);
+  tree r = build_value_init_noctor (type, complain);
+  pop_deferring_access_checks ();
+  return r;
 }
 
 /* Like build_value_init, but don't call the constructor for TYPE.  Used
@@ -503,14 +498,15 @@ perform_target_ctor (tree init)
   finish_expr_stmt (build_aggr_init (decl, init,
 				     LOOKUP_NORMAL|LOOKUP_DELEGATING_CONS,
 				     tf_warning_or_error));
-  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+  if (type_build_dtor_call (type))
     {
       tree expr = build_delete (type, decl, sfk_complete_destructor,
 				LOOKUP_NORMAL
 				|LOOKUP_NONVIRTUAL
 				|LOOKUP_DESTRUCTOR,
 				0, tf_warning_or_error);
-      if (expr != error_mark_node)
+      if (expr != error_mark_node
+	  && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
 	finish_eh_cleanup (expr);
     }
 }
@@ -732,7 +728,7 @@ perform_member_init (tree member, tree init)
 						tf_warning_or_error));
     }
 
-  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+  if (type_build_dtor_call (type))
     {
       tree expr;
 
@@ -744,7 +740,8 @@ perform_member_init (tree member, tree init)
 			   LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0,
 			   tf_warning_or_error);
 
-      if (expr != error_mark_node)
+      if (expr != error_mark_node
+	  && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
 	finish_eh_cleanup (expr);
     }
 }
@@ -1192,7 +1189,7 @@ expand_cleanup_for_base (tree binfo, tree flag)
 {
   tree expr;
 
-  if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (binfo)))
+  if (!type_build_dtor_call (BINFO_TYPE (binfo)))
     return;
 
   /* Call the destructor.  */
@@ -1202,6 +1199,10 @@ expand_cleanup_for_base (tree binfo, tree flag)
 				    binfo,
 				    LOOKUP_NORMAL | LOOKUP_NONVIRTUAL,
                                     tf_warning_or_error);
+
+  if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (binfo)))
+    return;
+
   if (flag)
     expr = fold_build3_loc (input_location,
 			COND_EXPR, void_type_node,
@@ -2360,7 +2361,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
 
   is_initialized = (type_build_ctor_call (elt_type) || *init != NULL);
 
-  if (*init == NULL)
+  if (*init == NULL && cxx_dialect < cxx11)
     {
       bool maybe_uninitialized_error = false;
       /* A program that calls for default-initialization [...] of an
@@ -3152,8 +3153,21 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
 
   size_exp = size_in_bytes (type);
 
-  if (! MAYBE_CLASS_TYPE_P (type) || TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
+  if (! MAYBE_CLASS_TYPE_P (type))
     goto no_destructor;
+  else if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
+    {
+      /* Make sure the destructor is callable.  */
+      if (type_build_dtor_call (type))
+	{
+	  tmp = build_delete (ptype, base, sfk_complete_destructor,
+			      LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1,
+			      complain);
+	  if (tmp == error_mark_node)
+	    return error_mark_node;
+	}
+      goto no_destructor;
+    }
 
   /* The below is short by the cookie size.  */
   virtual_size = size_binop (MULT_EXPR, size_exp,
@@ -3829,7 +3843,7 @@ build_dtor_call (tree exp, special_function_kind dtor_kind, int flags,
    flags.  See cp-tree.h for more info.  */
 
 tree
-build_delete (tree type, tree addr, special_function_kind auto_delete,
+build_delete (tree otype, tree addr, special_function_kind auto_delete,
 	      int flags, int use_global_delete, tsubst_flags_t complain)
 {
   tree expr;
@@ -3837,22 +3851,33 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
   if (addr == error_mark_node)
     return error_mark_node;
 
+  tree type = TYPE_MAIN_VARIANT (otype);
+
   /* Can happen when CURRENT_EXCEPTION_OBJECT gets its type
      set to `error_mark_node' before it gets properly cleaned up.  */
   if (type == error_mark_node)
     return error_mark_node;
 
-  type = TYPE_MAIN_VARIANT (type);
+  if (TREE_CODE (type) == POINTER_TYPE)
+    type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
 
-  addr = mark_rvalue_use (addr);
+  if (TREE_CODE (type) == ARRAY_TYPE)
+    {
+      if (TYPE_DOMAIN (type) == NULL_TREE)
+	{
+	  if (complain & tf_error)
+	    error ("unknown array size in delete");
+	  return error_mark_node;
+	}
+      return build_vec_delete (addr, array_type_nelts (type),
+			       auto_delete, use_global_delete, complain);
+    }
 
-  if (TYPE_PTR_P (type))
+  if (TYPE_PTR_P (otype))
     {
       bool complete_p = true;
 
-      type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
-      if (TREE_CODE (type) == ARRAY_TYPE)
-	goto handle_array;
+      addr = mark_rvalue_use (addr);
 
       /* We don't want to warn about delete of void*, only other
 	  incomplete types.  Deleting other incomplete types
@@ -3908,19 +3933,6 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
       /* Throw away const and volatile on target type of addr.  */
       addr = convert_force (build_pointer_type (type), addr, 0, complain);
     }
-  else if (TREE_CODE (type) == ARRAY_TYPE)
-    {
-    handle_array:
-
-      if (TYPE_DOMAIN (type) == NULL_TREE)
-	{
-	  if (complain & tf_error)
-	    error ("unknown array size in delete");
-	  return error_mark_node;
-	}
-      return build_vec_delete (addr, array_type_nelts (type),
-			       auto_delete, use_global_delete, complain);
-    }
   else
     {
       /* Don't check PROTECT here; leave that decision to the
@@ -3935,10 +3947,18 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
       addr = convert_force (build_pointer_type (type), addr, 0, complain);
     }
 
-  gcc_assert (MAYBE_CLASS_TYPE_P (type));
-
   if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
     {
+      /* Make sure the destructor is callable.  */
+      if (type_build_dtor_call (type))
+	{
+	  expr = build_dtor_call (cp_build_indirect_ref (addr, RO_NULL,
+							 complain),
+				  sfk_complete_destructor, flags, complain);
+	  if (expr == error_mark_node)
+	    return error_mark_node;
+	}
+
       if (auto_delete != sfk_deleting_destructor)
 	return void_zero_node;
 
@@ -4062,7 +4082,7 @@ push_base_cleanups (void)
       for (vbases = CLASSTYPE_VBASECLASSES (current_class_type), i = 0;
 	   vec_safe_iterate (vbases, i, &base_binfo); i++)
 	{
-	  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo)))
+	  if (type_build_dtor_call (BINFO_TYPE (base_binfo)))
 	    {
 	      expr = build_special_member_call (current_class_ref,
 						base_dtor_identifier,
@@ -4070,10 +4090,13 @@ push_base_cleanups (void)
 						base_binfo,
 						(LOOKUP_NORMAL
 						 | LOOKUP_NONVIRTUAL),
-                                                tf_warning_or_error);
-	      expr = build3 (COND_EXPR, void_type_node, cond,
-			     expr, void_zero_node);
-	      finish_decl_cleanup (NULL_TREE, expr);
+						tf_warning_or_error);
+	      if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo)))
+		{
+		  expr = build3 (COND_EXPR, void_type_node, cond,
+				 expr, void_zero_node);
+		  finish_decl_cleanup (NULL_TREE, expr);
+		}
 	    }
 	}
     }
@@ -4082,8 +4105,8 @@ push_base_cleanups (void)
   for (binfo = TYPE_BINFO (current_class_type), i = 0;
        BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
     {
-      if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo))
-	  || BINFO_VIRTUAL_P (base_binfo))
+      if (BINFO_VIRTUAL_P (base_binfo)
+	  || !type_build_dtor_call (BINFO_TYPE (base_binfo)))
 	continue;
 
       expr = build_special_member_call (current_class_ref,
@@ -4091,7 +4114,8 @@ push_base_cleanups (void)
 					NULL, base_binfo,
 					LOOKUP_NORMAL | LOOKUP_NONVIRTUAL,
                                         tf_warning_or_error);
-      finish_decl_cleanup (NULL_TREE, expr);
+      if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo)))
+	finish_decl_cleanup (NULL_TREE, expr);
     }
 
   /* Don't automatically destroy union members.  */
@@ -4108,7 +4132,7 @@ push_base_cleanups (void)
 	continue;
       if (ANON_UNION_TYPE_P (this_type))
 	continue;
-      if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (this_type))
+      if (type_build_dtor_call (this_type))
 	{
 	  tree this_member = (build_class_member_access_expr
 			      (current_class_ref, member,
@@ -4119,7 +4143,8 @@ push_base_cleanups (void)
 			       sfk_complete_destructor,
 			       LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL,
 			       0, tf_warning_or_error);
-	  finish_decl_cleanup (NULL_TREE, expr);
+	  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (this_type))
+	    finish_decl_cleanup (NULL_TREE, expr);
 	}
     }
 }
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 4ac533e..593a4a6 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1265,8 +1265,9 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
      class versions and other properties of the type.  But a subobject
      class can be trivially copyable and yet have overload resolution
      choose a template constructor for initialization, depending on
-     rvalueness and cv-quals.  So we can't exit early for copy/move
-     methods in C++0x.  The same considerations apply in C++98/03, but
+     rvalueness and cv-quals.  And furthermore, a member in a base might
+     be trivial but deleted or otherwise not callable.  So we can't exit
+     early in C++0x.  The same considerations apply in C++98/03, but
      there the definition of triviality does not consider overload
      resolution, so a constructor can be trivial even if it would otherwise
      call a non-trivial constructor.  */
@@ -1282,7 +1283,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
 	    inform (input_location, "defaulted default constructor does "
 		    "not initialize any non-static data member");
 	}
-      if (!diag)
+      if (!diag && cxx_dialect < cxx11)
 	return;
     }
 
@@ -1323,7 +1324,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
 
       process_subob_fn (rval, spec_p, trivial_p, deleted_p,
 			constexpr_p, diag, basetype);
-      if (ctor_p && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (basetype))
+      if (ctor_p)
 	{
 	  /* In a constructor we also need to check the subobject
 	     destructors for cleanup of partially constructed objects.  */
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index e56052d..052746c 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2521,6 +2521,10 @@ finish_compound_literal (tree type, tree compound_literal,
       decl = pushdecl_top_level (decl);
       DECL_NAME (decl) = make_anon_name ();
       SET_DECL_ASSEMBLER_NAME (decl, DECL_NAME (decl));
+      /* Make sure the destructor is callable.  */
+      tree clean = cxx_maybe_build_cleanup (decl, complain);
+      if (clean == error_mark_node)
+	return error_mark_node;
       return decl;
     }
   else
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 011406c..4b71a76 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -640,12 +640,13 @@ split_nonconstant_init_1 (tree dest, tree init)
 	      code = build_stmt (input_location, EXPR_STMT, code);
 	      code = maybe_cleanup_point_expr_void (code);
 	      add_stmt (code);
-	      if (!TYPE_HAS_TRIVIAL_DESTRUCTOR (inner_type))
+	      if (type_build_dtor_call (inner_type))
 		{
 		  code = (build_special_member_call
 			  (sub, complete_dtor_identifier, NULL, inner_type,
 			   LOOKUP_NORMAL, tf_warning_or_error));
-		  finish_eh_cleanup (code);
+		  if (!TYPE_HAS_TRIVIAL_DESTRUCTOR (inner_type))
+		    finish_eh_cleanup (code);
 		}
 
 	      num_split_elts++;
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted19.C b/gcc/testsuite/g++.dg/cpp0x/defaulted19.C
index 5603632..f7de073 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted19.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted19.C
@@ -1,5 +1,6 @@
-// We allocate a cookie to help us run the destructor even if it's deleted.
-// { dg-options -std=c++11 }
+// We don't allocate a cookie to help us run the destructor if it's trivial,
+// even if it's deleted.
+// { dg-options "-std=c++11" }
 // { dg-do run }
 
 struct A
@@ -17,5 +18,5 @@ void *operator new[](__SIZE_TYPE__ t)
 int main()
 {
   A* ap = new A[5];
-  return ap == p;
+  return ap != p;
 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted19a.C b/gcc/testsuite/g++.dg/cpp0x/defaulted19a.C
new file mode 100644
index 0000000..6d2a26a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted19a.C
@@ -0,0 +1,24 @@
+// We allocate a cookie to help us run the destructor if it's non-trivial,
+// even if it's deleted.
+// { dg-options "-std=c++0x" }
+// { dg-do run }
+
+struct B { ~B() {} };
+struct A
+{
+  B b;
+  ~A() = delete;
+};
+
+void *p = 0;
+void *operator new[](__SIZE_TYPE__ t)
+{
+  p = ::operator new (t);
+  return p;
+}
+
+int main()
+{
+  A* ap = new A[5];
+  return ap == p;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted2.C b/gcc/testsuite/g++.dg/cpp0x/defaulted2.C
index 8a8c874..3cef600 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted2.C
@@ -62,7 +62,7 @@ int main()
 {
   F f;
   F f2(f);			// { dg-error "use" }
-  B* b = new const B;		// { dg-error "uninitialized const" }
+  const B* b = new const B;		// { dg-error "uninitialized const" }
   U u;				// { dg-error "deleted" }
 }
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted46.C b/gcc/testsuite/g++.dg/cpp0x/defaulted46.C
new file mode 100644
index 0000000..d4562c9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted46.C
@@ -0,0 +1,17 @@
+// { dg-require-effective-target c++11 }
+
+struct A
+{
+protected:
+  A() = default;
+  int i;
+};
+
+struct B: A {
+  B() = default;
+};
+
+int main()
+{
+  B();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit11.C b/gcc/testsuite/g++.dg/cpp0x/implicit11.C
index 3b536e7..9f5841d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/implicit11.C
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit11.C
@@ -12,6 +12,6 @@ struct B: A { };		// { dg-error "deleted" }
 extern B eb;
 int main()
 {
-  B* b1 = new B;		// { dg-error "use of deleted function" "" { xfail *-*-* } }
+  B* b1 = new B;		// { dg-error "use of deleted function" }
   B* b2 = new B(eb);		// { dg-error "use of deleted function" }
 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae21.C b/gcc/testsuite/g++.dg/cpp0x/sfinae21.C
index 3eab43c..62c003a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae21.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae21.C
@@ -9,6 +9,10 @@ char f(int);
 template<class>
 char (&f(...))[2];
 
-struct ND { ND() = delete; };
+struct ND {
+  // Make ND() non-aggregate.
+  virtual void f();
+  ND() = delete;
+};
 
 static_assert(sizeof(f<ND[1]>(0)) != 1, "Error");
diff --git a/gcc/testsuite/g++.dg/ext/anon-struct4.C b/gcc/testsuite/g++.dg/ext/anon-struct4.C
index 5d0bf71..9c8e887 100644
--- a/gcc/testsuite/g++.dg/ext/anon-struct4.C
+++ b/gcc/testsuite/g++.dg/ext/anon-struct4.C
@@ -1,5 +1,5 @@
 // PR c++/14401
 
-struct { struct { int& i ; } bar ; } foo ; // { dg-error "uninitialized" "uninit" }
+struct { struct { int& i ; } bar ; } foo ; // { dg-error "deleted|uninitialized" "uninit" }
 // { dg-warning "anonymous" "anon" { target c++98 } 3 }
-// { dg-message "should be initialized" "ref-uninit" { target *-*-* } 3 }
+// { dg-message "should be initialized" "ref-uninit" { target c++98 } 3 }
diff --git a/gcc/testsuite/g++.dg/init/ctor8.C b/gcc/testsuite/g++.dg/init/ctor8.C
index 3491f6a..7eb72eb 100644
--- a/gcc/testsuite/g++.dg/init/ctor8.C
+++ b/gcc/testsuite/g++.dg/init/ctor8.C
@@ -1,9 +1,10 @@
 // PR c++/29039
 
-typedef struct S {
+typedef struct S {	    // { dg-error "reference" "" { target c++11 } }
   int &r; 
 }; // { dg-warning "'typedef' was ignored" }
 
+
 S f () {
-  return S (); // { dg-error "reference" }
+  return S (); // { dg-error "reference|deleted" }
 }
diff --git a/gcc/testsuite/g++.dg/init/pr25811.C b/gcc/testsuite/g++.dg/init/pr25811.C
index c906a9b..e8945da 100644
--- a/gcc/testsuite/g++.dg/init/pr25811.C
+++ b/gcc/testsuite/g++.dg/init/pr25811.C
@@ -1,51 +1,51 @@
 // PR c++/25811
 // { dg-do compile }
 
-struct A1
+struct A1		// { dg-error "uninitialized" "" { target c++11 } }
 {
-  int const j; // { dg-message "should be initialized" }
+  int const j; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
-struct A2
+struct A2		// { dg-error "uninitialized" "" { target c++11 } }
 {
-  int const volatile i; // { dg-message "should be initialized" }
+  int const volatile i; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
-struct A3
+struct A3		// { dg-error "uninitialized" "" { target c++11 } }
 {
-  int& ref; // { dg-message "should be initialized" }
+  int& ref; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
-struct A4
+struct A4		// { dg-error "uninitialized" "" { target c++11 } }
 {
-  int const& ref; // { dg-message "should be initialized" }
+  int const& ref; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
-struct A5
+struct A5		// { dg-error "uninitialized" "" { target c++11 } }
 {
-  int& ref; // { dg-message "should be initialized" }
-  int const i; // { dg-message "should be initialized" }
+  int& ref; // { dg-message "should be initialized" "" { target c++98 } }
+  int const i; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
-template <class T> struct S1
+template <class T> struct S1 // { dg-error "uninitialized" "" { target c++11 } }
 {
-  T const i; // { dg-message "should be initialized" }
+  T const i; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
-template <class T> struct S2
+template <class T> struct S2 // { dg-error "uninitialized" "" { target c++11 } }
 {
-  T const volatile i; // { dg-message "should be initialized" }
+  T const volatile i; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
-template <class T> struct S3
+template <class T> struct S3 // { dg-error "uninitialized" "" { target c++11 } }
 {
-  T& ref; // { dg-message "should be initialized" }
+  T& ref; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
-template <class T> struct S4
+template <class T> struct S4 // { dg-error "uninitialized" "" { target c++11 } }
 {
-  T const i; // { dg-message "should be initialized" }
-  T& ref; // { dg-message "should be initialized" }
+  T const i; // { dg-message "should be initialized" "" { target c++98 } }
+  T& ref; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
 struct X
@@ -55,44 +55,44 @@ struct X
   int const& r;
 };
 
-struct Y11
+struct Y11		// { dg-error "uninitialized" "" { target c++11 } }
 {
-  int const i; // { dg-message "should be initialized" }
+  int const i; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
-struct Y1
+struct Y1		// { dg-error "deleted" "" { target c++11 } }
 {
   Y11 a[1];
 };
 
-struct Y22
+struct Y22		// { dg-error "uninitialized" "" { target c++11 } }
 {
-  int& ref; // { dg-message "should be initialized" }
+  int& ref; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
-struct Y2
+struct Y2		// { dg-error "deleted" "" { target c++11 } }
 {
   Y22 a[1];
 };
 
-struct Z1
+struct Z1		// { dg-error "uninitialized" "" { target c++11 } }
 {
-  int const i; // { dg-message "should be initialized" }
+  int const i; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
-struct Z2
+struct Z2 // { dg-error "uninitialized" "" { target c++11 } }
 {
-  int& ref; // { dg-message "should be initialized" }
+  int& ref; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
-struct Z3
+struct Z3 // { dg-error "uninitialized" "" { target c++11 } }
 {
-  int const i; // { dg-message "should be initialized" }
+  int const i; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
-struct Z4
+struct Z4 // { dg-error "uninitialized" "" { target c++11 } }
 {
-  int& ref; // { dg-message "should be initialized" }
+  int& ref; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
 struct Z5
@@ -100,7 +100,7 @@ struct Z5
   int i;
 };
 
-struct Z
+struct Z		// { dg-error "deleted" "" { target c++11 } }
 {
   Z1 z1;
   Z2 z2;
@@ -109,54 +109,54 @@ struct Z
   Z5 z5;
 };
 
-union U
+union U // { dg-error "uninitialized" "" { target c++11 } }
 {
-  int const i; // { dg-message "should be initialized" }
+  int const i; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
 void f1 ()
 {
-  new A1; // { dg-error "uninitialized const member" }
+  new A1; // { dg-error "deleted|uninitialized const member" }
 }
 
 void f2 ()
 {
-  new A2; // { dg-error "uninitialized const member" }
+  new A2; // { dg-error "deleted|uninitialized const member" }
 }
 
 void f3 ()
 {
-  new A3; // { dg-error "uninitialized reference member" }
+  new A3; // { dg-error "deleted|uninitialized reference member" }
 }
 
 void f4 ()
 {
-  new A4; // { dg-error "uninitialized reference member" }
+  new A4; // { dg-error "deleted|uninitialized reference member" }
 }
 
 void f5 ()
 {
-  new A5; // { dg-error "uninitialized reference member|uninitialized const member" }
+  new A5; // { dg-error "deleted|uninitialized reference member|uninitialized const member" }
 }
 
 void f6 ()
 {
-  new S1<int>; // { dg-error "uninitialized const member" }
+  new S1<int>; // { dg-error "deleted|uninitialized const member" }
 }
 
 void f7 ()
 {
-  new S2<int>; // { dg-error "uninitialized const member" }
+  new S2<int>; // { dg-error "deleted|uninitialized const member" }
 }
 
 void f8 ()
 {
-  new S3<int>; // { dg-error "uninitialized reference member" }
+  new S3<int>; // { dg-error "deleted|uninitialized reference member" }
 }
 
 void f9 ()
 {
-  new S4<int>; // { dg-error "uninitialized reference member|uninitialized const member" }
+  new S4<int>; // { dg-error "deleted|uninitialized reference member|uninitialized const member" }
 }
 
 void f10 ()
@@ -166,30 +166,30 @@ void f10 ()
 
 void f11 ()
 {
-  new A1[1]; // { dg-error "uninitialized const member" }
+  new A1[1]; // { dg-error "deleted|uninitialized const member" }
 }
 
 void f12 ()
 {
-  new A3[1]; // { dg-error "uninitialized reference member" }
+  new A3[1]; // { dg-error "deleted|uninitialized reference member" }
 }
 
 void f13 ()
 {
-  new Y1; // { dg-error "uninitialized const member" }
+  new Y1; // { dg-error "deleted|uninitialized const member" }
 }
 
 void f14 ()
 {
-  new Y2; // { dg-error "uninitialized reference member" }
+  new Y2; // { dg-error "deleted|uninitialized reference member" }
 }
 
 void f15 ()
 {
-  new Z; // { dg-error "uninitialized reference member|uninitialized const member" }
+  new Z; // { dg-error "deleted|uninitialized reference member|uninitialized const member" }
 }
 
 void f16 ()
 {
-  new U; // { dg-error "uninitialized const member" }
+  new U; // { dg-error "deleted|uninitialized const member" }
 }
diff --git a/gcc/testsuite/g++.dg/init/pr29043.C b/gcc/testsuite/g++.dg/init/pr29043.C
index 6ed31b5..f868dfb 100644
--- a/gcc/testsuite/g++.dg/init/pr29043.C
+++ b/gcc/testsuite/g++.dg/init/pr29043.C
@@ -1,27 +1,27 @@
 // PR c++/29043
 // { dg-do compile }
 
-struct S 
+struct S		// { dg-error "uninitialized" "" { target c++11 } }
 {
-  int const i; // { dg-message "should be initialized" }
+  int const i; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
 class C
 {
 public:
-  C() {} // { dg-error "uninitialized const member" }   
+  C() {} // { dg-error "uninitialized const member|deleted" }
   S s;
 };
 
-struct S2
+struct S2		// { dg-error "uninitialized" "" { target c++11 } }
 {
-  int& ref; // { dg-message "should be initialized" }
+  int& ref;   // { dg-message "should be initialized" "" { target c++98 } }
 };
 
 class C2
 {
 public:
-  C2() {} // { dg-error "uninitialized reference member" }   
+  C2() {} // { dg-error "uninitialized reference member|deleted" }
   S2 s;
 };
 
@@ -33,14 +33,14 @@ class C3
   };
 };
 
-struct S4
+struct S4		// { dg-error "uninitialized" "" { target c++11 } }
 {
-  int const i; // { dg-message "should be initialized" }
+  int const i; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
 struct C4
 {
-  C4() {} // { dg-error "uninitialized const member" }
+  C4() {} // { dg-error "uninitialized const member|deleted" }
   S4 s4[ 1 ];
 };
 
diff --git a/gcc/testsuite/g++.dg/init/pr43719.C b/gcc/testsuite/g++.dg/init/pr43719.C
index d3487c9..13a8221 100644
--- a/gcc/testsuite/g++.dg/init/pr43719.C
+++ b/gcc/testsuite/g++.dg/init/pr43719.C
@@ -1,51 +1,51 @@
 // PR c++/43719
 // { dg-do compile }
 
-struct A1
+struct A1		  // { dg-error "uninitialized" "" { target c++11 } }
 {
-  int const j; // { dg-message "should be initialized" }
+  int const j; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
-struct A2
+struct A2		  // { dg-error "uninitialized" "" { target c++11 } }
 {
-  int const volatile i; // { dg-message "should be initialized" }
+  int const volatile i; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
-struct A3
+struct A3		  // { dg-error "uninitialized" "" { target c++11 } }
 {
-  int& ref; // { dg-message "should be initialized" }
+  int& ref; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
-struct A4
+struct A4		  // { dg-error "uninitialized" "" { target c++11 } }
 {
-  int const& ref; // { dg-message "should be initialized" }
+  int const& ref; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
-struct A5
+struct A5		  // { dg-error "uninitialized" "" { target c++11 } }
 {
-  int& ref; // { dg-message "should be initialized" }
-  int const i; // { dg-message "should be initialized" }
+  int& ref; // { dg-message "should be initialized" "" { target c++98 } }
+  int const i; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
-template <class T> struct S1
+template <class T> struct S1 // { dg-error "uninitialized" "" { target c++11 } }
 {
-  T const i; // { dg-message "should be initialized" }
+  T const i; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
-template <class T> struct S2
+template <class T> struct S2 // { dg-error "uninitialized" "" { target c++11 } }
 {
-  T const volatile i; // { dg-message "should be initialized" }
+  T const volatile i; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
-template <class T> struct S3
+template <class T> struct S3 // { dg-error "uninitialized" "" { target c++11 } }
 {
-  T& ref; // { dg-message "should be initialized" }
+  T& ref; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
-template <class T> struct S4
+template <class T> struct S4 // { dg-error "uninitialized" "" { target c++11 } }
 {
-  T const i; // { dg-message "should be initialized" }
-  T& ref; // { dg-message "should be initialized" }
+  T const i; // { dg-message "should be initialized" "" { target c++98 } }
+  T& ref; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
 struct X
@@ -55,44 +55,44 @@ struct X
   int const& r;
 };
 
-struct Y11
+struct Y11		  // { dg-error "uninitialized" "" { target c++11 } }
 {
-  int const i; // { dg-message "should be initialized" }
+  int const i; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
-struct Y1
+struct Y1		  // { dg-error "deleted" "" { target c++11 } }
 {
   Y11 a[1];
 };
 
-struct Y22
+struct Y22	       // { dg-error "uninitialized" "" { target c++11 } }
 {
-  int& ref; // { dg-message "should be initialized" }
+  int& ref; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
-struct Y2
+struct Y2		      // { dg-error "deleted" "" { target c++11 } }
 {
   Y22 a[1];
 };
 
-struct Z1
+struct Z1		// { dg-error "uninitialized" "" { target c++11 } }
 {
-  int const i; // { dg-message "should be initialized" }
+  int const i; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
-struct Z2
+struct Z2		// { dg-error "uninitialized" "" { target c++11 } }
 {
-  int& ref; // { dg-message "should be initialized" }
+  int& ref; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
-struct Z3
+struct Z3		// { dg-error "uninitialized" "" { target c++11 } }
 {
-  int const i; // { dg-message "should be initialized" }
+  int const i; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
-struct Z4
+struct Z4		// { dg-error "uninitialized" "" { target c++11 } }
 {
-  int& ref; // { dg-message "should be initialized" }
+  int& ref; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
 struct Z5
@@ -100,7 +100,7 @@ struct Z5
   int i;
 };
 
-struct Z
+struct Z		// { dg-error "deleted" "" { target c++11 } }
 {
   Z1 z1;
   Z2 z2;
@@ -109,55 +109,55 @@ struct Z
   Z5 z5;
 };
 
-union U
+union U			// { dg-error "uninitialized" "" { target c++11 } }
 {
-  int const i; // { dg-message "should be initialized" }
+  int const i; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
 
 void f1 ()
 {
-  A1 a1; // { dg-error "uninitialized const member" }
+  A1 a1; // { dg-error "uninitialized const member|deleted" }
 }
 
 void f2 ()
 {
-  A2 a2; // { dg-error "uninitialized const member" }
+  A2 a2; // { dg-error "uninitialized const member|deleted" }
 }
 
 void f3 ()
 {
-  A3 a3; // { dg-error "uninitialized reference member" }
+  A3 a3; // { dg-error "uninitialized reference member|deleted" }
 }
 
 void f4 ()
 {
-  A4 a4; // { dg-error "uninitialized reference member" }
+  A4 a4; // { dg-error "uninitialized reference member|deleted" }
 }
 
 void f5 ()
 {
-  A5 a5; // { dg-error "uninitialized reference member|uninitialized const member" }
+  A5 a5; // { dg-error "uninitialized reference member|uninitialized const member|deleted" }
 }
 
 void f6 ()
 {
-  S1<int> s; // { dg-error "uninitialized const member" }
+  S1<int> s; // { dg-error "uninitialized const member|deleted" }
 }
 
 void f7 ()
 {
-  S2<int> s; // { dg-error "uninitialized const member" }
+  S2<int> s; // { dg-error "uninitialized const member|deleted" }
 }
 
 void f8 ()
 {
-  S3<int> s; // { dg-error "uninitialized reference member" }
+  S3<int> s; // { dg-error "uninitialized reference member|deleted" }
 }
 
 void f9 ()
 {
-  S4<int> s; // { dg-error "uninitialized reference member|uninitialized const member" }
+  S4<int> s; // { dg-error "uninitialized reference member|uninitialized const member|deleted" }
 }
 
 void f10 ()
@@ -167,31 +167,31 @@ void f10 ()
 
 void f11 ()
 {
-  A1 a[ 1 ]; // { dg-error "uninitialized const member" }
+  A1 a[ 1 ]; // { dg-error "uninitialized const member|deleted" }
 }
 
 void f12 ()
 {
-  A3 a[ 1 ]; // { dg-error "uninitialized reference member" }
+  A3 a[ 1 ]; // { dg-error "uninitialized reference member|deleted" }
 }
 
 void f13 ()
 {
-  Y1 y1; // { dg-error "uninitialized const member" }
+  Y1 y1; // { dg-error "uninitialized const member|deleted" }
 }
 
 void f14 ()
 {
-  Y2 y2; // { dg-error "uninitialized reference member" }
+  Y2 y2; // { dg-error "uninitialized reference member|deleted" }
 }
 
 void f15 ()
 {
-  Z z; // { dg-error "uninitialized reference member|uninitialized const member" }
+  Z z; // { dg-error "uninitialized reference member|uninitialized const member|deleted" }
 }
 
 void f16 ()
 {
-  U u; // { dg-error "uninitialized const member" }
+  U u; // { dg-error "uninitialized const member|deleted" }
 }
 
diff --git a/gcc/testsuite/g++.dg/init/pr44086.C b/gcc/testsuite/g++.dg/init/pr44086.C
index e3304f4..b4b0833 100644
--- a/gcc/testsuite/g++.dg/init/pr44086.C
+++ b/gcc/testsuite/g++.dg/init/pr44086.C
@@ -1,15 +1,15 @@
 // PR c++/44086
 // { dg-do compile }
 
-struct A
+struct A		// { dg-error "uninitialized" "" { target c++11 } }
 {
-    int const i : 2; // { dg-message "should be initialized" }
+    int const i : 2; // { dg-message "should be initialized" "" { target c++98 } }
 };
 
 void f()
 {
-    A a;    // { dg-error "uninitialized const" }
-    new A;  // { dg-error "uninitialized const" }
-    A();
-    new A();
+    A a;		      // { dg-error "deleted|uninitialized const" }
+    new A;		      // { dg-error "deleted|uninitialized const" }
+    A();		      // { dg-error "deleted" "" { target c++11 } }
+    new A();		      // { dg-error "deleted" "" { target c++11 } }
 }
diff --git a/gcc/testsuite/g++.dg/init/ref14.C b/gcc/testsuite/g++.dg/init/ref14.C
index 212e6e9..6ac4241 100644
--- a/gcc/testsuite/g++.dg/init/ref14.C
+++ b/gcc/testsuite/g++.dg/init/ref14.C
@@ -1,4 +1,6 @@
 // PR c++/33459
+// { dg-prune-output "uninitialized" }
+// { dg-prune-output "deleted" }
 
 union A
 {
diff --git a/gcc/testsuite/g++.dg/init/uninitialized1.C b/gcc/testsuite/g++.dg/init/uninitialized1.C
index 200c424..1e4f7ae 100644
--- a/gcc/testsuite/g++.dg/init/uninitialized1.C
+++ b/gcc/testsuite/g++.dg/init/uninitialized1.C
@@ -1,12 +1,12 @@
 // PR c++/58126
 
-struct A {
+struct A {		// { dg-error "uninitialized" "" { target c++11 } }
   const int value1;
   int& value2;
 };
 
-struct B : A { };
+struct B : A { };	// { dg-error "deleted" "" { target c++11 } }
 
-A a;  // { dg-error "uninitialized const member in 'struct A'|uninitialized reference member in 'struct A'" }
+A a;  // { dg-error "deleted|uninitialized const member in 'struct A'|uninitialized reference member in 'struct A'" }
 
-B b;  // { dg-error "uninitialized const member in base 'struct A' of 'struct B'|uninitialized reference member in base 'struct A' of 'struct B'" }
+B b;  // { dg-error "deleted|uninitialized const member in base 'struct A' of 'struct B'|uninitialized reference member in base 'struct A' of 'struct B'" }

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

* Re: C++ PATCH to deal with trivial but non-callable [cd]tors
  2013-10-23 19:14 C++ PATCH to deal with trivial but non-callable [cd]tors Jason Merrill
@ 2013-10-23 19:16 ` Paolo Carlini
  2013-10-25 19:04 ` Eric Botcazou
  1 sibling, 0 replies; 11+ messages in thread
From: Paolo Carlini @ 2013-10-23 19:16 UTC (permalink / raw)
  To: Jason Merrill, gcc-patches List

On 10/23/2013 08:05 PM, Jason Merrill wrote:
> @@ -4674,15 +4674,8 @@ deduce_noexcept_on_destructors (tree t)
>     if (!CLASSTYPE_METHOD_VEC (t))
>       return;
>   
> -  bool saved_nontrivial_dtor = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t);
> -
> -  /* Avoid early exit from synthesized_method_walk (c++/57645).  */
> -  TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = true;
> -
>     for (tree fns = CLASSTYPE_DESTRUCTORS (t); fns; fns = OVL_NEXT (fns))
>       deduce_noexcept_on_destructor (OVL_CURRENT (fns));
> -
> -  TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = saved_nontrivial_dtor;
>   }
>   
>   /* Subroutine of set_one_vmethod_tm_attributes.  Search base classes
Cool.

Paolo.

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

* Re: C++ PATCH to deal with trivial but non-callable [cd]tors
  2013-10-23 19:14 C++ PATCH to deal with trivial but non-callable [cd]tors Jason Merrill
  2013-10-23 19:16 ` Paolo Carlini
@ 2013-10-25 19:04 ` Eric Botcazou
  2013-10-25 19:27   ` Jason Merrill
  1 sibling, 1 reply; 11+ messages in thread
From: Eric Botcazou @ 2013-10-25 19:04 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches

> Late in the C++11 process it was decided that a constructor or
> destructor can be trivial but not callable; as a result, everywhere that
> assumed that a call to a trivial function didn't need any processing
> needed to be updated.  This patch does that.

This has introduced a problem for the -fdump-ada-spec machinery, which boils 
down to the TYPE_METHODS field of the following structure:

 struct _outer {
   struct _inner {
     int x;
   } inner;
 } outer;

Previously it was empty, now it contains the following destructor:

 <function_decl 0x7ffff6c6e300 _outer
    type <method_type 0x7ffff6c6d2a0
        type <void_type 0x7ffff6b0ebd0 void VOID
            align 8 symtab 0 alias set -1 canonical type 0x7ffff6b0ebd0
            pointer_to_this <pointer_type 0x7ffff6b0ec78>>
        QI
        size <integer_cst 0x7ffff6b04280 constant 8>
        unit size <integer_cst 0x7ffff6b042a0 constant 1>
        align 8 symtab 0 alias set -1 canonical type 0x7ffff6c6d1f8 method 
basetype <record_type 0x7ffff6c5c930 _outer>
        arg-types <tree_list 0x7ffff6c52fa0 value <pointer_type 
0x7ffff6c5cc78>
            chain <tree_list 0x7ffff6c52f78 value <integer_type 0x7ffff6b0e5e8 
int>
                chain <tree_list 0x7ffff6b00b18 value <void_type 
0x7ffff6b0ebd0 void>>>>
        throws <tree_list 0x7ffff6c527a8>>
    public abstract external autoinline decl_3 QI file t5.h line 1 col 9 align 
16 context <record_type 0x7ffff6c5c930 _outer>
    arguments <parm_decl 0x7ffff6c6c480 this
[...]
   full-name "_outer::~_outer() throw ()"
    not-really-extern chain <function_decl 0x7ffff6c6e500 __base_dtor >>


The destructor is created as a side effect of the call to type_build_dtor_call 
added to cxx_maybe_build_cleanup by the patch:

@@ -14296,7 +14300,7 @@ cxx_maybe_build_cleanup (tree decl, tsub
     }
   /* Handle ordinary C++ destructors.  */
   type = TREE_TYPE (decl);
-  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+  if (type_build_dtor_call (type))
     {
       int flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
       bool has_vbases = (TREE_CODE (type) == RECORD_TYPE

#0  implicitly_declare_fn (kind=sfk_destructor, type=0x7ffff6c5c930, 
    const_p=false, inherited_ctor=0x0, inherited_parms=0x0)
    at /home/eric/gnat/gnat-head/src/gcc/cp/method.c:1551
#1  0x0000000000758ef5 in lazily_declare_fn (sfk=sfk_destructor, 
    type=0x7ffff6c5c930) at /home/eric/gnat/gnat-head/src/gcc/cp/method.c:1950
#2  0x000000000075ee64 in lookup_fnfields_1 (type=0x7ffff6c5c930, 
    name=0x7ffff6b0aec8) at /home/eric/gnat/gnat-head/src/gcc/cp/search.c:1471
#3  0x000000000075eea5 in lookup_fnfields_slot (type=0x7ffff6c5c930, 
    name=0x7ffff6b0aec8) at /home/eric/gnat/gnat-head/src/gcc/cp/search.c:1483
#4  0x0000000000687dc7 in type_build_dtor_call (t=0x7ffff6c5c930)
    at /home/eric/gnat/gnat-head/src/gcc/cp/class.c:5193
#5  0x00000000005ef967 in cxx_maybe_build_cleanup (decl=0x7ffff6c64390, 
    complain=3) at /home/eric/gnat/gnat-head/src/gcc/cp/decl.c:14303
#6  0x00000000005c99aa in expand_static_init (decl=0x7ffff6c64390, init=0x0)
    at /home/eric/gnat/gnat-head/src/gcc/cp/decl.c:6902
#7  0x00000000005c8d6c in cp_finish_decl (decl=0x7ffff6c64390, init=0x0, 
    init_const_expr_p=false, asmspec_tree=0x0, flags=1)
    at /home/eric/gnat/gnat-head/src/gcc/cp/decl.c:6504
#8  0x00000000006e22b5 in cp_parser_init_declarator (parser=0x7ffff6c5b068, 
    decl_specifiers=0x7fffffffda00, checks=0x0, 
    function_definition_allowed_p=true, member_p=false, 
    declares_class_or_enum=2, function_definition_p=0x7fffffffda8b, 
    maybe_range_for_decl=0x0)
    at /home/eric/gnat/gnat-head/src/gcc/cp/parser.c:16640


Is that expected and, consequently, should we adjust the machinery?

-- 
Eric Botcazou

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

* Re: C++ PATCH to deal with trivial but non-callable [cd]tors
  2013-10-25 19:04 ` Eric Botcazou
@ 2013-10-25 19:27   ` Jason Merrill
  2013-10-30 10:38     ` Eric Botcazou
  2013-10-31 14:40     ` Jason Merrill
  0 siblings, 2 replies; 11+ messages in thread
From: Jason Merrill @ 2013-10-25 19:27 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches

On 10/25/2013 01:53 PM, Eric Botcazou wrote:
> This has introduced a problem for the -fdump-ada-spec machinery, which boils
> down to the TYPE_METHODS field of the following structure:
>
>   struct _outer {
>     struct _inner {
>       int x;
>     } inner;
>   } outer;
>
> Previously it was empty, now it contains the following destructor:
>[snip]
> Is that expected and, consequently, should we adjust the machinery?

In C++ all classes have destructors, but we try to defer building the 
implicit declaration.  My patch causes us to build those implicit 
declarations more often, which is probably a bit of a memory regression, 
but it would be good for your code to handle the dtor being declared.

Jason

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

* Re: C++ PATCH to deal with trivial but non-callable [cd]tors
  2013-10-25 19:27   ` Jason Merrill
@ 2013-10-30 10:38     ` Eric Botcazou
  2013-10-30 17:02       ` Jason Merrill
  2013-10-31 14:40     ` Jason Merrill
  1 sibling, 1 reply; 11+ messages in thread
From: Eric Botcazou @ 2013-10-30 10:38 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches

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

> In C++ all classes have destructors, but we try to defer building the
> implicit declaration.  My patch causes us to build those implicit
> declarations more often, which is probably a bit of a memory regression,
> but it would be good for your code to handle the dtor being declared.

OK, patch attached.  It's large because of some internal shuffling, but it 
just implements that.  Tested on x86-64/Linux, any objections?


2013-10-31  Eric Botcazou  <ebotcazou@adacore.com>

c-family/
	* c-ada-spec.h (cpp_operation): Add HAS_TRIVIAL_DESTRUCTOR.
	(dump_ada_specs): Adjust prototype of second callback.
	* c-ada-spec.c (cpp_check): New global variable.
	(dump_ada_nodes): Remove cpp_check parameter and do not pass it down.
	(print_generic_ada_decl): Likewise.
	(has_static_fields): Change return type to bool and add guard.
	(is_trivial_method): New predicate.
	(has_nontrivial_methods): Likewise.
	(is_tagged_type): Change return type to bool.
	(separate_class_package): Call has_nontrivial_methods.
	(pp_ada_tree_identifier): Minor tweaks.
	(dump_ada_function_declaration): Adjust calls to dump_generic_ada_node.
	(dump_ada_array_domains): Likewise.
	(dump_ada_array_type): Likewise.
	(dump_template_types): Remove cpp_check parameter and do not pass it to
	dump_generic_ada_node.
	(dump_ada_template): Likewise.
	(dump_generic_ada_node): Remove cpp_check parameter and do not pass it
	recursively.
	(print_ada_methods): Change return type to integer.  Remove cpp_check
	parameter and do not pass it down.
	(dump_nested_types): Remove cpp_check parameter and do not pass it to
	dump_generic_ada_node.
	(print_ada_declaration): Likewise.  Do not print trivial methods.  Test
	RECORD_OR_UNION_TYPE_P predicate before accessing methods.
	(print_ada_struct_decl): Remove cpp_check parameter and do not pass it
	down.  Use has_nontrivial_methods to recognize C++ classes.  Use return
	value of print_ada_methods.
	(dump_ads): Rename cpp_check parameter to check and adjust prototype.
	Set cpp_check to it before invoking dump_ada_nodes.
 	(dump_ada_specs): Likewise.
cp/
	* decl2.c (cpp_check): Change type of first parameter and deal with
	HAS_TRIVIAL_DESTRUCTOR.


-- 
Eric Botcazou

[-- Attachment #2: dump_ada_spec.diff --]
[-- Type: text/x-patch, Size: 39774 bytes --]

Index: c-family/c-ada-spec.h
===================================================================
--- c-family/c-ada-spec.h	(revision 204152)
+++ c-family/c-ada-spec.h	(working copy)
@@ -29,13 +29,14 @@ typedef enum {
   IS_CONSTRUCTOR,
   IS_DESTRUCTOR,
   IS_COPY_CONSTRUCTOR,
-  IS_TEMPLATE
+  IS_TEMPLATE,
+  HAS_TRIVIAL_DESTRUCTOR
 } cpp_operation;
 
 extern location_t decl_sloc (const_tree, bool);
 extern void collect_ada_nodes (tree, const char *);
 extern void collect_source_ref (const char *);
 extern void dump_ada_specs (void (*)(const char *),
-			    int (*)(tree, cpp_operation));
+			    int (*)(const_tree, cpp_operation));
 
 #endif /* ! C_ADA_SPEC_H */
Index: c-family/c-ada-spec.c
===================================================================
--- c-family/c-ada-spec.c	(revision 204152)
+++ c-family/c-ada-spec.c	(working copy)
@@ -46,32 +46,31 @@ along with GCC; see the file COPYING3.
 #endif /* HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG */
 
 /* Local functions, macros and variables.  */
-static int dump_generic_ada_node (pretty_printer *, tree, tree,
-				  int (*)(tree, cpp_operation), int, int, bool);
-static int print_ada_declaration (pretty_printer *, tree, tree,
-				  int (*cpp_check)(tree, cpp_operation), int);
-static void print_ada_struct_decl (pretty_printer *, tree, tree,
-				   int (*cpp_check)(tree, cpp_operation), int,
-				   bool);
+static int dump_generic_ada_node (pretty_printer *, tree, tree, int, int,
+				  bool);
+static int print_ada_declaration (pretty_printer *, tree, tree, int);
+static void print_ada_struct_decl (pretty_printer *, tree, tree, int, bool);
 static void dump_sloc (pretty_printer *buffer, tree node);
 static void print_comment (pretty_printer *, const char *);
-static void print_generic_ada_decl (pretty_printer *, tree,
-				    int (*)(tree, cpp_operation), const char *);
+static void print_generic_ada_decl (pretty_printer *, tree, const char *);
 static char *get_ada_package (const char *);
-static void dump_ada_nodes (pretty_printer *, const char *,
-			    int (*)(tree, cpp_operation));
+static void dump_ada_nodes (pretty_printer *, const char *);
 static void reset_ada_withs (void);
 static void dump_ada_withs (FILE *);
 static void dump_ads (const char *, void (*)(const char *),
-		      int (*)(tree, cpp_operation));
+		      int (*)(const_tree, cpp_operation));
 static char *to_ada_name (const char *, int *);
 static bool separate_class_package (tree);
 
-#define INDENT(SPACE) do { \
-  int i; for (i = 0; i<SPACE; i++) pp_space (buffer); } while (0)
+#define INDENT(SPACE) \
+  do { int i; for (i = 0; i<SPACE; i++) pp_space (buffer); } while (0)
 
 #define INDENT_INCR 3
 
+/* Global hook used to perform C++ queries on nodes.  */
+static int (*cpp_check) (const_tree, cpp_operation) = NULL;
+
+
 /* Given a cpp MACRO, compute the max length BUFFER_LEN of the macro, as well
    as max length PARAM_LEN of arguments for fun_like macros, and also set
    SUPPORTED to 0 if the macro cannot be mapped to an Ada construct.  */
@@ -636,11 +635,10 @@ unmark_visited_r (tree *tp, int *walk_su
 }
 
 /* Dump nodes into PP relevant to SOURCE_FILE, as collected by previous calls
-   to collect_ada_nodes.  CPP_CHECK is used to perform C++ queries on nodes.  */
+   to collect_ada_nodes.  */
 
 static void
-dump_ada_nodes (pretty_printer *pp, const char *source_file,
-		int (*cpp_check)(tree, cpp_operation))
+dump_ada_nodes (pretty_printer *pp, const char *source_file)
 {
   int i, j;
   cpp_comment_table *comments;
@@ -676,7 +674,7 @@ dump_ada_nodes (pretty_printer *pp, cons
 	  if (j == comments->count
 	      || LOCATION_LINE (decl_sloc (to_dump[i], false))
 	      <  LOCATION_LINE (comments->entries[j].sloc))
-	    print_generic_ada_decl (pp, to_dump[i++], cpp_check, source_file);
+	    print_generic_ada_decl (pp, to_dump[i++], source_file);
 	  else
 	    break;
 	}
@@ -736,18 +734,15 @@ print_comment (pretty_printer *pp, const
     pp_newline (pp);
 }
 
-/* Prints declaration DECL to PP in Ada syntax. The current source file being
-   handled is SOURCE_FILE, and CPP_CHECK is used to perform C++ queries on
-   nodes.  */
+/* Print declaration DECL to PP in Ada syntax.  The current source file being
+   handled is SOURCE_FILE.  */
 
 static void
-print_generic_ada_decl (pretty_printer *pp, tree decl,
-			int (*cpp_check)(tree, cpp_operation),
-			const char* source_file)
+print_generic_ada_decl (pretty_printer *pp, tree decl, const char *source_file)
 {
   source_file_base = source_file;
 
-  if (print_ada_declaration (pp, decl, 0, cpp_check, INDENT_INCR))
+  if (print_ada_declaration (pp, decl, 0, INDENT_INCR))
     {
       pp_newline (pp);
       pp_newline (pp);
@@ -941,23 +936,60 @@ get_underlying_decl (tree type)
 
 /* Return whether TYPE has static fields.  */
 
-static int
+static bool
 has_static_fields (const_tree type)
 {
   tree tmp;
 
+  if (!type || !RECORD_OR_UNION_TYPE_P (type))
+    return false;
+
   for (tmp = TYPE_FIELDS (type); tmp; tmp = TREE_CHAIN (tmp))
-    {
-      if (DECL_NAME (tmp) && TREE_STATIC (tmp))
-	return true;
-    }
+    if (DECL_NAME (tmp) && TREE_STATIC (tmp))
+      return true;
+
+  return false;
+}
+
+/* Return whether DECL, a method of a C++ TYPE, is trivial, that is to say
+   doesn't do anything for the objects of TYPE.  */
+
+static bool
+is_trivial_method (const_tree decl, const_tree type)
+{
+  if (cpp_check (decl, IS_CONSTRUCTOR) && !TYPE_NEEDS_CONSTRUCTING (type))
+    return true;
+
+  if (cpp_check (decl, IS_DESTRUCTOR)
+      && cpp_check (type, HAS_TRIVIAL_DESTRUCTOR))
+    return true;
+
+  return false;
+}
+
+/* Return whether TYPE has non-trivial methods.  In C++, all classes have
+   implicit methods, e.g. constructors and destructors, but they can be
+   trivial if the type is sufficiently simple.  */
+
+static bool
+has_nontrivial_methods (const_tree type)
+{
+  tree tmp;
+
+  if (!type || !RECORD_OR_UNION_TYPE_P (type))
+    return false;
+
+  for (tmp = TYPE_METHODS (type); tmp; tmp = TREE_CHAIN (tmp))
+    if (!cpp_check || !is_trivial_method (tmp, type))
+      return true;
+
   return false;
 }
 
 /* Return whether TYPE corresponds to an Ada tagged type (has a dispatch
    table).  */
 
-static int
+static bool
 is_tagged_type (const_tree type)
 {
   tree tmp;
@@ -1193,15 +1225,8 @@ to_ada_name (const char *name, int *spac
 static bool
 separate_class_package (tree decl)
 {
-  if (decl) 
-    {
-      tree type = TREE_TYPE (decl);
-      return type
-	&& TREE_CODE (type) == RECORD_TYPE
-	&& (TYPE_METHODS (type) || has_static_fields (type));
-    }
-  else
-    return false;
+  tree type = TREE_TYPE (decl);
+  return has_nontrivial_methods (type) || has_static_fields (type);
 }
 
 static bool package_prefix = true;
@@ -1221,7 +1246,6 @@ pp_ada_tree_identifier (pretty_printer *
 
   /* If the entity is a type and comes from another file, generate "package"
      prefix.  */
-
   decl = get_underlying_decl (type);
 
   if (decl)
@@ -1246,30 +1270,27 @@ pp_ada_tree_identifier (pretty_printer *
 		  case UNION_TYPE:
 		  case QUAL_UNION_TYPE:
 		  case TYPE_DECL:
-		    {
-		      char *s1 = get_ada_package (xloc.file);
-
-		      if (package_prefix)
-			{
-			  append_withs (s1, limited_access);
-			  pp_string (buffer, s1);
-			  pp_dot (buffer);
-			}
-		      free (s1);
-		    }
+		    if (package_prefix)
+		      {
+			char *s1 = get_ada_package (xloc.file);
+			append_withs (s1, limited_access);
+			pp_string (buffer, s1);
+			pp_dot (buffer);
+			free (s1);
+		      }
 		    break;
 		  default:
 		    break;
 		}
-              
-              if (separate_class_package (decl))
-                {
-                  pp_string (buffer, "Class_");
-                  pp_string (buffer, s);
-                  pp_dot (buffer);
-                }
 
-            }
+	      /* Generate the additional package prefix for C++ classes.  */
+	      if (separate_class_package (decl))
+		{
+		  pp_string (buffer, "Class_");
+		  pp_string (buffer, s);
+		  pp_dot (buffer);
+		}
+	     }
 	}
     }
 
@@ -1527,15 +1548,13 @@ dump_ada_function_declaration (pretty_pr
 	      pp_string (buffer, buf);
 	    }
 
-	  dump_generic_ada_node
-	    (buffer, TREE_TYPE (arg), node, NULL, spc, 0, true);
+	  dump_generic_ada_node (buffer, TREE_TYPE (arg), node, spc, 0, true);
 	}
       else
 	{
 	  sprintf (buf, "arg%d : ", num);
 	  pp_string (buffer, buf);
-	  dump_generic_ada_node
-	    (buffer, TREE_VALUE (arg), node, NULL, spc, 0, true);
+	  dump_generic_ada_node (buffer, TREE_VALUE (arg), node, spc, 0, true);
 	}
 
       if (TREE_TYPE (arg) && TREE_TYPE (TREE_TYPE (arg))
@@ -1593,13 +1612,13 @@ dump_ada_array_domains (pretty_printer *
 	  first = 0;
 
 	  if (min)
-	    dump_generic_ada_node (buffer, min, NULL_TREE, NULL, spc, 0, true);
+	    dump_generic_ada_node (buffer, min, NULL_TREE, spc, 0, true);
 	  pp_string (buffer, " .. ");
 
 	  /* If the upper bound is zero, gcc may generate a NULL_TREE
 	     for TYPE_MAX_VALUE rather than an integer_cst.  */
 	  if (max)
-	    dump_generic_ada_node (buffer, max, NULL_TREE, NULL, spc, 0, true);
+	    dump_generic_ada_node (buffer, max, NULL_TREE, spc, 0, true);
 	  else
 	    pp_string (buffer, "0");
 	}
@@ -1687,18 +1706,16 @@ dump_ada_array_type (pretty_printer *buf
 	pp_string (buffer, "aliased ");
 
       dump_generic_ada_node
-	(buffer, TREE_TYPE (tmp), TREE_TYPE (t), NULL, spc, false, true);
+	(buffer, TREE_TYPE (tmp), TREE_TYPE (t), spc, false, true);
     }
 }
 
 /* Dump in BUFFER type names associated with a template, each prepended with
-   '_'.  TYPES is the TREE_PURPOSE of a DECL_TEMPLATE_INSTANTIATIONS.
-   CPP_CHECK is used to perform C++ queries on nodes.
-   SPC is the indentation level.  */
+   '_'.  TYPES is the TREE_PURPOSE of a DECL_TEMPLATE_INSTANTIATIONS.  SPC is
+   the indentation level.  */
 
 static void
-dump_template_types (pretty_printer *buffer, tree types,
-		     int (*cpp_check)(tree, cpp_operation), int spc)
+dump_template_types (pretty_printer *buffer, tree types, int spc)
 {
   size_t i;
   size_t len = TREE_VEC_LENGTH (types);
@@ -1707,7 +1724,7 @@ dump_template_types (pretty_printer *buf
     {
       tree elem = TREE_VEC_ELT (types, i);
       pp_underscore (buffer);
-      if (!dump_generic_ada_node (buffer, elem, 0, cpp_check, spc, false, true))
+      if (!dump_generic_ada_node (buffer, elem, 0, spc, false, true))
 	{
 	  pp_string (buffer, "unknown");
 	  pp_scalar (buffer, "%lu", (unsigned long) TREE_HASH (elem));
@@ -1716,12 +1733,10 @@ dump_template_types (pretty_printer *buf
 }
 
 /* Dump in BUFFER the contents of all class instantiations associated with
-   a given template T.  CPP_CHECK is used to perform C++ queries on nodes.
-   SPC is the indentation level. */
+   a given template T.  SPC is the indentation level.  */
 
 static int
-dump_ada_template (pretty_printer *buffer, tree t,
-		   int (*cpp_check)(tree, cpp_operation), int spc)
+dump_ada_template (pretty_printer *buffer, tree t, int spc)
 {
   /* DECL_VINDEX is DECL_TEMPLATE_INSTANTIATIONS in this context.  */
   tree inst = DECL_VINDEX (t);
@@ -1750,15 +1765,15 @@ dump_ada_template (pretty_printer *buffe
       INDENT (spc);
       pp_string (buffer, "package ");
       package_prefix = false;
-      dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true);
-      dump_template_types (buffer, types, cpp_check, spc);
+      dump_generic_ada_node (buffer, instance, t, spc, false, true);
+      dump_template_types (buffer, types, spc);
       pp_string (buffer, " is");
       spc += INDENT_INCR;
       newline_and_indent (buffer, spc);
 
       TREE_VISITED (get_underlying_decl (instance)) = 1;
       pp_string (buffer, "type ");
-      dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true);
+      dump_generic_ada_node (buffer, instance, t, spc, false, true);
       package_prefix = true;
 
       if (is_tagged_type (instance))
@@ -1766,7 +1781,7 @@ dump_ada_template (pretty_printer *buffe
       else
 	pp_string (buffer, " is limited ");
 
-      dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, false);
+      dump_generic_ada_node (buffer, instance, t, spc, false, false);
       pp_newline (buffer);
       spc -= INDENT_INCR;
       newline_and_indent (buffer, spc);
@@ -1775,8 +1790,8 @@ dump_ada_template (pretty_printer *buffe
       newline_and_indent (buffer, spc);
       pp_string (buffer, "use ");
       package_prefix = false;
-      dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true);
-      dump_template_types (buffer, types, cpp_check, spc);
+      dump_generic_ada_node (buffer, instance, t, spc, false, true);
+      dump_template_types (buffer, types, spc);
       package_prefix = true;
       pp_semicolon (buffer);
       pp_newline (buffer);
@@ -1819,14 +1834,12 @@ static bool in_function = true;
 static bool bitfield_used = false;
 
 /* Recursively dump in BUFFER Ada declarations corresponding to NODE of type
-   TYPE.  CPP_CHECK is used to perform C++ queries on nodes.  SPC is the
-   indentation level.  LIMITED_ACCESS indicates whether NODE can be referenced
-   via a "limited with" clause.  NAME_ONLY indicates whether we should only
-   dump the name of NODE, instead of its full declaration.  */
+   TYPE.  SPC is the indentation level.  LIMITED_ACCESS indicates whether NODE
+   can be referenced via a "limited with" clause.  NAME_ONLY indicates whether
+   we should only dump the name of NODE, instead of its full declaration.  */
 
 static int
-dump_generic_ada_node (pretty_printer *buffer, tree node, tree type,
-		       int (*cpp_check)(tree, cpp_operation), int spc,
+dump_generic_ada_node (pretty_printer *buffer, tree node, tree type, int spc,
 		       int limited_access, bool name_only)
 {
   if (node == NULL_TREE)
@@ -1848,8 +1861,7 @@ dump_generic_ada_node (pretty_printer *b
 
     case TREE_BINFO:
       dump_generic_ada_node
-	(buffer, BINFO_TYPE (node), type, cpp_check,
-	 spc, limited_access, name_only);
+	(buffer, BINFO_TYPE (node), type, spc, limited_access, name_only);
 
     case TREE_VEC:
       pp_string (buffer, "--- unexpected node: TREE_VEC");
@@ -1876,7 +1888,7 @@ dump_generic_ada_node (pretty_printer *b
     case ENUMERAL_TYPE:
       if (name_only)
 	dump_generic_ada_node
-	  (buffer, TYPE_NAME (node), node, cpp_check, spc, 0, true);
+	  (buffer, TYPE_NAME (node), node, spc, 0, true);
       else
 	{
 	  tree value = TYPE_VALUES (node);
@@ -1906,7 +1918,7 @@ dump_generic_ada_node (pretty_printer *b
 	      pp_string (buffer, "pragma Convention (C, ");
 	      dump_generic_ada_node
 		(buffer, DECL_NAME (type) ? type : TYPE_NAME (node), type,
-		 cpp_check, spc, 0, true);
+		 spc, 0, true);
 	      pp_right_paren (buffer);
 	    }
 	  else
@@ -1923,14 +1935,14 @@ dump_generic_ada_node (pretty_printer *b
 
 		  dump_generic_ada_node
 		    (buffer, DECL_NAME (type) ? type : TYPE_NAME (node), type,
-		     cpp_check, spc, 0, true);
+		     spc, 0, true);
 
 		  pp_string (buffer, " := ");
 		  dump_generic_ada_node
 		    (buffer,
 		     TREE_CODE (TREE_VALUE (value)) == INTEGER_CST ?
 		       TREE_VALUE (value) : DECL_INITIAL (TREE_VALUE (value)),
-		     node, cpp_check, spc, false, true);
+		     node, spc, false, true);
 		}
 	    }
 	}
@@ -1991,8 +2003,7 @@ dump_generic_ada_node (pretty_printer *b
     case REFERENCE_TYPE:
       if (name_only && TYPE_NAME (node))
 	dump_generic_ada_node
-	  (buffer, TYPE_NAME (node), node, cpp_check,
-	   spc, limited_access, true);
+	  (buffer, TYPE_NAME (node), node, spc, limited_access, true);
 
       else if (TREE_CODE (TREE_TYPE (node)) == FUNCTION_TYPE)
 	{
@@ -2020,7 +2031,7 @@ dump_generic_ada_node (pretty_printer *b
 	    {
 	      pp_string (buffer, " return ");
 	      dump_generic_ada_node
-		(buffer, TREE_TYPE (fnode), type, cpp_check, spc, 0, true);
+		(buffer, TREE_TYPE (fnode), type, spc, 0, true);
 	    }
 
 	    /* If we are dumping the full type, it means we are part of a
@@ -2031,7 +2042,7 @@ dump_generic_ada_node (pretty_printer *b
 		newline_and_indent (buffer, spc);
 		pp_string (buffer, "pragma Convention (C, ");
 		dump_generic_ada_node
-		  (buffer, type, 0, cpp_check, spc, false, true);
+		  (buffer, type, 0, spc, false, true);
 		pp_right_paren (buffer);
 	      }
 	}
@@ -2158,11 +2169,11 @@ dump_generic_ada_node (pretty_printer *b
 		      && type_name != NULL_TREE)
 		    dump_generic_ada_node
 		      (buffer, type_name,
-		       TREE_TYPE (node), cpp_check, spc, is_access, true);
+		       TREE_TYPE (node), spc, is_access, true);
 		  else
 		    dump_generic_ada_node
 		      (buffer, TREE_TYPE (node), TREE_TYPE (node),
-		       cpp_check, spc, 0, true);
+		       spc, 0, true);
 		}
 	    }
 	}
@@ -2171,8 +2182,7 @@ dump_generic_ada_node (pretty_printer *b
     case ARRAY_TYPE:
       if (name_only)
 	dump_generic_ada_node
-	  (buffer, TYPE_NAME (node), node, cpp_check,
-	   spc, limited_access, true);
+	  (buffer, TYPE_NAME (node), node, spc, limited_access, true);
       else
 	dump_ada_array_type (buffer, node, spc);
       break;
@@ -2184,8 +2194,7 @@ dump_generic_ada_node (pretty_printer *b
 	{
 	  if (TYPE_NAME (node))
 	    dump_generic_ada_node
-	      (buffer, TYPE_NAME (node), node, cpp_check,
-	       spc, limited_access, true);
+	      (buffer, TYPE_NAME (node), node, spc, limited_access, true);
 	  else
 	    {
 	      pp_string (buffer, "anon_");
@@ -2193,8 +2202,7 @@ dump_generic_ada_node (pretty_printer *b
 	    }
 	}
       else
-	print_ada_struct_decl
-	  (buffer, node, type, cpp_check, spc, true);
+	print_ada_struct_decl (buffer, node, type, spc, true);
       break;
 
     case INTEGER_CST:
@@ -2287,12 +2295,11 @@ dump_generic_ada_node (pretty_printer *b
 
 	      pp_string (buffer, first ? "tagged limited " : " with ");
 	    }
-	  else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node))
-		   && TYPE_METHODS (TREE_TYPE (node)))
+	  else if (has_nontrivial_methods (TREE_TYPE (node)))
 	    pp_string (buffer, "limited ");
 
 	  dump_generic_ada_node
-	    (buffer, TREE_TYPE (node), type, cpp_check, spc, false, false);
+	    (buffer, TREE_TYPE (node), type, spc, false, false);
 	}
       break;
 
@@ -2311,41 +2318,41 @@ dump_generic_ada_node (pretty_printer *b
   return 1;
 }
 
-/* Dump in BUFFER NODE's methods.  CPP_CHECK is used to perform C++ queries on
-   nodes.  SPC is the indentation level.  */
+/* Dump in BUFFER NODE's methods.  SPC is the indentation level.  Return 1 if
+   methods were printed, 0 otherwise.  */
 
-static void
-print_ada_methods (pretty_printer *buffer, tree node,
-		   int (*cpp_check)(tree, cpp_operation), int spc)
+static int
+print_ada_methods (pretty_printer *buffer, tree node, int spc)
 {
-  tree tmp = TYPE_METHODS (node);
   int res = 1;
+  tree tmp;
 
-  if (tmp)
-    {
-      pp_semicolon (buffer);
+  if (!has_nontrivial_methods (node))
+    return 0;
 
-      for (; tmp; tmp = TREE_CHAIN (tmp))
+  pp_semicolon (buffer);
+
+  for (tmp = TYPE_METHODS (node); tmp; tmp = TREE_CHAIN (tmp))
+    {
+      if (res)
 	{
-	  if (res)
-	    {
-	      pp_newline (buffer);
-	      pp_newline (buffer);
-	    }
-	  res = print_ada_declaration (buffer, tmp, node, cpp_check, spc);
+	  pp_newline (buffer);
+	  pp_newline (buffer);
 	}
+      res = print_ada_declaration (buffer, tmp, node, spc);
     }
+
+  return 1;
 }
 
 /* Dump in BUFFER anonymous types nested inside T's definition.
    PARENT is the parent node of T.
    FORWARD indicates whether a forward declaration of T should be generated.
-   CPP_CHECK is used to perform C++ queries on
-   nodes.  SPC is the indentation level.  */
+   SPC is the indentation level.  */
 
 static void
 dump_nested_types (pretty_printer *buffer, tree t, tree parent, bool forward,
-		   int (*cpp_check)(tree, cpp_operation), int spc)
+		   int spc)
 {
   tree field, outer, decl;
 
@@ -2363,8 +2370,7 @@ dump_nested_types (pretty_printer *buffe
   if (forward)
     {
       pp_string (buffer, "type ");
-      dump_generic_ada_node
-	(buffer, t, t, cpp_check, spc, false, true);
+      dump_generic_ada_node (buffer, t, t, spc, false, true);
       pp_semicolon (buffer);
       newline_and_indent (buffer, spc);
       TREE_VISITED (t) = 1;
@@ -2406,8 +2412,7 @@ dump_nested_types (pretty_printer *buffe
 		    /* Generate forward declaration.  */
 
 		    pp_string (buffer, "type ");
-		    dump_generic_ada_node
-		      (buffer, decl, 0, cpp_check, spc, false, true);
+		    dump_generic_ada_node (buffer, decl, 0, spc, false, true);
 		    pp_semicolon (buffer);
 		    newline_and_indent (buffer, spc);
 
@@ -2431,30 +2436,28 @@ dump_nested_types (pretty_printer *buffe
 
 	      case UNION_TYPE:
 		TREE_VISITED (t) = 1;
-		dump_nested_types (buffer, field, t, false, cpp_check, spc);
+		dump_nested_types (buffer, field, t, false, spc);
 
 		pp_string (buffer, "type ");
 
 		if (TYPE_NAME (TREE_TYPE (field)))
 		  {
 		    dump_generic_ada_node
-		      (buffer, TYPE_NAME (TREE_TYPE (field)), 0, cpp_check,
-		       spc, false, true);
+		      (buffer, TYPE_NAME (TREE_TYPE (field)), 0, spc, false,
+		       true);
 		    pp_string (buffer, " (discr : unsigned := 0) is ");
 		    print_ada_struct_decl
-		      (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
+		      (buffer, TREE_TYPE (field), t, spc, false);
 
 		    pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
 		    dump_generic_ada_node
-		      (buffer, TREE_TYPE (field), 0, cpp_check,
-		       spc, false, true);
+		      (buffer, TREE_TYPE (field), 0, spc, false, true);
 		    pp_string (buffer, ");");
 		    newline_and_indent (buffer, spc);
 
 		    pp_string (buffer, "pragma Unchecked_Union (");
 		    dump_generic_ada_node
-		      (buffer, TREE_TYPE (field), 0, cpp_check,
-		       spc, false, true);
+		      (buffer, TREE_TYPE (field), 0, spc, false, true);
 		    pp_string (buffer, ");");
 		  }
 		else
@@ -2463,7 +2466,7 @@ dump_nested_types (pretty_printer *buffe
 		      (buffer, parent, field,
 		       	"_union (discr : unsigned := 0) is ");
 		    print_ada_struct_decl
-		      (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
+		      (buffer, TREE_TYPE (field), t, spc, false);
 		    pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
 		    dump_ada_double_name (buffer, parent, field, "_union);");
 		    newline_and_indent (buffer, spc);
@@ -2480,27 +2483,25 @@ dump_nested_types (pretty_printer *buffe
 		  {
 		    pp_string (buffer, "type ");
 		    dump_generic_ada_node
-		      (buffer, t, parent, 0, spc, false, true);
+		      (buffer, t, parent, spc, false, true);
 		    pp_semicolon (buffer);
 		    newline_and_indent (buffer, spc);
 		  }
 
 		TREE_VISITED (t) = 1;
-		dump_nested_types (buffer, field, t, false, cpp_check, spc);
+		dump_nested_types (buffer, field, t, false, spc);
 		pp_string (buffer, "type ");
 
 		if (TYPE_NAME (TREE_TYPE (field)))
 		  {
 		    dump_generic_ada_node
-		      (buffer, TREE_TYPE (field), 0, cpp_check,
-		       spc, false, true);
+		      (buffer, TREE_TYPE (field), 0, spc, false, true);
 		    pp_string (buffer, " is ");
 		    print_ada_struct_decl
-		      (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
+		      (buffer, TREE_TYPE (field), t, spc, false);
 		    pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
 		    dump_generic_ada_node
-		      (buffer, TREE_TYPE (field), 0, cpp_check,
-		       spc, false, true);
+		      (buffer, TREE_TYPE (field), 0, spc, false, true);
 		    pp_string (buffer, ");");
 		  }
 		else
@@ -2508,7 +2509,7 @@ dump_nested_types (pretty_printer *buffe
 		    dump_ada_double_name
 		      (buffer, parent, field, "_struct is ");
 		    print_ada_struct_decl
-		      (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
+		      (buffer, TREE_TYPE (field), t, spc, false);
 		    pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
 		    dump_ada_double_name (buffer, parent, field, "_struct);");
 		  }
@@ -2557,12 +2558,11 @@ type_name (tree t)
 }
 
 /* Print in BUFFER the declaration of a variable T of type TYPE in Ada syntax.
-   CPP_CHECK is used to perform C++ queries on nodes.  SPC is the indentation
-   level.  Return 1 if a declaration was printed, 0 otherwise.  */
+   SPC is the indentation level.  Return 1 if a declaration was printed,
+   0 otherwise.  */
 
 static int
-print_ada_declaration (pretty_printer *buffer, tree t, tree type,
-		       int (*cpp_check)(tree, cpp_operation), int spc)
+print_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc)
 {
   int is_var = 0, need_indent = 0;
   int is_class = false;
@@ -2571,7 +2571,7 @@ print_ada_declaration (pretty_printer *b
   tree orig = NULL_TREE;
 
   if (cpp_check && cpp_check (t, IS_TEMPLATE))
-    return dump_ada_template (buffer, t, cpp_check, spc);
+    return dump_ada_template (buffer, t, spc);
 
   if (TREE_CODE (t) == CONST_DECL && TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE)
     /* Skip enumeral values: will be handled as part of the type itself.  */
@@ -2599,20 +2599,18 @@ print_ada_declaration (pretty_printer *b
 	      if (RECORD_OR_UNION_TYPE_P (typ) && !TYPE_FIELDS (typ))
 		{
 		  pp_string (buffer, "--  skipped empty struct ");
-		  dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+		  dump_generic_ada_node (buffer, t, type, spc, false, true);
 		}
 	      else
 		{
 		  if (!TREE_VISITED (stub)
 		      && DECL_SOURCE_FILE (stub) == source_file_base)
-		    dump_nested_types
-		      (buffer, stub, stub, true, cpp_check, spc);
+		    dump_nested_types (buffer, stub, stub, true, spc);
 
 		  pp_string (buffer, "subtype ");
-		  dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+		  dump_generic_ada_node (buffer, t, type, spc, false, true);
 		  pp_string (buffer, " is ");
-		  dump_generic_ada_node
-		    (buffer, typ, type, 0, spc, false, true);
+		  dump_generic_ada_node (buffer, typ, type, spc, false, true);
 		  pp_semicolon (buffer);
 		}
 	      return 1;
@@ -2671,7 +2669,7 @@ print_ada_declaration (pretty_printer *b
 	    if (!TYPE_FIELDS (TREE_TYPE (t)))
 	      {
 		pp_string (buffer, "--  skipped empty struct ");
-		dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+		dump_generic_ada_node (buffer, t, type, spc, false, true);
 		return 1;
 	      }
 
@@ -2680,7 +2678,7 @@ print_ada_declaration (pretty_printer *b
 		    || *IDENTIFIER_POINTER (decl_name) == '$'))
 	      {
 		pp_string (buffer, "--  skipped anonymous struct ");
-		dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+		dump_generic_ada_node (buffer, t, type, spc, false, true);
 		TREE_VISITED (t) = 1;
 		return 1;
 	      }
@@ -2689,14 +2687,13 @@ print_ada_declaration (pretty_printer *b
 	      pp_string (buffer, "subtype ");
 	    else
 	      {
-		dump_nested_types (buffer, t, t, false, cpp_check, spc);
+		dump_nested_types (buffer, t, t, false, spc);
 
                 if (separate_class_package (t))
 		  {
 		    is_class = true;
 		    pp_string (buffer, "package Class_");
-		    dump_generic_ada_node
-		      (buffer, t, type, 0, spc, false, true);
+		    dump_generic_ada_node (buffer, t, type, spc, false, true);
 		    pp_string (buffer, " is");
 		    spc += INDENT_INCR;
 		    newline_and_indent (buffer, spc);
@@ -2718,7 +2715,7 @@ print_ada_declaration (pretty_printer *b
 
 	  case FUNCTION_TYPE:
 	    pp_string (buffer, "--  skipped function type ");
-	    dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+	    dump_generic_ada_node (buffer, t, type, spc, false, true);
 	    return 1;
 	    break;
 
@@ -2752,7 +2749,7 @@ print_ada_declaration (pretty_printer *b
 	INDENT (spc);
 
       /* Print variable's name.  */
-      dump_generic_ada_node (buffer, t, type, cpp_check, spc, false, true);
+      dump_generic_ada_node (buffer, t, type, spc, false, true);
 
       if (TREE_CODE (t) == TYPE_DECL)
 	{
@@ -2760,8 +2757,7 @@ print_ada_declaration (pretty_printer *b
 
 	  if (orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
 	    dump_generic_ada_node
-	      (buffer, TYPE_NAME (orig), type,
-	       cpp_check, spc, false, true);
+	      (buffer, TYPE_NAME (orig), type, spc, false, true);
 	  else
 	    dump_ada_array_type (buffer, t, spc);
 	}
@@ -2780,7 +2776,7 @@ print_ada_declaration (pretty_printer *b
 		  && TREE_CODE (tmp) != INTEGER_TYPE)
 		pp_string (buffer, "aliased ");
 
-	      dump_generic_ada_node (buffer, tmp, type, 0, spc, false, true);
+	      dump_generic_ada_node (buffer, tmp, type, spc, false, true);
 	    }
 	  else
 	    {
@@ -2795,7 +2791,8 @@ print_ada_declaration (pretty_printer *b
     }
   else if (TREE_CODE (t) == FUNCTION_DECL)
     {
-      bool is_function = true, is_method, is_abstract_class = false;
+      bool is_function = true, is_abstract_class = false;
+      bool is_method = TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE;
       tree decl_name = DECL_NAME (t);
       int prev_in_function = in_function;
       bool is_abstract = false;
@@ -2808,6 +2805,9 @@ print_ada_declaration (pretty_printer *b
 
       if (cpp_check)
 	{
+	  if (is_method && is_trivial_method (t, type))
+	    return 0;
+
 	  is_abstract = cpp_check (t, IS_ABSTRACT);
 	  is_constructor = cpp_check (t, IS_CONSTRUCTOR);
 	  is_destructor = cpp_check (t, IS_DESTRUCTOR);
@@ -2852,7 +2852,6 @@ print_ada_declaration (pretty_printer *b
 	pp_string (buffer, "function ");
 
       in_function = is_function;
-      is_method = TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE;
 
       if (is_destructor)
 	print_destructor (buffer, t);
@@ -2874,18 +2873,17 @@ print_ada_declaration (pretty_printer *b
 	  else
 	    {
 	      dump_generic_ada_node
-		(buffer, TREE_TYPE (TREE_TYPE (t)), type, cpp_check,
-		 spc, false, true);
+		(buffer, TREE_TYPE (TREE_TYPE (t)), type, spc, false, true);
 	    }
 	}
 
-      if (is_constructor && cpp_check && type
-	  && AGGREGATE_TYPE_P (type)
+      if (is_constructor
+	  && RECORD_OR_UNION_TYPE_P (type)
 	  && TYPE_METHODS (type))
 	{
-	  tree tmp = TYPE_METHODS (type);
+	  tree tmp;
 
-	  for (; tmp; tmp = TREE_CHAIN (tmp))
+	  for (tmp = TYPE_METHODS (type); tmp; tmp = TREE_CHAIN (tmp))
 	    if (cpp_check (tmp, IS_ABSTRACT))
 	      {
 		is_abstract_class = 1;
@@ -2937,8 +2935,7 @@ print_ada_declaration (pretty_printer *b
 	INDENT (spc);
 
       /* Anonymous structs/unions */
-      dump_generic_ada_node
-	(buffer, TREE_TYPE (t), t, cpp_check, spc, false, true);
+      dump_generic_ada_node (buffer, TREE_TYPE (t), t, spc, false, true);
 
       if (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE
 	  || TREE_CODE (TREE_TYPE (t)) == QUAL_UNION_TYPE)
@@ -2949,14 +2946,15 @@ print_ada_declaration (pretty_printer *b
       pp_string (buffer, " is ");
 
       /* Check whether we have an Ada interface compatible class.  */
-      if (cpp_check && AGGREGATE_TYPE_P (TREE_TYPE (t))
+      if (cpp_check
+	  && RECORD_OR_UNION_TYPE_P (TREE_TYPE (t))
 	  && TYPE_METHODS (TREE_TYPE (t)))
 	{
 	  int num_fields = 0;
-	  tree tmp = TYPE_FIELDS (TREE_TYPE (t));
+	  tree tmp;
 
 	  /* Check that there are no fields other than the virtual table.  */
-	  for (; tmp; tmp = TREE_CHAIN (tmp))
+	  for (tmp = TYPE_FIELDS (TREE_TYPE (t)); tmp; tmp = TREE_CHAIN (tmp))
 	    {
 	      if (TREE_CODE (tmp) == TYPE_DECL)
 		continue;
@@ -2984,17 +2982,16 @@ print_ada_declaration (pretty_printer *b
 	  newline_and_indent (buffer, spc);
 	  pp_string (buffer, "pragma Import (CPP, ");
  	  dump_generic_ada_node
-	    (buffer, TYPE_NAME (TREE_TYPE (t)), type, cpp_check,
-	     spc, false, true);
+	    (buffer, TYPE_NAME (TREE_TYPE (t)), type, spc, false, true);
   	  pp_right_paren (buffer);
 
-	  print_ada_methods (buffer, TREE_TYPE (t), cpp_check, spc);
+	  print_ada_methods (buffer, TREE_TYPE (t), spc);
 	}
       else
 	{
 	  if (is_abstract_record)
 	    pp_string (buffer, "abstract ");
-	  dump_generic_ada_node (buffer, t, t, cpp_check, spc, false, false);
+	  dump_generic_ada_node (buffer, t, t, spc, false, false);
 	}
     }
   else
@@ -3006,7 +3003,7 @@ print_ada_declaration (pretty_printer *b
 	check_name (buffer, t);
 
       /* Print variable/type's name.  */
-      dump_generic_ada_node (buffer, t, t, cpp_check, spc, false, true);
+      dump_generic_ada_node (buffer, t, t, spc, false, true);
 
       if (TREE_CODE (t) == TYPE_DECL)
 	{
@@ -3020,8 +3017,7 @@ print_ada_declaration (pretty_printer *b
 
 	  pp_string (buffer, " is ");
 
-	  dump_generic_ada_node
-	    (buffer, orig, t, cpp_check, spc, false, is_subtype);
+	  dump_generic_ada_node (buffer, orig, t, spc, false, is_subtype);
 	}
       else
 	{
@@ -3043,7 +3039,7 @@ print_ada_declaration (pretty_printer *b
 		pp_string (buffer, "aliased ");
 
 	      dump_generic_ada_node
-		(buffer, TREE_TYPE (t), t, cpp_check, spc, false, true);
+		(buffer, TREE_TYPE (t), t, spc, false, true);
 	    }
 	  else
 	    {
@@ -3053,8 +3049,7 @@ print_ada_declaration (pretty_printer *b
 		pp_string (buffer, "aliased ");
 
 	      dump_generic_ada_node
-		(buffer, TREE_TYPE (t), TREE_TYPE (t), cpp_check,
-		 spc, false, true);
+		(buffer, TREE_TYPE (t), TREE_TYPE (t), spc, false, true);
 	    }
 	}
     }
@@ -3066,7 +3061,7 @@ print_ada_declaration (pretty_printer *b
       pp_string (buffer, "end;");
       newline_and_indent (buffer, spc);
       pp_string (buffer, "use Class_");
-      dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+      dump_generic_ada_node (buffer, t, type, spc, false, true);
       pp_semicolon (buffer);
       pp_newline (buffer);
 
@@ -3089,18 +3084,16 @@ print_ada_declaration (pretty_printer *b
 }
 
 /* Prints in BUFFER a structure NODE of type TYPE: name, fields, and methods
-   with Ada syntax.  CPP_CHECK is used to perform C++ queries on nodes.  SPC
-   is the indentation level.  If DISPLAY_CONVENTION is true, also print the
-   pragma Convention for NODE.  */
+   with Ada syntax.  SPC is the indentation level.  If DISPLAY_CONVENTION is
+   true, also print the pragma Convention for NODE.  */
 
 static void
-print_ada_struct_decl (pretty_printer *buffer, tree node, tree type,
-		       int (*cpp_check)(tree, cpp_operation), int spc,
+print_ada_struct_decl (pretty_printer *buffer, tree node, tree type, int spc,
 		       bool display_convention)
 {
   tree tmp;
-  int is_union =
-    TREE_CODE (node) == UNION_TYPE || TREE_CODE (node) == QUAL_UNION_TYPE;
+  const bool is_union
+    = TREE_CODE (node) == UNION_TYPE || TREE_CODE (node) == QUAL_UNION_TYPE;
   char buf[32];
   int field_num = 0;
   int field_spc = spc + INDENT_INCR;
@@ -3134,8 +3127,7 @@ print_ada_struct_decl (pretty_printer *b
 	      if (!is_tagged_type (TREE_TYPE (tmp)))
 		{
 		  if (!TYPE_NAME (TREE_TYPE (tmp)))
-		    print_ada_declaration
-		      (buffer, tmp, type, cpp_check, field_spc);
+		    print_ada_declaration (buffer, tmp, type, field_spc);
 		  else
 		    {
 		      INDENT (field_spc);
@@ -3179,8 +3171,7 @@ print_ada_struct_decl (pretty_printer *b
 		      pp_newline (buffer);
 		    }
 
-		  if (print_ada_declaration (buffer,
-					     tmp, type, cpp_check, field_spc))
+		  if (print_ada_declaration (buffer, tmp, type, field_spc))
 		    {
 		      pp_newline (buffer);
 		      field_num++;
@@ -3214,7 +3205,7 @@ print_ada_struct_decl (pretty_printer *b
 
   if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
     {
-      if (TYPE_METHODS (TREE_TYPE (type)))
+      if (has_nontrivial_methods (TREE_TYPE (type)))
 	pp_string (buffer, "pragma Import (CPP, ");
       else
 	pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
@@ -3223,8 +3214,7 @@ print_ada_struct_decl (pretty_printer *b
     pp_string (buffer, "pragma Convention (C, ");
 
   package_prefix = false;
-  dump_generic_ada_node
-    (buffer, TREE_TYPE (type), type, cpp_check, spc, false, true);
+  dump_generic_ada_node (buffer, TREE_TYPE (type), type, spc, false, true);
   package_prefix = true;
   pp_right_paren (buffer);
 
@@ -3234,8 +3224,7 @@ print_ada_struct_decl (pretty_printer *b
       newline_and_indent (buffer, spc);
       pp_string (buffer, "pragma Unchecked_Union (");
 
-      dump_generic_ada_node
-	(buffer, TREE_TYPE (type), type, cpp_check, spc, false, true);
+      dump_generic_ada_node (buffer, TREE_TYPE (type), type, spc, false, true);
       pp_right_paren (buffer);
     }
 
@@ -3245,15 +3234,14 @@ print_ada_struct_decl (pretty_printer *b
       newline_and_indent (buffer, spc);
       pp_string (buffer, "pragma Pack (");
       dump_generic_ada_node
-	(buffer, TREE_TYPE (type), type, cpp_check, spc, false, true);
+	(buffer, TREE_TYPE (type), type, spc, false, true);
       pp_right_paren (buffer);
       bitfield_used = false;
     }
 
-  print_ada_methods (buffer, node, cpp_check, spc);
+  need_semicolon = !print_ada_methods (buffer, node, spc);
 
   /* Print the static fields of the structure, if any.  */
-  need_semicolon = TYPE_METHODS (node) == NULL_TREE;
   for (tmp = TYPE_FIELDS (node); tmp; tmp = TREE_CHAIN (tmp))
     {
       if (DECL_NAME (tmp) && TREE_STATIC (tmp))
@@ -3265,20 +3253,19 @@ print_ada_struct_decl (pretty_printer *b
 	    }
 	  pp_newline (buffer);
 	  pp_newline (buffer);
-	  print_ada_declaration (buffer, tmp, type, cpp_check, spc);
+	  print_ada_declaration (buffer, tmp, type, spc);
 	}
     }
 }
 
 /* Dump all the declarations in SOURCE_FILE to an Ada spec.
    COLLECT_ALL_REFS is a front-end callback used to collect all relevant
-   nodes for SOURCE_FILE.  CPP_CHECK is used to perform C++ queries on
-   nodes.  */
+   nodes for SOURCE_FILE.  CHECK is used to perform C++ queries on nodes.  */
 
 static void
 dump_ads (const char *source_file,
 	  void (*collect_all_refs)(const char *),
-	  int (*cpp_check)(tree, cpp_operation))
+	  int (*check)(const_tree, cpp_operation))
 {
   char *ads_name;
   char *pkg_name;
@@ -3316,7 +3303,8 @@ dump_ads (const char *source_file,
       (*collect_all_refs) (source_file);
 
       /* Dump all references.  */
-      dump_ada_nodes (&pp, source_file, cpp_check);
+      cpp_check = check;
+      dump_ada_nodes (&pp, source_file);
 
       /* Requires Ada 2005 syntax, so generate corresponding pragma.
          Also, disable style checks since this file is auto-generated.  */
@@ -3370,21 +3358,21 @@ collect_source_ref (const char *filename
 }
 
 /* Main entry point: dump all Ada specs corresponding to SOURCE_REFS
-   using callbacks COLLECT_ALL_REFS and CPP_CHECK.
+   using callbacks COLLECT_ALL_REFS and CHECK.
    COLLECT_ALL_REFS is a front-end callback used to collect all relevant
    nodes for a given source file.
-   CPP_CHECK is used to perform C++ queries on nodes, or NULL for the C
+   CHECK is used to perform C++ queries on nodes, or NULL for the C
    front-end.  */
 
 void
 dump_ada_specs (void (*collect_all_refs)(const char *),
-		int (*cpp_check)(tree, cpp_operation))
+		int (*check)(const_tree, cpp_operation))
 {
   int i;
 
   /* Iterate over the list of files to dump specs for */
   for (i = 0; i < source_refs_used; i++)
-    dump_ads (source_refs[i], collect_all_refs, cpp_check);
+    dump_ads (source_refs[i], collect_all_refs, check);
 
   /* Free files table.  */
   free (source_refs);
Index: cp/decl2.c
===================================================================
--- cp/decl2.c	(revision 204152)
+++ cp/decl2.c	(working copy)
@@ -3826,7 +3826,7 @@ build_java_method_aliases (struct pointe
 /* Return C++ property of T, based on given operation OP.  */
 
 static int
-cpp_check (tree t, cpp_operation op)
+cpp_check (const_tree t, cpp_operation op)
 {
   switch (op)
     {
@@ -3840,6 +3840,8 @@ cpp_check (tree t, cpp_operation op)
 	return DECL_COPY_CONSTRUCTOR_P (t);
       case IS_TEMPLATE:
 	return TREE_CODE (t) == TEMPLATE_DECL;
+      case HAS_TRIVIAL_DESTRUCTOR:
+	return TYPE_HAS_TRIVIAL_DESTRUCTOR (t);
       default:
         return 0;
     }

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

* Re: C++ PATCH to deal with trivial but non-callable [cd]tors
  2013-10-30 10:38     ` Eric Botcazou
@ 2013-10-30 17:02       ` Jason Merrill
  2013-10-30 19:22         ` Eric Botcazou
  2013-10-31 15:15         ` Eric Botcazou
  0 siblings, 2 replies; 11+ messages in thread
From: Jason Merrill @ 2013-10-30 17:02 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches

On 10/30/2013 06:14 AM, Eric Botcazou wrote:
> +/* Return whether DECL, a method of a C++ TYPE, is trivial, that is to say
> +   doesn't do anything for the objects of TYPE.  */
> +
> +static bool
> +is_trivial_method (const_tree decl, const_tree type)
> +{
> +  if (cpp_check (decl, IS_CONSTRUCTOR) && !TYPE_NEEDS_CONSTRUCTING (type))
> +    return true;

This will tell you whether decl is a constructor for a type with some 
non-trivial constructor, but not whether decl itself is non-trivial.

I think a good way to check for any non-trivial methods would be to 
check trivial_type_p in the front end and then see if there are any 
!DECL_ARTIFICIAL decls in TYPE_METHODS.

Jason

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

* Re: C++ PATCH to deal with trivial but non-callable [cd]tors
  2013-10-30 17:02       ` Jason Merrill
@ 2013-10-30 19:22         ` Eric Botcazou
  2013-10-31 15:15         ` Eric Botcazou
  1 sibling, 0 replies; 11+ messages in thread
From: Eric Botcazou @ 2013-10-30 19:22 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches

> > +/* Return whether DECL, a method of a C++ TYPE, is trivial, that is to
> > say +   doesn't do anything for the objects of TYPE.  */
> > +
> > +static bool
> > +is_trivial_method (const_tree decl, const_tree type)
> > +{
> > +  if (cpp_check (decl, IS_CONSTRUCTOR) && !TYPE_NEEDS_CONSTRUCTING
> > (type)) +    return true;
> 
> This will tell you whether decl is a constructor for a type with some
> non-trivial constructor, but not whether decl itself is non-trivial.

I think that's good enough though, in practice we only need to eliminate 
constructors/destructors for POD types.  As soon as there is one non-trivial 
method, the game is essentially over.

> I think a good way to check for any non-trivial methods would be to
> check trivial_type_p in the front end and then see if there are any
> !DECL_ARTIFICIAL decls in TYPE_METHODS.

That sounds interesting indeed, thanks for the tip.  I was initially reluctant 
to call into the front-end because of side-effects, but the various predicates 
in tree.c seem fine in this respect.

-- 
Eric Botcazou

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

* Re: C++ PATCH to deal with trivial but non-callable [cd]tors
  2013-10-25 19:27   ` Jason Merrill
  2013-10-30 10:38     ` Eric Botcazou
@ 2013-10-31 14:40     ` Jason Merrill
  1 sibling, 0 replies; 11+ messages in thread
From: Jason Merrill @ 2013-10-31 14:40 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches

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

On 10/25/2013 03:04 PM, Jason Merrill wrote:
> In C++ all classes have destructors, but we try to defer building the
> implicit declaration.  My patch causes us to build those implicit
> declarations more often, which is probably a bit of a memory regression,

We can still avoid doing this in C++98 mode.

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


[-- Attachment #2: trivial-cxx98.patch --]
[-- Type: text/x-patch, Size: 1114 bytes --]

commit 7b8a53224af20adaa67a3df38523fcc0051cec3d
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Oct 31 09:39:54 2013 -0400

    	* class.c (type_build_ctor_call): Return early in C++98 mode.
    	(type_build_dtor_call): Likewise.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 43f90d7..64681ba 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -5163,6 +5163,8 @@ type_build_ctor_call (tree t)
     return false;
   if (!TYPE_HAS_DEFAULT_CONSTRUCTOR (inner))
     return true;
+  if (cxx_dialect < cxx11)
+    return false;
   /* A user-declared constructor might be private, and a constructor might
      be trivial but deleted.  */
   for (tree fns = lookup_fnfields_slot (inner, complete_ctor_identifier);
@@ -5188,6 +5190,8 @@ type_build_dtor_call (tree t)
   if (!CLASS_TYPE_P (inner) || ANON_AGGR_TYPE_P (inner)
       || !COMPLETE_TYPE_P (inner))
     return false;
+  if (cxx_dialect < cxx11)
+    return false;
   /* A user-declared destructor might be private, and a destructor might
      be trivial but deleted.  */
   for (tree fns = lookup_fnfields_slot (inner, complete_dtor_identifier);

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

* Re: C++ PATCH to deal with trivial but non-callable [cd]tors
  2013-10-30 17:02       ` Jason Merrill
  2013-10-30 19:22         ` Eric Botcazou
@ 2013-10-31 15:15         ` Eric Botcazou
  2013-10-31 16:27           ` Jason Merrill
  2014-01-20 10:19           ` Eric Botcazou
  1 sibling, 2 replies; 11+ messages in thread
From: Eric Botcazou @ 2013-10-31 15:15 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches

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

> I think a good way to check for any non-trivial methods would be to
> check trivial_type_p in the front end and then see if there are any
> !DECL_ARTIFICIAL decls in TYPE_METHODS.

Revised patch attached, tested on x86-64/Linux.


2013-10-31  Eric Botcazou  <ebotcazou@adacore.com>

c-family/
	* c-ada-spec.h (cpp_operation): Add IS_TRIVIAL.
	(dump_ada_specs): Adjust prototype of second callback.
	* c-ada-spec.c (cpp_check): New global variable.
	(dump_ada_nodes): Remove cpp_check parameter and do not pass it down.
	(print_generic_ada_decl): Likewise.
	(has_static_fields): Change return type to bool and add guard.
	(has_nontrivial_methods): New predicate.
	(is_tagged_type): Change return type to bool.
	(separate_class_package): Call has_nontrivial_methods.
	(pp_ada_tree_identifier): Minor tweaks.
	(dump_ada_function_declaration): Adjust calls to dump_generic_ada_node.
	(dump_ada_array_domains): Likewise.
	(dump_ada_array_type): Likewise.
	(dump_template_types): Remove cpp_check parameter and do not pass it to
	dump_generic_ada_node.
	(dump_ada_template): Likewise.
	(dump_generic_ada_node): Remove cpp_check parameter and do not pass it
	recursively.
	(print_ada_methods): Change return type to integer.  Remove cpp_check
	parameter and do not pass it down.
	(dump_nested_types): Remove cpp_check parameter and do not pass it to
	dump_generic_ada_node.
	(print_ada_declaration): Likewise.  Test RECORD_OR_UNION_TYPE_P before
	accessing methods.
	(print_ada_struct_decl): Remove cpp_check parameter and do not pass it
	down.  Use has_nontrivial_methods to recognize C++ classes.  Use return
	value of print_ada_methods.
	(dump_ads): Rename cpp_check parameter to check and adjust prototype.
	Set cpp_check to it before invoking dump_ada_nodes.
	(dump_ada_specs): Likewise.
cp/
	* decl2.c (cpp_check): Change type of first parameter and deal with
	IS_TRIVIAL.


-- 
Eric Botcazou

[-- Attachment #2: dump_ada_spec-2.diff --]
[-- Type: text/x-patch, Size: 39566 bytes --]

Index: c-family/c-ada-spec.h
===================================================================
--- c-family/c-ada-spec.h	(revision 204201)
+++ c-family/c-ada-spec.h	(working copy)
@@ -29,13 +29,14 @@ typedef enum {
   IS_CONSTRUCTOR,
   IS_DESTRUCTOR,
   IS_COPY_CONSTRUCTOR,
-  IS_TEMPLATE
+  IS_TEMPLATE,
+  IS_TRIVIAL
 } cpp_operation;
 
 extern location_t decl_sloc (const_tree, bool);
 extern void collect_ada_nodes (tree, const char *);
 extern void collect_source_ref (const char *);
 extern void dump_ada_specs (void (*)(const char *),
-			    int (*)(tree, cpp_operation));
+			    int (*)(const_tree, cpp_operation));
 
 #endif /* ! C_ADA_SPEC_H */
Index: c-family/c-ada-spec.c
===================================================================
--- c-family/c-ada-spec.c	(revision 204201)
+++ c-family/c-ada-spec.c	(working copy)
@@ -46,32 +46,31 @@ along with GCC; see the file COPYING3.
 #endif /* HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG */
 
 /* Local functions, macros and variables.  */
-static int dump_generic_ada_node (pretty_printer *, tree, tree,
-				  int (*)(tree, cpp_operation), int, int, bool);
-static int print_ada_declaration (pretty_printer *, tree, tree,
-				  int (*cpp_check)(tree, cpp_operation), int);
-static void print_ada_struct_decl (pretty_printer *, tree, tree,
-				   int (*cpp_check)(tree, cpp_operation), int,
-				   bool);
+static int dump_generic_ada_node (pretty_printer *, tree, tree, int, int,
+				  bool);
+static int print_ada_declaration (pretty_printer *, tree, tree, int);
+static void print_ada_struct_decl (pretty_printer *, tree, tree, int, bool);
 static void dump_sloc (pretty_printer *buffer, tree node);
 static void print_comment (pretty_printer *, const char *);
-static void print_generic_ada_decl (pretty_printer *, tree,
-				    int (*)(tree, cpp_operation), const char *);
+static void print_generic_ada_decl (pretty_printer *, tree, const char *);
 static char *get_ada_package (const char *);
-static void dump_ada_nodes (pretty_printer *, const char *,
-			    int (*)(tree, cpp_operation));
+static void dump_ada_nodes (pretty_printer *, const char *);
 static void reset_ada_withs (void);
 static void dump_ada_withs (FILE *);
 static void dump_ads (const char *, void (*)(const char *),
-		      int (*)(tree, cpp_operation));
+		      int (*)(const_tree, cpp_operation));
 static char *to_ada_name (const char *, int *);
 static bool separate_class_package (tree);
 
-#define INDENT(SPACE) do { \
-  int i; for (i = 0; i<SPACE; i++) pp_space (buffer); } while (0)
+#define INDENT(SPACE) \
+  do { int i; for (i = 0; i<SPACE; i++) pp_space (buffer); } while (0)
 
 #define INDENT_INCR 3
 
+/* Global hook used to perform C++ queries on nodes.  */
+static int (*cpp_check) (const_tree, cpp_operation) = NULL;
+
+
 /* Given a cpp MACRO, compute the max length BUFFER_LEN of the macro, as well
    as max length PARAM_LEN of arguments for fun_like macros, and also set
    SUPPORTED to 0 if the macro cannot be mapped to an Ada construct.  */
@@ -636,11 +635,10 @@ unmark_visited_r (tree *tp, int *walk_su
 }
 
 /* Dump nodes into PP relevant to SOURCE_FILE, as collected by previous calls
-   to collect_ada_nodes.  CPP_CHECK is used to perform C++ queries on nodes.  */
+   to collect_ada_nodes.  */
 
 static void
-dump_ada_nodes (pretty_printer *pp, const char *source_file,
-		int (*cpp_check)(tree, cpp_operation))
+dump_ada_nodes (pretty_printer *pp, const char *source_file)
 {
   int i, j;
   cpp_comment_table *comments;
@@ -676,7 +674,7 @@ dump_ada_nodes (pretty_printer *pp, cons
 	  if (j == comments->count
 	      || LOCATION_LINE (decl_sloc (to_dump[i], false))
 	      <  LOCATION_LINE (comments->entries[j].sloc))
-	    print_generic_ada_decl (pp, to_dump[i++], cpp_check, source_file);
+	    print_generic_ada_decl (pp, to_dump[i++], source_file);
 	  else
 	    break;
 	}
@@ -736,18 +734,15 @@ print_comment (pretty_printer *pp, const
     pp_newline (pp);
 }
 
-/* Prints declaration DECL to PP in Ada syntax. The current source file being
-   handled is SOURCE_FILE, and CPP_CHECK is used to perform C++ queries on
-   nodes.  */
+/* Print declaration DECL to PP in Ada syntax.  The current source file being
+   handled is SOURCE_FILE.  */
 
 static void
-print_generic_ada_decl (pretty_printer *pp, tree decl,
-			int (*cpp_check)(tree, cpp_operation),
-			const char* source_file)
+print_generic_ada_decl (pretty_printer *pp, tree decl, const char *source_file)
 {
   source_file_base = source_file;
 
-  if (print_ada_declaration (pp, decl, 0, cpp_check, INDENT_INCR))
+  if (print_ada_declaration (pp, decl, 0, INDENT_INCR))
     {
       pp_newline (pp);
       pp_newline (pp);
@@ -941,23 +936,25 @@ get_underlying_decl (tree type)
 
 /* Return whether TYPE has static fields.  */
 
-static int
+static bool
 has_static_fields (const_tree type)
 {
   tree tmp;
 
+  if (!type || !RECORD_OR_UNION_TYPE_P (type))
+    return false;
+
   for (tmp = TYPE_FIELDS (type); tmp; tmp = TREE_CHAIN (tmp))
-    {
-      if (DECL_NAME (tmp) && TREE_STATIC (tmp))
-	return true;
-    }
+    if (DECL_NAME (tmp) && TREE_STATIC (tmp))
+      return true;
+
   return false;
 }
 
 /* Return whether TYPE corresponds to an Ada tagged type (has a dispatch
    table).  */
 
-static int
+static bool
 is_tagged_type (const_tree type)
 {
   tree tmp;
@@ -972,6 +969,35 @@ is_tagged_type (const_tree type)
   return false;
 }
 
+/* Return whether TYPE has non-trivial methods, i.e. methods that do something
+   for the objects of TYPE.  In C++, all classes have implicit special methods,
+   e.g. constructors and destructors, but they can be trivial if the type is
+   sufficiently simple.  */
+
+static bool
+has_nontrivial_methods (const_tree type)
+{
+  tree tmp;
+
+  if (!type || !RECORD_OR_UNION_TYPE_P (type))
+    return false;
+
+  /* Only C++ types can have methods.  */
+  if (!cpp_check)
+    return false;
+
+  /* A non-trivial type has non-trivial special methods.  */
+  if (!cpp_check (type, IS_TRIVIAL))
+    return true;
+
+  /* If there are user-defined methods, they are deemed non-trivial.  */
+  for (tmp = TYPE_METHODS (type); tmp; tmp = TREE_CHAIN (tmp))
+    if (!DECL_ARTIFICIAL (tmp))
+      return true;
+
+  return false;
+}
+
 /* Generate a legal Ada name from a C NAME, returning a malloc'd string.
    SPACE_FOUND, if not NULL, is used to indicate whether a space was found in
    NAME.  */
@@ -1193,15 +1219,8 @@ to_ada_name (const char *name, int *spac
 static bool
 separate_class_package (tree decl)
 {
-  if (decl) 
-    {
-      tree type = TREE_TYPE (decl);
-      return type
-	&& TREE_CODE (type) == RECORD_TYPE
-	&& (TYPE_METHODS (type) || has_static_fields (type));
-    }
-  else
-    return false;
+  tree type = TREE_TYPE (decl);
+  return has_nontrivial_methods (type) || has_static_fields (type);
 }
 
 static bool package_prefix = true;
@@ -1221,7 +1240,6 @@ pp_ada_tree_identifier (pretty_printer *
 
   /* If the entity is a type and comes from another file, generate "package"
      prefix.  */
-
   decl = get_underlying_decl (type);
 
   if (decl)
@@ -1246,30 +1264,27 @@ pp_ada_tree_identifier (pretty_printer *
 		  case UNION_TYPE:
 		  case QUAL_UNION_TYPE:
 		  case TYPE_DECL:
-		    {
-		      char *s1 = get_ada_package (xloc.file);
-
-		      if (package_prefix)
-			{
-			  append_withs (s1, limited_access);
-			  pp_string (buffer, s1);
-			  pp_dot (buffer);
-			}
-		      free (s1);
-		    }
+		    if (package_prefix)
+		      {
+			char *s1 = get_ada_package (xloc.file);
+			append_withs (s1, limited_access);
+			pp_string (buffer, s1);
+			pp_dot (buffer);
+			free (s1);
+		      }
 		    break;
 		  default:
 		    break;
 		}
-              
-              if (separate_class_package (decl))
-                {
-                  pp_string (buffer, "Class_");
-                  pp_string (buffer, s);
-                  pp_dot (buffer);
-                }
 
-            }
+	      /* Generate the additional package prefix for C++ classes.  */
+	      if (separate_class_package (decl))
+		{
+		  pp_string (buffer, "Class_");
+		  pp_string (buffer, s);
+		  pp_dot (buffer);
+		}
+	     }
 	}
     }
 
@@ -1527,15 +1542,13 @@ dump_ada_function_declaration (pretty_pr
 	      pp_string (buffer, buf);
 	    }
 
-	  dump_generic_ada_node
-	    (buffer, TREE_TYPE (arg), node, NULL, spc, 0, true);
+	  dump_generic_ada_node (buffer, TREE_TYPE (arg), node, spc, 0, true);
 	}
       else
 	{
 	  sprintf (buf, "arg%d : ", num);
 	  pp_string (buffer, buf);
-	  dump_generic_ada_node
-	    (buffer, TREE_VALUE (arg), node, NULL, spc, 0, true);
+	  dump_generic_ada_node (buffer, TREE_VALUE (arg), node, spc, 0, true);
 	}
 
       if (TREE_TYPE (arg) && TREE_TYPE (TREE_TYPE (arg))
@@ -1593,13 +1606,13 @@ dump_ada_array_domains (pretty_printer *
 	  first = 0;
 
 	  if (min)
-	    dump_generic_ada_node (buffer, min, NULL_TREE, NULL, spc, 0, true);
+	    dump_generic_ada_node (buffer, min, NULL_TREE, spc, 0, true);
 	  pp_string (buffer, " .. ");
 
 	  /* If the upper bound is zero, gcc may generate a NULL_TREE
 	     for TYPE_MAX_VALUE rather than an integer_cst.  */
 	  if (max)
-	    dump_generic_ada_node (buffer, max, NULL_TREE, NULL, spc, 0, true);
+	    dump_generic_ada_node (buffer, max, NULL_TREE, spc, 0, true);
 	  else
 	    pp_string (buffer, "0");
 	}
@@ -1687,18 +1700,16 @@ dump_ada_array_type (pretty_printer *buf
 	pp_string (buffer, "aliased ");
 
       dump_generic_ada_node
-	(buffer, TREE_TYPE (tmp), TREE_TYPE (t), NULL, spc, false, true);
+	(buffer, TREE_TYPE (tmp), TREE_TYPE (t), spc, false, true);
     }
 }
 
 /* Dump in BUFFER type names associated with a template, each prepended with
-   '_'.  TYPES is the TREE_PURPOSE of a DECL_TEMPLATE_INSTANTIATIONS.
-   CPP_CHECK is used to perform C++ queries on nodes.
-   SPC is the indentation level.  */
+   '_'.  TYPES is the TREE_PURPOSE of a DECL_TEMPLATE_INSTANTIATIONS.  SPC is
+   the indentation level.  */
 
 static void
-dump_template_types (pretty_printer *buffer, tree types,
-		     int (*cpp_check)(tree, cpp_operation), int spc)
+dump_template_types (pretty_printer *buffer, tree types, int spc)
 {
   size_t i;
   size_t len = TREE_VEC_LENGTH (types);
@@ -1707,7 +1718,7 @@ dump_template_types (pretty_printer *buf
     {
       tree elem = TREE_VEC_ELT (types, i);
       pp_underscore (buffer);
-      if (!dump_generic_ada_node (buffer, elem, 0, cpp_check, spc, false, true))
+      if (!dump_generic_ada_node (buffer, elem, 0, spc, false, true))
 	{
 	  pp_string (buffer, "unknown");
 	  pp_scalar (buffer, "%lu", (unsigned long) TREE_HASH (elem));
@@ -1716,12 +1727,10 @@ dump_template_types (pretty_printer *buf
 }
 
 /* Dump in BUFFER the contents of all class instantiations associated with
-   a given template T.  CPP_CHECK is used to perform C++ queries on nodes.
-   SPC is the indentation level. */
+   a given template T.  SPC is the indentation level.  */
 
 static int
-dump_ada_template (pretty_printer *buffer, tree t,
-		   int (*cpp_check)(tree, cpp_operation), int spc)
+dump_ada_template (pretty_printer *buffer, tree t, int spc)
 {
   /* DECL_VINDEX is DECL_TEMPLATE_INSTANTIATIONS in this context.  */
   tree inst = DECL_VINDEX (t);
@@ -1750,15 +1759,15 @@ dump_ada_template (pretty_printer *buffe
       INDENT (spc);
       pp_string (buffer, "package ");
       package_prefix = false;
-      dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true);
-      dump_template_types (buffer, types, cpp_check, spc);
+      dump_generic_ada_node (buffer, instance, t, spc, false, true);
+      dump_template_types (buffer, types, spc);
       pp_string (buffer, " is");
       spc += INDENT_INCR;
       newline_and_indent (buffer, spc);
 
       TREE_VISITED (get_underlying_decl (instance)) = 1;
       pp_string (buffer, "type ");
-      dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true);
+      dump_generic_ada_node (buffer, instance, t, spc, false, true);
       package_prefix = true;
 
       if (is_tagged_type (instance))
@@ -1766,7 +1775,7 @@ dump_ada_template (pretty_printer *buffe
       else
 	pp_string (buffer, " is limited ");
 
-      dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, false);
+      dump_generic_ada_node (buffer, instance, t, spc, false, false);
       pp_newline (buffer);
       spc -= INDENT_INCR;
       newline_and_indent (buffer, spc);
@@ -1775,8 +1784,8 @@ dump_ada_template (pretty_printer *buffe
       newline_and_indent (buffer, spc);
       pp_string (buffer, "use ");
       package_prefix = false;
-      dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true);
-      dump_template_types (buffer, types, cpp_check, spc);
+      dump_generic_ada_node (buffer, instance, t, spc, false, true);
+      dump_template_types (buffer, types, spc);
       package_prefix = true;
       pp_semicolon (buffer);
       pp_newline (buffer);
@@ -1819,14 +1828,12 @@ static bool in_function = true;
 static bool bitfield_used = false;
 
 /* Recursively dump in BUFFER Ada declarations corresponding to NODE of type
-   TYPE.  CPP_CHECK is used to perform C++ queries on nodes.  SPC is the
-   indentation level.  LIMITED_ACCESS indicates whether NODE can be referenced
-   via a "limited with" clause.  NAME_ONLY indicates whether we should only
-   dump the name of NODE, instead of its full declaration.  */
+   TYPE.  SPC is the indentation level.  LIMITED_ACCESS indicates whether NODE
+   can be referenced via a "limited with" clause.  NAME_ONLY indicates whether
+   we should only dump the name of NODE, instead of its full declaration.  */
 
 static int
-dump_generic_ada_node (pretty_printer *buffer, tree node, tree type,
-		       int (*cpp_check)(tree, cpp_operation), int spc,
+dump_generic_ada_node (pretty_printer *buffer, tree node, tree type, int spc,
 		       int limited_access, bool name_only)
 {
   if (node == NULL_TREE)
@@ -1848,8 +1855,7 @@ dump_generic_ada_node (pretty_printer *b
 
     case TREE_BINFO:
       dump_generic_ada_node
-	(buffer, BINFO_TYPE (node), type, cpp_check,
-	 spc, limited_access, name_only);
+	(buffer, BINFO_TYPE (node), type, spc, limited_access, name_only);
 
     case TREE_VEC:
       pp_string (buffer, "--- unexpected node: TREE_VEC");
@@ -1876,7 +1882,7 @@ dump_generic_ada_node (pretty_printer *b
     case ENUMERAL_TYPE:
       if (name_only)
 	dump_generic_ada_node
-	  (buffer, TYPE_NAME (node), node, cpp_check, spc, 0, true);
+	  (buffer, TYPE_NAME (node), node, spc, 0, true);
       else
 	{
 	  tree value = TYPE_VALUES (node);
@@ -1906,7 +1912,7 @@ dump_generic_ada_node (pretty_printer *b
 	      pp_string (buffer, "pragma Convention (C, ");
 	      dump_generic_ada_node
 		(buffer, DECL_NAME (type) ? type : TYPE_NAME (node), type,
-		 cpp_check, spc, 0, true);
+		 spc, 0, true);
 	      pp_right_paren (buffer);
 	    }
 	  else
@@ -1923,14 +1929,14 @@ dump_generic_ada_node (pretty_printer *b
 
 		  dump_generic_ada_node
 		    (buffer, DECL_NAME (type) ? type : TYPE_NAME (node), type,
-		     cpp_check, spc, 0, true);
+		     spc, 0, true);
 
 		  pp_string (buffer, " := ");
 		  dump_generic_ada_node
 		    (buffer,
 		     TREE_CODE (TREE_VALUE (value)) == INTEGER_CST ?
 		       TREE_VALUE (value) : DECL_INITIAL (TREE_VALUE (value)),
-		     node, cpp_check, spc, false, true);
+		     node, spc, false, true);
 		}
 	    }
 	}
@@ -1991,8 +1997,7 @@ dump_generic_ada_node (pretty_printer *b
     case REFERENCE_TYPE:
       if (name_only && TYPE_NAME (node))
 	dump_generic_ada_node
-	  (buffer, TYPE_NAME (node), node, cpp_check,
-	   spc, limited_access, true);
+	  (buffer, TYPE_NAME (node), node, spc, limited_access, true);
 
       else if (TREE_CODE (TREE_TYPE (node)) == FUNCTION_TYPE)
 	{
@@ -2020,7 +2025,7 @@ dump_generic_ada_node (pretty_printer *b
 	    {
 	      pp_string (buffer, " return ");
 	      dump_generic_ada_node
-		(buffer, TREE_TYPE (fnode), type, cpp_check, spc, 0, true);
+		(buffer, TREE_TYPE (fnode), type, spc, 0, true);
 	    }
 
 	    /* If we are dumping the full type, it means we are part of a
@@ -2031,7 +2036,7 @@ dump_generic_ada_node (pretty_printer *b
 		newline_and_indent (buffer, spc);
 		pp_string (buffer, "pragma Convention (C, ");
 		dump_generic_ada_node
-		  (buffer, type, 0, cpp_check, spc, false, true);
+		  (buffer, type, 0, spc, false, true);
 		pp_right_paren (buffer);
 	      }
 	}
@@ -2158,11 +2163,11 @@ dump_generic_ada_node (pretty_printer *b
 		      && type_name != NULL_TREE)
 		    dump_generic_ada_node
 		      (buffer, type_name,
-		       TREE_TYPE (node), cpp_check, spc, is_access, true);
+		       TREE_TYPE (node), spc, is_access, true);
 		  else
 		    dump_generic_ada_node
 		      (buffer, TREE_TYPE (node), TREE_TYPE (node),
-		       cpp_check, spc, 0, true);
+		       spc, 0, true);
 		}
 	    }
 	}
@@ -2171,8 +2176,7 @@ dump_generic_ada_node (pretty_printer *b
     case ARRAY_TYPE:
       if (name_only)
 	dump_generic_ada_node
-	  (buffer, TYPE_NAME (node), node, cpp_check,
-	   spc, limited_access, true);
+	  (buffer, TYPE_NAME (node), node, spc, limited_access, true);
       else
 	dump_ada_array_type (buffer, node, spc);
       break;
@@ -2184,8 +2188,7 @@ dump_generic_ada_node (pretty_printer *b
 	{
 	  if (TYPE_NAME (node))
 	    dump_generic_ada_node
-	      (buffer, TYPE_NAME (node), node, cpp_check,
-	       spc, limited_access, true);
+	      (buffer, TYPE_NAME (node), node, spc, limited_access, true);
 	  else
 	    {
 	      pp_string (buffer, "anon_");
@@ -2193,8 +2196,7 @@ dump_generic_ada_node (pretty_printer *b
 	    }
 	}
       else
-	print_ada_struct_decl
-	  (buffer, node, type, cpp_check, spc, true);
+	print_ada_struct_decl (buffer, node, type, spc, true);
       break;
 
     case INTEGER_CST:
@@ -2287,12 +2289,11 @@ dump_generic_ada_node (pretty_printer *b
 
 	      pp_string (buffer, first ? "tagged limited " : " with ");
 	    }
-	  else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node))
-		   && TYPE_METHODS (TREE_TYPE (node)))
+	  else if (has_nontrivial_methods (TREE_TYPE (node)))
 	    pp_string (buffer, "limited ");
 
 	  dump_generic_ada_node
-	    (buffer, TREE_TYPE (node), type, cpp_check, spc, false, false);
+	    (buffer, TREE_TYPE (node), type, spc, false, false);
 	}
       break;
 
@@ -2311,41 +2312,41 @@ dump_generic_ada_node (pretty_printer *b
   return 1;
 }
 
-/* Dump in BUFFER NODE's methods.  CPP_CHECK is used to perform C++ queries on
-   nodes.  SPC is the indentation level.  */
+/* Dump in BUFFER NODE's methods.  SPC is the indentation level.  Return 1 if
+   methods were printed, 0 otherwise.  */
 
-static void
-print_ada_methods (pretty_printer *buffer, tree node,
-		   int (*cpp_check)(tree, cpp_operation), int spc)
+static int
+print_ada_methods (pretty_printer *buffer, tree node, int spc)
 {
-  tree tmp = TYPE_METHODS (node);
   int res = 1;
+  tree tmp;
 
-  if (tmp)
-    {
-      pp_semicolon (buffer);
+  if (!has_nontrivial_methods (node))
+    return 0;
 
-      for (; tmp; tmp = TREE_CHAIN (tmp))
+  pp_semicolon (buffer);
+
+  for (tmp = TYPE_METHODS (node); tmp; tmp = TREE_CHAIN (tmp))
+    {
+      if (res)
 	{
-	  if (res)
-	    {
-	      pp_newline (buffer);
-	      pp_newline (buffer);
-	    }
-	  res = print_ada_declaration (buffer, tmp, node, cpp_check, spc);
+	  pp_newline (buffer);
+	  pp_newline (buffer);
 	}
+      res = print_ada_declaration (buffer, tmp, node, spc);
     }
+
+  return 1;
 }
 
 /* Dump in BUFFER anonymous types nested inside T's definition.
    PARENT is the parent node of T.
    FORWARD indicates whether a forward declaration of T should be generated.
-   CPP_CHECK is used to perform C++ queries on
-   nodes.  SPC is the indentation level.  */
+   SPC is the indentation level.  */
 
 static void
 dump_nested_types (pretty_printer *buffer, tree t, tree parent, bool forward,
-		   int (*cpp_check)(tree, cpp_operation), int spc)
+		   int spc)
 {
   tree field, outer, decl;
 
@@ -2363,8 +2364,7 @@ dump_nested_types (pretty_printer *buffe
   if (forward)
     {
       pp_string (buffer, "type ");
-      dump_generic_ada_node
-	(buffer, t, t, cpp_check, spc, false, true);
+      dump_generic_ada_node (buffer, t, t, spc, false, true);
       pp_semicolon (buffer);
       newline_and_indent (buffer, spc);
       TREE_VISITED (t) = 1;
@@ -2406,8 +2406,7 @@ dump_nested_types (pretty_printer *buffe
 		    /* Generate forward declaration.  */
 
 		    pp_string (buffer, "type ");
-		    dump_generic_ada_node
-		      (buffer, decl, 0, cpp_check, spc, false, true);
+		    dump_generic_ada_node (buffer, decl, 0, spc, false, true);
 		    pp_semicolon (buffer);
 		    newline_and_indent (buffer, spc);
 
@@ -2431,30 +2430,28 @@ dump_nested_types (pretty_printer *buffe
 
 	      case UNION_TYPE:
 		TREE_VISITED (t) = 1;
-		dump_nested_types (buffer, field, t, false, cpp_check, spc);
+		dump_nested_types (buffer, field, t, false, spc);
 
 		pp_string (buffer, "type ");
 
 		if (TYPE_NAME (TREE_TYPE (field)))
 		  {
 		    dump_generic_ada_node
-		      (buffer, TYPE_NAME (TREE_TYPE (field)), 0, cpp_check,
-		       spc, false, true);
+		      (buffer, TYPE_NAME (TREE_TYPE (field)), 0, spc, false,
+		       true);
 		    pp_string (buffer, " (discr : unsigned := 0) is ");
 		    print_ada_struct_decl
-		      (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
+		      (buffer, TREE_TYPE (field), t, spc, false);
 
 		    pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
 		    dump_generic_ada_node
-		      (buffer, TREE_TYPE (field), 0, cpp_check,
-		       spc, false, true);
+		      (buffer, TREE_TYPE (field), 0, spc, false, true);
 		    pp_string (buffer, ");");
 		    newline_and_indent (buffer, spc);
 
 		    pp_string (buffer, "pragma Unchecked_Union (");
 		    dump_generic_ada_node
-		      (buffer, TREE_TYPE (field), 0, cpp_check,
-		       spc, false, true);
+		      (buffer, TREE_TYPE (field), 0, spc, false, true);
 		    pp_string (buffer, ");");
 		  }
 		else
@@ -2463,7 +2460,7 @@ dump_nested_types (pretty_printer *buffe
 		      (buffer, parent, field,
 		       	"_union (discr : unsigned := 0) is ");
 		    print_ada_struct_decl
-		      (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
+		      (buffer, TREE_TYPE (field), t, spc, false);
 		    pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
 		    dump_ada_double_name (buffer, parent, field, "_union);");
 		    newline_and_indent (buffer, spc);
@@ -2480,27 +2477,25 @@ dump_nested_types (pretty_printer *buffe
 		  {
 		    pp_string (buffer, "type ");
 		    dump_generic_ada_node
-		      (buffer, t, parent, 0, spc, false, true);
+		      (buffer, t, parent, spc, false, true);
 		    pp_semicolon (buffer);
 		    newline_and_indent (buffer, spc);
 		  }
 
 		TREE_VISITED (t) = 1;
-		dump_nested_types (buffer, field, t, false, cpp_check, spc);
+		dump_nested_types (buffer, field, t, false, spc);
 		pp_string (buffer, "type ");
 
 		if (TYPE_NAME (TREE_TYPE (field)))
 		  {
 		    dump_generic_ada_node
-		      (buffer, TREE_TYPE (field), 0, cpp_check,
-		       spc, false, true);
+		      (buffer, TREE_TYPE (field), 0, spc, false, true);
 		    pp_string (buffer, " is ");
 		    print_ada_struct_decl
-		      (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
+		      (buffer, TREE_TYPE (field), t, spc, false);
 		    pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
 		    dump_generic_ada_node
-		      (buffer, TREE_TYPE (field), 0, cpp_check,
-		       spc, false, true);
+		      (buffer, TREE_TYPE (field), 0, spc, false, true);
 		    pp_string (buffer, ");");
 		  }
 		else
@@ -2508,7 +2503,7 @@ dump_nested_types (pretty_printer *buffe
 		    dump_ada_double_name
 		      (buffer, parent, field, "_struct is ");
 		    print_ada_struct_decl
-		      (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
+		      (buffer, TREE_TYPE (field), t, spc, false);
 		    pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
 		    dump_ada_double_name (buffer, parent, field, "_struct);");
 		  }
@@ -2557,12 +2552,11 @@ type_name (tree t)
 }
 
 /* Print in BUFFER the declaration of a variable T of type TYPE in Ada syntax.
-   CPP_CHECK is used to perform C++ queries on nodes.  SPC is the indentation
-   level.  Return 1 if a declaration was printed, 0 otherwise.  */
+   SPC is the indentation level.  Return 1 if a declaration was printed,
+   0 otherwise.  */
 
 static int
-print_ada_declaration (pretty_printer *buffer, tree t, tree type,
-		       int (*cpp_check)(tree, cpp_operation), int spc)
+print_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc)
 {
   int is_var = 0, need_indent = 0;
   int is_class = false;
@@ -2571,7 +2565,7 @@ print_ada_declaration (pretty_printer *b
   tree orig = NULL_TREE;
 
   if (cpp_check && cpp_check (t, IS_TEMPLATE))
-    return dump_ada_template (buffer, t, cpp_check, spc);
+    return dump_ada_template (buffer, t, spc);
 
   if (TREE_CODE (t) == CONST_DECL && TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE)
     /* Skip enumeral values: will be handled as part of the type itself.  */
@@ -2599,20 +2593,18 @@ print_ada_declaration (pretty_printer *b
 	      if (RECORD_OR_UNION_TYPE_P (typ) && !TYPE_FIELDS (typ))
 		{
 		  pp_string (buffer, "--  skipped empty struct ");
-		  dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+		  dump_generic_ada_node (buffer, t, type, spc, false, true);
 		}
 	      else
 		{
 		  if (!TREE_VISITED (stub)
 		      && DECL_SOURCE_FILE (stub) == source_file_base)
-		    dump_nested_types
-		      (buffer, stub, stub, true, cpp_check, spc);
+		    dump_nested_types (buffer, stub, stub, true, spc);
 
 		  pp_string (buffer, "subtype ");
-		  dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+		  dump_generic_ada_node (buffer, t, type, spc, false, true);
 		  pp_string (buffer, " is ");
-		  dump_generic_ada_node
-		    (buffer, typ, type, 0, spc, false, true);
+		  dump_generic_ada_node (buffer, typ, type, spc, false, true);
 		  pp_semicolon (buffer);
 		}
 	      return 1;
@@ -2671,7 +2663,7 @@ print_ada_declaration (pretty_printer *b
 	    if (!TYPE_FIELDS (TREE_TYPE (t)))
 	      {
 		pp_string (buffer, "--  skipped empty struct ");
-		dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+		dump_generic_ada_node (buffer, t, type, spc, false, true);
 		return 1;
 	      }
 
@@ -2680,7 +2672,7 @@ print_ada_declaration (pretty_printer *b
 		    || *IDENTIFIER_POINTER (decl_name) == '$'))
 	      {
 		pp_string (buffer, "--  skipped anonymous struct ");
-		dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+		dump_generic_ada_node (buffer, t, type, spc, false, true);
 		TREE_VISITED (t) = 1;
 		return 1;
 	      }
@@ -2689,14 +2681,13 @@ print_ada_declaration (pretty_printer *b
 	      pp_string (buffer, "subtype ");
 	    else
 	      {
-		dump_nested_types (buffer, t, t, false, cpp_check, spc);
+		dump_nested_types (buffer, t, t, false, spc);
 
                 if (separate_class_package (t))
 		  {
 		    is_class = true;
 		    pp_string (buffer, "package Class_");
-		    dump_generic_ada_node
-		      (buffer, t, type, 0, spc, false, true);
+		    dump_generic_ada_node (buffer, t, type, spc, false, true);
 		    pp_string (buffer, " is");
 		    spc += INDENT_INCR;
 		    newline_and_indent (buffer, spc);
@@ -2718,7 +2709,7 @@ print_ada_declaration (pretty_printer *b
 
 	  case FUNCTION_TYPE:
 	    pp_string (buffer, "--  skipped function type ");
-	    dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+	    dump_generic_ada_node (buffer, t, type, spc, false, true);
 	    return 1;
 	    break;
 
@@ -2752,7 +2743,7 @@ print_ada_declaration (pretty_printer *b
 	INDENT (spc);
 
       /* Print variable's name.  */
-      dump_generic_ada_node (buffer, t, type, cpp_check, spc, false, true);
+      dump_generic_ada_node (buffer, t, type, spc, false, true);
 
       if (TREE_CODE (t) == TYPE_DECL)
 	{
@@ -2760,8 +2751,7 @@ print_ada_declaration (pretty_printer *b
 
 	  if (orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
 	    dump_generic_ada_node
-	      (buffer, TYPE_NAME (orig), type,
-	       cpp_check, spc, false, true);
+	      (buffer, TYPE_NAME (orig), type, spc, false, true);
 	  else
 	    dump_ada_array_type (buffer, t, spc);
 	}
@@ -2780,7 +2770,7 @@ print_ada_declaration (pretty_printer *b
 		  && TREE_CODE (tmp) != INTEGER_TYPE)
 		pp_string (buffer, "aliased ");
 
-	      dump_generic_ada_node (buffer, tmp, type, 0, spc, false, true);
+	      dump_generic_ada_node (buffer, tmp, type, spc, false, true);
 	    }
 	  else
 	    {
@@ -2795,7 +2785,8 @@ print_ada_declaration (pretty_printer *b
     }
   else if (TREE_CODE (t) == FUNCTION_DECL)
     {
-      bool is_function = true, is_method, is_abstract_class = false;
+      bool is_function = true, is_abstract_class = false;
+      bool is_method = TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE;
       tree decl_name = DECL_NAME (t);
       int prev_in_function = in_function;
       bool is_abstract = false;
@@ -2852,7 +2843,6 @@ print_ada_declaration (pretty_printer *b
 	pp_string (buffer, "function ");
 
       in_function = is_function;
-      is_method = TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE;
 
       if (is_destructor)
 	print_destructor (buffer, t);
@@ -2874,18 +2864,17 @@ print_ada_declaration (pretty_printer *b
 	  else
 	    {
 	      dump_generic_ada_node
-		(buffer, TREE_TYPE (TREE_TYPE (t)), type, cpp_check,
-		 spc, false, true);
+		(buffer, TREE_TYPE (TREE_TYPE (t)), type, spc, false, true);
 	    }
 	}
 
-      if (is_constructor && cpp_check && type
-	  && AGGREGATE_TYPE_P (type)
+      if (is_constructor
+	  && RECORD_OR_UNION_TYPE_P (type)
 	  && TYPE_METHODS (type))
 	{
-	  tree tmp = TYPE_METHODS (type);
+	  tree tmp;
 
-	  for (; tmp; tmp = TREE_CHAIN (tmp))
+	  for (tmp = TYPE_METHODS (type); tmp; tmp = TREE_CHAIN (tmp))
 	    if (cpp_check (tmp, IS_ABSTRACT))
 	      {
 		is_abstract_class = 1;
@@ -2937,8 +2926,7 @@ print_ada_declaration (pretty_printer *b
 	INDENT (spc);
 
       /* Anonymous structs/unions */
-      dump_generic_ada_node
-	(buffer, TREE_TYPE (t), t, cpp_check, spc, false, true);
+      dump_generic_ada_node (buffer, TREE_TYPE (t), t, spc, false, true);
 
       if (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE
 	  || TREE_CODE (TREE_TYPE (t)) == QUAL_UNION_TYPE)
@@ -2949,14 +2937,15 @@ print_ada_declaration (pretty_printer *b
       pp_string (buffer, " is ");
 
       /* Check whether we have an Ada interface compatible class.  */
-      if (cpp_check && AGGREGATE_TYPE_P (TREE_TYPE (t))
+      if (cpp_check
+	  && RECORD_OR_UNION_TYPE_P (TREE_TYPE (t))
 	  && TYPE_METHODS (TREE_TYPE (t)))
 	{
 	  int num_fields = 0;
-	  tree tmp = TYPE_FIELDS (TREE_TYPE (t));
+	  tree tmp;
 
 	  /* Check that there are no fields other than the virtual table.  */
-	  for (; tmp; tmp = TREE_CHAIN (tmp))
+	  for (tmp = TYPE_FIELDS (TREE_TYPE (t)); tmp; tmp = TREE_CHAIN (tmp))
 	    {
 	      if (TREE_CODE (tmp) == TYPE_DECL)
 		continue;
@@ -2984,17 +2973,16 @@ print_ada_declaration (pretty_printer *b
 	  newline_and_indent (buffer, spc);
 	  pp_string (buffer, "pragma Import (CPP, ");
  	  dump_generic_ada_node
-	    (buffer, TYPE_NAME (TREE_TYPE (t)), type, cpp_check,
-	     spc, false, true);
+	    (buffer, TYPE_NAME (TREE_TYPE (t)), type, spc, false, true);
   	  pp_right_paren (buffer);
 
-	  print_ada_methods (buffer, TREE_TYPE (t), cpp_check, spc);
+	  print_ada_methods (buffer, TREE_TYPE (t), spc);
 	}
       else
 	{
 	  if (is_abstract_record)
 	    pp_string (buffer, "abstract ");
-	  dump_generic_ada_node (buffer, t, t, cpp_check, spc, false, false);
+	  dump_generic_ada_node (buffer, t, t, spc, false, false);
 	}
     }
   else
@@ -3006,7 +2994,7 @@ print_ada_declaration (pretty_printer *b
 	check_name (buffer, t);
 
       /* Print variable/type's name.  */
-      dump_generic_ada_node (buffer, t, t, cpp_check, spc, false, true);
+      dump_generic_ada_node (buffer, t, t, spc, false, true);
 
       if (TREE_CODE (t) == TYPE_DECL)
 	{
@@ -3020,8 +3008,7 @@ print_ada_declaration (pretty_printer *b
 
 	  pp_string (buffer, " is ");
 
-	  dump_generic_ada_node
-	    (buffer, orig, t, cpp_check, spc, false, is_subtype);
+	  dump_generic_ada_node (buffer, orig, t, spc, false, is_subtype);
 	}
       else
 	{
@@ -3043,7 +3030,7 @@ print_ada_declaration (pretty_printer *b
 		pp_string (buffer, "aliased ");
 
 	      dump_generic_ada_node
-		(buffer, TREE_TYPE (t), t, cpp_check, spc, false, true);
+		(buffer, TREE_TYPE (t), t, spc, false, true);
 	    }
 	  else
 	    {
@@ -3053,8 +3040,7 @@ print_ada_declaration (pretty_printer *b
 		pp_string (buffer, "aliased ");
 
 	      dump_generic_ada_node
-		(buffer, TREE_TYPE (t), TREE_TYPE (t), cpp_check,
-		 spc, false, true);
+		(buffer, TREE_TYPE (t), TREE_TYPE (t), spc, false, true);
 	    }
 	}
     }
@@ -3066,7 +3052,7 @@ print_ada_declaration (pretty_printer *b
       pp_string (buffer, "end;");
       newline_and_indent (buffer, spc);
       pp_string (buffer, "use Class_");
-      dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+      dump_generic_ada_node (buffer, t, type, spc, false, true);
       pp_semicolon (buffer);
       pp_newline (buffer);
 
@@ -3089,18 +3075,16 @@ print_ada_declaration (pretty_printer *b
 }
 
 /* Prints in BUFFER a structure NODE of type TYPE: name, fields, and methods
-   with Ada syntax.  CPP_CHECK is used to perform C++ queries on nodes.  SPC
-   is the indentation level.  If DISPLAY_CONVENTION is true, also print the
-   pragma Convention for NODE.  */
+   with Ada syntax.  SPC is the indentation level.  If DISPLAY_CONVENTION is
+   true, also print the pragma Convention for NODE.  */
 
 static void
-print_ada_struct_decl (pretty_printer *buffer, tree node, tree type,
-		       int (*cpp_check)(tree, cpp_operation), int spc,
+print_ada_struct_decl (pretty_printer *buffer, tree node, tree type, int spc,
 		       bool display_convention)
 {
   tree tmp;
-  int is_union =
-    TREE_CODE (node) == UNION_TYPE || TREE_CODE (node) == QUAL_UNION_TYPE;
+  const bool is_union
+    = TREE_CODE (node) == UNION_TYPE || TREE_CODE (node) == QUAL_UNION_TYPE;
   char buf[32];
   int field_num = 0;
   int field_spc = spc + INDENT_INCR;
@@ -3134,8 +3118,7 @@ print_ada_struct_decl (pretty_printer *b
 	      if (!is_tagged_type (TREE_TYPE (tmp)))
 		{
 		  if (!TYPE_NAME (TREE_TYPE (tmp)))
-		    print_ada_declaration
-		      (buffer, tmp, type, cpp_check, field_spc);
+		    print_ada_declaration (buffer, tmp, type, field_spc);
 		  else
 		    {
 		      INDENT (field_spc);
@@ -3179,8 +3162,7 @@ print_ada_struct_decl (pretty_printer *b
 		      pp_newline (buffer);
 		    }
 
-		  if (print_ada_declaration (buffer,
-					     tmp, type, cpp_check, field_spc))
+		  if (print_ada_declaration (buffer, tmp, type, field_spc))
 		    {
 		      pp_newline (buffer);
 		      field_num++;
@@ -3214,7 +3196,7 @@ print_ada_struct_decl (pretty_printer *b
 
   if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
     {
-      if (TYPE_METHODS (TREE_TYPE (type)))
+      if (has_nontrivial_methods (TREE_TYPE (type)))
 	pp_string (buffer, "pragma Import (CPP, ");
       else
 	pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
@@ -3223,8 +3205,7 @@ print_ada_struct_decl (pretty_printer *b
     pp_string (buffer, "pragma Convention (C, ");
 
   package_prefix = false;
-  dump_generic_ada_node
-    (buffer, TREE_TYPE (type), type, cpp_check, spc, false, true);
+  dump_generic_ada_node (buffer, TREE_TYPE (type), type, spc, false, true);
   package_prefix = true;
   pp_right_paren (buffer);
 
@@ -3234,8 +3215,7 @@ print_ada_struct_decl (pretty_printer *b
       newline_and_indent (buffer, spc);
       pp_string (buffer, "pragma Unchecked_Union (");
 
-      dump_generic_ada_node
-	(buffer, TREE_TYPE (type), type, cpp_check, spc, false, true);
+      dump_generic_ada_node (buffer, TREE_TYPE (type), type, spc, false, true);
       pp_right_paren (buffer);
     }
 
@@ -3245,15 +3225,14 @@ print_ada_struct_decl (pretty_printer *b
       newline_and_indent (buffer, spc);
       pp_string (buffer, "pragma Pack (");
       dump_generic_ada_node
-	(buffer, TREE_TYPE (type), type, cpp_check, spc, false, true);
+	(buffer, TREE_TYPE (type), type, spc, false, true);
       pp_right_paren (buffer);
       bitfield_used = false;
     }
 
-  print_ada_methods (buffer, node, cpp_check, spc);
+  need_semicolon = !print_ada_methods (buffer, node, spc);
 
   /* Print the static fields of the structure, if any.  */
-  need_semicolon = TYPE_METHODS (node) == NULL_TREE;
   for (tmp = TYPE_FIELDS (node); tmp; tmp = TREE_CHAIN (tmp))
     {
       if (DECL_NAME (tmp) && TREE_STATIC (tmp))
@@ -3265,20 +3244,19 @@ print_ada_struct_decl (pretty_printer *b
 	    }
 	  pp_newline (buffer);
 	  pp_newline (buffer);
-	  print_ada_declaration (buffer, tmp, type, cpp_check, spc);
+	  print_ada_declaration (buffer, tmp, type, spc);
 	}
     }
 }
 
 /* Dump all the declarations in SOURCE_FILE to an Ada spec.
    COLLECT_ALL_REFS is a front-end callback used to collect all relevant
-   nodes for SOURCE_FILE.  CPP_CHECK is used to perform C++ queries on
-   nodes.  */
+   nodes for SOURCE_FILE.  CHECK is used to perform C++ queries on nodes.  */
 
 static void
 dump_ads (const char *source_file,
 	  void (*collect_all_refs)(const char *),
-	  int (*cpp_check)(tree, cpp_operation))
+	  int (*check)(const_tree, cpp_operation))
 {
   char *ads_name;
   char *pkg_name;
@@ -3316,7 +3294,8 @@ dump_ads (const char *source_file,
       (*collect_all_refs) (source_file);
 
       /* Dump all references.  */
-      dump_ada_nodes (&pp, source_file, cpp_check);
+      cpp_check = check;
+      dump_ada_nodes (&pp, source_file);
 
       /* Requires Ada 2005 syntax, so generate corresponding pragma.
          Also, disable style checks since this file is auto-generated.  */
@@ -3370,21 +3349,21 @@ collect_source_ref (const char *filename
 }
 
 /* Main entry point: dump all Ada specs corresponding to SOURCE_REFS
-   using callbacks COLLECT_ALL_REFS and CPP_CHECK.
+   using callbacks COLLECT_ALL_REFS and CHECK.
    COLLECT_ALL_REFS is a front-end callback used to collect all relevant
    nodes for a given source file.
-   CPP_CHECK is used to perform C++ queries on nodes, or NULL for the C
+   CHECK is used to perform C++ queries on nodes, or NULL for the C
    front-end.  */
 
 void
 dump_ada_specs (void (*collect_all_refs)(const char *),
-		int (*cpp_check)(tree, cpp_operation))
+		int (*check)(const_tree, cpp_operation))
 {
   int i;
 
   /* Iterate over the list of files to dump specs for */
   for (i = 0; i < source_refs_used; i++)
-    dump_ads (source_refs[i], collect_all_refs, cpp_check);
+    dump_ads (source_refs[i], collect_all_refs, check);
 
   /* Free files table.  */
   free (source_refs);
Index: cp/decl2.c
===================================================================
--- cp/decl2.c	(revision 204201)
+++ cp/decl2.c	(working copy)
@@ -3806,7 +3806,7 @@ build_java_method_aliases (struct pointe
 /* Return C++ property of T, based on given operation OP.  */
 
 static int
-cpp_check (tree t, cpp_operation op)
+cpp_check (const_tree t, cpp_operation op)
 {
   switch (op)
     {
@@ -3820,6 +3820,8 @@ cpp_check (tree t, cpp_operation op)
 	return DECL_COPY_CONSTRUCTOR_P (t);
       case IS_TEMPLATE:
 	return TREE_CODE (t) == TEMPLATE_DECL;
+      case IS_TRIVIAL:
+	return trivial_type_p (t);
       default:
         return 0;
     }

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

* Re: C++ PATCH to deal with trivial but non-callable [cd]tors
  2013-10-31 15:15         ` Eric Botcazou
@ 2013-10-31 16:27           ` Jason Merrill
  2014-01-20 10:19           ` Eric Botcazou
  1 sibling, 0 replies; 11+ messages in thread
From: Jason Merrill @ 2013-10-31 16:27 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches

On 10/31/2013 10:47 AM, Eric Botcazou wrote:
>> I think a good way to check for any non-trivial methods would be to
>> check trivial_type_p in the front end and then see if there are any
>> !DECL_ARTIFICIAL decls in TYPE_METHODS.
>
> Revised patch attached, tested on x86-64/Linux.

Looks good.

Jason


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

* Re: C++ PATCH to deal with trivial but non-callable [cd]tors
  2013-10-31 15:15         ` Eric Botcazou
  2013-10-31 16:27           ` Jason Merrill
@ 2014-01-20 10:19           ` Eric Botcazou
  1 sibling, 0 replies; 11+ messages in thread
From: Eric Botcazou @ 2014-01-20 10:19 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches

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

> 2013-10-31  Eric Botcazou  <ebotcazou@adacore.com>
> 
> c-family/
> 	* c-ada-spec.h (cpp_operation): Add IS_TRIVIAL.
> 	(dump_ada_specs): Adjust prototype of second callback.

It turns out that adjusting (constifying) the prototype of the second callback 
was a gratuitous change and future enhancements will run afoul of it, so I've 
adjusted it back with the attached patch.  No functional changes.

Tested on x86_64-suse-linux, applied on the mainline.


2014-01-20  Eric Botcazou  <ebotcazou@adacore.com>

c-family/
	* c-ada-spec.h (dump_ada_specs): Revert prototype change.
	* c-ada-spec.c (dump_ads): Likewise.
	(cpp_check): Likewise.
	(dump_ada_specs): Likewise.
cp/
	* decl2.c (cpp_check): Revert prototype change.


-- 
Eric Botcazou

[-- Attachment #2: p.diff --]
[-- Type: text/x-patch, Size: 2504 bytes --]

Index: c-family/c-ada-spec.h
===================================================================
--- c-family/c-ada-spec.h	(revision 206790)
+++ c-family/c-ada-spec.h	(working copy)
@@ -37,6 +37,6 @@ extern location_t decl_sloc (const_tree,
 extern void collect_ada_nodes (tree, const char *);
 extern void collect_source_ref (const char *);
 extern void dump_ada_specs (void (*)(const char *),
-			    int (*)(const_tree, cpp_operation));
+			    int (*)(tree, cpp_operation));
 
 #endif /* ! C_ADA_SPEC_H */
Index: c-family/c-ada-spec.c
===================================================================
--- c-family/c-ada-spec.c	(revision 206790)
+++ c-family/c-ada-spec.c	(working copy)
@@ -58,7 +58,7 @@ static void dump_ada_nodes (pretty_print
 static void reset_ada_withs (void);
 static void dump_ada_withs (FILE *);
 static void dump_ads (const char *, void (*)(const char *),
-		      int (*)(const_tree, cpp_operation));
+		      int (*)(tree, cpp_operation));
 static char *to_ada_name (const char *, int *);
 static bool separate_class_package (tree);
 
@@ -68,7 +68,7 @@ static bool separate_class_package (tree
 #define INDENT_INCR 3
 
 /* Global hook used to perform C++ queries on nodes.  */
-static int (*cpp_check) (const_tree, cpp_operation) = NULL;
+static int (*cpp_check) (tree, cpp_operation) = NULL;
 
 
 /* Given a cpp MACRO, compute the max length BUFFER_LEN of the macro, as well
@@ -975,7 +975,7 @@ is_tagged_type (const_tree type)
    sufficiently simple.  */
 
 static bool
-has_nontrivial_methods (const_tree type)
+has_nontrivial_methods (tree type)
 {
   tree tmp;
 
@@ -3263,7 +3263,7 @@ print_ada_struct_decl (pretty_printer *b
 static void
 dump_ads (const char *source_file,
 	  void (*collect_all_refs)(const char *),
-	  int (*check)(const_tree, cpp_operation))
+	  int (*check)(tree, cpp_operation))
 {
   char *ads_name;
   char *pkg_name;
@@ -3364,7 +3364,7 @@ collect_source_ref (const char *filename
 
 void
 dump_ada_specs (void (*collect_all_refs)(const char *),
-		int (*check)(const_tree, cpp_operation))
+		int (*check)(tree, cpp_operation))
 {
   int i;
 
Index: cp/decl2.c
===================================================================
--- cp/decl2.c	(revision 206790)
+++ cp/decl2.c	(working copy)
@@ -3817,7 +3817,7 @@ build_java_method_aliases (struct pointe
 /* Return C++ property of T, based on given operation OP.  */
 
 static int
-cpp_check (const_tree t, cpp_operation op)
+cpp_check (tree t, cpp_operation op)
 {
   switch (op)
     {

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

end of thread, other threads:[~2014-01-20 10:19 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-10-23 19:14 C++ PATCH to deal with trivial but non-callable [cd]tors Jason Merrill
2013-10-23 19:16 ` Paolo Carlini
2013-10-25 19:04 ` Eric Botcazou
2013-10-25 19:27   ` Jason Merrill
2013-10-30 10:38     ` Eric Botcazou
2013-10-30 17:02       ` Jason Merrill
2013-10-30 19:22         ` Eric Botcazou
2013-10-31 15:15         ` Eric Botcazou
2013-10-31 16:27           ` Jason Merrill
2014-01-20 10:19           ` Eric Botcazou
2013-10-31 14:40     ` 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).