public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: C++ PATCHes to add __is_trivially_*
@ 2014-09-30 22:48 Ville Voutilainen
  2014-10-01  2:16 ` Jason Merrill
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Ville Voutilainen @ 2014-09-30 22:48 UTC (permalink / raw)
  To: Paolo Carlini, Jason Merrill, gcc-patches, libstdc++

>>Ville asked for help with the necessary compiler intrinsics for the is_trivially_* >>C++11 library traits. The first patch cleans up a few oddities I noticed with the
>Great. I think this can be as well marked as PR c++/26099.

There's also PR c++/63362.

The intrinsics still fail to support certain variadic cases, such as

template <class T, class... Args> void bar() {
  static_assert(__is_trivially_constructible(T, Args...), "");
}

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

* Re: C++ PATCHes to add __is_trivially_*
  2014-09-30 22:48 C++ PATCHes to add __is_trivially_* Ville Voutilainen
@ 2014-10-01  2:16 ` Jason Merrill
  2014-10-01  8:05 ` Paolo Carlini
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 9+ messages in thread
From: Jason Merrill @ 2014-10-01  2:16 UTC (permalink / raw)
  To: Ville Voutilainen, Paolo Carlini, gcc-patches, libstdc++

On 09/30/2014 06:48 PM, Ville Voutilainen wrote:
> The intrinsics still fail to support certain variadic cases, such as
>
> template <class T, class... Args> void bar() {
>    static_assert(__is_trivially_constructible(T, Args...), "");
> }

Oops.

Jason


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

* Re: C++ PATCHes to add __is_trivially_*
  2014-09-30 22:48 C++ PATCHes to add __is_trivially_* Ville Voutilainen
  2014-10-01  2:16 ` Jason Merrill
@ 2014-10-01  8:05 ` Paolo Carlini
  2014-10-01  8:11 ` Paolo Carlini
  2014-10-01 17:20 ` Jason Merrill
  3 siblings, 0 replies; 9+ messages in thread
From: Paolo Carlini @ 2014-10-01  8:05 UTC (permalink / raw)
  To: Ville Voutilainen, Jason Merrill, gcc-patches, libstdc++

Hi,

On 10/01/2014 12:48 AM, Ville Voutilainen wrote:
>>> Ville asked for help with the necessary compiler intrinsics for the is_trivially_* >>C++11 library traits. The first patch cleans up a few oddities I noticed with the
>> Great. I think this can be as well marked as PR c++/26099.
> There's also PR c++/63362.
I see. Then we can resolve both, I'll do that.

Thanks!
Paolo.

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

* Re: C++ PATCHes to add __is_trivially_*
  2014-09-30 22:48 C++ PATCHes to add __is_trivially_* Ville Voutilainen
  2014-10-01  2:16 ` Jason Merrill
  2014-10-01  8:05 ` Paolo Carlini
@ 2014-10-01  8:11 ` Paolo Carlini
  2014-10-01  8:48   ` Ville Voutilainen
  2014-10-01 17:20 ` Jason Merrill
  3 siblings, 1 reply; 9+ messages in thread
From: Paolo Carlini @ 2014-10-01  8:11 UTC (permalink / raw)
  To: Ville Voutilainen, Jason Merrill, gcc-patches, libstdc++

Hi again,

On 10/01/2014 12:48 AM, Ville Voutilainen wrote:
> The intrinsics still fail to support certain variadic cases, such as 
> template <class T, class... Args> void bar() { 
> static_assert(__is_trivially_constructible(T, Args...), ""); } 
... depending on your arrangements with Jason you may or may not want to 
open a separate bug report for this...

Paolo.

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

* Re: C++ PATCHes to add __is_trivially_*
  2014-10-01  8:11 ` Paolo Carlini
@ 2014-10-01  8:48   ` Ville Voutilainen
  0 siblings, 0 replies; 9+ messages in thread
From: Ville Voutilainen @ 2014-10-01  8:48 UTC (permalink / raw)
  To: Paolo Carlini; +Cc: Jason Merrill, gcc-patches, libstdc++

On 1 October 2014 11:11, Paolo Carlini <paolo.carlini@oracle.com> wrote:
> Hi again,
>
> On 10/01/2014 12:48 AM, Ville Voutilainen wrote:
>>
>> The intrinsics still fail to support certain variadic cases, such as
>> template <class T, class... Args> void bar() {
>> static_assert(__is_trivially_constructible(T, Args...), ""); }
>
> ... depending on your arrangements with Jason you may or may not want to
> open a separate bug report for this...

It's a tad incorrect/premature to close c++/63362 as resolved yet.
is_trivially_constructible
is a variadic trait, so while that example is for a function template,
we need to do exactly
that sort of an operation in the trait class, so the intrinsic needs
to support variadic
arguments. I don't think the status of the bug is a big deal though,
I'm sure Jason knows
this issue. :)

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

* Re: C++ PATCHes to add __is_trivially_*
  2014-09-30 22:48 C++ PATCHes to add __is_trivially_* Ville Voutilainen
                   ` (2 preceding siblings ...)
  2014-10-01  8:11 ` Paolo Carlini
@ 2014-10-01 17:20 ` Jason Merrill
  2014-10-01 17:38   ` Ville Voutilainen
  3 siblings, 1 reply; 9+ messages in thread
From: Jason Merrill @ 2014-10-01 17:20 UTC (permalink / raw)
  To: Ville Voutilainen, Paolo Carlini, gcc-patches, libstdc++

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

On 09/30/2014 06:48 PM, Ville Voutilainen wrote:
>>> Ville asked for help with the necessary compiler intrinsics for the is_trivially_* >>C++11 library traits. The first patch cleans up a few oddities I noticed with the
>> Great. I think this can be as well marked as PR c++/26099.
>
> There's also PR c++/63362.
>
> The intrinsics still fail to support certain variadic cases, such as
>
> template <class T, class... Args> void bar() {
>    static_assert(__is_trivially_constructible(T, Args...), "");
> }

