This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [C++ Patch] PR 26099 (first part)


Hi again,

I agree with all your comments and I'm going to do the various changes, updated patch forthcoming.

The patch is below. This time I'm also including for real the minimal libstdc++-v3 changes.


Tested x86-64. Ok now?

Paolo.

/////////////
gcc/
2007-03-30  Paolo Carlini  <pcarlini@suse.de>

	PR c++/26099
	* c-common.h (enum rid): Add RID_HAS_NOTHROW_ASSIGN,
	RID_HAS_NOTHROW_CONSTRUCTOR, RID_HAS_NOTHROW_COPY,
	RID_HAS_TRIVIAL_ASSIGN, RID_HAS_TRIVIAL_CONSTRUCTOR,
	RID_HAS_TRIVIAL_COPY, RID_HAS_TRIVIAL_DESTRUCTOR,
	RID_HAS_VIRTUAL_DESTRUCTOR, RID_IS_ABSTRACT, RID_IS_BASE_OF,
	RID_IS_CONVERTIBLE_TO, RID_IS_CLASS, RID_IS_EMPTY, RID_IS_ENUM,
	RID_IS_POD, RID_IS_POLYMORPHIC, RID_IS_UNION, as
	C++ extensions.
	* doc/extend.texi (Extensions to the C++ Language): Add Type Traits.

gcc/cp/
2007-03-30  Paolo Carlini  <pcarlini@suse.de>

	PR c++/26099
	* cp-tree.h (enum cp_trait_kind, struct tree_trait_expr,
	TRAIT_EXPR_TYPE1, TRAIT_EXPR_TYPE2, TRAIT_EXPR_KIND): Add.
	(enum cp_tree_node_structure_enum, union lang_tree_node): Update.
	(CLASS_TYPE_NON_UNION_P): Add.
	(struct lang_type_class): Add has_complex_dflt.
	(TYPE_HAS_COMPLEX_DFLT, TYPE_HAS_TRIVIAL_DFLT): Add.
	(locate_copy, locate_ctor, locate_dtor, finish_trait_expr): Declare.
	* cp-tree.def: Add TRAIT_EXPR.
	* cp-objcp-common.c (cp_tree_size): Add TRAIT_EXPR case.
	* lex.c (struct resword): Add __has_nothrow_assign,
	__has_nothrow_constructor, __has_nothrow_copy, __has_trivial_assign,
	__has_trivial_constructor, __has_trivial_copy,
	__has_trivial_destructor, __has_virtual_destructor, __is_abstract,
	__is_base_of, __is_class, __is_convertible_to, __is_empty, __is_enum,
	__is_pod, __is_polymorphic, __is_union.
	* parser.c (cp_parser_primary_expression): Deal with the new RIDs.
	(cp_parser_trait_expr): New.
	* semantics.c (finish_trait_expr, trait_expr_value
	classtype_has_nothrow_copy_or_assign_p): New.
	* method.c (locate_copy, locate_ctor, locate_dtor): Do not define
	as static.
	* decl.c (cp_tree_node_structure): Add TRAIT_EXPR.
	* class.c (check_bases, check_field_decl, check_bases_and_members):
	Deal with TYPE_HAS_COMPLEX_DFLT (t) too.
	* pt.c (uses_template_parms, tsubst_copy_and_build,
	value_dependent_expression_p, type_dependent_expression_p): Deal with
	TRAIT_EXPR.

gcc/testsuite/
2007-03-30  Paolo Carlini  <pcarlini@suse.de>

	PR c++/26099
	* g++.dg/ext/is_base_of.C: New.
	* g++.dg/ext/has_virtual_destructor.C: New.
	* g++.dg/ext/is_polymorphic.C: New.
	* g++.dg/ext/is_base_of_diagnostic.C: New.
	* g++.dg/ext/is_enum.C: New.
	* g++.dg/ext/has_nothrow_assign.C: New.
	* g++.dg/ext/has_nothrow_constructor.C: New.
	* g++.dg/ext/is_empty.C: New.
	* g++.dg/ext/has_trivial_copy.C: New.
	* g++.dg/ext/has_trivial_assign.C: New.
	* g++.dg/ext/is_abstract.C: New.
	* g++.dg/ext/is_pod.C: New.
	* g++.dg/ext/has_nothrow_copy.C: New.
	* g++.dg/ext/is_class.C: New.
	* g++.dg/ext/has_trivial_constructor.C: New.
	* g++.dg/ext/is_union.C: New.
	* g++.dg/ext/has_trivial_destructor.C: New.
	* g++.dg/tree-ssa/pr22444.C: Adjust, avoid __is_pod.
	* g++.dg/template/crash43.C: Likewise.

libstdc++-v3/
2007-03-30  Paolo Carlini  <pcarlini@suse.de>

	PR c++/26099
	* include/bits/cpp_type_traits.h (struct __is_pod, struct __is_empty):
	Remove.
	* include/bits/valarray_array.h: Adjust.
	* include/bits/allocator.h: Likewise.
	* include/bits/stl_tree.h: Likewise.
Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 123155)
+++ gcc/doc/extend.texi	(working copy)
@@ -10675,6 +10675,7 @@
                         method denoted by a @samp{->*} or @samp{.*} expression.
 * C++ Attributes::      Variable, function, and type attributes for C++ only.
 * Namespace Association:: Strong using-directives for namespace association.
+* Type Traits::         Compiler support for type traits
 * Java Exceptions::     Tweaking exception handling to work with Java.
 * Deprecated Features:: Things will disappear from g++.
 * Backwards Compatibility:: Compatibilities with earlier definitions of C++.
@@ -11232,6 +11233,124 @@
 @}
 @end smallexample
 
+@node Type Traits
+@section Type Traits
+
+The C++ front-end implements syntactic extensions that allow to
+determine at compile time various characteristics of a type (or of a
+pair of types).
+
+@table @code
+@item __has_nothrow_assign (type)
+If @code{__has_trivial_assign (type)} is true then the trait is true, else if
+@code{type} is a cv class or union type with copy assignment operators that
+are known not to throw an exception then the trait is true, else it is false.
+If @code{type} is const qualified, any copy assignment operator must
+be both known not to throw an exception, and const qualified, for the
+trait to be true.  Requires: @code{type} shall be a complete type, an
+array type of unknown bound, or is a @code{void} type.
+
+@item __has_nothrow_copy (type)
+If @code{__has_trivial_copy (type)} is true then the trait is true, else if
+@code{type} is a cv class or union type with copy constructors that
+are known not to throw an exception then the trait is true, else it is false.
+Requires: @code{type} shall be a complete type, an array type of
+unknown bound, or is a @code{void} type.
+
+@item __has_nothrow_constructor (type)
+If @code{__has_trivial_constructor (type)} is true then the trait is
+true, else if @code{type} is a cv class or union type (or array
+thereof) with a default constructor that is known not to throw an
+exception then the trait is true, else it is false.  Requires:
+@code{type} shall be a complete type, an array type of unknown bound,
+or is a @code{void} type.
+
+@item __has_trivial_assign (type)
+If @code{type} is const qualified or is a reference type then the trait is
+false.  Otherwise if @code{__is_pod (type)} is true then the trait is
+true, else if @code{type} is a cv class or union type with a trivial
+copy assignment ([class.copy]) then the trait is true, else it is
+false.  Requires: @code{type} shall be a complete type, an array type
+of unknown bound, or is a @code{void} type.
+
+@item __has_trivial_copy (type)
+If @code{__is_pod (type)} is true or @code{type} is a reference type 
+then the trait is true, else if @code{type} is a cv class or union type
+with a trivial copy constructor ([class.copy]) then the trait
+is true, else it is false.  Requires: @code{type} shall be a complete
+type, an array type of unknown bound, or is a @code{void} type.
+
+@item __has_trivial_constructor (type)
+If @code{__is_pod (type)} is true then the trait is true, else if
+@code{type} is a cv class or union type (or array thereof) with a
+trivial default constructor ([class.ctor]) then the trait is true,
+else it is false.  Requires: @code{type} shall be a complete type, an
+array type of unknown bound, or is a @code{void} type.
+
+@item __has_trivial_destructor (type)
+If @code{__is_pod (type)} is true or @code{type} is a reference type then
+the trait is true, else if @code{type} is a cv class or union type (or
+array thereof) with a trivial destructor ([class.dtor]) then the trait
+is true, else it is false.  Requires: @code{type} shall be a complete
+type, an array type of unknown bound, or is a @code{void} type.
+
+@item __has_virtual_destructor (type)
+If @code{type} is a class type with a virtual destructor
+([class.dtor]) then the trait is true, else it is false.  Requires:
+@code{type}  shall be a complete type, an array type of unknown bound,
+or is a @code{void} type.
+
+@item __is_abstract (type)
+If @code{type} is an abstract class ([class.abstract]) then the trait
+is true, else it is false.  Requires: @code{type} shall be a complete
+type, an array type of unknown bound, or is a @code{void} type.
+
+@item __is_base_of (base_type, derived_type)
+If @code{base_type} is a base class of @code{derived_type}
+([class.derived]) then the trait is true, otherwise it is false.
+Top-level cv qualifications of @code{base_type} and
+@code{derived_type} are ignored.  For the purposes of this trait, a
+class type is considered is own base.  Requires: if @code{__is_class
+(base_type)} and @code{__is_class (derived_type)} are true and
+@code{base_type} and @code{derived_type} are not the same type
+(disregarding cv-qualifiers), @code{derived_type} shall be a complete
+type.  Diagnostic is produced if this requirement is not met.
+
+@item __is_class (type)
+If @code{type} is a cv class type, and not a union type
+([basic.compound]) the the trait is true, else it is false.
+
+@item __is_empty (type)
+If @code{__is_class (type)} is false then the trait is false.
+Otherwise @code{type} is considered empty if and only if: @code{type}
+has no non-static data members, or all non-static data members, if
+any, are bit-fields of lenght 0, and @code{type} has no virtual
+members, and @code{type} has no virtual base classes, and @code{type}
+has no base classes @code{base_type} for which 
+@code{__is_empty (base_type)} is false.  Requires: @code{type} shall
+be a complete type, an array type of unknown bound, or is a
+@code{void} type.
+
+@item __is_enum (type)
+If @code{type} is a cv enumeration type ([basic.compound]) the the trait is 
+true, else it is false.
+
+@item __is_pod (type)
+If @code{type} is a cv POD type ([basic.types]) then the trait is true,
+else it is false.  Requires: @code{type} shall be a complete type, 
+an array type of unknown bound, or is a @code{void} type.
+
+@item __is_polymorphic (type)
+If @code{type} is a polymorphic class ([class.virtual]) then the trait
+is true, else it is false.  Requires: @code{type} shall be a complete
+type, an array type of unknown bound, or is a @code{void} type.
+
+@item __is_union (type)
+If @code{type} is a cv union type ([basic.compound]) the the trait is 
+true, else it is false.
+
+@end table
+
 @node Java Exceptions
 @section Java Exceptions
 
