public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* C++/v3 PATCH for libstdc++/37907 (POD -> standard-layout/trivial)
@ 2009-07-16 21:00 Jason Merrill
  2010-03-11 21:21 ` H.J. Lu
  0 siblings, 1 reply; 2+ messages in thread
From: Jason Merrill @ 2009-07-16 21:00 UTC (permalink / raw)
  To: gcc-patches List, Benjamin Kosnik

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

Benjamin asked me to make PR 37907 a priority, and then the patch just 
kept growing...

This patch implements the changes in the language's notion of POD type 
from the N2230.  Basically, a POD is now a type which is both trivial 
(has trivial default init, copy init, copy assign and destructor) and 
standard-layout.  Pretty much everything in the standard that used to 
talk about POD type now either refers to one of those properties, or to 
a subset of the trivial conditions, typically either default 
init/destructor or copy init/destructor.

As a result, we now no longer give warnings/errors on a lot of cases 
where the language used to require them for no good reason, on offsetof, 
passing by ..., or jumping into scope of an object.  The ... case has 
changed from undefined to the new notion of conditionally-supported 
behavior, so I added a file to document our implementation choice while 
I was thinking about it.

We still retain the old notion of POD for use in class layout, as that 
is part of the ABI.  I renamed the macro so it's clear that it's only 
being used for that purpose.  __is_pod now gives the new definition.

libstdc++ folks: I'd think that the type_traits stuff should live in 
libsupc++ with the other compiler-interface bits; what do you think?

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


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

2009-07-16  Jason Merrill  <jason@redhat.com>

	PR libstdc++/37907
	Split POD into "standard-layout" and "trivial" as per N2230,
	Support std::is_standard_layout and std::is_trivial traits.
	* libstdc++-v3/include/std/type_traits: Add is_standard_layout, is_trivial.
	* gcc/c-common.c (c_common_reswords): Add __is_standard_layout
	and __is_trivial.
	* gcc/c-common.h (enum rid): Add RID_IS_STD_LAYOUT and RID_IS_TRIVIAL.
	* gcc/cp/cp-tree.h (enum cp_trait_kind): Add CPTK_IS_STD_LAYOUT,
	CPTK_IS_TRIVIAL.
	(struct lang_type_class): Add non_std_layout.
	(CLASSTYPE_NON_STD_LAYOUT): New.
	* gcc/cp/class.c (check_bases): Set it.
	(check_field_decls): Likewise.
	(check_bases_and_members): Likewise.
	* gcc/cp/parser.c (cp_parser_primary_expression): Handle RID_IS_STD_LAYOUT,
	RID_IS_TRIVIAL.
	(cp_parser_trait_expr): Likewise.
	* gcc/cp/semantics.c (trait_expr_value): Handle CPTK_IS_STD_LAYOUT,
	CPTK_IS_TRIVIAL.
	(finish_trait_expr): Likewise.
	* gcc/cp/tree.c (scalarish_type_p, trivial_type_p, std_layout_type_p): New.
	(pod_type_p): Use them.
	(type_has_nontrivial_copy_init, type_has_nontrivial_default_init): New.

	Adjust bits of the language that no longer refer to POD types.
	* gcc/cp/call.c (convert_arg_to_ellipsis): Use type_has_nontrivial_copy_init
	and TYPE_HAS_NONTRIVIAL_DESTRUCTOR rather than pod_type_p.
	(build_x_va_arg): Likewise.
	(call_builtin_trap): Remove.
	* gcc/doc/implement-cxx.texi: New.
	* gcc/doc/gcc.texi: Include it.
	* gcc/cp/decl.c (declare_local_label): Use type_has_nontrivial_default_init
	and TYPE_HAS_NONTRIVIAL_DESTRUCTOR rather than pod_type_p.
	(cp_finish_decl): Likewise.
	(check_previous_goto_1, check_goto): Adjust error.
	* gcc/cp/typeck.c (build_class_member_access_expr): Check
	CLASSTYPE_NON_STD_LAYOUT rather than CLASSTYPE_NON_POD_P.

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 11a4bcb..18f25d5 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -3777,7 +3777,7 @@ TEXI_GCC_FILES = gcc.texi gcc-common.texi gcc-vers.texi frontends.texi	\
 	 gcov.texi trouble.texi bugreport.texi service.texi		\
 	 contribute.texi compat.texi funding.texi gnu.texi gpl_v3.texi	\
 	 fdl.texi contrib.texi cppenv.texi cppopts.texi			\
-	 implement-c.texi arm-neon-intrinsics.texi
+	 implement-c.texi implement-cxx.texi arm-neon-intrinsics.texi
 
 TEXI_GCCINT_FILES = gccint.texi gcc-common.texi gcc-vers.texi		\
 	 contribute.texi makefile.texi configterms.texi options.texi	\
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 20dac6b..069452c 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -598,6 +598,8 @@ const struct c_common_resword c_common_reswords[] =
   { "__is_enum",	RID_IS_ENUM,	D_CXXONLY },
   { "__is_pod",		RID_IS_POD,	D_CXXONLY },
   { "__is_polymorphic",	RID_IS_POLYMORPHIC, D_CXXONLY },
+  { "__is_standard_layout", RID_IS_STD_LAYOUT, D_CXXONLY },
+  { "__is_trivial",     RID_IS_TRIVIAL, D_CXXONLY },
   { "__is_union",	RID_IS_UNION,	D_CXXONLY },
   { "__imag",		RID_IMAGPART,	0 },
   { "__imag__",		RID_IMAGPART,	0 },
diff --git a/gcc/c-common.h b/gcc/c-common.h
index 04a1945..ec5705e 100644
--- a/gcc/c-common.h
+++ b/gcc/c-common.h
@@ -110,6 +110,7 @@ enum rid
   RID_IS_CONVERTIBLE_TO,       RID_IS_CLASS,
   RID_IS_EMPTY,                RID_IS_ENUM,
   RID_IS_POD,                  RID_IS_POLYMORPHIC,
+  RID_IS_STD_LAYOUT,           RID_IS_TRIVIAL,
   RID_IS_UNION,
 
   /* C++0x */
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 588c997..6a7a1b8 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -197,7 +197,6 @@ static conversion *direct_reference_binding (tree, conversion *);
 static bool promoted_arithmetic_type_p (tree);
 static conversion *conditional_conversion (tree, tree);
 static char *name_as_c_string (tree, tree, bool *);
-static tree call_builtin_trap (void);
 static tree prep_operand (tree);
 static void add_candidates (tree, const VEC(tree,gc) *, tree, bool, tree, tree,
 			    int, struct z_candidate **);
@@ -5042,18 +5041,6 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
   return expr;
 }
 
-/* Build a call to __builtin_trap.  */
-
-static tree
-call_builtin_trap (void)
-{
-  tree fn = implicit_built_in_decls[BUILT_IN_TRAP];
-
-  gcc_assert (fn != NULL);
-  fn = build_call_n (fn, 0);
-  return fn;
-}
-
 /* ARG is being passed to a varargs function.  Perform any conversions
    required.  Return the converted value.  */
 
@@ -5082,20 +5069,23 @@ convert_arg_to_ellipsis (tree arg)
   arg = require_complete_type (arg);
 
   if (arg != error_mark_node
-      && !pod_type_p (TREE_TYPE (arg)))
+      && (type_has_nontrivial_copy_init (TREE_TYPE (arg))
+	  || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (arg))))
     {
-      /* Undefined behavior [expr.call] 5.2.2/7.  We used to just warn
-	 here and do a bitwise copy, but now cp_expr_size will abort if we
-	 try to do that.
+      /* [expr.call] 5.2.2/7:
+	 Passing a potentially-evaluated argument of class type (Clause 9)
+	 with a non-trivial copy constructor or a non-trivial destructor
+	 with no corresponding parameter is conditionally-supported, with
+	 implementation-defined semantics.
+
+	 We used to just warn here and do a bitwise copy, but now
+	 cp_expr_size will abort if we try to do that.
+
 	 If the call appears in the context of a sizeof expression,
-	 there is no need to emit a warning, since the expression won't be
-	 evaluated. We keep the builtin_trap just as a safety check.  */
+	 it is not potentially-evaluated.  */
       if (cp_unevaluated_operand == 0)
-	warning (0, "cannot pass objects of non-POD type %q#T through %<...%>; "
-		 "call will abort at runtime", TREE_TYPE (arg));
-      arg = call_builtin_trap ();
-      arg = build2 (COMPOUND_EXPR, integer_type_node, arg,
-		    integer_zero_node);
+	error ("cannot pass objects of non-trivially-copyable "
+	       "type %q#T through %<...%>", TREE_TYPE (arg));
     }
 
   return arg;
@@ -5114,16 +5104,16 @@ build_x_va_arg (tree expr, tree type)
   if (expr == error_mark_node || !type)
     return error_mark_node;
 
-  if (! pod_type_p (type))
+  if (type_has_nontrivial_copy_init (type)
+      || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
+      || TREE_CODE (type) == REFERENCE_TYPE)
     {
       /* Remove reference types so we don't ICE later on.  */
       tree type1 = non_reference (type);
-      /* Undefined behavior [expr.call] 5.2.2/7.  */
-      warning (0, "cannot receive objects of non-POD type %q#T through %<...%>; "
-	       "call will abort at runtime", type);
+      /* conditionally-supported behavior [expr.call] 5.2.2/7.  */
+      error ("cannot receive objects of non-trivially-copyable type %q#T "
+	     "through %<...%>; ", type);
       expr = convert (build_pointer_type (type1), null_node);
-      expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr),
-		     call_builtin_trap (), expr);
       expr = cp_build_indirect_ref (expr, NULL, tf_warning_or_error);
       return expr;
     }
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 4668c68..373f457 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -1248,9 +1248,15 @@ check_bases (tree t,
   int seen_non_virtual_nearly_empty_base_p;
   tree base_binfo;
   tree binfo;
+  tree field = NULL_TREE;
 
   seen_non_virtual_nearly_empty_base_p = 0;
 
+  if (!CLASSTYPE_NON_STD_LAYOUT (t))
+    for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
+      if (TREE_CODE (field) == FIELD_DECL)
+	break;
+
   for (binfo = TYPE_BINFO (t), i = 0;
        BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
     {
@@ -1305,6 +1311,36 @@ check_bases (tree t,
       CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t)
 	|= CLASSTYPE_CONTAINS_EMPTY_CLASS_P (basetype);
       TYPE_HAS_COMPLEX_DFLT (t) |= TYPE_HAS_COMPLEX_DFLT (basetype);      
+
+      /*  A standard-layout class is a class that:
+	  ...
+	  * has no non-standard-layout base classes,  */
+      CLASSTYPE_NON_STD_LAYOUT (t) |= CLASSTYPE_NON_STD_LAYOUT (basetype);
+      if (!CLASSTYPE_NON_STD_LAYOUT (t))
+	{
+	  tree basefield;
+	  /* ...has no base classes of the same type as the first non-static
+	     data member...  */
+	  if (field && DECL_CONTEXT (field) == t
+	      && (same_type_ignoring_top_level_qualifiers_p
+		  (TREE_TYPE (field), basetype)))
+	    CLASSTYPE_NON_STD_LAYOUT (t) = 1;
+	  else
+	    /* ...either has no non-static data members in the most-derived
+	       class and at most one base class with non-static data
+	       members, or has no base classes with non-static data
+	       members */
+	    for (basefield = TYPE_FIELDS (basetype); basefield;
+		 basefield = TREE_CHAIN (basefield))
+	      if (TREE_CODE (basefield) == FIELD_DECL)
+		{
+		  if (field)
+		    CLASSTYPE_NON_STD_LAYOUT (t) = 1;
+		  else
+		    field = basefield;
+		  break;
+		}
+	}
     }
 }
 
@@ -2870,6 +2906,7 @@ check_field_decls (tree t, tree *access_decls,
   bool has_pointers;
   int any_default_members;
   int cant_pack = 0;
+  int field_access = -1;
 
   /* Assume there are no access declarations.  */
   *access_decls = NULL_TREE;
@@ -2883,6 +2920,7 @@ check_field_decls (tree t, tree *access_decls,
     {
       tree x = *field;
       tree type = TREE_TYPE (x);
+      int this_field_access;
 
       next = &TREE_CHAIN (x);
 
@@ -2957,10 +2995,21 @@ check_field_decls (tree t, tree *access_decls,
       if (TREE_PRIVATE (x) || TREE_PROTECTED (x))
 	CLASSTYPE_NON_AGGREGATE (t) = 1;
 
+      /* A standard-layout class is a class that:
+	 ...
+	 has the same access control (Clause 11) for all non-static data members,
+         ...  */
+      this_field_access = TREE_PROTECTED (x) ? 1 : TREE_PRIVATE (x) ? 2 : 0;
+      if (field_access == -1)
+	field_access = this_field_access;
+      else if (this_field_access != field_access)
+	CLASSTYPE_NON_STD_LAYOUT (t) = 1;
+
       /* If this is of reference type, check if it needs an init.  */
       if (TREE_CODE (type) == REFERENCE_TYPE)
 	{
-	  CLASSTYPE_NON_POD_P (t) = 1;
+	  CLASSTYPE_NON_LAYOUT_POD_P (t) = 1;
+	  CLASSTYPE_NON_STD_LAYOUT (t) = 1;
 	  if (DECL_INITIAL (x) == NULL_TREE)
 	    SET_CLASSTYPE_REF_FIELDS_NEED_INIT (t, 1);
 
@@ -2975,7 +3024,7 @@ check_field_decls (tree t, tree *access_decls,
 
       if (TYPE_PACKED (t))
 	{
-	  if (!pod_type_p (type) && !TYPE_PACKED (type))
+	  if (!layout_pod_type_p (type) && !TYPE_PACKED (type))
 	    {
 	      warning
 		(0,
@@ -3024,10 +3073,13 @@ check_field_decls (tree t, tree *access_decls,
       if (DECL_MUTABLE_P (x) || TYPE_HAS_MUTABLE_P (type))
 	CLASSTYPE_HAS_MUTABLE (t) = 1;
 
-      if (! pod_type_p (type))
+      if (! layout_pod_type_p (type))
 	/* DR 148 now allows pointers to members (which are POD themselves),
 	   to be allowed in POD structs.  */
-	CLASSTYPE_NON_POD_P (t) = 1;
+	CLASSTYPE_NON_LAYOUT_POD_P (t) = 1;
+
+      if (!std_layout_type_p (type))
+	CLASSTYPE_NON_STD_LAYOUT (t) = 1;
 
       if (! zero_init_p (type))
 	CLASSTYPE_NON_ZERO_INIT_P (t) = 1;
@@ -4280,7 +4332,7 @@ type_requires_array_cookie (tree type)
 /* Check the validity of the bases and members declared in T.  Add any
    implicitly-generated functions (like copy-constructors and
    assignment operators).  Compute various flag bits (like
-   CLASSTYPE_NON_POD_T) for T.  This routine works purely at the C++
+   CLASSTYPE_NON_LAYOUT_POD_T) for T.  This routine works purely at the C++
    level: i.e., independently of the ABI in use.  */
 
 static void
@@ -4346,9 +4398,12 @@ check_bases_and_members (tree t)
      elsewhere.  */
   CLASSTYPE_NON_AGGREGATE (t)
     |= (type_has_user_provided_constructor (t) || TYPE_POLYMORPHIC_P (t));
-  CLASSTYPE_NON_POD_P (t)
+  /* This is the C++98/03 definition of POD; it changed in C++0x, but we
+     retain the old definition internally for ABI reasons.  */
+  CLASSTYPE_NON_LAYOUT_POD_P (t)
     |= (CLASSTYPE_NON_AGGREGATE (t)
 	|| saved_nontrivial_dtor || saved_complex_asn_ref);
+  CLASSTYPE_NON_STD_LAYOUT (t) |= TYPE_CONTAINS_VPTR_P (t);
   TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_CONTAINS_VPTR_P (t);
   TYPE_HAS_COMPLEX_DFLT (t) |= TYPE_CONTAINS_VPTR_P (t);
 
@@ -5031,7 +5086,7 @@ layout_class_type (tree t, tree *virtuals_p)
   /* Create the version of T used for virtual bases.  We do not use
      make_class_type for this version; this is an artificial type.  For
      a POD type, we just reuse T.  */
-  if (CLASSTYPE_NON_POD_P (t) || CLASSTYPE_EMPTY_P (t))
+  if (CLASSTYPE_NON_LAYOUT_POD_P (t) || CLASSTYPE_EMPTY_P (t))
     {
       base_t = make_node (TREE_CODE (t));
 
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 933da19..6ad039a 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -494,6 +494,8 @@ typedef enum cp_trait_kind
   CPTK_IS_ENUM,
   CPTK_IS_POD,
   CPTK_IS_POLYMORPHIC,
+  CPTK_IS_STD_LAYOUT,
+  CPTK_IS_TRIVIAL,
   CPTK_IS_UNION
 } cp_trait_kind;
 
@@ -1124,6 +1126,7 @@ struct GTY(()) lang_type_class {
   unsigned non_aggregate : 1;
   unsigned has_complex_dflt : 1;
   unsigned has_list_ctor : 1;
+  unsigned non_std_layout : 1;
 
   /* When adding a flag here, consider whether or not it ought to
      apply to a template instance if it applies to the template.  If
@@ -1132,7 +1135,7 @@ struct GTY(()) lang_type_class {
   /* There are some bits left to fill out a 32-bit word.  Keep track
      of this by updating the size of this bitfield whenever you add or
      remove a flag.  */
-  unsigned dummy : 10;
+  unsigned dummy : 9;
 
   tree primary_base;
   VEC(tree_pair_s,gc) *vcall_indices;
@@ -1385,8 +1388,14 @@ struct GTY(()) lang_type {
 #define CLASSTYPE_HAS_MUTABLE(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_mutable)
 #define TYPE_HAS_MUTABLE_P(NODE) (cp_has_mutable_p (NODE))
 
-/* Nonzero means that this class type is a non-POD class.  */
-#define CLASSTYPE_NON_POD_P(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->non_pod_class)
+/* Nonzero means that this class type is not POD for the purpose of layout
+   (as defined in the ABI).  This is different from the language's POD.  */
+#define CLASSTYPE_NON_LAYOUT_POD_P(NODE) \
+  (LANG_TYPE_CLASS_CHECK (NODE)->non_pod_class)
+
+/* Nonzero means that this class type is a non-standard-layout class.  */
+#define CLASSTYPE_NON_STD_LAYOUT(NODE) \
+  (LANG_TYPE_CLASS_CHECK (NODE)->non_std_layout)
 
 /* Nonzero means that this class contains pod types whose default
    initialization is not a zero initialization (namely, pointers to
@@ -4877,7 +4886,12 @@ extern void stabilize_aggr_init			(tree, tree *);
 extern bool stabilize_init			(tree, tree *);
 extern tree add_stmt_to_compound		(tree, tree);
 extern void init_tree				(void);
-extern int pod_type_p				(const_tree);
+extern bool pod_type_p				(const_tree);
+extern bool layout_pod_type_p			(const_tree);
+extern bool std_layout_type_p			(const_tree);
+extern bool trivial_type_p			(const_tree);
+extern bool type_has_nontrivial_default_init	(const_tree);
+extern bool type_has_nontrivial_copy_init	(const_tree);
 extern bool class_tmpl_impl_spec_p		(const_tree);
 extern int zero_init_p				(const_tree);
 extern tree strip_typedefs			(tree);
diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
index b873289..0b13bc1 100644
--- a/gcc/cp/cxx-pretty-print.c
+++ b/gcc/cp/cxx-pretty-print.c
@@ -2296,6 +2296,12 @@ pp_cxx_trait_expression (cxx_pretty_printer *pp, tree t)
     case CPTK_IS_POLYMORPHIC:
       pp_cxx_ws_string (pp, "__is_polymorphic");
       break;
+    case CPTK_IS_STD_LAYOUT:
+      pp_cxx_ws_string (pp, "__is_std_layout");
+      break;
+    case CPTK_IS_TRIVIAL:
+      pp_cxx_ws_string (pp, "__is_trivial");
+      break;
     case CPTK_IS_UNION:
       pp_cxx_ws_string (pp, "__is_union");
       break;
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index e1b6678..e65e636 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -2473,20 +2473,28 @@ declare_local_label (tree id)
 static int
 decl_jump_unsafe (tree decl)
 {
+  /* [stmt.dcl]/3: A program that jumps from a point where a local variable
+     with automatic storage duration is not in scope to a point where it is
+     in scope is ill-formed unless the variable has scalar type, class type
+     with a trivial default constructor and a trivial destructor, a
+     cv-qualified version of one of these types, or an array of one of the
+     preceding types and is declared without an initializer (8.5).  */
+  tree type = TREE_TYPE (decl);
+
   if (TREE_CODE (decl) != VAR_DECL || TREE_STATIC (decl)
-      || TREE_TYPE (decl) == error_mark_node)
+      || type == error_mark_node)
     return 0;
 
-  if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
+  type = strip_array_types (type);
+
+  if (type_has_nontrivial_default_init (TREE_TYPE (decl))
       || DECL_NONTRIVIALLY_INITIALIZED_P (decl))
     return 2;
 
-  if (pod_type_p (TREE_TYPE (decl)))
-    return 0;
+  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
+    return 1;
 
-  /* The POD stuff is just pedantry; why should it matter if the class
-     contains a field of pointer to member type?  */
-  return 1;
+  return 0;
 }
 
 /* A subroutine of check_previous_goto_1 to identify a branch to the user.  */
@@ -2541,7 +2549,8 @@ check_previous_goto_1 (tree decl, struct cp_binding_level* level, tree names,
 	  if (problem > 1)
 	    error ("  crosses initialization of %q+#D", new_decls);
 	  else
-	    permerror (input_location, "  enters scope of non-POD %q+#D", new_decls);
+	    permerror (input_location, "  enters scope of %q+#D which has "
+		       "non-trivial destructor", new_decls);
 	}
 
       if (b == level)
@@ -2656,7 +2665,8 @@ check_goto (tree decl)
       else if (u > 1)
 	error ("  skips initialization of %q+#D", b);
       else
-	permerror (input_location, "  enters scope of non-POD %q+#D", b);
+	permerror (input_location, "  enters scope of %q+#D which has "
+		   "non-trivial destructor", b);
     }
 
   if (ent->in_try_scope)
@@ -5687,11 +5697,13 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
 
   if (TREE_CODE (decl) == VAR_DECL)
     {
-      /* Only PODs can have thread-local storage.  Other types may require
-	 various kinds of non-trivial initialization.  */
-      if (DECL_THREAD_LOCAL_P (decl) && !pod_type_p (TREE_TYPE (decl)))
-	error ("%qD cannot be thread-local because it has non-POD type %qT",
-	       decl, TREE_TYPE (decl));
+      /* Only variables with trivial initialization and destruction can
+	 have thread-local storage.  */
+      if (DECL_THREAD_LOCAL_P (decl)
+	  && (type_has_nontrivial_default_init (TREE_TYPE (decl))
+	      || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (decl))))
+	error ("%qD cannot be thread-local because it has non-trivial "
+	       "type %qT", decl, TREE_TYPE (decl));
       /* If this is a local variable that will need a mangled name,
 	 register it now.  We must do this before processing the
 	 initializer for the variable, since the initialization might
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 19b2489..9118c61 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -2703,7 +2703,7 @@ build_vec_init (tree base, tree maxindex, tree init,
 	       || ! TYPE_HAS_NONTRIVIAL_DESTRUCTOR (inner_elt_type)))
 	  || from_array))
     {
-      /* Do non-default initialization of POD arrays resulting from
+      /* Do non-default initialization of trivial arrays resulting from
 	 brace-enclosed initializers.  In this case, digest_init and
 	 store_constructor will handle the semantics for us.  */
 
@@ -2769,7 +2769,7 @@ build_vec_init (tree base, tree maxindex, tree init,
 
   if (init != NULL_TREE && TREE_CODE (init) == CONSTRUCTOR)
     {
-      /* Do non-default initialization of non-POD arrays resulting from
+      /* Do non-default initialization of non-trivial arrays resulting from
 	 brace-enclosed initializers.  */
       unsigned HOST_WIDE_INT idx;
       tree elt;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 94fba02..e64d0bf 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -3399,6 +3399,8 @@ cp_parser_primary_expression (cp_parser *parser,
 	case RID_IS_ENUM:
 	case RID_IS_POD:
 	case RID_IS_POLYMORPHIC:
+	case RID_IS_STD_LAYOUT:
+	case RID_IS_TRIVIAL:
 	case RID_IS_UNION:
 	  return cp_parser_trait_expr (parser, token->keyword);
 
@@ -6865,6 +6867,12 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
     case RID_IS_POLYMORPHIC:
       kind = CPTK_IS_POLYMORPHIC;
       break;
+    case RID_IS_STD_LAYOUT:
+      kind = CPTK_IS_STD_LAYOUT;
+      break;
+    case RID_IS_TRIVIAL:
+      kind = CPTK_IS_TRIVIAL;
+      break;
     case RID_IS_UNION:
       kind = CPTK_IS_UNION;
       break;
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 61dff51..4473c49 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -4878,6 +4878,7 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
   switch (kind)
     {
     case CPTK_HAS_NOTHROW_ASSIGN:
+      type1 = strip_array_types (type1);
       return (!CP_TYPE_CONST_P (type1) && type_code1 != REFERENCE_TYPE
 	      && (trait_expr_value (CPTK_HAS_TRIVIAL_ASSIGN, type1, type2)
 		  || (CLASS_TYPE_P (type1)
@@ -4885,8 +4886,11 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
 								 true))));
 
     case CPTK_HAS_TRIVIAL_ASSIGN:
+      /* ??? The standard seems to be missing the "or array of such a class
+	 type" wording for this trait.  */
+      type1 = strip_array_types (type1);
       return (!CP_TYPE_CONST_P (type1) && type_code1 != REFERENCE_TYPE
-	      && (pod_type_p (type1)
+	      && (trivial_type_p (type1)
 		    || (CLASS_TYPE_P (type1)
 			&& TYPE_HAS_TRIVIAL_ASSIGN_REF (type1))));
 
@@ -4899,21 +4903,25 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
 
     case CPTK_HAS_TRIVIAL_CONSTRUCTOR:
       type1 = strip_array_types (type1);
-      return (pod_type_p (type1)
+      return (trivial_type_p (type1)
 	      || (CLASS_TYPE_P (type1) && TYPE_HAS_TRIVIAL_DFLT (type1)));
 
     case CPTK_HAS_NOTHROW_COPY:
+      type1 = strip_array_types (type1);
       return (trait_expr_value (CPTK_HAS_TRIVIAL_COPY, type1, type2)
 	      || (CLASS_TYPE_P (type1)
 		  && classtype_has_nothrow_assign_or_copy_p (type1, false)));
 
     case CPTK_HAS_TRIVIAL_COPY:
-      return (pod_type_p (type1) || type_code1 == REFERENCE_TYPE
+      /* ??? The standard seems to be missing the "or array of such a class
+	 type" wording for this trait.  */
+      type1 = strip_array_types (type1);
+      return (trivial_type_p (type1) || type_code1 == REFERENCE_TYPE
 	      || (CLASS_TYPE_P (type1) && TYPE_HAS_TRIVIAL_INIT_REF (type1)));
 
     case CPTK_HAS_TRIVIAL_DESTRUCTOR:
       type1 = strip_array_types (type1);
-      return (pod_type_p (type1) || type_code1 == REFERENCE_TYPE
+      return (trivial_type_p (type1) || type_code1 == REFERENCE_TYPE
 	      || (CLASS_TYPE_P (type1)
 		  && TYPE_HAS_TRIVIAL_DESTRUCTOR (type1)));
 
@@ -4947,6 +4955,12 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_POLYMORPHIC:
       return (CLASS_TYPE_P (type1) && TYPE_POLYMORPHIC_P (type1));
 
+    case CPTK_IS_STD_LAYOUT:
+      return (std_layout_type_p (type1));
+
+    case CPTK_IS_TRIVIAL:
+      return (trivial_type_p (type1));
+
     case CPTK_IS_UNION:
       return (type_code1 == UNION_TYPE);
 
@@ -4995,6 +5009,8 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
 	      || kind == CPTK_IS_ENUM
 	      || kind == CPTK_IS_POD
 	      || kind == CPTK_IS_POLYMORPHIC
+	      || kind == CPTK_IS_STD_LAYOUT
+	      || kind == CPTK_IS_TRIVIAL
 	      || kind == CPTK_IS_UNION);
 
   if (kind == CPTK_IS_CONVERTIBLE_TO)
@@ -5036,6 +5052,8 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_EMPTY:
     case CPTK_IS_POD:
     case CPTK_IS_POLYMORPHIC:
+    case CPTK_IS_STD_LAYOUT:
+    case CPTK_IS_TRIVIAL:
       if (!check_trait_type (type1))
 	{
 	  error ("incomplete type %qT not allowed", type1);
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index a003b44..255a297 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -2238,36 +2238,108 @@ is_dummy_object (const_tree ob)
 	  && TREE_OPERAND (ob, 0) == void_zero_node);
 }
 
+/* Returns 1 iff type T is something we want to treat as a scalar type for
+   the purpose of deciding whether it is trivial/POD/standard-layout.  */
+
+static bool
+scalarish_type_p (const_tree t)
+{
+  if (t == error_mark_node)
+    return 1;
+
+  return (SCALAR_TYPE_P (t)
+	  || TREE_CODE (t) == VECTOR_TYPE);
+}
+
+/* Returns true iff T requires non-trivial default initialization.  */
+
+bool
+type_has_nontrivial_default_init (const_tree t)
+{
+  t = strip_array_types (CONST_CAST_TREE (t));
+
+  if (CLASS_TYPE_P (t))
+    return TYPE_HAS_COMPLEX_DFLT (t);
+  else
+    return 0;
+}
+
+/* Returns true iff copying an object of type T is non-trivial.  */
+
+bool
+type_has_nontrivial_copy_init (const_tree t)
+{
+  t = strip_array_types (CONST_CAST_TREE (t));
+
+  if (CLASS_TYPE_P (t))
+    return TYPE_HAS_COMPLEX_INIT_REF (t);
+  else
+    return 0;
+}
+
+/* Returns 1 iff type T is a trivial type, as defined in [basic.types].  */
+
+bool
+trivial_type_p (const_tree t)
+{
+  t = strip_array_types (CONST_CAST_TREE (t));
+
+  if (CLASS_TYPE_P (t))
+    return !(TYPE_HAS_COMPLEX_DFLT (t)
+	     || TYPE_HAS_COMPLEX_INIT_REF (t)
+	     || TYPE_HAS_COMPLEX_ASSIGN_REF (t)
+	     || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t));
+  else
+    return scalarish_type_p (t);
+}
+
 /* Returns 1 iff type T is a POD type, as defined in [basic.types].  */
 
-int
+bool
 pod_type_p (const_tree t)
 {
   /* This CONST_CAST is okay because strip_array_types returns its
      argument unmodified and we assign it to a const_tree.  */
   t = strip_array_types (CONST_CAST_TREE(t));
 
-  if (t == error_mark_node)
-    return 1;
-  if (INTEGRAL_OR_ENUMERATION_TYPE_P (t))
-    return 1;  /* integral, character or enumeral type */
-  if (FLOAT_TYPE_P (t))
-    return 1;
-  if (TYPE_PTR_P (t))
-    return 1; /* pointer to non-member */
-  if (TYPE_PTR_TO_MEMBER_P (t))
-    return 1; /* pointer to member */
-
-  if (TREE_CODE (t) == VECTOR_TYPE)
-    return 1; /* vectors are (small) arrays of scalars */
-
-  if (! RECORD_OR_UNION_CODE_P (TREE_CODE (t)))
-    return 0; /* other non-class type (reference or function) */
-  if (! CLASS_TYPE_P (t))
-    return 1; /* struct created by the back end */
-  if (CLASSTYPE_NON_POD_P (t))
-    return 0;
-  return 1;
+  if (CLASS_TYPE_P (t))
+    /* [class]/10: A POD struct is a class that is both a trivial class and a
+       standard-layout class, and has no non-static data members of type
+       non-POD struct, non-POD union (or array of such types).
+
+       We don't need to check individual members because if a member is
+       non-std-layout or non-trivial, the class will be too.  */
+    return (std_layout_type_p (t) && trivial_type_p (t));
+  else
+    return scalarish_type_p (t);
+}
+
+/* Returns true iff T is POD for the purpose of layout, as defined in the
+   C++ ABI.  */
+
+bool
+layout_pod_type_p (const_tree t)
+{
+  t = strip_array_types (CONST_CAST_TREE (t));
+
+  if (CLASS_TYPE_P (t))
+    return !CLASSTYPE_NON_LAYOUT_POD_P (t);
+  else
+    return scalarish_type_p (t);
+}
+
+/* Returns true iff T is a standard-layout type, as defined in
+   [basic.types].  */
+
+bool
+std_layout_type_p (const_tree t)
+{
+  t = strip_array_types (CONST_CAST_TREE (t));
+
+  if (CLASS_TYPE_P (t))
+    return !CLASSTYPE_NON_STD_LAYOUT (t);
+  else
+    return scalarish_type_p (t);
 }
 
 /* Nonzero iff type T is a class template implicit specialization.  */
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 6a4802e..9e49ce5 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -2017,7 +2017,7 @@ build_class_member_access_expr (tree object, tree member,
 	 in various testsuite cases where a null object is passed where a
 	 vtable access is required.  */
       if (null_object_p && warn_invalid_offsetof
-	  && CLASSTYPE_NON_POD_P (object_type)
+	  && CLASSTYPE_NON_STD_LAYOUT (object_type)
 	  && !DECL_FIELD_IS_BASE (member)
 	  && cp_unevaluated_operand == 0
 	  && (complain & tf_warning))
@@ -3134,7 +3134,7 @@ convert_arguments (tree typelist, VEC(tree,gc) **values, tree fndecl,
 	  if (fndecl && DECL_BUILT_IN (fndecl)
 	      && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CONSTANT_P)
 	    /* Don't do ellipsis conversion for __built_in_constant_p
-	       as this will result in spurious warnings for non-POD
+	       as this will result in spurious errors for non-trivial
 	       types.  */
 	    val = require_complete_type (val);
 	  else
diff --git a/gcc/doc/gcc.texi b/gcc/doc/gcc.texi
index 4103175..34b8963 100644
--- a/gcc/doc/gcc.texi
+++ b/gcc/doc/gcc.texi
@@ -134,6 +134,7 @@ Introduction, gccint, GNU Compiler Collection (GCC) Internals}.
 * Invoking GCC::    Command options supported by @samp{gcc}.
 * C Implementation:: How GCC implements the ISO C specification.
 * C Extensions::    GNU extensions to the C language family.
+* C++ Implementation:: How GCC implements the ISO C++ specification.
 * C++ Extensions::  GNU extensions to the C++ language.
 * Objective-C::     GNU Objective-C runtime features.
 * Compatibility::   Binary Compatibility
@@ -159,6 +160,7 @@ Introduction, gccint, GNU Compiler Collection (GCC) Internals}.
 @include standards.texi
 @include invoke.texi
 @include implement-c.texi
+@include implement-cxx.texi
 @include extend.texi
 @include objc.texi
 @include compat.texi
diff --git a/gcc/doc/implement-cxx.texi b/gcc/doc/implement-cxx.texi
new file mode 100644
index 0000000..9968f59
--- /dev/null
+++ b/gcc/doc/implement-cxx.texi
@@ -0,0 +1,47 @@
+@c Copyright (C) 2009
+@c Free Software Foundation, Inc.
+@c This is part of the GCC manual.
+@c For copying conditions, see the file gcc.texi.
+
+@node C++ Implementation
+@chapter C++ Implementation-defined behavior
+@cindex implementation-defined behavior, C++ language
+
+A conforming implementation of ISO C++ is required to document its
+choice of behavior in each of the areas that are designated
+``implementation defined''.  The following lists all such areas,
+along with the section numbers from the ISO/IEC 14822:1998 and ISO/IEC
+14822:2003 standards.  Some areas are only implementation-defined in
+one version of the standard.
+
+Some choices depend on the externally determined ABI for the platform
+(including standard character encodings) which GCC follows; these are
+listed as ``determined by ABI'' below.  @xref{Compatibility, , Binary
+Compatibility}, and @uref{http://gcc.gnu.org/readings.html}.  Some
+choices are documented in the preprocessor manual.
+@xref{Implementation-defined behavior, , Implementation-defined
+behavior, cpp, The C Preprocessor}.  Some choices are documented in
+the corresponding document for the C language.  @xref{C
+Implementation}.  Some choices are made by the library and operating
+system (or other environment when compiling for a freestanding
+environment); refer to their documentation for details.
+
+@menu
+* Conditionally-supported behavior::
+@end menu
+
+@node Conditionally-supported behavior
+@section Conditionally-supported behavior
+
+@cite{Each implementation shall include documentation that identifies
+all conditionally-supported constructs that it does not support (C++0x
+1.4).}
+
+@itemize @bullet
+@item
+@cite{Whether an argument of class type with a non-trivial copy
+constructor or destructor can be passed to ... (C++0x 5.2.2).}
+
+Such argument passing is not supported.
+
+@end itemize
diff --git a/gcc/testsuite/g++.dg/cpp0x/std-layout1.C b/gcc/testsuite/g++.dg/cpp0x/std-layout1.C
new file mode 100644
index 0000000..bdad821
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/std-layout1.C
@@ -0,0 +1,91 @@
+// { dg-options "-std=c++0x" }
+
+// [basic.types]/10:
+// Scalar types, standard-layout class types (Clause 9), arrays of such
+// types and cv-qualified versions of these types (3.9.3) are collectively
+// called standard-layout types.
+
+// [class]/7:
+// A standard-layout class is a class that:
+// * has no non-static data members of type non-standard-layout class (or
+// array of such types) or reference,
+// * has no virtual functions (10.3) and no virtual base classes (10.1),
+// * has the same access control (Clause 11) for all non-static data members,
+// * has no non-standard-layout base classes,
+// * either has no non-static data members in the most-derived class and at
+// most one base class with non-static data members, or has no base classes
+// with non-static data members, and
+// * has no base classes of the same type as the first non-static data member.
+
+#include <type_traits>
+
+#define TRY(expr) static_assert (expr, #expr)
+#define YES(type) TRY(std::is_standard_layout<type>::value); \
+  TRY(std::is_standard_layout<type[]>::value); \
+  TRY(std::is_standard_layout<const volatile type>::value);
+#define NO(type) TRY(!std::is_standard_layout<type>::value); \
+  TRY(!std::is_standard_layout<type[]>::value); \
+  TRY(!std::is_standard_layout<const volatile type>::value);
+#define NONPOD(type) TRY(!std::is_pod<type>::value); \
+  TRY(!std::is_pod<type[]>::value); \
+  TRY(!std::is_pod<const volatile type>::value);
+
+struct A;
+
+YES(int);
+YES(__complex int);
+YES(void *);
+YES(int A::*);
+typedef int (A::*pmf)();
+YES(pmf);
+
+struct A { ~A(); };
+YES(A);
+NONPOD(A);
+struct F: public A { int i; };
+YES(F);
+NONPOD(F);
+struct G: public A { A a; };
+NO(G);
+struct M { A a; };
+YES(M);
+
+class B
+{
+  int i;
+  __complex int c;
+  void *p;
+  double ar[4];
+  int A::* pm;
+  int (A::*pmf)();
+};
+YES(B);
+struct D: public B { };
+YES(D);
+struct E: public B { int q; };
+NO(E);
+struct D2: public B { };
+YES(D2);
+struct I: public D, public D2 { };
+NO(I);
+
+struct C
+{
+  int i;
+private:
+  int j;
+};
+NO(C);
+struct H: public C { };
+NO(H);
+struct N { C c; };
+NO(N);
+
+struct J { virtual void f(); };
+struct J2: J { };
+NO(J);
+NO(J2);
+struct K { };
+struct L: virtual K {};
+YES(K);
+NO(L);
diff --git a/gcc/testsuite/g++.dg/cpp0x/trivial1.C b/gcc/testsuite/g++.dg/cpp0x/trivial1.C
new file mode 100644
index 0000000..62173ac
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/trivial1.C
@@ -0,0 +1,82 @@
+// { dg-options "-std=c++0x" }
+
+// [basic.types]/10:
+// Scalar types, trivial class types (Clause 9), arrays of such types and
+// cv-qualified versions of these types (3.9.3) are collectively called
+// trivial types.
+
+// [class]/6:
+// A trivially copyable class is a class that:
+// * has no non-trivial copy constructors (12.8),
+// * has no non-trivial copy assignment operators (13.5.3, 12.8), and
+// * has a trivial destructor (12.4).
+// A trivial class is a class that has a trivial default constructor (12.1)
+// and is trivially copyable.
+
+#include <type_traits>
+
+#define TRY(expr) static_assert (expr, #expr)
+#define YES(type) TRY(std::is_trivial<type>::value); \
+  TRY(std::is_trivial<type[]>::value); \
+  TRY(std::is_trivial<const volatile type>::value);
+#define NO(type) TRY(!std::is_trivial<type>::value); \
+  TRY(!std::is_trivial<type[]>::value); \
+  TRY(!std::is_trivial<const volatile type>::value);
+
+struct A;
+
+YES(int);
+YES(__complex int);
+YES(void *);
+YES(int A::*);
+typedef int (A::*pmf)();
+YES(pmf);
+
+struct A { ~A(); };
+NO(A);
+struct F: public A { int i; };
+NO(F);
+struct G: public A { A a; };
+NO(G);
+struct M { A a; };
+NO(M);
+
+class B
+{
+  int i;
+  __complex int c;
+  void *p;
+  double ar[4];
+  int A::* pm;
+  int (A::*pmf)();
+};
+YES(B);
+struct D: public B { };
+YES(D);
+struct E: public B { int q; };
+YES(E);
+struct D2: public B { };
+YES(D2);
+struct I: public D, public D2 { };
+YES(I);
+
+struct C
+{
+  int i;
+private:
+  int j;
+};
+YES(C);
+struct H: public C { };
+YES(H);
+struct N { C c; };
+YES(N);
+
+struct J { virtual void f(); };
+struct J2: J { };
+NO(J);
+NO(J2);
+struct K { };
+struct L: virtual K {};
+YES(K);
+NO(L);
diff --git a/gcc/testsuite/g++.dg/ext/has_nothrow_assign.C b/gcc/testsuite/g++.dg/ext/has_nothrow_assign.C
index 73a904e..f3b4a8b 100644
--- a/gcc/testsuite/g++.dg/ext/has_nothrow_assign.C
+++ b/gcc/testsuite/g++.dg/ext/has_nothrow_assign.C
@@ -134,7 +134,7 @@ int main()
   assert (PTEST (A));
   assert (PTEST (B));
   assert (PTEST (C));
-  assert (NTEST (C[]));
+  assert (PTEST (C[]));
   assert (PTEST (D));
   assert (NTEST (E));
   assert (NTEST (E1));
diff --git a/gcc/testsuite/g++.dg/ext/has_nothrow_copy-1.C b/gcc/testsuite/g++.dg/ext/has_nothrow_copy-1.C
index e8507cf..056c9be 100644
--- a/gcc/testsuite/g++.dg/ext/has_nothrow_copy-1.C
+++ b/gcc/testsuite/g++.dg/ext/has_nothrow_copy-1.C
@@ -124,7 +124,7 @@ int main()
   assert (PTEST (A));
   assert (PTEST (B));
   assert (PTEST (C));
-  assert (NTEST (C[]));
+  assert (PTEST (C[]));
   assert (PTEST (D));
   assert (NTEST (E));
   assert (NTEST (E1));
diff --git a/gcc/testsuite/g++.dg/ext/has_trivial_assign.C b/gcc/testsuite/g++.dg/ext/has_trivial_assign.C
index 97bcbf2..46d8c34 100644
--- a/gcc/testsuite/g++.dg/ext/has_trivial_assign.C
+++ b/gcc/testsuite/g++.dg/ext/has_trivial_assign.C
@@ -96,7 +96,7 @@ int main()
   assert (NTEST (C));
   assert (NTEST (D));
   assert (PTEST (E));
-  assert (NTEST (E[]));
+  assert (PTEST (E[]));
   assert (PTEST (F));
   assert (NTEST (G));
   assert (NTEST (const A));
diff --git a/gcc/testsuite/g++.dg/ext/has_trivial_copy.C b/gcc/testsuite/g++.dg/ext/has_trivial_copy.C
index ca2eeec..4b8cc15 100644
--- a/gcc/testsuite/g++.dg/ext/has_trivial_copy.C
+++ b/gcc/testsuite/g++.dg/ext/has_trivial_copy.C
@@ -96,7 +96,7 @@ int main()
   assert (NTEST (C));
   assert (NTEST (D));
   assert (PTEST (E));
-  assert (NTEST (E[]));
+  assert (PTEST (E[]));
   assert (PTEST (F));
   assert (NTEST (G));
   assert (PTEST (B&));
diff --git a/gcc/testsuite/g++.dg/ext/is_pod.C b/gcc/testsuite/g++.dg/ext/is_pod.C
index 5c1f0cd..c984283 100644
--- a/gcc/testsuite/g++.dg/ext/is_pod.C
+++ b/gcc/testsuite/g++.dg/ext/is_pod.C
@@ -68,8 +68,8 @@ int main()
   assert (PTEST (A));
   assert (PTEST (A[]));
   assert (NTEST (B));
-  assert (NTEST (C));
-  assert (NTEST (C[]));
+  assert (PTEST (C));
+  assert (PTEST (C[]));
 
   return 0;
 }
diff --git a/gcc/testsuite/g++.dg/other/offsetof3.C b/gcc/testsuite/g++.dg/other/offsetof3.C
index 1e83af9..5946c81 100644
--- a/gcc/testsuite/g++.dg/other/offsetof3.C
+++ b/gcc/testsuite/g++.dg/other/offsetof3.C
@@ -1,16 +1,17 @@
-/* Verify that offsetof warns if given a non-POD */
+/* Verify that offsetof warns if given a non-standard-layout class */
 /* Copyright (C) 2003 Free Software Foundation, Inc. */
 /* Contributed by Matt Austern <austern@apple.com> 15 May 2003 */
 /* { dg-do compile } */
 
 struct X
 {
-  X() : x(3), y(4) { }
   int x, y;
+protected:
+  int z;
 };
 
 typedef X* pX;
 typedef __SIZE_TYPE__ size_t;
 
 size_t yoff = size_t(&(pX(0)->y)); /* { dg-warning "invalid access" "" } */
-/* { dg-warning "macro was used incorrectly" "macro" { target *-*-* } 15 } */
+/* { dg-warning "macro was used incorrectly" "macro" { target *-*-* } 16 } */
diff --git a/gcc/testsuite/g++.dg/overload/ellipsis1.C b/gcc/testsuite/g++.dg/overload/ellipsis1.C
index bdd3cd2..3dedaa6 100644
--- a/gcc/testsuite/g++.dg/overload/ellipsis1.C
+++ b/gcc/testsuite/g++.dg/overload/ellipsis1.C
@@ -1,9 +1,6 @@
 // PR c++/15142
 // Bug: We were aborting after giving a warning about passing a non-POD.
 
-// Suppress the warning about undefined behavior.
-// { dg-options "-w" }
-
 struct B { 
     B() throw() { } 
     B(const B&) throw() { } 
@@ -17,5 +14,5 @@ struct X {
 struct S { S(...); }; 
  
 void SillyFunc() { 
-  throw S(X()); 
+  throw S(X()); 		// { dg-error "copy" }
 } 
diff --git a/gcc/testsuite/g++.dg/warn/var-args1.C b/gcc/testsuite/g++.dg/warn/var-args1.C
index aadac20..9bd84a7 100644
--- a/gcc/testsuite/g++.dg/warn/var-args1.C
+++ b/gcc/testsuite/g++.dg/warn/var-args1.C
@@ -6,6 +6,6 @@ void foo(int, ...)
 {
     va_list va;
     int i;
-    i = va_arg(va, int&); /* { dg-warning "cannot receive objects" } */
+    i = va_arg(va, int&); /* { dg-error "cannot receive objects" } */
 }
 
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/crash63.C b/gcc/testsuite/g++.old-deja/g++.brendan/crash63.C
index 13f8339..89685fc 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/crash63.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/crash63.C
@@ -4,6 +4,7 @@ class String
    {
  public:
    String (const char *str);
+   String (const String&);
    };
 
 class UnitList 
@@ -12,4 +13,4 @@ class UnitList
    UnitList (...);
    };
 
-UnitList unit_list (String("keV")); // { dg-warning "" } cannot pass non-pod
+UnitList unit_list (String("keV")); // { dg-error "" } cannot pass non-pod
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/crash64.C b/gcc/testsuite/g++.old-deja/g++.brendan/crash64.C
index 6046cb1..3c98692 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/crash64.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/crash64.C
@@ -16,4 +16,4 @@ struct metatype { int base_list; };
 
 static _type_desc _type_metatype("metatype", sizeof(metatype),
   (RF_Ptr)0, 0, 1, 1,
-  _im_pers_mem_spec( ((size_t)&((( metatype *)0)-> base_list )) , 1)); // { dg-warning "" } cannot pass non-pod
+  _im_pers_mem_spec( ((size_t)&((( metatype *)0)-> base_list )) , 1));
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/overload8.C b/gcc/testsuite/g++.old-deja/g++.brendan/overload8.C
index fc1b23b..bf129b0 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/overload8.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/overload8.C
@@ -6,4 +6,4 @@ class Complex{public:double re,im;
 void zxcvbnm(int n,...){n=1;}
 int main(){complex c; Complex C;
 zxcvbnm(1,c);
-zxcvbnm(1,C);} // { dg-warning "" } cannot pass non pod
+zxcvbnm(1,C);}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/vaarg3.C b/gcc/testsuite/g++.old-deja/g++.other/vaarg3.C
index f852b08..3408a18 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/vaarg3.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/vaarg3.C
@@ -9,14 +9,14 @@
 #include <stdarg.h>
 
 struct X {int m;};
-struct Y : X {int m;};
+struct Y { Y(const Y&); };
 struct Z;   // { dg-error "forward decl" } 
 void fn1(va_list args)
 {
   int i = va_arg (args, int);
-  Y x = va_arg (args, Y);         // { dg-warning "cannot receive" } 
-  Y y = va_arg (args, struct Y);  // { dg-warning "cannot receive" } 
-  int &r = va_arg (args, int &);  // { dg-warning "cannot receive" } 
+  Y x = va_arg (args, Y);         // { dg-error "cannot receive" }
+  Y y = va_arg (args, struct Y);  // { dg-error "cannot receive" }
+  int &r = va_arg (args, int &);  // { dg-error "cannot receive" }
   
   Z z1 = va_arg (args, Z);        // { dg-error "incomplete" } 
   const Z &z2 = va_arg (args, Z);       // { dg-error "incomplete" } 
@@ -25,7 +25,8 @@ void fn1(va_list args)
   // { dg-message "should pass" "pass" { target *-*-* } 24 }
   // { dg-message "abort" "abort" { target *-*-* } 24 }
   va_arg (args, int []);  // { dg-error "array with unspecified bounds" } promote
-  va_arg (args, int ());  // { dg-warning "non-POD" } promote
+  va_arg (args, int ());  // { dg-warning "promoted" } promote
+  // { dg-message "abort" "abort" { target *-*-* } 28 }
   va_arg (args, bool);    // { dg-warning "promote" "promote" } 
-  // { dg-message "abort" "abort" { target *-*-* } 29 }
+  // { dg-message "abort" "abort" { target *-*-* } 30 }
 }
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/vaarg3.C b/gcc/testsuite/g++.old-deja/g++.pt/vaarg3.C
index dced89d..07fb18d 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/vaarg3.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/vaarg3.C
@@ -14,14 +14,14 @@ void PrintArgs (Type somearg, ...)
 va_list argp;
 va_start (argp, somearg);
 Type value;
-value = va_arg (argp, Type); // { dg-warning "non-POD" } cannot pass non-POD
+value = va_arg (argp, Type); // { dg-error "cannot receive" } cannot pass non-POD
 va_end (argp);
 }
 
 int main (void)
 {
 A dummy;
-PrintArgs (dummy, dummy); // { dg-warning "non-POD" } cannot pass non-POD
+PrintArgs (dummy, dummy); // { dg-error "cannot pass" } cannot pass non-POD
 // { dg-message "instantiated" "inst" { target *-*-* } 24 }
 return 0;
 }
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 94c40df..dd26bb8 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -173,11 +173,18 @@ namespace std
   // Member introspection.
 
   /// is_pod
+  // Could use is_standard_layout && is_trivial instead of the builtin.
   template<typename _Tp>
     struct is_pod
     : public integral_constant<bool, __is_pod(_Tp)>
     { };
 
+  /// is_standard_layout
+  template<typename _Tp>
+    struct is_standard_layout
+    : public integral_constant<bool, __is_standard_layout(_Tp)>
+    { };
+
   /// has_trivial_default_constructor
   template<typename _Tp>
     struct has_trivial_default_constructor
@@ -202,6 +209,12 @@ namespace std
     : public integral_constant<bool, __has_trivial_destructor(_Tp)>
     { };
 
+  /// is_trivial
+  template<typename _Tp>
+    struct is_trivial
+    : public integral_constant<bool, __is_trivial(_Tp)>
+    { };
+
   /// has_nothrow_default_constructor
   template<typename _Tp>
     struct has_nothrow_default_constructor
diff --git a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc
index ca7ee97..3455462 100644
--- a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc
@@ -48,8 +48,8 @@ void test01()
 // { dg-error "instantiated from here" "" { target *-*-* } 40 }
 // { dg-error "instantiated from here" "" { target *-*-* } 42 }
 
-// { dg-error "invalid use of incomplete type" "" { target *-*-* } 557 }
-// { dg-error "declaration of" "" { target *-*-* } 519 }
+// { dg-error "invalid use of incomplete type" "" { target *-*-* } 570 }
+// { dg-error "declaration of" "" { target *-*-* } 532 }
 
 // { dg-excess-errors "At global scope" }
 // { dg-excess-errors "In instantiation of" }
diff --git a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc
index ac9fef1..3d3a10a 100644
--- a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc
@@ -48,8 +48,8 @@ void test01()
 // { dg-error "instantiated from here" "" { target *-*-* } 40 }
 // { dg-error "instantiated from here" "" { target *-*-* } 42 }
 
-// { dg-error "invalid use of incomplete type" "" { target *-*-* } 478 }
-// { dg-error "declaration of" "" { target *-*-* } 440 }
+// { dg-error "invalid use of incomplete type" "" { target *-*-* } 491 }
+// { dg-error "declaration of" "" { target *-*-* } 453 }
 
 // { dg-excess-errors "At global scope" }
 // { dg-excess-errors "In instantiation of" }


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

* Re: C++/v3 PATCH for libstdc++/37907 (POD -> standard-layout/trivial)
  2009-07-16 21:00 C++/v3 PATCH for libstdc++/37907 (POD -> standard-layout/trivial) Jason Merrill
@ 2010-03-11 21:21 ` H.J. Lu
  0 siblings, 0 replies; 2+ messages in thread