Here are two more patches: the first fixes trivial_fn_p for a defaulted 
default constructor overloaded with a template default constructor, and 
the second fixes the variadic case above.



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

commit 68a53de3f12b1d2adacf39d59836a558cc257759
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Sep 30 17:24:13 2014 -0400

    	PR c++/63362
    	* class.c (type_has_non_user_provided_default_constructor): Rename
    	from type_has_user_provided_default_constructor, reverse sense.
    	(default_init_uninitialized_part, explain_non_literal_class): Adjust.
    	(check_bases_and_members): Set TYPE_HAS_COMPLEX_DFLT.
    	* call.c (build_new_method_call_1): Adjust.
    	* cp-tree.h: Adjust.
    	* decl.c (grok_special_member_properties): Don't set
    	TYPE_HAS_COMPLEX_DFLT.
    	* init.c (build_value_init_noctor): Don't use
    	type_has_user_provided_default_constructor.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 8f1b91a..3c8b338 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -7941,7 +7941,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
 	  && TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype)
 	  /* For a user-provided default constructor, use the normal
 	     mechanisms so that protected access works.  */
-	  && !type_has_user_provided_default_constructor (basetype)
+	  && type_has_non_user_provided_default_constructor (basetype)
 	  && !processing_template_decl)
 	init = build_value_init (basetype, complain);
 
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index acf5768..12ac30a 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -4937,21 +4937,25 @@ type_has_user_provided_constructor (tree t)
   return false;
 }
 
-/* Returns true iff class T has a user-provided default constructor.  */
+/* Returns true iff class T has a non-user-provided (i.e. implicitly
+   declared or explicitly defaulted in the class body) default
+   constructor.  */
 
 bool