Index: gcc/testsuite/g++.dg/tree-ssa/pr22444.C
===================================================================
--- gcc/testsuite/g++.dg/tree-ssa/pr22444.C	(revision 123155)
+++ gcc/testsuite/g++.dg/tree-ssa/pr22444.C	(working copy)
@@ -22,7 +22,7 @@
 }
 namespace std
 {
-  template<typename _Tp> struct __is_pod
+  template<typename _Tp> struct ___is_pod
   {
     enum { __value = (sizeof(__gnu_internal::__test_type<_Tp>(0))!= sizeof(__gnu_internal::__one)) };
   };
@@ -111,7 +111,7 @@
     typedef _Val value_type;
     typedef value_type* pointer;
     typedef _Rb_tree_node* _Link_type;
-    template<typename _Key_compare, bool _Is_pod_comparator = std::__is_pod<_Key_compare>::__value> struct _Rb_tree_impl
+    template<typename _Key_compare, bool _Is_pod_comparator = std::___is_pod<_Key_compare>::__value> struct _Rb_tree_impl
       : _Node_allocator
     {
       _Rb_tree_node_base _M_header;
Index: gcc/testsuite/g++.dg/ext/is_base_of.C
===================================================================
--- gcc/testsuite/g++.dg/ext/is_base_of.C	(revision 0)
+++ gcc/testsuite/g++.dg/ext/is_base_of.C	(revision 0)
@@ -0,0 +1,94 @@
+// { dg-do "run" }
+#include <cassert>
+
+class A1
+{ 
+  double a;
+  double b;  
+};
+
+class A2
+{ 
+  double a;
+  double b;
+};
+
+class B
+: private A1 { };
+
+class C
+: private A1, private A2 { };
+
+union U
+{ 
+  double a;
+  double b;
+};
+
+template<typename T, typename U>
+  bool
+  f()
+  { return __is_base_of(T, U); } 
+
+template<typename T, typename U>
+  class My
+  {
+  public:
+    bool
+    f()
+    { return !!__is_base_of(T, U); }
+  };
+
+template<typename T, typename U>
+  class My2
+  {
+  public:
+    static const bool trait = __is_base_of(T, U);
+  };
+
+template<typename T, typename U>
+  const bool My2<T, U>::trait;
+
+template<typename T, typename U, bool b = __is_base_of(T, U)>
+  struct My3_help
+  { static const bool trait = b; };
+
+template<typename T, typename U, bool b>
+  const bool My3_help<T, U, b>::trait;
+
+template<typename T, typename U>
+  class My3
+  {
+  public:
+    bool
+    f()
+    { return My3_help<T, U>::trait; }
+  };
+
+#define PTEST(T, U) (__is_base_of(T, U) && f<T, U>() \
+                  && My<T, U>().f() && My2<T, U>::trait && My3<T, U>().f())
+
+#define NTEST(T, U) (!__is_base_of(T, U) && !f<T, U>() \
+                  && !My<T, U>().f() && !My2<T, U>::trait && !My3<T, U>().f())
+
+int main()
+{
+  assert (NTEST (int, A1));
+  assert (NTEST (A1, void));
+  assert (PTEST (A1, A1));
+  assert (NTEST (A1*, A1*));
+  assert (NTEST (A1&, A1&));
+  assert (PTEST (A1, B));
+  assert (NTEST (B, A1));
+  assert (PTEST (A1, C));
+  assert (PTEST (A2, C));
+  assert (NTEST (C, A1));
+  assert (PTEST (A1, const B));
+  assert (NTEST (const B, A1));
+  assert (PTEST (A1, volatile C));
+  assert (PTEST (volatile A2, const C));
+  assert (NTEST (const volatile C, A1));
+  assert (NTEST (U, U));
+
+  return 0;
+}
Index: gcc/testsuite/g++.dg/ext/has_virtual_destructor.C
===================================================================
--- gcc/testsuite/g++.dg/ext/has_virtual_destructor.C	(revision 0)
+++ gcc/testsuite/g++.dg/ext/has_virtual_destructor.C	(revision 0)
@@ -0,0 +1,89 @@
+// { dg-do "run" }
+#include <cassert>
+#include <exception>
+
+struct A
+{
+  double a;
+  double b;
+};
+
+union U
+{
+  double a;
+  double b;
+};
+
+class B
+{
+  virtual ~B() { }
+};
+
+class C
+: public B { };
+
+class D
+{
+  ~D() { }
+};
+
+template<typename T>
+  bool
+  f()
+  { return __has_virtual_destructor(T); } 
+
+template<typename T>
+  class My
+  {
+  public:
+    bool
+    f()
+    { return !!__has_virtual_destructor(T); }
+  };
+
+template<typename T>
+  class My2
+  {
+  public:
+    static const bool trait = __has_virtual_destructor(T);
+  };
+
+template<typename T>
+  const bool My2<T>::trait;
+
+template<typename T, bool b = __has_virtual_destructor(T)>
+  struct My3_help
+  { static const bool trait = b; };
+
+template<typename T, bool b>
+  const bool My3_help<T, b>::trait;
+
+template<typename T>
+  class My3
+  {
+  public:
+    bool
+    f()
+    { return My3_help<T>::trait; }
+  };
+
+#define PTEST(T) (__has_virtual_destructor(T) && f<T>() \
+                  && My<T>().f() && My2<T>::trait && My3<T>().f())
+
+#define NTEST(T) (!__has_virtual_destructor(T) && !f<T>() \
+                  && !My<T>().f() && !My2<T>::trait && !My3<T>().f())
+
+int main()
+{
+  assert (NTEST (int));
+  assert (NTEST (void));
+  assert (PTEST (std::exception));
+  assert (NTEST (A));
+  assert (NTEST (U));
+  assert (PTEST (B));
+  assert (PTEST (C));
+  assert (NTEST (C[]));
+  assert (NTEST (D));
+
+  return 0;
+}
Index: gcc/testsuite/g++.dg/ext/is_polymorphic.C
===================================================================
--- gcc/testsuite/g++.dg/ext/is_polymorphic.C	(revision 0)
+++ gcc/testsuite/g++.dg/ext/is_polymorphic.C	(revision 0)
@@ -0,0 +1,83 @@
+// { dg-do "run" }
+#include <cassert>
+#include <exception>
+
+struct A
+{
+  double a;
+  double b;
+};
+
+class B
+{
+  virtual void rotate(int) { }
+};
+
+class C
+: public B { };
+
+union U
+{
+  double a;
+  double b;
+};
+
+template<typename T>
+  bool
+  f()
+  { return __is_polymorphic(T); } 
+
+template<typename T>
+  class My
+  {
+  public:
+    bool
+    f()
+    { return !!__is_polymorphic(T); }
+  };
+
+template<typename T>
+  class My2
+  {
+  public:
+    static const bool trait = __is_polymorphic(T);
+  };
+
+template<typename T>
+  const bool My2<T>::trait;
+
+template<typename T, bool b = __is_polymorphic(T)>
+  struct My3_help
+  { static const bool trait = b; };
+
+template<typename T, bool b>
+  const bool My3_help<T, b>::trait;
+
+template<typename T>
+  class My3
+  {
+  public:
+    bool
+    f()
+    { return My3_help<T>::trait; }
+  };
+
+#define PTEST(T) (__is_polymorphic(T) && f<T>() \
+                  && My<T>().f() && My2<T>::trait && My3<T>().f())
+
+#define NTEST(T) (!__is_polymorphic(T) && !f<T>() \
+                  && !My<T>().f() && !My2<T>::trait && !My3<T>().f())
+
+int main()
+{
+  assert (NTEST (int));
+  assert (NTEST (void));
+  assert (PTEST (std::exception));
+  assert (NTEST (A));
+  assert (PTEST (B));
+  assert (PTEST (C));
+  assert (NTEST (C[]));
+  assert (NTEST (U));
+
+  return 0;
+}
Index: gcc/testsuite/g++.dg/ext/is_base_of_diagnostic.C
===================================================================
--- gcc/testsuite/g++.dg/ext/is_base_of_diagnostic.C	(revision 0)
+++ gcc/testsuite/g++.dg/ext/is_base_of_diagnostic.C	(revision 0)
@@ -0,0 +1,15 @@
+class A
+{ };
+
+class B;
+
+union C
+{ };
+
+union D;
+
+void f()
+{
+  __is_base_of(A, B);  // { dg-error "incomplete type" }
+  __is_base_of(C, D);  
+}
Index: gcc/testsuite/g++.dg/ext/is_enum.C
===================================================================
--- gcc/testsuite/g++.dg/ext/is_enum.C	(revision 0)
+++ gcc/testsuite/g++.dg/ext/is_enum.C	(revision 0)
@@ -0,0 +1,73 @@
+// { dg-do "run" }
+#include <cassert>
+
+struct A
+{
+  double a;
+  double b;
+};
+
+class B
+{ };
+
+enum E
+{
+  e0
+};
+
+template<typename T>
+  bool
+  f()
+  { return __is_enum(T); } 
+
+template<typename T>
+  class My
+  {
+  public:
+    bool
+    f()
+    { return !!__is_enum(T); }
+  };
+
+template<typename T>
+  class My2
+  {
+  public:
+    static const bool trait = __is_enum(T);
+  };
+
+template<typename T>
+  const bool My2<T>::trait;
+
+template<typename T, bool b = __is_enum(T)>
+  struct My3_help
+  { static const bool trait = b; };
+
+template<typename T, bool b>
+  const bool My3_help<T, b>::trait;
+
+template<typename T>
+  class My3
+  {
+  public:
+    bool
+    f()
+    { return My3_help<T>::trait; }
+  };
+
+#define PTEST(T) (__is_enum(T) && f<T>() \
+                  && My<T>().f() && My2<T>::trait && My3<T>().f())
+
+#define NTEST(T) (!__is_enum(T) && !f<T>() \
+                  && !My<T>().f() && !My2<T>::trait && !My3<T>().f())
+
+int main()
+{
+  assert (NTEST (int));
+  assert (NTEST (void));
+  assert (NTEST (A));
+  assert (NTEST (B));
+  assert (PTEST (E));
+
+  return 0;
+}
Index: gcc/testsuite/g++.dg/ext/has_nothrow_assign.C
===================================================================
--- gcc/testsuite/g++.dg/ext/has_nothrow_assign.C	(revision 0)
+++ gcc/testsuite/g++.dg/ext/has_nothrow_assign.C	(revision 0)
@@ -0,0 +1,152 @@
+// { dg-do "run" }
+#include <cassert>
+
+struct A
+{
+  double a;
+  double b;
+};
+
+struct B
+{
+  A a;
+};
+
+struct C
+: public A { };
+
+struct D
+{
+  D& operator=(const D&) throw() { return *this; }
+};
+
+struct E
+{
+  E& operator=(const E&) throw(int) { return *this; }
+};
+
+struct E1
+{
+  E1& operator=(const E1&) throw(int) { throw int(); return *this; }
+};
+
+struct F
+{
+  F() throw(int) { }
+};
+
+struct G
+{
+  G() throw(int) { throw int(); }
+};
+
+struct H
+{
+  H& operator=(H&) throw(int) { return *this; }
+};
+
+struct H1
+{
+  H1& operator=(H1&) throw(int) { throw int(); return *this; }
+};
+
+struct I
+{
+  I& operator=(I&) throw(int) { return *this; }
+  I& operator=(const I&) throw() { return *this; }
+};
+
+struct I1
+{
+  I1& operator=(I1&) throw(int) { throw int(); return *this; }
+  I1& operator=(const I1&) throw() { return *this; }
+};
+
+struct J
+{
+  J& operator=(J&) throw() { return *this; }
+  J& operator=(const J&) throw() { return *this; }
+  J& operator=(volatile J&) throw() { return *this; }
+  J& operator=(const volatile J&) throw() { return *this; }
+};
+
+struct K
+{
+  K& operator=(K&) throw() { return *this; }
+};
+
+struct L
+{
+  L& operator=(const L&) throw() { return *this; }
+};
+
+template<typename T>
+  bool
+  f()
+  { return __has_nothrow_assign(T); } 
+
+template<typename T>
+  class My
+  {
+  public:
+    bool
+    f()
+    { return !!__has_nothrow_assign(T); }
+  };
+
+template<typename T>
+  class My2
+  {
+  public:
+    static const bool trait = __has_nothrow_assign(T);
+  };
+
+template<typename T>
+  const bool My2<T>::trait;
+
+template<typename T, bool b = __has_nothrow_assign(T)>
+  struct My3_help
+  { static const bool trait = b; };
+
+template<typename T, bool b>
+  const bool My3_help<T, b>::trait;
+
+template<typename T>
+  class My3
+  {
+  public:
+    bool
+    f()
+    { return My3_help<T>::trait; }
+  };
+
+#define PTEST(T) (__has_nothrow_assign(T) && f<T>() \
+                  && My<T>().f() && My2<T>::trait && My3<T>().f())
+
+#define NTEST(T) (!__has_nothrow_assign(T) && !f<T>() \
+                  && !My<T>().f() && !My2<T>::trait && !My3<T>().f())
+
+int main()
+{
+  assert (PTEST (int));
+  assert (NTEST (int (int)));
+  assert (NTEST (void));
+  assert (PTEST (A));
+  assert (PTEST (B));
+  assert (PTEST (C));
+  assert (NTEST (C[]));
+  assert (PTEST (D));
+  assert (PTEST (E));
+  assert (NTEST (E1));
+  assert (PTEST (F));
+  assert (PTEST (G));
+  assert (PTEST (H));
+  assert (NTEST (H1));
+  assert (PTEST (I));
+  assert (NTEST (I1));
+  assert (PTEST (J));
+  assert (NTEST (const K));
+  assert (PTEST (const L));
+
+  return 0;
+}
Index: gcc/testsuite/g++.dg/ext/has_nothrow_constructor.C
===================================================================
--- gcc/testsuite/g++.dg/ext/has_nothrow_constructor.C	(revision 0)
+++ gcc/testsuite/g++.dg/ext/has_nothrow_constructor.C	(revision 0)
@@ -0,0 +1,106 @@
+// { dg-do "run" }
+#include <cassert>
+
+struct A
+{
+  double a;
+  double b;
+};
+
+struct B
+{
+  A a;
+};
+
+struct C 
+: public A { };
+
+struct D
+{
+  D() throw() { }
+};
+
+struct E
+{
+  E() throw(int) { }
+};
+
+struct E1
+{
+  E1() throw(int) { throw int(); }
+};
+
+struct F
+{
+  F(const F&) throw() { }
+};
+
+struct G
+{
+  G(const G&) throw(int) { throw int(); }
+};
+
+template<typename T>
+  bool
+  f()
+  { return __has_nothrow_constructor(T); } 
+
+template<typename T>
+  class My
+  {
+  public:
+    bool
+    f()
+    { return !!__has_nothrow_constructor(T); }
+  };
+
+template<typename T>
+  class My2
+  {
+  public:
+    static const bool trait = __has_nothrow_constructor(T);
+  };
+
+template<typename T>
+  const bool My2<T>::trait;
+
+
+template<typename T, bool b = __has_nothrow_constructor(T)>
+  struct My3_help
+  { static const bool trait = b; };
+
+template<typename T, bool b>
+  const bool My3_help<T, b>::trait;
+
+template<typename T>
+  class My3
+  {
+  public:
+    bool
+    f()
+    { return My3_help<T>::trait; }
+  };
+
+#define PTEST(T) (__has_nothrow_constructor(T) && f<T>() \
+                  && My<T>().f() && My2<T>::trait && My3<T>().f())
+
+#define NTEST(T) (!__has_nothrow_constructor(T) && !f<T>() \
+                  && !My<T>().f() && !My2<T>::trait && !My3<T>().f())
+
+int main()
+{
+  assert (PTEST (int));
+  assert (NTEST (int (int)));
+  assert (NTEST (void));
+  assert (PTEST (A));
+  assert (PTEST (B));
+  assert (PTEST (C));
+  assert (PTEST (C[]));
+  assert (PTEST (D));
+  assert (PTEST (E));
+  assert (NTEST (E1));
+  assert (NTEST (F));
+  assert (NTEST (G));
+
+  return 0;
+}
Index: gcc/testsuite/g++.dg/ext/is_empty.C
===================================================================
--- gcc/testsuite/g++.dg/ext/is_empty.C	(revision 0)
+++ gcc/testsuite/g++.dg/ext/is_empty.C	(revision 0)
@@ -0,0 +1,78 @@
+// { dg-do "run" }
+#include <cassert>
+
+struct A
+{
+  double a;
+  double b;
+};
+
+struct B
+{
+  virtual ~B() { }
+};
+
+class C 
+{ };
+
+union U
+{ };
+
+template<typename T>
+  bool
+  f()
+  { return __is_empty(T); } 
+
+template<typename T>
+  class My
+  {
+  public:
+    bool
+    f()
+    { return !!__is_empty(T); }
+  };
+
+template<typename T>
+  class My2
+  {
+  public:
+    static const bool trait = __is_empty(T);
+  };
+
+template<typename T>
+  const bool My2<T>::trait;
+
+template<typename T, bool b = __is_empty(T)>
+  struct My3_help
+  { static const bool trait = b; };
+
+template<typename T, bool b>
+  const bool My3_help<T, b>::trait;
+
+template<typename T>
+  class My3
+  {
+  public:
+    bool
+    f()
+    { return My3_help<T>::trait; }
+  };
+
+#define PTEST(T) (__is_empty(T) && f<T>() \
+                  && My<T>().f() && My2<T>::trait && My3<T>().f())
+
+#define NTEST(T) (!__is_empty(T) && !f<T>() \
+                  && !My<T>().f() && !My2<T>::trait && !My3<T>().f())
+
+int main()
+{
+  assert (NTEST (int));
+  assert (NTEST (void));
+  assert (NTEST (A));
+  assert (NTEST (B));
+  assert (PTEST (C));
+  assert (NTEST (C[]));
+  assert (NTEST (U));
+
+  return 0;
+}
Index: gcc/testsuite/g++.dg/ext/has_trivial_copy.C
===================================================================
--- gcc/testsuite/g++.dg/ext/has_trivial_copy.C	(revision 0)
+++ gcc/testsuite/g++.dg/ext/has_trivial_copy.C	(revision 0)
@@ -0,0 +1,105 @@
+// { dg-do "run" }
+#include <cassert>
+
+struct A
+{
+  double a;
+  double b;
+};
+
+union U
+{
+  double a;
+  double b;
+};
+
+struct B
+{
+  B(const B&) { }
+};
+
+struct C
+{
+  virtual int f() { return 1; }
+};
+
+struct D 
+: public B { };
+
+struct E
+: public A { };
+
+struct F
+{
+  A a;
+};
+
+struct G
+{
+  B b;
+};
+
+template<typename T>
+  bool
+  f()
+  { return __has_trivial_copy(T); } 
+
+template<typename T>
+  class My
+  {
+  public:
+    bool
+    f()
+    { return !!__has_trivial_copy(T); }
+  };
+
+template<typename T>
+  class My2
+  {
+  public:
+    static const bool trait = __has_trivial_copy(T);
+  };
+
+template<typename T>
+  const bool My2<T>::trait;
+
+template<typename T, bool b = __has_trivial_copy(T)>
+  struct My3_help
+  { static const bool trait = b; };
+
+template<typename T, bool b>
+  const bool My3_help<T, b>::trait;
+
+template<typename T>
+  class My3
+  {
+  public:
+    bool
+    f()
+    { return My3_help<T>::trait; }
+  };
+
+#define PTEST(T) (__has_trivial_copy(T) && f<T>() \
+                  && My<T>().f() && My2<T>::trait && My3<T>().f())
+
+#define NTEST(T) (!__has_trivial_copy(T) && !f<T>() \
+                  && !My<T>().f() && !My2<T>::trait && !My3<T>().f())
+
+int main()
+{
+  assert (PTEST (int));
+  assert (NTEST (int (int)));
+  assert (NTEST (void));
+  assert (PTEST (A));
+  assert (PTEST (U));
+  assert (NTEST (B));
+  assert (NTEST (C));
+  assert (NTEST (D));
+  assert (PTEST (E));
+  assert (NTEST (E[]));
+  assert (PTEST (F));
+  assert (NTEST (G));
+  assert (PTEST (B&));
+
+  return 0;
+}
Index: gcc/testsuite/g++.dg/ext/has_trivial_assign.C
===================================================================
--- gcc/testsuite/g++.dg/ext/has_trivial_assign.C	(revision 0)
+++ gcc/testsuite/g++.dg/ext/has_trivial_assign.C	(revision 0)
@@ -0,0 +1,106 @@
+// { dg-do "run" }
+#include <cassert>
+
+struct A
+{
+  double a;
+  double b;
+};
+
+union U
+{
+  double a;
+  double b;
+};
+
+struct B
+{
+  B& operator=(const B&) { return *this;}
+};
+
+struct C
+{
+  virtual int f() { return 1; }
+};
+
+struct D 
+: public B { };
+
+struct E
+: public A { };
+
+struct F
+{
+  A a;
+};
+
+struct G
+{
+  B b;
+};
+
+template<typename T>
+  bool
+  f()
+  { return __has_trivial_assign(T); } 
+
+template<typename T>
+  class My
+  {
+  public:
+    bool
+    f()
+    { return !!__has_trivial_assign(T); }
+  };
+
+template<typename T>
+  class My2
+  {
+  public:
+    static const bool trait = __has_trivial_assign(T);
+  };
+
+template<typename T>
+  const bool My2<T>::trait;
+
+template<typename T, bool b = __has_trivial_assign(T)>
+  struct My3_help
+  { static const bool trait = b; };
+
+template<typename T, bool b>
+  const bool My3_help<T, b>::trait;
+
+template<typename T>
+  class My3
+  {
+  public:
+    bool
+    f()
+    { return My3_help<T>::trait; }
+  };
+
+#define PTEST(T) (__has_trivial_assign(T) && f<T>() \
+                  && My<T>().f() && My2<T>::trait && My3<T>().f())
+
+#define NTEST(T) (!__has_trivial_assign(T) && !f<T>() \
+                  && !My<T>().f() && !My2<T>::trait && !My3<T>().f())
+
+int main()
+{
+  assert (PTEST (int));
+  assert (NTEST (int (int)));
+  assert (NTEST (void));
+  assert (PTEST (A));
+  assert (PTEST (U));
+  assert (NTEST (B));
+  assert (NTEST (C));
+  assert (NTEST (D));
+  assert (PTEST (E));
+  assert (NTEST (E[]));
+  assert (PTEST (F));
+  assert (NTEST (G));
+  assert (NTEST (const A));
+  assert (NTEST (A&));
+  
+  return 0;
+}
Index: gcc/testsuite/g++.dg/ext/is_abstract.C
===================================================================
--- gcc/testsuite/g++.dg/ext/is_abstract.C	(revision 0)
+++ gcc/testsuite/g++.dg/ext/is_abstract.C	(revision 0)
@@ -0,0 +1,89 @@
+// { dg-do "run" }
+#include <cassert>
+
+struct A
+{
+  double a;
+  double b;
+};
+
+union U
+{
+  double a;
+  double b;
+};
+
+class B
+{
+  B();
+};
+
+class C
+{
+  virtual void rotate(int) = 0;
+};
+
+class D
+{
+  virtual void rotate(int) { }
+};
+
+template<typename T>
+  bool
+  f()
+  { return __is_abstract(T); } 
+
+template<typename T>
+  class My
+  {
+  public:
+    bool
+    f()
+    { return !!__is_abstract(T); }
+  };
+
+template<typename T>
+  class My2
+  {
+  public:
+    static const bool trait = __is_abstract(T);
+  };
+
+template<typename T>
+  const bool My2<T>::trait;
+
+template<typename T, bool b = __is_abstract(T)>
+  struct My3_help
+  { static const bool trait = b; };
+
+template<typename T, bool b>
+  const bool My3_help<T, b>::trait;
+
+template<typename T>
+  class My3
+  {
+  public:
+    bool
+    f()
+    { return My3_help<T>::trait; }
+  };
+
+#define PTEST(T) (__is_abstract(T) && f<T>() \
+                  && My<T>().f() && My2<T>::trait && My3<T>().f())
+
+#define NTEST(T) (!__is_abstract(T) && !f<T>() \
+                  && !My<T>().f() && !My2<T>::trait && !My3<T>().f())
+
+int main()
+{
+  assert (NTEST (int));
+  assert (NTEST (void));
+  assert (NTEST (A));
+  assert (NTEST (U));
+  assert (NTEST (B));
+  assert (NTEST (B[]));  
+  assert (PTEST (C));
+  assert (NTEST (D));
+
+  return 0;
+}
Index: gcc/testsuite/g++.dg/ext/is_pod.C
===================================================================
--- gcc/testsuite/g++.dg/ext/is_pod.C	(revision 0)
+++ gcc/testsuite/g++.dg/ext/is_pod.C	(revision 0)
@@ -0,0 +1,75 @@
+// { dg-do "run" }
+#include <cassert>
+
+struct A
+{
+  double a;
+  double b;
+};
+
+struct B
+{
+  B() { }
+};
+
+struct C
+: public A { };
+
+template<typename T>
+  bool
+  f()
+  { return __is_pod(T); } 
+
+template<typename T>
+  class My
+  {
+  public:
+    bool
+    f()
+    { return !!__is_pod(T); }
+  };
+
+template<typename T>
+  class My2
+  {
+  public:
+    static const bool trait = __is_pod(T);
+  };
+
+template<typename T>
+  const bool My2<T>::trait;
+
+template<typename T, bool b = __is_pod(T)>
+  struct My3_help
+  { static const bool trait = b; };
+
+template<typename T, bool b>
+  const bool My3_help<T, b>::trait;
+
+template<typename T>
+  class My3
+  {
+  public:
+    bool
+    f()
+    { return My3_help<T>::trait; }
+  };
+
+#define PTEST(T) (__is_pod(T) && f<T>() \
+                  && My<T>().f() && My2<T>::trait && My3<T>().f())
+
+#define NTEST(T) (!__is_pod(T) && !f<T>() \
+                  && !My<T>().f() && !My2<T>::trait && !My3<T>().f())
+
+int main()
+{
+  assert (PTEST (int));
+  assert (NTEST (void));
+  assert (PTEST (A));
+  assert (PTEST (A[]));
+  assert (NTEST (B));
+  assert (NTEST (C));
+  assert (NTEST (C[]));
+
+  return 0;
+}
Index: gcc/testsuite/g++.dg/ext/has_nothrow_copy.C
===================================================================
--- gcc/testsuite/g++.dg/ext/has_nothrow_copy.C	(revision 0)
+++ gcc/testsuite/g++.dg/ext/has_nothrow_copy.C	(revision 0)
@@ -0,0 +1,140 @@
+// { dg-do "run" }
+#include <cassert>
+
+struct A
+{
+  double a;
+  double b;
+};
+
+struct B
+{
+  A a;
+};
+
+struct C
+: public A { };
+
+struct D
+{
+  D(const D&) throw() { }
+};
+
+struct E
+{
+  E(const E&) throw(int) { }
+};
+
+struct E1
+{
+  E1(const E1&) throw(int) { throw int(); }
+};
+
+struct F
+{
+  F() throw() { }
+};
+
+struct G
+{
+  G() throw(int) { throw int(); }
+};
+
+struct H
+{
+  H(H&) throw(int) { }
+};
+
+struct H1
+{
+  H1(H1&) throw(int) { throw int(); }
+};
+
+struct I
+{
+  I(I&) throw(int) { }
+  I(const I&) throw() { }
+};
+
+struct I1
+{
+  I1(I1&) throw(int) { throw int(); }
+  I1(const I1&) throw() { }
+};
+
+struct J
+{
+  J(J&) throw() { }
+  J(const J&) throw() { }
+  J(volatile J&) throw() { }
+  J(const volatile J&) throw() { }
+};
+
+template<typename T>
+  bool
+  f()
+  { return __has_nothrow_copy(T); } 
+
+template<typename T>
+  class My
+  {
+  public:
+    bool
+    f()
+    { return !!__has_nothrow_copy(T); }
+  };
+
+template<typename T>
+  class My2
+  {
+  public:
+    static const bool trait = __has_nothrow_copy(T);
+  };
+
+template<typename T>
+  const bool My2<T>::trait;
+
+template<typename T, bool b = __has_nothrow_copy(T)>
+  struct My3_help
+  { static const bool trait = b; };
+
+template<typename T, bool b>
+  const bool My3_help<T, b>::trait;
+
+template<typename T>
+  class My3
+  {
+  public:
+    bool
+    f()
+    { return My3_help<T>::trait; }
+  };
+
+#define PTEST(T) (__has_nothrow_copy(T) && f<T>() \
+                  && My<T>().f() && My2<T>::trait && My3<T>().f())
+
+#define NTEST(T) (!__has_nothrow_copy(T) && !f<T>() \
+                  && !My<T>().f() && !My2<T>::trait && !My3<T>().f())
+
+int main()
+{
+  assert (PTEST (int));
+  assert (NTEST (int (int)));
+  assert (NTEST (void));
+  assert (PTEST (A));
+  assert (PTEST (B));
+  assert (PTEST (C));
+  assert (NTEST (C[]));
+  assert (PTEST (D));
+  assert (PTEST (E));
+  assert (NTEST (E1));
+  assert (PTEST (F));
+  assert (PTEST (G));
+  assert (PTEST (H));
+  assert (NTEST (H1));
+  assert (PTEST (I));
+  assert (NTEST (I1));  
+  assert (PTEST (J));
+
+  return 0;
+}
Index: gcc/testsuite/g++.dg/ext/is_class.C
===================================================================
--- gcc/testsuite/g++.dg/ext/is_class.C	(revision 0)
+++ gcc/testsuite/g++.dg/ext/is_class.C	(revision 0)
@@ -0,0 +1,76 @@
+// { dg-do "run" }
+#include <cassert>
+
+struct A
+{
+  double a;
+  double b;
+};
+
+class B
+{
+  B() { }
+};
+
+union U
+{
+  double a;
+  double b;
+};
+
+template<typename T>
+  bool
+  f()
+  { return __is_class(T); } 
+
+template<typename T>
+  class My
+  {
+  public:
+    bool
+    f()
+    { return !!__is_class(T); }
+  };
+
+template<typename T>
+  class My2
+  {
+  public:
+    static const bool trait = __is_class(T);
+  };
+
+template<typename T>
+  const bool My2<T>::trait;
+
+template<typename T, bool b = __is_class(T)>
+  struct My3_help
+  { static const bool trait = b; };
+
+template<typename T, bool b>
+  const bool My3_help<T, b>::trait;
+
+template<typename T>
+  class My3
+  {
+  public:
+    bool
+    f()
+    { return My3_help<T>::trait; }
+  };
+
+#define PTEST(T) (__is_class(T) && f<T>() \
+                  && My<T>().f() && My2<T>::trait && My3<T>().f())
+
+#define NTEST(T) (!__is_class(T) && !f<T>() \
+                  && !My<T>().f() && !My2<T>::trait && !My3<T>().f())
+
+int main()
+{
+  assert (NTEST (int));
+  assert (NTEST (void));
+  assert (PTEST (A));
+  assert (PTEST (B));
+  assert (NTEST (U));
+
+  return 0;
+}
Index: gcc/testsuite/g++.dg/ext/has_trivial_constructor.C
===================================================================
--- gcc/testsuite/g++.dg/ext/has_trivial_constructor.C	(revision 0)
+++ gcc/testsuite/g++.dg/ext/has_trivial_constructor.C	(revision 0)
@@ -0,0 +1,98 @@
+// { dg-do "run" }
+#include <cassert>
+
+struct A
+{
+  double a;
+  double b;
+};
+
+union U
+{
+  double a;
+  double b;  
+};
+
+struct B
+{
+  B() { }
+};
+
+struct C 
+: public B { };
+
+struct D
+: public A { };
+
+struct E
+{
+  A a;
+};
+
+struct F
+{
+  B b;
+};
+
+template<typename T>
+  bool
+  f()
+  { return __has_trivial_constructor(T); } 
+
+template<typename T>
+  class My
+  {
+  public:
+    bool
+    f()
+    { return !!__has_trivial_constructor(T); }
+  };
+
+template<typename T>
+  class My2
+  {
+  public:
+    static const bool trait = __has_trivial_constructor(T);
+  };
+
+template<typename T>
+  const bool My2<T>::trait;
+
+template<typename T, bool b = __has_trivial_constructor(T)>
+  struct My3_help
+  { static const bool trait = b; };
+
+template<typename T, bool b>
+  const bool My3_help<T, b>::trait;
+
+template<typename T>
+  class My3
+  {
+  public:
+    bool
+    f()
+    { return My3_help<T>::trait; }
+  };
+
+#define PTEST(T) (__has_trivial_constructor(T) && f<T>() \
+                  && My<T>().f() && My2<T>::trait && My3<T>().f())
+
+#define NTEST(T) (!__has_trivial_constructor(T) && !f<T>() \
+                  && !My<T>().f() && !My2<T>::trait && !My3<T>().f())
+
+int main()
+{
+  assert (PTEST (int));
+  assert (NTEST (int (int)));
+  assert (NTEST (void));
+  assert (PTEST (A));
+  assert (PTEST (U));
+  assert (NTEST (B));
+  assert (NTEST (C));
+  assert (PTEST (D));
+  assert (PTEST (D[]));
+  assert (PTEST (E));
+  assert (NTEST (F));
+
+  return 0;
+}
Index: gcc/testsuite/g++.dg/ext/is_union.C
===================================================================
--- gcc/testsuite/g++.dg/ext/is_union.C	(revision 0)
+++ gcc/testsuite/g++.dg/ext/is_union.C	(revision 0)
@@ -0,0 +1,76 @@
+// { dg-do "run" }
+#include <cassert>
+
+struct A
+{
+  double a;
+  double b;
+};
+
+class B
+{
+  B() { }
+};
+
+union U
+{ 
+  double a;
+  double b;  
+};
+
+template<typename T>
+  bool
+  f()
+  { return __is_union(T); } 
+
+template<typename T>
+  class My
+  {
+  public:
+    bool
+    f()
+    { return !!__is_union(T); }
+  };
+
+template<typename T>
+  class My2
+  {
+  public:
+    static const bool trait = __is_union(T);
+  };
+
+template<typename T>
+  const bool My2<T>::trait;
+
+template<typename T, bool b = __is_union(T)>
+  struct My3_help
+  { static const bool trait = b; };
+
+template<typename T, bool b>
+  const bool My3_help<T, b>::trait;
+
+template<typename T>
+  class My3
+  {
+  public:
+    bool
+    f()
+    { return My3_help<T>::trait; }
+  };
+
+#define PTEST(T) (__is_union(T) && f<T>() \
+                  && My<T>().f() && My2<T>::trait && My3<T>().f())
+
+#define NTEST(T) (!__is_union(T) && !f<T>() \
+                  && !My<T>().f() && !My2<T>::trait && !My3<T>().f())
+
+int main()
+{
+  assert (NTEST (int));
+  assert (NTEST (void));
+  assert (NTEST (A));
+  assert (NTEST (B));
+  assert (PTEST (U));
+
+  return 0;
+}
Index: gcc/testsuite/g++.dg/ext/has_trivial_destructor.C
===================================================================
--- gcc/testsuite/g++.dg/ext/has_trivial_destructor.C	(revision 0)
+++ gcc/testsuite/g++.dg/ext/has_trivial_destructor.C	(revision 0)
@@ -0,0 +1,86 @@
+// { dg-do "run" }
+#include <cassert>
+
+struct A
+{
+  double a;
+  double b;
+};
+
+union U
+{
+  double a;
+  double b;
+};
+
+struct B
+{
+  ~B() { }
+};
+
+struct C 
+: public B { };
+
+struct D
+: public A { };
+
+template<typename T>
+  bool
+  f()
+  { return __has_trivial_destructor(T); } 
+
+template<typename T>
+  class My
+  {
+  public:
+    bool
+    f()
+    { return !!__has_trivial_destructor(T); }
+  };
+
+template<typename T>
+  class My2
+  {
+  public:
+    static const bool trait = __has_trivial_destructor(T);
+  };
+
+template<typename T>
+  const bool My2<T>::trait;
+
+template<typename T, bool b = __has_trivial_destructor(T)>
+  struct My3_help
+  { static const bool trait = b; };
+
+template<typename T, bool b>
+  const bool My3_help<T, b>::trait;
+
+template<typename T>
+  class My3
+  {
+  public:
+    bool
+    f()
+    { return My3_help<T>::trait; }
+  };
+
+#define PTEST(T) (__has_trivial_destructor(T) && f<T>() \
+                  && My<T>().f() && My2<T>::trait && My3<T>().f())
+
+#define NTEST(T) (!__has_trivial_destructor(T) && !f<T>() \
+                  && !My<T>().f() && !My2<T>::trait && !My3<T>().f())
+
+int main()
+{
+  assert (PTEST (int));
+  assert (NTEST (int (int)));
+  assert (NTEST (void));
+  assert (PTEST (A));
+  assert (PTEST (U));
+  assert (NTEST (B));
+  assert (NTEST (C));
+  assert (PTEST (D));
+  assert (PTEST (D[]));
+
+  return 0;
+}
Index: gcc/testsuite/g++.dg/template/crash43.C
===================================================================
--- gcc/testsuite/g++.dg/template/crash43.C	(revision 123155)
+++ gcc/testsuite/g++.dg/template/crash43.C	(working copy)
@@ -2,7 +2,7 @@
 
 extern "C" {
   template<typename _Tp>  // { dg-error "C" }   
-  struct __is_pod {
+  struct ___is_pod {
     enum {
       __value = (sizeof(__gnu_internal::__test_type<_Tp>(0)))}; // { dg-error "declared|expected" }
 
Index: gcc/cp/class.c
===================================================================
--- gcc/cp/class.c	(revision 123155)
+++ gcc/cp/class.c	(working copy)
@@ -1270,6 +1270,7 @@
       TYPE_POLYMORPHIC_P (t) |= TYPE_POLYMORPHIC_P (basetype);
       CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t)
 	|= CLASSTYPE_CONTAINS_EMPTY_CLASS_P (basetype);
+      TYPE_HAS_COMPLEX_DFLT (t) |= TYPE_HAS_COMPLEX_DFLT (basetype);      
     }
 }
 