From: H.J. Lu @ 2010-03-11 21:21 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches List, Benjamin Kosnik

On Thu, Jul 16, 2009 at 12:34 PM, Jason Merrill <jason@redhat.com> wrote:
> Benjamin asked me to make PR 37907 a priority, and then the patch just kept
> growing...
>
> This patch implements the changes in the language's notion of POD type from
> the N2230.  Basically, a POD is now a type which is both trivial (has
> trivial default init, copy init, copy assign and destructor) and
> standard-layout.  Pretty much everything in the standard that used to talk
> about POD type now either refers to one of those properties, or to a subset
> of the trivial conditions, typically either default init/destructor or copy
> init/destructor.
>
> As a result, we now no longer give warnings/errors on a lot of cases where
> the language used to require them for no good reason, on offsetof, passing
> by ..., or jumping into scope of an object.  The ... case has changed from
> undefined to the new notion of conditionally-supported behavior, so I added
> a file to document our implementation choice while I was thinking about it.
>
> We still retain the old notion of POD for use in class layout, as that is
> part of the ABI.  I renamed the macro so it's clear that it's only being
> used for that purpose.  __is_pod now gives the new definition.
>
> libstdc++ folks: I'd think that the type_traits stuff should live in
> libsupc++ with the other compiler-interface bits; what do you think?
>
> Tested x86_64-pc-linux-gnu, applied to trunk.
>
>

This caused:

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



-- 
H.J.

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

end of thread, other threads:[~2010-03-11 21:14 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-07-16 21:00 C++/v3 PATCH for libstdc++/37907 (POD -> standard-layout/trivial) Jason Merrill
2010-03-11 21:21 ` H.J. Lu

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).