@@ -3834,6 +3834,9 @@ diagnose_trait_expr (tree expr, tree args)
case CPTK_IS_UNION:
inform (loc, " %qT is not a union", t1);
break;
+ case CPTK_IS_UNSIGNED:
+ inform (loc, " %qT is not an unsigned type", t1);
+ break;
case CPTK_REF_CONSTRUCTS_FROM_TEMPORARY:
inform (loc, " %qT is not a reference that binds to a temporary "
"object of type %qT (direct-initialization)", t1, t2);
@@ -94,6 +94,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_ASSIGNABLE, "__is_trivially_assignable", 2)
DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
+DEFTRAIT_EXPR (IS_UNSIGNED, "__is_unsigned", 1)
DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, "__reference_constructs_from_temporary", 2)
DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, "__reference_converts_from_temporary", 2)
DEFTRAIT_TYPE (REMOVE_CV, "__remove_cv", 1)
@@ -12566,6 +12566,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
case CPTK_IS_UNION:
return type_code1 == UNION_TYPE;
+ case CPTK_IS_UNSIGNED:
+ return TYPE_UNSIGNED (type1);
+
case CPTK_REF_CONSTRUCTS_FROM_TEMPORARY:
return ref_xes_from_temporary (type1, type2, /*direct_init=*/true);
@@ -12738,6 +12741,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
case CPTK_IS_SAME:
case CPTK_IS_SCOPED_ENUM:
case CPTK_IS_UNION:
+ case CPTK_IS_UNSIGNED:
break;
case CPTK_IS_LAYOUT_COMPATIBLE:
@@ -164,6 +164,9 @@
#if !__has_builtin (__is_union)
# error "__has_builtin (__is_union) failed"
#endif
+#if !__has_builtin (__is_unsigned)
+# error "__has_builtin (__is_unsigned) failed"
+#endif
#if !__has_builtin (__reference_constructs_from_temporary)
# error "__has_builtin (__reference_constructs_from_temporary) failed"
#endif
new file mode 100644
@@ -0,0 +1,45 @@
+// { dg-do compile { target c++11 } }
+
+#define SA(X) static_assert((X),#X)
+
+#define SA_TEST_CATEGORY(TRAIT, X, expect) \
+ SA(TRAIT(X) == expect); \
+ SA(TRAIT(const X) == expect); \
+ SA(TRAIT(volatile X) == expect); \
+ SA(TRAIT(const volatile X) == expect)
+
+SA_TEST_CATEGORY(__is_unsigned, void, false);
+
+SA_TEST_CATEGORY(__is_unsigned, bool, (bool(-1) > bool(0)));
+SA_TEST_CATEGORY(__is_unsigned, char, (char(-1) > char(0)));
+SA_TEST_CATEGORY(__is_unsigned, signed char, false);
+SA_TEST_CATEGORY(__is_unsigned, unsigned char, true);
+SA_TEST_CATEGORY(__is_unsigned, wchar_t, (wchar_t(-1) > wchar_t(0)));
+SA_TEST_CATEGORY(__is_unsigned, short, false);
+SA_TEST_CATEGORY(__is_unsigned, unsigned short, true);
+SA_TEST_CATEGORY(__is_unsigned, int, false);
+SA_TEST_CATEGORY(__is_unsigned, unsigned int, true);
+SA_TEST_CATEGORY(__is_unsigned, long, false);
+SA_TEST_CATEGORY(__is_unsigned, unsigned long, true);
+SA_TEST_CATEGORY(__is_unsigned, long long, false);
+SA_TEST_CATEGORY(__is_unsigned, unsigned long long, true);
+
+SA_TEST_CATEGORY(__is_unsigned, float, false);
+SA_TEST_CATEGORY(__is_unsigned, double, false);
+SA_TEST_CATEGORY(__is_unsigned, long double, false);
+
+#ifndef __STRICT_ANSI__
+// GNU Extensions.
+#ifdef __SIZEOF_INT128__
+SA_TEST_CATEGORY(__is_unsigned, unsigned __int128, true);
+SA_TEST_CATEGORY(__is_unsigned, __int128, false);
+#endif
+
+#ifdef _GLIBCXX_USE_FLOAT128
+SA_TEST_CATEGORY(__is_unsigned, __float128, false);
+#endif
+#endif
+
+// Sanity check.
+class ClassType { };
+SA_TEST_CATEGORY(__is_unsigned, ClassType, false);