@@ -2753,6 +2754,7 @@
 	    |= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type);
 	  TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (type);
 	  TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (type);
+	  TYPE_HAS_COMPLEX_DFLT (t) |= TYPE_HAS_COMPLEX_DFLT (type);
 	}
 
       if (!TYPE_HAS_CONST_INIT_REF (type))
@@ -4113,6 +4115,8 @@
 	|| TYPE_HAS_ASSIGN_REF (t));
   TYPE_HAS_COMPLEX_ASSIGN_REF (t)
     |= TYPE_HAS_ASSIGN_REF (t) || TYPE_CONTAINS_VPTR_P (t);
+  TYPE_HAS_COMPLEX_DFLT (t)
+    |= (TYPE_HAS_DEFAULT_CONSTRUCTOR (t) || TYPE_CONTAINS_VPTR_P (t));
 
   /* Synthesize any needed methods.  */
   add_implicitly_declared_members (t,
Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	(revision 123155)
+++ gcc/cp/decl.c	(working copy)
@@ -11717,6 +11717,7 @@
     case BASELINK:		return TS_CP_BASELINK;
     case STATIC_ASSERT:		return TS_CP_STATIC_ASSERT;
     case ARGUMENT_PACK_SELECT:  return TS_CP_ARGUMENT_PACK_SELECT;
+    case TRAIT_EXPR:		return TS_CP_TRAIT_EXPR;
     default:			return TS_CP_GENERIC;
     }
 }