-type_has_user_provided_default_constructor (tree t)
+type_has_non_user_provided_default_constructor (tree t)
 {
   tree fns;
 
-  if (!TYPE_HAS_USER_CONSTRUCTOR (t))
+  if (!TYPE_HAS_DEFAULT_CONSTRUCTOR (t))
     return false;
+  if (CLASSTYPE_LAZY_DEFAULT_CTOR (t))
+    return true;
 
   for (fns = CLASSTYPE_CONSTRUCTORS (t); fns; fns = OVL_NEXT (fns))
     {
       tree fn = OVL_CURRENT (fns);
       if (TREE_CODE (fn) == FUNCTION_DECL
-	  && user_provided_p (fn)
+	  && !user_provided_p (fn)
 	  && sufficient_parms_p (FUNCTION_FIRST_USER_PARMTYPE (fn)))
 	return true;
     }
@@ -5009,7 +5013,7 @@ default_init_uninitialized_part (tree type)
   type = strip_array_types (type);
   if (!CLASS_TYPE_P (type))
     return type;
-  if (type_has_user_provided_default_constructor (type))
+  if (!type_has_non_user_provided_default_constructor (type))
     return NULL_TREE;
   for (binfo = TYPE_BINFO (type), i = 0;
        BINFO_BASE_ITERATE (binfo, i, t); ++i)
@@ -5383,8 +5387,7 @@ explain_non_literal_class (tree t)
       inform (0, "  %q+T is not an aggregate, does not have a trivial "
 	      "default constructor, and has no constexpr constructor that "
 	      "is not a copy or move constructor", t);
-      if (TYPE_HAS_DEFAULT_CONSTRUCTOR (t)
-	  && !type_has_user_provided_default_constructor (t))
+      if (type_has_non_user_provided_default_constructor (t))
 	{
 	  /* Note that we can't simply call locate_ctor because when the
 	     constructor is deleted it just returns NULL_TREE.  */
@@ -5528,6 +5531,13 @@ check_bases_and_members (tree t)
   TYPE_HAS_COMPLEX_MOVE_ASSIGN (t) |= TYPE_CONTAINS_VPTR_P (t);
   TYPE_HAS_COMPLEX_DFLT (t) |= TYPE_CONTAINS_VPTR_P (t);
 
+  /* If the only explicitly declared default constructor is user-provided,
+     set TYPE_HAS_COMPLEX_DFLT.  */
+  if (!TYPE_HAS_COMPLEX_DFLT (t)
+      && TYPE_HAS_DEFAULT_CONSTRUCTOR (t)
+      && !type_has_non_user_provided_default_constructor (t))
+    TYPE_HAS_COMPLEX_DFLT (t) = true;
+
   /* Warn if a public base of a polymorphic type has an accessible
      non-virtual destructor.  It is only now that we know the class is
      polymorphic.  Although a polymorphic base will have a already
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index b2b9063..14ec837 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3484,7 +3484,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
 /* Nonzero if there is a non-trivial X::X(X&&) for this class.  */
 #define TYPE_HAS_COMPLEX_MOVE_CTOR(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_complex_move_ctor)
 
-/* Nonzero if there is a non-trivial default constructor for this class.  */
+/* Nonzero if there is no trivial 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]:
@@ -5195,7 +5195,7 @@ extern bool type_has_user_nondefault_constructor (tree);
 extern tree in_class_defaulted_default_constructor (tree);
 extern bool user_provided_p			(tree);
 extern bool type_has_user_provided_constructor  (tree);
-extern bool type_has_user_provided_default_constructor (tree);
+extern bool type_has_non_user_provided_default_constructor (tree);
 extern bool vbase_has_user_provided_move_assign (tree);
 extern tree default_init_uninitialized_part (tree);
 extern bool trivial_default_constructor_is_constexpr (tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index d26a432..7856dd8 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -11476,11 +11476,7 @@ grok_special_member_properties (tree decl)
 	    TYPE_HAS_CONST_COPY_CTOR (class_type) = 1;
 	}
       else if (sufficient_parms_p (FUNCTION_FIRST_USER_PARMTYPE (decl)))
-	{
-	  TYPE_HAS_DEFAULT_CONSTRUCTOR (class_type) = 1;
-	  if (user_provided_p (decl))
-	    TYPE_HAS_COMPLEX_DFLT (class_type) = 1;
-	}
+	TYPE_HAS_DEFAULT_CONSTRUCTOR (class_type) = 1;
       else if (move_fn_p (decl) && user_provided_p (decl))
 	TYPE_HAS_COMPLEX_MOVE_CTOR (class_type) = 1;
       else if (is_list_ctor (decl))
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index f0ca9b9..6851fe9 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -343,13 +343,17 @@ build_value_init (tree type, tsubst_flags_t complain)
   if (CLASS_TYPE_P (type)
       && type_build_ctor_call (type))
     {
-      tree ctor = build_aggr_init_expr
-	(type,
+      tree ctor =
 	 build_special_member_call (NULL_TREE, complete_ctor_identifier,
 				    NULL, type, LOOKUP_NORMAL,
-				    complain));
-      if (ctor == error_mark_node
-	  || type_has_user_provided_default_constructor (type))
+				    complain);
+      if (ctor == error_mark_node)
+	return ctor;
+      tree fn = NULL_TREE;
+      if (TREE_CODE (ctor) == CALL_EXPR)
+	fn = get_callee_fndecl (ctor);
+      ctor = build_aggr_init_expr (type, ctor);
+      if (fn && user_provided_p (fn))
 	return ctor;
       else if (TYPE_HAS_COMPLEX_DFLT (type))
 	{
diff --git a/gcc/testsuite/g++.dg/ext/is_trivially_constructible2.C b/gcc/testsuite/g++.dg/ext/is_trivially_constructible2.C
new file mode 100644
index 0000000..4e0a657
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_trivially_constructible2.C
@@ -0,0 +1,15 @@
+// { dg-do compile { target c++11 } }
+
+struct X {
+  X() = default;
+  template<class... U> X(U...);
+};
+
+struct Y {
+  template<class... U> Y(U...);
+};
+
+#define SA(X) static_assert((X),#X)
+
+SA(__is_trivially_constructible(X));
+SA(!__is_trivially_constructible(Y));

commit 591e70a3906af599160ec59287f20ed20b8082ca
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Oct 1 13:00:49 2014 -0400

    	PR c++/63362
    	* method.c (constructible_expr): Handle value-init of non-class.
    	* parser.c (cp_parser_trait_expr): Allow pack expansion.
    	* pt.c (tsubst_copy_and_build): Handle pack expansion.

diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 9a2bd0f..8828986 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1077,7 +1077,9 @@ constructible_expr (tree to, tree from)
     }
   else
     {
-      if (TREE_CHAIN (from))
+      if (from == NULL_TREE)
+	return build_value_init (to, tf_none);
+      else if (TREE_CHAIN (from))
 	return error_mark_node; // too many initializers
       from = build_stub_object (TREE_VALUE (from));
       expr = perform_direct_initialization_if_possible (to, from,
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index e4aaf53..01b2fad 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -8780,6 +8780,11 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
 	{
 	  cp_lexer_consume_token (parser->lexer);
 	  tree elt = cp_parser_type_id (parser);
+	  if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
+	    {
+	      cp_lexer_consume_token (parser->lexer);
+	      elt = make_pack_expansion (elt);
+	    }
 	  if (elt == error_mark_node)
 	    return error_mark_node;
 	  type2 = tree_cons (NULL_TREE, elt, type2);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 9dd61f3..f03e74c 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -15487,7 +15487,9 @@ tsubst_copy_and_build (tree t,
 			     complain, in_decl);
 
 	tree type2 = TRAIT_EXPR_TYPE2 (t);
-	if (type2)
+	if (type2 && TREE_CODE (type2) == TREE_LIST)
+	  type2 = RECUR (type2);
+	else if (type2)
 	  type2 = tsubst (type2, args, complain, in_decl);
 	
 	RETURN (finish_trait_expr (TRAIT_EXPR_KIND (t), type1, type2));
diff --git a/gcc/testsuite/g++.dg/ext/is_trivially_constructible3.C b/gcc/testsuite/g++.dg/ext/is_trivially_constructible3.C
new file mode 100644
index 0000000..02a678a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_trivially_constructible3.C
@@ -0,0 +1,8 @@
+// { dg-do compile { target c++11 } }
+
+template <class T, class... Args> void bar() {
+  static_assert(__is_trivially_constructible(T, Args...), "");
+}
+
+template void bar<int>();
+template void bar<int,int>();

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

* Re: C++ PATCHes to add __is_trivially_*
  2014-10-01 17:20 ` Jason Merrill
@ 2014-10-01 17:38   ` Ville Voutilainen
  0 siblings, 0 replies; 9+ messages in thread
From: Ville Voutilainen @ 2014-10-01 17:38 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Paolo Carlini, gcc-patches, libstdc++

On 1 October 2014 20:20, Jason Merrill <jason@redhat.com> wrote:
> Here are two more patches: the first fixes trivial_fn_p for a defaulted
> default constructor overloaded with a template default constructor, and the
> second fixes the variadic case above.


Excellent, thank you very much. Paolo, feel free to close PR c++/63362 now,
unless you wish to keep it open until the library bits are done, which I will do
as soon as possible.

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

* Re: C++ PATCHes to add __is_trivially_*
  2014-09-30 17:13 Jason Merrill
@ 2014-09-30 17:34 ` Paolo Carlini
  0 siblings, 0 replies; 9+ messages in thread
From: Paolo Carlini @ 2014-09-30 17:34 UTC (permalink / raw)
  To: Jason Merrill, gcc-patches List, libstdc++

Hi,

On 09/30/2014 07:13 PM, Jason Merrill wrote:
> Ville asked for help with the necessary compiler intrinsics for the 
> is_trivially_* C++11 library traits.
>
> The first patch cleans up a few oddities I noticed with the existing 
> intrinsics.  __is_convertible_to was never implemented and isn't 
> needed.  There's no need for a second grokdeclarator in trait parsing 
> since cp_parser_type_id already does a grokdeclarator.  And the assert 
> at the top of finish_trait_expr is redundant with the gcc_unreachable 
> in the switch.
>
> The second patch adds __is_trivially_copyable, which just uses the 
> existing trivially_copyable_p predicate in the compiler.
>
> The third patch adds __is_trivially_assignable and 
> __is_trivially_constructible, which work by building up an expression 
> representing assignment or object declaration and then scanning it for 
> calls to functions other than trivial special member functions.  Note 
> that there are still bugs in trivial_fn_p that are exposed by this 
> intrinsic.
Great. I think this can be as well marked as PR c++/26099.

By the way, if I remember correctly, the idea of having 
__is_convertible_to leading to unimplemented instead of simply being not 
recognized, goes back to this kind of idea:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2518.html

and Intel too was in favor of somewhat standardizing those intrinsics. 
In fact, both current icc and clang++ accept and implement 
__is_convertible_to.

Paolo.

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

* C++ PATCHes to add __is_trivially_*
@ 2014-09-30 17:13 Jason Merrill
  2014-09-30 17:34 ` Paolo Carlini
  0 siblings, 1 reply; 9+ messages in thread
From: Jason Merrill @ 2014-09-30 17:13 UTC (permalink / raw)
  To: gcc-patches List, libstdc++

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

Ville asked for help with the necessary compiler intrinsics for the 
is_trivially_* C++11 library traits.

The first patch cleans up a few oddities I noticed with the existing 
intrinsics.  __is_convertible_to was never implemented and isn't needed. 
  There's no need for a second grokdeclarator in trait parsing since 
cp_parser_type_id already does a grokdeclarator.  And the assert at the 
top of finish_trait_expr is redundant with the gcc_unreachable in the 
switch.

The second patch adds __is_trivially_copyable, which just uses the 
existing trivially_copyable_p predicate in the compiler.

The third patch adds __is_trivially_assignable and 
__is_trivially_constructible, which work by building up an expression 
representing assignment or object declaration and then scanning it for 
calls to functions other than trivial special member functions.  Note 
that there are still bugs in trivial_fn_p that are exposed by this 
intrinsic.

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

[-- Attachment #2: trait-cleanup.patch --]
[-- Type: text/x-patch, Size: 8904 bytes --]

commit 7a3d9e80fb97691115e574915fd632f85c0974b7
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Sep 25 12:34:43 2014 -0400

    c-family/
    	* c-common.h (enum rid): Remove RID_IS_CONVERTIBLE_TO.
    	* c-common.c (c_common_reswords): Remove __is_convertible_to.
    cp/
    	* cp-tree.h (cp_trait_kind): Remove CPTK_IS_CONVERTIBLE_TO.
    	* cxx-pretty-print.c (pp_cxx_trait_expression): Likewise.
    	* semantics.c (trait_expr_value): Likewise.
    	(finish_trait_expr): Likewise.
    	* parser.c (cp_parser_primary_expression): Likewise.
    	(cp_parser_trait_expr): Likewise. Remove redundant grokdeclarator.

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index a9e0191..0324a0a 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -472,7 +472,6 @@ const struct c_common_resword c_common_reswords[] =
   { "__is_abstract",	RID_IS_ABSTRACT, D_CXXONLY },
   { "__is_base_of",	RID_IS_BASE_OF, D_CXXONLY },
   { "__is_class",	RID_IS_CLASS,	D_CXXONLY },
-  { "__is_convertible_to", RID_IS_CONVERTIBLE_TO, D_CXXONLY },
   { "__is_empty",	RID_IS_EMPTY,	D_CXXONLY },
   { "__is_enum",	RID_IS_ENUM,	D_CXXONLY },
   { "__is_final",	RID_IS_FINAL,	D_CXXONLY },
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 5ec79a0..5ba7859 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -138,7 +138,7 @@ enum rid
   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_CLASS,                RID_IS_CONVERTIBLE_TO,
+  RID_IS_CLASS,
   RID_IS_EMPTY,                RID_IS_ENUM,
   RID_IS_FINAL,                RID_IS_LITERAL_TYPE,
   RID_IS_POD,                  RID_IS_POLYMORPHIC,
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index b4a72d6..e6e90f7 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -354,9 +354,9 @@ DEFTREECODE (STMT_EXPR, "stmt_expr", tcc_expression, 1)
    is applied.  */
 DEFTREECODE (UNARY_PLUS_EXPR, "unary_plus_expr", tcc_unary, 1)
 
-/** C++0x extensions. */
+/** C++11 extensions. */
 
-/* A static assertion.  This is a C++0x extension.
+/* A static assertion.  This is a C++11 extension.
    STATIC_ASSERT_CONDITION contains the condition that is being
    checked.  STATIC_ASSERT_MESSAGE contains the message (a string
    literal) to be displayed if the condition fails to hold.  */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 5d8badc..0bb6ef9 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -645,7 +645,6 @@ typedef enum cp_trait_kind
   CPTK_IS_ABSTRACT,
   CPTK_IS_BASE_OF,
   CPTK_IS_CLASS,
-  CPTK_IS_CONVERTIBLE_TO,
   CPTK_IS_EMPTY,
   CPTK_IS_ENUM,
   CPTK_IS_FINAL,
diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
index f5f91c8..f0734ec 100644
--- a/gcc/cp/cxx-pretty-print.c
+++ b/gcc/cp/cxx-pretty-print.c
@@ -388,7 +388,6 @@ pp_cxx_userdef_literal (cxx_pretty_printer *pp, tree t)
      __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_literal_type ( type-id )
@@ -2373,9 +2372,6 @@ pp_cxx_trait_expression (cxx_pretty_printer *pp, tree t)
     case CPTK_IS_CLASS:
       pp_cxx_ws_string (pp, "__is_class");
       break;
-    case CPTK_IS_CONVERTIBLE_TO:
-      pp_cxx_ws_string (pp, "__is_convertible_to");
-      break;
     case CPTK_IS_EMPTY:
       pp_cxx_ws_string (pp, "__is_empty");
       break;
@@ -2411,7 +2407,7 @@ pp_cxx_trait_expression (cxx_pretty_printer *pp, tree t)
   pp_cxx_left_paren (pp);
   pp->type_id (TRAIT_EXPR_TYPE1 (t));
 
-  if (kind == CPTK_IS_BASE_OF || kind == CPTK_IS_CONVERTIBLE_TO)
+  if (kind == CPTK_IS_BASE_OF)
     {
       pp_cxx_separate_with (pp, ',');
       pp->type_id (TRAIT_EXPR_TYPE2 (t));
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 4563145..63cc0d3 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -4134,7 +4134,6 @@ complain_flags (bool decltype_p)
      __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_final ( type-id )
@@ -4483,7 +4482,6 @@ cp_parser_primary_expression (cp_parser *parser,
 	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_FINAL:
@@ -8665,7 +8663,6 @@ 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)
     {
@@ -8703,10 +8700,6 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
     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;
@@ -8757,14 +8750,6 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
   if (type1 == error_mark_node)
     return error_mark_node;
 
-  /* 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, RT_COMMA);
@@ -8773,14 +8758,6 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
 
       if (type2 == error_mark_node)
 	return error_mark_node;
-
-      /* 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, RT_CLOSE_PAREN);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index debd785..3fbbb17 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -7355,10 +7355,6 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree 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));
 
@@ -7413,36 +7409,8 @@ check_trait_type (tree type)
 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_FINAL
-	      || kind == CPTK_IS_LITERAL_TYPE
-	      || 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)
-    {
-      sorry ("__is_convertible_to");
-      return error_mark_node;
-    }
-
   if (type1 == error_mark_node
-      || ((kind == CPTK_IS_BASE_OF || kind == CPTK_IS_CONVERTIBLE_TO)
+      || ((kind == CPTK_IS_BASE_OF)
 	  && type2 == error_mark_node))
     return error_mark_node;
 
@@ -7491,7 +7459,6 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_UNION:
       break;
     
-    case CPTK_IS_CONVERTIBLE_TO:
     default:
       gcc_unreachable ();
     }
diff --git a/gcc/testsuite/g++.dg/ext/is_class_error2.C b/gcc/testsuite/g++.dg/ext/is_class_error2.C
index 8649dc4..b8c0385 100644
--- a/gcc/testsuite/g++.dg/ext/is_class_error2.C
+++ b/gcc/testsuite/g++.dg/ext/is_class_error2.C
@@ -13,7 +13,6 @@ template<int> void foo()
   __is_abstract(int)(); // { dg-error "'__is_abstract\\(int\\)' cannot be used" }
   __is_base_of(int, float)(); // { dg-error "'__is_base_of\\(int, float\\)' cannot be used" }
   __is_class(int)(); // { dg-error "'__is_class\\(int\\)' cannot be used" }
-  __is_convertible_to(int, float)(); // { dg-message "unimplemented" }
   __is_empty(int)(); // { dg-error "'__is_empty\\(int\\)' cannot be used" }
   __is_enum(int)(); // { dg-error "'__is_enum\\(int\\)' cannot be used" }
   __is_pod(int)(); // { dg-error "'__is_pod\\(int\\)' cannot be used" }

[-- Attachment #3: is_trivially_copyable.patch --]
[-- Type: text/x-patch, Size: 3882 bytes --]

commit dc3e9ae069b4d55ca1d684fa5fa6f0757d997c60
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Sep 25 13:36:05 2014 -0400

    c-family/
    	* c-common.h (enum rid): Add RID_IS_TRIVIALLY_COPYABLE.
    	* c-common.c (c_common_reswords): Add __is_trivially_copyable.
    cp/
    	* cp-tree.h (cp_trait_kind): Add CPTK_IS_TRIVIALLY_COPYABLE.
    	* cxx-pretty-print.c (pp_cxx_trait_expression): Likewise.
    	* parser.c (cp_parser_primary_expression): Likewise.
    	(cp_parser_trait_expr): Likewise.
    	* semantics.c (trait_expr_value): Likewise.
    	(finish_trait_expr): Likewise.

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 0324a0a..482dd44 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -480,6 +480,7 @@ const struct c_common_resword c_common_reswords[] =
   { "__is_polymorphic",	RID_IS_POLYMORPHIC, D_CXXONLY },
   { "__is_standard_layout", RID_IS_STD_LAYOUT, D_CXXONLY },
   { "__is_trivial",     RID_IS_TRIVIAL, D_CXXONLY },
+  { "__is_trivially_copyable", RID_IS_TRIVIALLY_COPYABLE, D_CXXONLY },
   { "__is_union",	RID_IS_UNION,	D_CXXONLY },
   { "__label__",	RID_LABEL,	0 },
   { "__null",		RID_NULL,	0 },
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 5ba7859..b7e3385 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -143,6 +143,7 @@ enum rid
   RID_IS_FINAL,                RID_IS_LITERAL_TYPE,
   RID_IS_POD,                  RID_IS_POLYMORPHIC,
   RID_IS_STD_LAYOUT,           RID_IS_TRIVIAL,
+  RID_IS_TRIVIALLY_COPYABLE,
   RID_IS_UNION,                RID_UNDERLYING_TYPE,
 
   /* C++11 */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 0bb6ef9..c22fbfa 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -653,6 +653,7 @@ typedef enum cp_trait_kind
   CPTK_IS_POLYMORPHIC,
   CPTK_IS_STD_LAYOUT,
   CPTK_IS_TRIVIAL,
+  CPTK_IS_TRIVIALLY_COPYABLE,
   CPTK_IS_UNION,
   CPTK_UNDERLYING_TYPE
 } cp_trait_kind;
diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
index f0734ec..7b2d7fd 100644
--- a/gcc/cp/cxx-pretty-print.c
+++ b/gcc/cp/cxx-pretty-print.c
@@ -2393,6 +2393,9 @@ pp_cxx_trait_expression (cxx_pretty_printer *pp, tree t)
     case CPTK_IS_TRIVIAL:
       pp_cxx_ws_string (pp, "__is_trivial");
       break;
+    case CPTK_IS_TRIVIALLY_COPYABLE:
+      pp_cxx_ws_string (pp, "__is_trivially_copyable");
+      break;
     case CPTK_IS_UNION:
       pp_cxx_ws_string (pp, "__is_union");
       break;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 63cc0d3..b1feef5 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -4490,6 +4490,7 @@ cp_parser_primary_expression (cp_parser *parser,
 	case RID_IS_POLYMORPHIC:
 	case RID_IS_STD_LAYOUT:
 	case RID_IS_TRIVIAL:
+	case RID_IS_TRIVIALLY_COPYABLE:
 	case RID_IS_UNION:
 	  return cp_parser_trait_expr (parser, token->keyword);
 
@@ -8724,6 +8725,9 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
     case RID_IS_TRIVIAL:
       kind = CPTK_IS_TRIVIAL;
       break;
+    case RID_IS_TRIVIALLY_COPYABLE:
+      kind = CPTK_IS_TRIVIALLY_COPYABLE;
+      break;
     case RID_IS_UNION:
       kind = CPTK_IS_UNION;
       break;
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 3fbbb17..9bcc6d7 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -7379,6 +7379,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_TRIVIAL:
       return (trivial_type_p (type1));
 
+    case CPTK_IS_TRIVIALLY_COPYABLE:
+      return (trivially_copyable_p (type1));
+
     case CPTK_IS_UNION:
       return (type_code1 == UNION_TYPE);
 
@@ -7442,6 +7445,7 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_POLYMORPHIC:
     case CPTK_IS_STD_LAYOUT:
     case CPTK_IS_TRIVIAL:
+    case CPTK_IS_TRIVIALLY_COPYABLE:
       if (!check_trait_type (type1))
 	return error_mark_node;
       break;

[-- Attachment #4: is_trivially_xable.patch --]
[-- Type: text/x-patch, Size: 13101 bytes --]

commit 6d2c4c2a1d74c455d2a0fc381965a859088de606
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Sep 29 16:39:55 2014 -0400

    c-family/
    	* c-common.h (enum rid): Add RID_IS_TRIVIALLY_ASSIGNABLE and
    	RID_IS_TRIVIALLY_CONSTRUCTIBLE.
    	* c-common.c (c_common_reswords): Add __is_trivially_copyable.
    cp/
    	* cp-tree.h (cp_trait_kind): Add CPTK_IS_TRIVIALLY_ASSIGNABLE and
    	CPTK_IS_TRIVIALLY_CONSTRUCTIBLE.
    	* cxx-pretty-print.c (pp_cxx_trait_expression): Likewise.
    	* parser.c (cp_parser_primary_expression): Likewise.
    	(cp_parser_trait_expr): Likewise.  Handle variadic trait.
    	* semantics.c (trait_expr_value): Likewise.
    	(finish_trait_expr): Likewise.
    	(check_trait_type): Handle variadic trait.  Return bool.
    	* method.c (build_stub_object): Add rvalue reference here.
    	(locate_fn_flags): Not here.
    	(check_nontriv, assignable_expr, constructible_expr): New.
    	(is_trivially_xible): New.

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 482dd44..b16d030 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -480,6 +480,8 @@ const struct c_common_resword c_common_reswords[] =
   { "__is_polymorphic",	RID_IS_POLYMORPHIC, D_CXXONLY },
   { "__is_standard_layout", RID_IS_STD_LAYOUT, D_CXXONLY },
   { "__is_trivial",     RID_IS_TRIVIAL, D_CXXONLY },
+  { "__is_trivially_assignable", RID_IS_TRIVIALLY_ASSIGNABLE, D_CXXONLY },
+  { "__is_trivially_constructible", RID_IS_TRIVIALLY_CONSTRUCTIBLE, D_CXXONLY },
   { "__is_trivially_copyable", RID_IS_TRIVIALLY_COPYABLE, D_CXXONLY },
   { "__is_union",	RID_IS_UNION,	D_CXXONLY },
   { "__label__",	RID_LABEL,	0 },
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index b7e3385..1e3477f 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -143,6 +143,7 @@ enum rid
   RID_IS_FINAL,                RID_IS_LITERAL_TYPE,
   RID_IS_POD,                  RID_IS_POLYMORPHIC,
   RID_IS_STD_LAYOUT,           RID_IS_TRIVIAL,
+  RID_IS_TRIVIALLY_ASSIGNABLE, RID_IS_TRIVIALLY_CONSTRUCTIBLE,
   RID_IS_TRIVIALLY_COPYABLE,
   RID_IS_UNION,                RID_UNDERLYING_TYPE,
 
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index c22fbfa..cc11bba 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -653,6 +653,8 @@ typedef enum cp_trait_kind
   CPTK_IS_POLYMORPHIC,
   CPTK_IS_STD_LAYOUT,
   CPTK_IS_TRIVIAL,
+  CPTK_IS_TRIVIALLY_ASSIGNABLE,
+  CPTK_IS_TRIVIALLY_CONSTRUCTIBLE,
   CPTK_IS_TRIVIALLY_COPYABLE,
   CPTK_IS_UNION,
   CPTK_UNDERLYING_TYPE
@@ -5522,6 +5524,7 @@ extern tree make_thunk				(tree, bool, tree, tree);
 extern void finish_thunk			(tree);
 extern void use_thunk				(tree, bool);
 extern bool trivial_fn_p			(tree);
+extern bool is_trivially_xible			(enum tree_code, tree, tree);
 extern tree get_defaulted_eh_spec		(tree);
 extern tree unevaluated_noexcept_spec		(void);
 extern void after_nsdmi_defaulted_late_checks   (tree);
diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
index 7b2d7fd..67e84c0 100644
--- a/gcc/cp/cxx-pretty-print.c
+++ b/gcc/cp/cxx-pretty-print.c
@@ -2393,6 +2393,12 @@ pp_cxx_trait_expression (cxx_pretty_printer *pp, tree t)
     case CPTK_IS_TRIVIAL:
       pp_cxx_ws_string (pp, "__is_trivial");
       break;
+    case CPTK_IS_TRIVIALLY_ASSIGNABLE:
+      pp_cxx_ws_string (pp, "__is_trivially_assignable");
+      break;
+    case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE:
+      pp_cxx_ws_string (pp, "__is_trivially_constructible");
+      break;
     case CPTK_IS_TRIVIALLY_COPYABLE:
       pp_cxx_ws_string (pp, "__is_trivially_copyable");
       break;
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index b427d65..9a2bd0f 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -852,6 +852,8 @@ build_stub_type (tree type, int quals, bool rvalue)
 static tree
 build_stub_object (tree reftype)
 {
+  if (TREE_CODE (reftype) != REFERENCE_TYPE)
+    reftype = cp_build_reference_type (reftype, /*rval*/true);
   tree stub = build1 (CONVERT_EXPR, reftype, integer_one_node);
   return convert_from_reference (stub);
 }
@@ -889,8 +891,6 @@ locate_fn_flags (tree type, tree name, tree argtype, int flags,
 	       elt = TREE_CHAIN (elt))
 	    {
 	      tree type = TREE_VALUE (elt);
-	      if (TREE_CODE (type) != REFERENCE_TYPE)
-		type = cp_build_reference_type (type, /*rval*/true);
 	      tree arg = build_stub_object (type);
 	      vec_safe_push (args, arg);
 	    }
@@ -1001,6 +1001,113 @@ get_inherited_ctor (tree ctor)
   return fn;
 }
 
+/* walk_tree helper function for is_trivially_xible.  If *TP is a call,
+   return it if it calls something other than a trivial special member
+   function.  */
+
+static tree
+check_nontriv (tree *tp, int *, void *)
+{
+  tree fn;
+  if (TREE_CODE (*tp) == CALL_EXPR)
+    fn = CALL_EXPR_FN (*tp);
+  else if (TREE_CODE (*tp) == AGGR_INIT_EXPR)
+    fn = AGGR_INIT_EXPR_FN (*tp);
+  else
+    return NULL_TREE;
+
+  if (TREE_CODE (fn) == ADDR_EXPR)
+    fn = TREE_OPERAND (fn, 0);
+
+  if (TREE_CODE (fn) != FUNCTION_DECL
+      || !trivial_fn_p (fn))
+    return fn;
+  return NULL_TREE;
+}
+
+/* Return declval<T>() = declval<U>() treated as an unevaluated operand.  */
+
+static tree
+assignable_expr (tree to, tree from)
+{
+  ++cp_unevaluated_operand;
+  to = build_stub_object (to);
+  from = build_stub_object (from);
+  tree r = cp_build_modify_expr (to, NOP_EXPR, from, tf_none);
+  --cp_unevaluated_operand;
+  return r;
+}
+
+/* The predicate condition for a template specialization
+   is_constructible<T, Args...> shall be satisfied if and only if the
+   following variable definition would be well-formed for some invented
+   variable t: T t(create<Args>()...);
+
+   Return something equivalent in well-formedness and triviality.  */
+
+static tree
+constructible_expr (tree to, tree from)
+{
+  tree expr;
+  if (CLASS_TYPE_P (to))
+    {
+      tree ctype = to;
+      vec<tree, va_gc> *args = NULL;
+      if (TREE_CODE (to) != REFERENCE_TYPE)
+	to = cp_build_reference_type (to, /*rval*/false);
+      tree ob = build_stub_object (to);
+      for (; from; from = TREE_CHAIN (from))
+	vec_safe_push (args, build_stub_object (TREE_VALUE (from)));
+      expr = build_special_member_call (ob, complete_ctor_identifier, &args,
+					ctype, LOOKUP_NORMAL, tf_none);
+      if (expr == error_mark_node)
+	return error_mark_node;
+      /* The current state of the standard vis-a-vis LWG 2116 is that
+	 is_*constructible involves destruction as well.  */
+      if (type_build_dtor_call (ctype))
+	{
+	  tree dtor = build_special_member_call (ob, complete_dtor_identifier,
+						 NULL, ctype, LOOKUP_NORMAL,
+						 tf_none);
+	  if (dtor == error_mark_node)
+	    return error_mark_node;
+	  if (!TYPE_HAS_TRIVIAL_DESTRUCTOR (ctype))
+	    expr = build2 (COMPOUND_EXPR, void_type_node, expr, dtor);
+	}
+    }
+  else
+    {
+      if (TREE_CHAIN (from))
+	return error_mark_node; // too many initializers
+      from = build_stub_object (TREE_VALUE (from));
+      expr = perform_direct_initialization_if_possible (to, from,
+							/*cast*/false,
+							tf_none);
+    }
+  return expr;
+}
+
+/* Returns true iff TO is trivially assignable (if CODE is MODIFY_EXPR) or
+   constructible (otherwise) from FROM, which is a single type for
+   assignment or a list of types for construction.  */
+
+bool
+is_trivially_xible (enum tree_code code, tree to, tree from)
+{
+  tree expr;
+  if (code == MODIFY_EXPR)
+    expr = assignable_expr (to, from);
+  else if (from && TREE_CHAIN (from))
+    return false; // only 0- and 1-argument ctors can be trivial
+  else
+    expr = constructible_expr (to, from);
+
+  if (expr == error_mark_node)
+    return false;
+  tree nt = cp_walk_tree_without_duplicates (&expr, check_nontriv, NULL);
+  return !nt;
+}
+
 /* Subroutine of synthesized_method_walk.  Update SPEC_P, TRIVIAL_P and
    DELETED_P or give an error message MSG with argument ARG.  */
 
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index b1feef5..e4aaf53 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -4490,6 +4490,8 @@ cp_parser_primary_expression (cp_parser *parser,
 	case RID_IS_POLYMORPHIC:
 	case RID_IS_STD_LAYOUT:
 	case RID_IS_TRIVIAL:
+	case RID_IS_TRIVIALLY_ASSIGNABLE:
+	case RID_IS_TRIVIALLY_CONSTRUCTIBLE:
 	case RID_IS_TRIVIALLY_COPYABLE:
 	case RID_IS_UNION:
 	  return cp_parser_trait_expr (parser, token->keyword);
@@ -8664,6 +8666,7 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
   cp_trait_kind kind;
   tree type1, type2 = NULL_TREE;
   bool binary = false;
+  bool variadic = false;
 
   switch (keyword)
     {
@@ -8725,6 +8728,14 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
     case RID_IS_TRIVIAL:
       kind = CPTK_IS_TRIVIAL;
       break;
+    case RID_IS_TRIVIALLY_ASSIGNABLE:
+      kind = CPTK_IS_TRIVIALLY_ASSIGNABLE;
+      binary = true;
+      break;
+    case RID_IS_TRIVIALLY_CONSTRUCTIBLE:
+      kind = CPTK_IS_TRIVIALLY_CONSTRUCTIBLE;
+      variadic = true;
+      break;
     case RID_IS_TRIVIALLY_COPYABLE:
       kind = CPTK_IS_TRIVIALLY_COPYABLE;
       break;
@@ -8763,6 +8774,17 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
       if (type2 == error_mark_node)
 	return error_mark_node;
     }
+  else if (variadic)
+    {
+      while (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+	{
+	  cp_lexer_consume_token (parser->lexer);
+	  tree elt = cp_parser_type_id (parser);
+	  if (elt == error_mark_node)
+	    return error_mark_node;
+	  type2 = tree_cons (NULL_TREE, elt, type2);
+	}
+    }
 
   cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
 
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 9bcc6d7..7569826 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -7379,6 +7379,12 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_TRIVIAL:
       return (trivial_type_p (type1));
 
+    case CPTK_IS_TRIVIALLY_ASSIGNABLE:
+      return is_trivially_xible (MODIFY_EXPR, type1, type2);
+
+    case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE:
+      return is_trivially_xible (INIT_EXPR, type1, type2);
+
     case CPTK_IS_TRIVIALLY_COPYABLE:
       return (trivially_copyable_p (type1));
 
@@ -7392,19 +7398,26 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
 }
 
 /* If TYPE is an array of unknown bound, or (possibly cv-qualified)
-   void, or a complete type, returns it, otherwise NULL_TREE.  */
+   void, or a complete type, returns true, otherwise false.  */
 
-static tree
+static bool
 check_trait_type (tree type)
 {
+  if (type == NULL_TREE)
+    return true;
+
+  if (TREE_CODE (type) == TREE_LIST)
+    return (check_trait_type (TREE_VALUE (type))
+	    && check_trait_type (TREE_CHAIN (type)));
+
   if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)
       && COMPLETE_TYPE_P (TREE_TYPE (type)))
-    return type;
+    return true;
 
   if (VOID_TYPE_P (type))
-    return type;
+    return true;
 
-  return complete_type_or_else (strip_array_types (type), NULL_TREE);
+  return !!complete_type_or_else (strip_array_types (type), NULL_TREE);
 }
 
 /* Process a trait expression.  */
@@ -7413,8 +7426,7 @@ tree
 finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
 {
   if (type1 == error_mark_node
-      || ((kind == CPTK_IS_BASE_OF)
-	  && type2 == error_mark_node))
+      || type2 == error_mark_node)
     return error_mark_node;
 
   if (processing_template_decl)
@@ -7450,6 +7462,13 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
 	return error_mark_node;
       break;
 
+    case CPTK_IS_TRIVIALLY_ASSIGNABLE:
+    case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE:
+      if (!check_trait_type (type1)
+	  || !check_trait_type (type2))
+	return error_mark_node;
+      break;
+
     case CPTK_IS_BASE_OF:
       if (NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2)
 	  && !same_type_ignoring_top_level_qualifiers_p (type1, type2)
diff --git a/gcc/testsuite/g++.dg/ext/is_trivially_constructible1.C b/gcc/testsuite/g++.dg/ext/is_trivially_constructible1.C
new file mode 100644
index 0000000..f558538
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_trivially_constructible1.C
@@ -0,0 +1,35 @@
+// { dg-do compile { target c++11 } }
+
+struct A { };
+struct B { B(); operator int(); };
+struct C {
+  C() = default;
+  C(const C&);
+  C(C&&) = default;
+  C& operator=(C&&);
+  C& operator= (const C&) = default;
+};
+struct D { ~D() {} };
+
+#define SA(X) static_assert((X),#X)
+
+SA(__is_trivially_constructible(A));
+SA(__is_trivially_constructible(A,A));
+SA(!__is_trivially_constructible(B));
+SA(__is_trivially_constructible(B,B));
+
+SA(!__is_trivially_constructible(A,B));
+SA(!__is_trivially_constructible(B,A));
+
+SA(__is_trivially_constructible(C));
+SA(__is_trivially_constructible(C,C));
+SA(!__is_trivially_constructible(C,C&));
+SA(__is_trivially_assignable(C,C&));
+SA(!__is_trivially_assignable(C,C));
+SA(!__is_trivially_assignable(C,C&&));
+
+SA(__is_trivially_constructible(int,int));
+SA(__is_trivially_constructible(int,double));
+SA(!__is_trivially_constructible(int,B));
+
+SA(!__is_trivially_constructible(D));

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

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

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-30 22:48 C++ PATCHes to add __is_trivially_* Ville Voutilainen
2014-10-01  2:16 ` Jason Merrill
2014-10-01  8:05 ` Paolo Carlini
2014-10-01  8:11 ` Paolo Carlini
2014-10-01  8:48   ` Ville Voutilainen
2014-10-01 17:20 ` Jason Merrill
2014-10-01 17:38   ` Ville Voutilainen
  -- strict thread matches above, loose matches on Subject: below --
2014-09-30 17:13 Jason Merrill
2014-09-30 17:34 ` Paolo Carlini

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