Index: gcc/cp/cp-tree.def
===================================================================
--- gcc/cp/cp-tree.def	(revision 123155)
+++ gcc/cp/cp-tree.def	(working copy)
@@ -422,6 +422,11 @@
    index is a machine integer.  */
 DEFTREECODE (ARGUMENT_PACK_SELECT, "argument_pack_select", tcc_exceptional, 0)
 
+/** C++ extensions. */
+
+/* Represents a trait expression during template expansion.  */
+DEFTREECODE (TRAIT_EXPR, "trait_expr", tcc_exceptional, 0)
+
 /*
 Local variables:
 mode:c
Index: gcc/cp/method.c
===================================================================
--- gcc/cp/method.c	(revision 123155)
+++ gcc/cp/method.c	(working copy)
@@ -61,9 +61,6 @@
 static void do_build_assign_ref (tree);
 static void do_build_copy_constructor (tree);
 static tree synthesize_exception_spec (tree, tree (*) (tree, void *), void *);
-static tree locate_dtor (tree, void *);
-static tree locate_ctor (tree, void *);
-static tree locate_copy (tree, void *);
 static tree make_alias_for_thunk (tree);
 
 /* Called once to initialize method.c.  */
@@ -868,7 +865,7 @@
 
 /* Locate the dtor of TYPE.  */
 
-static tree
+tree
 locate_dtor (tree type, void *client ATTRIBUTE_UNUSED)
 {
   return CLASSTYPE_DESTRUCTORS (type);
@@ -876,7 +873,7 @@
 
 /* Locate the default ctor of TYPE.  */
 
-static tree
+tree
 locate_ctor (tree type, void *client ATTRIBUTE_UNUSED)
 {
   tree fns;
@@ -912,7 +909,7 @@
    points to a COPY_DATA holding the name (NULL for the ctor)
    and desired qualifiers of the source operand.  */
 
-static tree
+tree
 locate_copy (tree type, void *client_)
 {
   struct copy_data *client = (struct copy_data *)client_;
Index: gcc/cp/cp-objcp-common.c
===================================================================
--- gcc/cp/cp-objcp-common.c	(revision 123155)
+++ gcc/cp/cp-objcp-common.c	(working copy)
@@ -135,6 +135,9 @@
     case ARGUMENT_PACK_SELECT:
       return sizeof (struct tree_argument_pack_select);
 
+    case TRAIT_EXPR:
+      return sizeof (struct tree_trait_expr);
+
     default:
       gcc_unreachable ();
     }
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(revision 123155)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -478,6 +478,48 @@
   int index;
 };
 
+/* The different kinds of traits that we encounter.  */
+
+typedef enum cp_trait_kind
+{
+  CPTK_HAS_NOTHROW_ASSIGN,
+  CPTK_HAS_NOTHROW_CONSTRUCTOR,
+  CPTK_HAS_NOTHROW_COPY,
+  CPTK_HAS_TRIVIAL_ASSIGN,
+  CPTK_HAS_TRIVIAL_CONSTRUCTOR,
+  CPTK_HAS_TRIVIAL_COPY,
+  CPTK_HAS_TRIVIAL_DESTRUCTOR,
+  CPTK_HAS_VIRTUAL_DESTRUCTOR,
+  CPTK_IS_ABSTRACT,
+  CPTK_IS_BASE_OF,
+  CPTK_IS_CLASS,
+  CPTK_IS_CONVERTIBLE_TO,
+  CPTK_IS_EMPTY,
+  CPTK_IS_ENUM,
+  CPTK_IS_POD,
+  CPTK_IS_POLYMORPHIC,
+  CPTK_IS_UNION
+} cp_trait_kind;
+
+/* The types that we are processing.  */
+#define TRAIT_EXPR_TYPE1(NODE) \
+  (((struct tree_trait_expr *)TRAIT_EXPR_CHECK (NODE))->type1)
+
+#define TRAIT_EXPR_TYPE2(NODE) \
+  (((struct tree_trait_expr *)TRAIT_EXPR_CHECK (NODE))->type2)
+
+/* The specific trait that we are processing.  */
+#define TRAIT_EXPR_KIND(NODE) \
+  (((struct tree_trait_expr *)TRAIT_EXPR_CHECK (NODE))->kind)
+
+struct tree_trait_expr GTY (())
+{
+  struct tree_common common;
+  tree type1;
+  tree type2;  
+  enum cp_trait_kind kind;
+};
+
 enum cp_tree_node_structure_enum {
   TS_CP_GENERIC,
   TS_CP_IDENTIFIER,
@@ -491,6 +533,7 @@
   TS_CP_DEFAULT_ARG,
   TS_CP_STATIC_ASSERT,
   TS_CP_ARGUMENT_PACK_SELECT,
+  TS_CP_TRAIT_EXPR,
   LAST_TS_CP_ENUM
 };
 
@@ -511,6 +554,8 @@
     static_assertion;
   struct tree_argument_pack_select GTY ((tag ("TS_CP_ARGUMENT_PACK_SELECT")))
     argument_pack_select;
+  struct tree_trait_expr GTY ((tag ("TS_CP_TRAIT_EXPR")))
+    trait_expression;
 };
 
 
@@ -936,6 +981,10 @@
 #define CLASS_TYPE_P(T) \
   (IS_AGGR_TYPE_CODE (TREE_CODE (T)) && TYPE_LANG_FLAG_5 (T))
 
+/* Nonzero if T is a class type but not an union.  */
+#define NON_UNION_CLASS_TYPE_P(T) \
+  (CLASS_TYPE_P (T) && TREE_CODE (T) != UNION_TYPE)
+
 /* Keep these checks in ascending code order.  */
 #define IS_AGGR_TYPE_CODE(T)	\
   ((T) == RECORD_TYPE || (T) == UNION_TYPE)
@@ -1093,6 +1142,7 @@
   unsigned has_complex_init_ref : 1;
   unsigned has_complex_assign_ref : 1;
   unsigned non_aggregate : 1;
+  unsigned has_complex_dflt : 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
@@ -1101,7 +1151,7 @@
   /* 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 : 12;
+  unsigned dummy : 11;
 
   tree primary_base;
   VEC(tree_pair_s,gc) *vcall_indices;
@@ -2682,8 +2732,13 @@
 
 /* Nonzero if there is a user-defined X::op=(x&) for this class.  */
 #define TYPE_HAS_COMPLEX_ASSIGN_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_complex_assign_ref)
+
+/* Nonzero if there is a user-defined X::X(x&) for this class.  */
 #define TYPE_HAS_COMPLEX_INIT_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_complex_init_ref)
 
+/* Nonzero if there is a user-defined default constructor for this class.  */
+#define TYPE_HAS_COMPLEX_DFLT(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_complex_dflt)
+
 /* Nonzero if TYPE has a trivial destructor.  From [class.dtor]:
 
      A destructor is trivial if it is an implicitly declared
@@ -2705,6 +2760,10 @@
 #define TYPE_HAS_NONTRIVIAL_DESTRUCTOR(NODE) \
   (TYPE_LANG_FLAG_4 (NODE))
 
+/* Nonzero for class type means that the default constructor is trivial.  */
+#define TYPE_HAS_TRIVIAL_DFLT(NODE) \
+  (TYPE_HAS_DEFAULT_CONSTRUCTOR (NODE) && ! TYPE_HAS_COMPLEX_DFLT (NODE))
+
 /* Nonzero for class type means that copy initialization of this type can use
    a bitwise copy.  */
 #define TYPE_HAS_TRIVIAL_INIT_REF(NODE) \
@@ -4280,6 +4339,9 @@
 extern tree skip_artificial_parms_for		(tree, tree);
 extern int num_artificial_parms_for		(tree);
 extern tree make_alias_for			(tree, tree);
+extern tree locate_copy				(tree, void *);
+extern tree locate_ctor				(tree, void *);
+extern tree locate_dtor				(tree, void *);
 
 /* In optimize.c */
 extern bool maybe_clone_body			(tree);
@@ -4556,6 +4618,7 @@
 extern tree baselink_for_fns                    (tree);
 extern void finish_static_assert                (tree, tree, location_t,
                                                  bool);
+extern tree finish_trait_expr			(enum cp_trait_kind, tree, tree);
 
 /* in tree.c */
 extern void lang_check_failed			(const char *, int,
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(revision 123155)
+++ gcc/cp/pt.c	(working copy)
@@ -5790,6 +5790,7 @@
 	   || TREE_CODE (t) == OVERLOAD
 	   || TREE_CODE (t) == BASELINK
 	   || TREE_CODE (t) == IDENTIFIER_NODE
+	   || TREE_CODE (t) == TRAIT_EXPR
 	   || CONSTANT_CLASS_P (t))
     dependent_p = (type_dependent_expression_p (t)
 		   || value_dependent_expression_p (t));
@@ -10675,6 +10676,18 @@
     case OFFSETOF_EXPR:
       return finish_offsetof (RECUR (TREE_OPERAND (t, 0)));
 
+    case TRAIT_EXPR:
+      {
+	tree type1 = tsubst_copy (TRAIT_EXPR_TYPE1 (t), args,
+				  complain, in_decl);
+
+	tree type2 = TRAIT_EXPR_TYPE2 (t);
+	if (type2)
+	  type2 = tsubst_copy (type2, args, complain, in_decl);
+	
+	return finish_trait_expr (TRAIT_EXPR_KIND (t), type1, type2);
+      }
+
     case STMT_EXPR:
       {
 	tree old_stmt_expr = cur_stmt_expr;
@@ -14860,6 +14873,13 @@
         return false;
       }
 
+    case TRAIT_EXPR:
+      {
+	tree type2 = TRAIT_EXPR_TYPE2 (expression);
+	return (dependent_type_p (TRAIT_EXPR_TYPE1 (expression))
+		|| (type2 ? dependent_type_p (type2) : false));
+      }
+
     default:
       /* A constant expression is value-dependent if any subexpression is
 	 value-dependent.  */
@@ -14923,6 +14943,7 @@
   if (TREE_CODE (expression) == PSEUDO_DTOR_EXPR
       || TREE_CODE (expression) == SIZEOF_EXPR
       || TREE_CODE (expression) == ALIGNOF_EXPR
+      || TREE_CODE (expression) == TRAIT_EXPR
       || TREE_CODE (expression) == TYPEID_EXPR
       || TREE_CODE (expression) == DELETE_EXPR
       || TREE_CODE (expression) == VEC_DELETE_EXPR
Index: gcc/cp/semantics.c
===================================================================
--- gcc/cp/semantics.c	(revision 123155)
+++ gcc/cp/semantics.c	(working copy)
@@ -4007,4 +4007,210 @@
     }
 }
 
+/* Called from trait_expr_value to evaluate either __has_nothrow_copy or 
+   __has_nothrow_assign, depending on copy_p.  */
+
+static bool
+classtype_has_nothrow_copy_or_assign_p (tree type, bool copy_p)
+{
+  if ((copy_p && TYPE_HAS_INIT_REF (type))
+      || (!copy_p && TYPE_HAS_ASSIGN_REF (type)))
+    {
+      bool const_p = false;
+      tree t;
+
+      struct copy_data 
+      {
+	tree name;
+	int quals;
+      } data;
+
+      data.name = copy_p ? NULL_TREE : ansi_assopname (NOP_EXPR);
+
+      data.quals = TYPE_QUAL_CONST;
+      t = locate_copy (type, &data);
+      if (t)
+	{
+	  const_p = true;
+	  if (!TREE_NOTHROW (t))
+	    return false;
+	}
+
+      if (copy_p || !CP_TYPE_CONST_P (type))
+	{
+	  data.quals = TYPE_UNQUALIFIED;
+	  t = locate_copy (type, &data);
+	  if (t && !TREE_NOTHROW (t))
+	    return false;
+
+	  data.quals = TYPE_QUAL_VOLATILE;
+	  t = locate_copy (type, &data);
+	  if (t && !TREE_NOTHROW (t))
+	    return false;
+	}
+
+      data.quals = (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
+      t = locate_copy (type, &data);
+      if (t)
+	{
+	  const_p = true;
+	  if (!TREE_NOTHROW (t))
+	    return false;
+	}
+
+      if (!copy_p && CP_TYPE_CONST_P (type) && !const_p)
+	return false;
+    }
+  else
+    return false;
+
+  return true;
+}
+
+/* Actually evaluates the trait.  */
+
+static bool
+trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
+{
+  enum tree_code type_code1;
+  tree t;
+
+  type_code1 = TREE_CODE (type1);
+
+  switch (kind)
+    {
+    case CPTK_HAS_NOTHROW_ASSIGN:
+      return (trait_expr_value (CPTK_HAS_TRIVIAL_ASSIGN, type1, type2)
+	      || (CLASS_TYPE_P (type1)
+		  && classtype_has_nothrow_copy_or_assign_p (type1, false)));
+
+    case CPTK_HAS_TRIVIAL_ASSIGN:
+      return (!CP_TYPE_CONST_P (type1) && type_code1 != REFERENCE_TYPE
+	      && (pod_type_p (type1)
+		    || (CLASS_TYPE_P (type1)
+			&& TYPE_HAS_TRIVIAL_ASSIGN_REF (type1))));
+
+    case CPTK_HAS_NOTHROW_CONSTRUCTOR:
+      type1 = strip_array_types (type1);
+      return (trait_expr_value (CPTK_HAS_TRIVIAL_CONSTRUCTOR, type1, type2) 
+	      || (CLASS_TYPE_P (type1)
+		  && (t = locate_ctor (type1, NULL)) && TREE_NOTHROW (t)));
+
+    case CPTK_HAS_TRIVIAL_CONSTRUCTOR:
+      type1 = strip_array_types (type1);
+      return (pod_type_p (type1)
+	      || (CLASS_TYPE_P (type1) && TYPE_HAS_TRIVIAL_DFLT (type1)));
+
+    case CPTK_HAS_NOTHROW_COPY:
+      return (trait_expr_value (CPTK_HAS_TRIVIAL_COPY, type1, type2)
+	      || (CLASS_TYPE_P (type1)
+		  && classtype_has_nothrow_copy_or_assign_p (type1, true)));
+
+    case CPTK_HAS_TRIVIAL_COPY:
+      return (pod_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)
+	      || (CLASS_TYPE_P (type1)
+		  && TYPE_HAS_TRIVIAL_DESTRUCTOR (type1)));
+
+    case CPTK_HAS_VIRTUAL_DESTRUCTOR:
+      return (CLASS_TYPE_P (type1)
+	      && (t = locate_dtor (type1, NULL)) && DECL_VIRTUAL_P (t));
+
+    case CPTK_IS_ABSTRACT:
+      return (CLASS_TYPE_P (type1) && CLASSTYPE_PURE_VIRTUALS (type1));
+
+    case CPTK_IS_BASE_OF:
+      return (NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2)
+	      && DERIVED_FROM_P (type1, type2));
+
+    case CPTK_IS_CLASS:
+      return (NON_UNION_CLASS_TYPE_P (type1));
+
+    case CPTK_IS_CONVERTIBLE_TO:
+      /* TODO  */
+      return false;
+
+    case CPTK_IS_EMPTY:
+      return (NON_UNION_CLASS_TYPE_P (type1) && CLASSTYPE_EMPTY_P (type1));
+
+    case CPTK_IS_ENUM:
+      return (type_code1 == ENUMERAL_TYPE);
+
+    case CPTK_IS_POD:
+      return (pod_type_p (type1));
+
+    case CPTK_IS_POLYMORPHIC:
+      return (CLASS_TYPE_P (type1) && TYPE_POLYMORPHIC_P (type1));
+
+    case CPTK_IS_UNION:
+      return (type_code1 == UNION_TYPE);
+
+    default:
+      gcc_unreachable ();
+      return false;
+    }
+}
+
+/* Process a trait expression.  */
+
+tree
+finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
+{
+  gcc_assert (kind == CPTK_HAS_NOTHROW_ASSIGN
+	      || kind == CPTK_HAS_NOTHROW_CONSTRUCTOR
+	      || kind == CPTK_HAS_NOTHROW_COPY
+	      || kind == CPTK_HAS_TRIVIAL_ASSIGN
+	      || kind == CPTK_HAS_TRIVIAL_CONSTRUCTOR
+	      || kind == CPTK_HAS_TRIVIAL_COPY
+	      || kind == CPTK_HAS_TRIVIAL_DESTRUCTOR
+	      || kind == CPTK_HAS_VIRTUAL_DESTRUCTOR	      
+	      || kind == CPTK_IS_ABSTRACT
+	      || kind == CPTK_IS_BASE_OF
+	      || kind == CPTK_IS_CLASS
+	      || kind == CPTK_IS_CONVERTIBLE_TO
+	      || kind == CPTK_IS_EMPTY
+	      || kind == CPTK_IS_ENUM
+	      || kind == CPTK_IS_POD
+	      || kind == CPTK_IS_POLYMORPHIC
+	      || kind == CPTK_IS_UNION);
+
+  if (kind == CPTK_IS_CONVERTIBLE_TO)
+    {
+      sorry ("__is_convertible_to");
+      return error_mark_node;
+    }
+
+  if (type1 == error_mark_node
+      || ((kind == CPTK_IS_BASE_OF || kind == CPTK_IS_CONVERTIBLE_TO)
+	  && type2 == error_mark_node))
+    return error_mark_node;
+
+  if (processing_template_decl)
+    {
+      tree trait_expr = make_node (TRAIT_EXPR);
+      TREE_TYPE (trait_expr) = boolean_type_node;
+      TRAIT_EXPR_TYPE1 (trait_expr) = type1;
+      TRAIT_EXPR_TYPE2 (trait_expr) = type2;
+      TRAIT_EXPR_KIND (trait_expr) = kind;
+      return trait_expr;
+    }
+
+  /* The only required diagnostic.  */
+  if (kind == CPTK_IS_BASE_OF
+      && NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2)
+      && !same_type_ignoring_top_level_qualifiers_p (type1, type2)
+      && !COMPLETE_TYPE_P (type2))
+    {
+      error ("incomplete type %qT not allowed", type2);
+      return error_mark_node;
+    }
+
+  return (trait_expr_value (kind, type1, type2)
+	  ? boolean_true_node : boolean_false_node);
+}
+
 #include "gt-cp-semantics.h"
Index: gcc/cp/lex.c
===================================================================
--- gcc/cp/lex.c	(revision 123155)
+++ gcc/cp/lex.c	(working copy)
@@ -199,6 +199,23 @@
   { "__const__",	RID_CONST,	0 },
   { "__extension__",	RID_EXTENSION,	0 },
   { "__func__",		RID_C99_FUNCTION_NAME,	0 },
+  { "__has_nothrow_assign", RID_HAS_NOTHROW_ASSIGN, 0 },
+  { "__has_nothrow_constructor", RID_HAS_NOTHROW_CONSTRUCTOR, 0 },
+  { "__has_nothrow_copy", RID_HAS_NOTHROW_COPY, 0 },
+  { "__has_trivial_assign", RID_HAS_TRIVIAL_ASSIGN, 0 },
+  { "__has_trivial_constructor", RID_HAS_TRIVIAL_CONSTRUCTOR, 0 },
+  { "__has_trivial_copy", RID_HAS_TRIVIAL_COPY, 0 },
+  { "__has_trivial_destructor", RID_HAS_TRIVIAL_DESTRUCTOR, 0 },
+  { "__has_virtual_destructor", RID_HAS_VIRTUAL_DESTRUCTOR, 0 },
+  { "__is_abstract",	RID_IS_ABSTRACT, 0 },
+  { "__is_base_of",	RID_IS_BASE_OF, 0 },
+  { "__is_class",	RID_IS_CLASS,	0 },
+  { "__is_convertible_to", RID_IS_CONVERTIBLE_TO, 0 },
+  { "__is_empty",	RID_IS_EMPTY,	0 },
+  { "__is_enum",	RID_IS_ENUM,	0 },
+  { "__is_pod",		RID_IS_POD,	0 },
+  { "__is_polymorphic",	RID_IS_POLYMORPHIC, 0 },
+  { "__is_union",	RID_IS_UNION,	0 },
   { "__imag",		RID_IMAGPART,	0 },
   { "__imag__",		RID_IMAGPART,	0 },
   { "__inline",		RID_INLINE,	0 },
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 123155)
+++ gcc/cp/parser.c	(working copy)
@@ -1895,6 +1895,8 @@
   (cp_parser *, tree);
 static tree cp_parser_sizeof_operand
   (cp_parser *, enum rid);
+static tree cp_parser_trait_expr
+  (cp_parser *, enum rid);
 static bool cp_parser_declares_only_class_p
   (cp_parser *);
 static void cp_parser_set_storage_class
@@ -2957,6 +2959,25 @@
      __builtin_va_arg ( assignment-expression , type-id )
      __builtin_offsetof ( type-id , offsetof-expression )
 
+   C++ Extensions:
+     __has_nothrow_assign ( type-id )   
+     __has_nothrow_constructor ( type-id )
+     __has_nothrow_copy ( type-id )
+     __has_trivial_assign ( type-id )   
+     __has_trivial_constructor ( type-id )
+     __has_trivial_copy ( type-id )
+     __has_trivial_destructor ( type-id )
+     __has_virtual_destructor ( type-id )     
+     __is_abstract ( type-id )
+     __is_base_of ( type-id , type-id )
+     __is_class ( type-id )
+     __is_convertible_to ( type-id , type-id )     
+     __is_empty ( type-id )
+     __is_enum ( type-id )
+     __is_pod ( type-id )
+     __is_polymorphic ( type-id )
+     __is_union ( type-id )
+
    Objective-C++ Extension:
 
    primary-expression:
@@ -3194,7 +3215,26 @@
 	case RID_OFFSETOF:
 	  return cp_parser_builtin_offsetof (parser);
 
-	  /* Objective-C++ expressions.  */
+	case RID_HAS_NOTHROW_ASSIGN:
+	case RID_HAS_NOTHROW_CONSTRUCTOR:
+	case RID_HAS_NOTHROW_COPY:	  
+	case RID_HAS_TRIVIAL_ASSIGN:
+	case RID_HAS_TRIVIAL_CONSTRUCTOR:
+	case RID_HAS_TRIVIAL_COPY:	  
+	case RID_HAS_TRIVIAL_DESTRUCTOR:
+	case RID_HAS_VIRTUAL_DESTRUCTOR:
+	case RID_IS_ABSTRACT:
+	case RID_IS_BASE_OF:
+	case RID_IS_CLASS:
+	case RID_IS_CONVERTIBLE_TO:
+	case RID_IS_EMPTY:
+	case RID_IS_ENUM:
+	case RID_IS_POD:
+	case RID_IS_POLYMORPHIC:
+	case RID_IS_UNION:
+	  return cp_parser_trait_expr (parser, token->keyword);
+
+	/* Objective-C++ expressions.  */
 	case RID_AT_ENCODE:
 	case RID_AT_PROTOCOL:
 	case RID_AT_SELECTOR:
@@ -6289,6 +6329,112 @@
   return expr;
 }
 
+/* Parse a trait expression.  */
+
+static tree
+cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
+{
+  cp_trait_kind kind;
+  tree type1, type2 = NULL_TREE;
+  bool binary = false;
+  cp_decl_specifier_seq decl_specs;
+
+  switch (keyword)
+    {
+    case RID_HAS_NOTHROW_ASSIGN:
+      kind = CPTK_HAS_NOTHROW_ASSIGN;
+      break;
+    case RID_HAS_NOTHROW_CONSTRUCTOR:
+      kind = CPTK_HAS_NOTHROW_CONSTRUCTOR;
+      break;
+    case RID_HAS_NOTHROW_COPY:
+      kind = CPTK_HAS_NOTHROW_COPY;
+      break;
+    case RID_HAS_TRIVIAL_ASSIGN:
+      kind = CPTK_HAS_TRIVIAL_ASSIGN;
+      break;
+    case RID_HAS_TRIVIAL_CONSTRUCTOR:
+      kind = CPTK_HAS_TRIVIAL_CONSTRUCTOR;
+      break;
+    case RID_HAS_TRIVIAL_COPY:
+      kind = CPTK_HAS_TRIVIAL_COPY;
+      break;
+    case RID_HAS_TRIVIAL_DESTRUCTOR:
+      kind = CPTK_HAS_TRIVIAL_DESTRUCTOR;
+      break;
+    case RID_HAS_VIRTUAL_DESTRUCTOR:
+      kind = CPTK_HAS_VIRTUAL_DESTRUCTOR;
+      break;
+    case RID_IS_ABSTRACT:
+      kind = CPTK_IS_ABSTRACT;
+      break;
+    case RID_IS_BASE_OF:
+      kind = CPTK_IS_BASE_OF;
+      binary = true;
+      break;
+    case RID_IS_CLASS:
+      kind = CPTK_IS_CLASS;
+      break;
+    case RID_IS_CONVERTIBLE_TO:
+      kind = CPTK_IS_CONVERTIBLE_TO;
+      binary = true;
+      break;
+    case RID_IS_EMPTY:
+      kind = CPTK_IS_EMPTY;
+      break;
+    case RID_IS_ENUM:
+      kind = CPTK_IS_ENUM;
+      break;
+    case RID_IS_POD:
+      kind = CPTK_IS_POD;
+      break;
+    case RID_IS_POLYMORPHIC:
+      kind = CPTK_IS_POLYMORPHIC;
+      break;
+    case RID_IS_UNION:
+      kind = CPTK_IS_UNION;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  /* Consume the token.  */
+  cp_lexer_consume_token (parser->lexer);
+
+  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+
+  type1 = cp_parser_type_id (parser);
+
+  /* Build a trivial decl-specifier-seq.  */
+  clear_decl_specs (&decl_specs);
+  decl_specs.type = type1;
+
+  /* Call grokdeclarator to figure out what type this is.  */
+  type1 = grokdeclarator (NULL, &decl_specs, TYPENAME,
+			  /*initialized=*/0, /*attrlist=*/NULL);
+
+  if (binary)
+    {
+      cp_parser_require (parser, CPP_COMMA, "`,'");
+ 
+      type2 = cp_parser_type_id (parser);
+
+      /* Build a trivial decl-specifier-seq.  */
+      clear_decl_specs (&decl_specs);
+      decl_specs.type = type2;
+
+      /* Call grokdeclarator to figure out what type this is.  */
+      type2 = grokdeclarator (NULL, &decl_specs, TYPENAME,
+			      /*initialized=*/0, /*attrlist=*/NULL);
+    }
+
+  cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+
+  /* Complete the trait expr, which may mean either processing the
+     static assert now or saving it for template instantiation.  */
+  return finish_trait_expr (kind, type1, type2);
+}
+
 /* Statements [gram.stmt.stmt]  */
 
 /* Parse a statement.
Index: gcc/c-common.h
===================================================================
--- gcc/c-common.h	(revision 123155)
+++ gcc/c-common.h	(working copy)
@@ -90,6 +90,17 @@
   /* casts */
   RID_CONSTCAST, RID_DYNCAST, RID_REINTCAST, RID_STATCAST,
 
+  /* C++ extensions */
+  RID_HAS_NOTHROW_ASSIGN,      RID_HAS_NOTHROW_CONSTRUCTOR,
+  RID_HAS_NOTHROW_COPY,        RID_HAS_TRIVIAL_ASSIGN,
+  RID_HAS_TRIVIAL_CONSTRUCTOR, RID_HAS_TRIVIAL_COPY,
+  RID_HAS_TRIVIAL_DESTRUCTOR,  RID_HAS_VIRTUAL_DESTRUCTOR,
+  RID_IS_ABSTRACT,             RID_IS_BASE_OF,
+  RID_IS_CONVERTIBLE_TO,       RID_IS_CLASS,
+  RID_IS_EMPTY,                RID_IS_ENUM,
+  RID_IS_POD,                  RID_IS_POLYMORPHIC,
+  RID_IS_UNION,
+
   /* C++0x */
   RID_STATIC_ASSERT,
 
Index: libstdc++-v3/include/bits/valarray_array.h
===================================================================
--- libstdc++-v3/include/bits/valarray_array.h	(revision 123157)
+++ libstdc++-v3/include/bits/valarray_array.h	(working copy)
@@ -1,6 +1,6 @@
 // The template and inlines for the -*- C++ -*- internal _Array helper class.
 
-// Copyright (C) 1997, 1998, 1999, 2000, 2003, 2004, 2005, 2006
+// Copyright (C) 1997, 1998, 1999, 2000, 2003, 2004, 2005, 2006, 2007
 //  Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
@@ -98,7 +98,7 @@
     inline void
     __valarray_default_construct(_Tp* __restrict__ __b, _Tp* __restrict__ __e)
     {
-      _Array_default_ctor<_Tp, __is_pod<_Tp>::__value>::_S_do_it(__b, __e);
+      _Array_default_ctor<_Tp, __is_pod(_Tp)>::_S_do_it(__b, __e);
     }
 
   // Turn a raw-memory into an array of _Tp filled with __t
@@ -133,7 +133,7 @@
     __valarray_fill_construct(_Tp* __restrict__ __b, _Tp* __restrict__ __e,
 			      const _Tp __t)
     {
-      _Array_init_ctor<_Tp, __is_pod<_Tp>::__value>::_S_do_it(__b, __e, __t);
+      _Array_init_ctor<_Tp, __is_pod(_Tp)>::_S_do_it(__b, __e, __t);
     }
 
   //
@@ -169,7 +169,7 @@
 			      const _Tp* __restrict__ __e,
 			      _Tp* __restrict__ __o)
     {
-      _Array_copy_ctor<_Tp, __is_pod<_Tp>::__value>::_S_do_it(__b, __e, __o);
+      _Array_copy_ctor<_Tp, __is_pod(_Tp)>::_S_do_it(__b, __e, __o);
     }
 
   // copy-construct raw array [__o, *) from strided array __a[<__n : __s>]
@@ -178,7 +178,7 @@
     __valarray_copy_construct (const _Tp* __restrict__ __a, size_t __n,
 			       size_t __s, _Tp* __restrict__ __o)
     {
-      if (__is_pod<_Tp>::__value)
+      if (__is_pod(_Tp))
 	while (__n--)
 	  {
 	    *__o++ = *__a;
@@ -199,7 +199,7 @@
 			       const size_t* __restrict__ __i,
 			       _Tp* __restrict__ __o, size_t __n)
     {
-      if (__is_pod<_Tp>::__value)
+      if (__is_pod(_Tp))
 	while (__n--)
 	  *__o++ = __a[*__i++];
       else
@@ -212,7 +212,7 @@
     inline void
     __valarray_destroy_elements(_Tp* __restrict__ __b, _Tp* __restrict__ __e)
     {
-      if (!__is_pod<_Tp>::__value)
+      if (!__is_pod(_Tp))
 	while (__b != __e)
 	  {
 	    __b->~_Tp();
@@ -276,7 +276,7 @@
     __valarray_copy(const _Tp* __restrict__ __a, size_t __n,
 		    _Tp* __restrict__ __b)
     {
-      _Array_copier<_Tp, __is_pod<_Tp>::__value>::_S_do_it(__a, __n, __b);
+      _Array_copier<_Tp, __is_pod(_Tp)>::_S_do_it(__a, __n, __b);
     }
 
   // Copy strided array __a[<__n : __s>] in plain __b[<__n>]
Index: libstdc++-v3/include/bits/cpp_type_traits.h
===================================================================
--- libstdc++-v3/include/bits/cpp_type_traits.h	(revision 123157)
+++ libstdc++-v3/include/bits/cpp_type_traits.h	(working copy)
@@ -1,6 +1,6 @@
 // The  -*- C++ -*- type traits classes for internal use in libstdc++
 
-// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
 // Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
@@ -80,20 +80,6 @@
 
 _GLIBCXX_BEGIN_NAMESPACE(std)
 
-namespace __detail
-{
-  // NB: g++ can not compile these if declared within the class
-  // __is_pod itself.
-  typedef char __one;
-  typedef char __two[2];
-
-  template<typename _Tp>
-  __one __test_type(int _Tp::*);
-  template<typename _Tp>
-  __two& __test_type(...);
-} // namespace __detail
-
-
   struct __true_type { };
   struct __false_type { };
 
@@ -341,38 +327,7 @@
     : public __traitor<__is_arithmetic<_Tp>, __is_pointer<_Tp> >
     { };
 
-  // For the immediate use, the following is a good approximation.
-  template<typename _Tp>
-    struct __is_pod
-    {
-      enum
-	{
-	  __value = (sizeof(__detail::__test_type<_Tp>(0))
-		     != sizeof(__detail::__one))
-	};
-    };
-
   //
-  // A stripped-down version of std::tr1::is_empty
-  //
-  template<typename _Tp>
-    struct __is_empty
-    { 
-    private:
-      template<typename>
-        struct __first { };
-      template<typename _Up>
-        struct __second
-        : public _Up { };
-           
-    public:
-      enum
-	{
-	  __value = sizeof(__first<_Tp>) == sizeof(__second<_Tp>)
-	};
-    };
-
-  //
   // For use in std::copy and std::find overloads for streambuf iterators.
   //
   template<typename _Tp>
Index: libstdc++-v3/include/bits/allocator.h
===================================================================
--- libstdc++-v3/include/bits/allocator.h	(revision 123157)
+++ libstdc++-v3/include/bits/allocator.h	(working copy)
@@ -1,6 +1,6 @@
 // Allocators -*- C++ -*-
 
-// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006
+// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007
 // Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
@@ -132,7 +132,7 @@
 #undef __glibcxx_base_allocator
 
   // To implement Option 3 of DR 431.
-  template<typename _Alloc, bool = std::__is_empty<_Alloc>::__value>
+  template<typename _Alloc, bool = __is_empty(_Alloc)>
     struct __alloc_swap
     { static void _S_do_it(_Alloc&, _Alloc&) { } };
 
Index: libstdc++-v3/include/bits/stl_tree.h
===================================================================
--- libstdc++-v3/include/bits/stl_tree.h	(revision 123157)
+++ libstdc++-v3/include/bits/stl_tree.h	(working copy)
@@ -393,7 +393,7 @@
 
     protected:
       template<typename _Key_compare, 
-	       bool _Is_pod_comparator = std::__is_pod<_Key_compare>::__value>
+	       bool _Is_pod_comparator = __is_pod(_Key_compare)>
         struct _Rb_tree_impl : public _Node_allocator
         {
 	  _Key_compare		_M_key_compare;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]