diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 0b543ec52f6..a129f5def77 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,9 @@ +2017-03-31 Jakub Jelinek + + PR libstdc++/80251 + * c-common.h (enum rid): Add RID_IS_AGGREGATE. + * c-common.c (c_common_reswords): Add __is_aggregate trait. + 2017-03-27 Jakub Jelinek PR middle-end/80162 diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 07af384cd6b..824fdc71233 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -403,6 +403,7 @@ const struct c_common_resword c_common_reswords[] = { "__inline", RID_INLINE, 0 }, { "__inline__", RID_INLINE, 0 }, { "__is_abstract", RID_IS_ABSTRACT, D_CXXONLY }, + { "__is_aggregate", RID_IS_AGGREGATE, D_CXXONLY }, { "__is_base_of", RID_IS_BASE_OF, D_CXXONLY }, { "__is_class", RID_IS_CLASS, D_CXXONLY }, { "__is_empty", RID_IS_EMPTY, D_CXXONLY }, diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index ac86712ceaf..b9333420434 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -162,8 +162,8 @@ enum rid RID_HAS_TRIVIAL_CONSTRUCTOR, RID_HAS_TRIVIAL_COPY, RID_HAS_TRIVIAL_DESTRUCTOR, RID_HAS_UNIQUE_OBJ_REPRESENTATIONS, RID_HAS_VIRTUAL_DESTRUCTOR, - RID_IS_ABSTRACT, RID_IS_BASE_OF, - RID_IS_CLASS, + RID_IS_ABSTRACT, RID_IS_AGGREGATE, + RID_IS_BASE_OF, 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/ChangeLog b/gcc/cp/ChangeLog index 1d75be5a2d4..14eee1c3340 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,15 @@ +2017-03-31 Jakub Jelinek + + PR libstdc++/80251 + * cp-tree.h (enum cp_trait_kind): Add CPTK_IS_AGGREGATE. + * cxx-pretty-print.c (pp_cxx_trait_expression): Handle + CPTK_IS_AGGREGATE. + * semantics.c (trait_expr_value): Handle CPTK_IS_AGGREGATE. + Remove extraneous parens. + (finish_trait_expr): Handle CPTK_IS_AGGREGATE. + * parser.c (cp_parser_primary_expression): Handle RID_IS_AGGREGATE. + (cp_parser_trait_expr): Likewise. + 2017-03-27 Jakub Jelinek PR middle-end/80162 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index daa1a81103e..57c1401a9d1 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -728,6 +728,7 @@ enum cp_trait_kind CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS, CPTK_HAS_VIRTUAL_DESTRUCTOR, CPTK_IS_ABSTRACT, + CPTK_IS_AGGREGATE, CPTK_IS_BASE_OF, CPTK_IS_CLASS, CPTK_IS_EMPTY, diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c index 150b6031e80..470d124102d 100644 --- a/gcc/cp/cxx-pretty-print.c +++ b/gcc/cp/cxx-pretty-print.c @@ -2585,6 +2585,9 @@ pp_cxx_trait_expression (cxx_pretty_printer *pp, tree t) case CPTK_IS_ABSTRACT: pp_cxx_ws_string (pp, "__is_abstract"); break; + case CPTK_IS_AGGREGATE: + pp_cxx_ws_string (pp, "__is_aggregate"); + break; case CPTK_IS_BASE_OF: pp_cxx_ws_string (pp, "__is_base_of"); break; diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index c1b6496af4b..e93855fb69d 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -5121,6 +5121,7 @@ cp_parser_primary_expression (cp_parser *parser, case RID_HAS_UNIQUE_OBJ_REPRESENTATIONS: case RID_HAS_VIRTUAL_DESTRUCTOR: case RID_IS_ABSTRACT: + case RID_IS_AGGREGATE: case RID_IS_BASE_OF: case RID_IS_CLASS: case RID_IS_EMPTY: @@ -9611,6 +9612,9 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword) case RID_IS_ABSTRACT: kind = CPTK_IS_ABSTRACT; break; + case RID_IS_AGGREGATE: + kind = CPTK_IS_AGGREGATE; + break; case RID_IS_BASE_OF: kind = CPTK_IS_BASE_OF; binary = true; diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index ad5299a06ee..c57264623d1 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -9144,7 +9144,10 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2) return type_has_unique_obj_representations (type1); case CPTK_IS_ABSTRACT: - return (ABSTRACT_CLASS_TYPE_P (type1)); + return ABSTRACT_CLASS_TYPE_P (type1); + + case CPTK_IS_AGGREGATE: + return CP_AGGREGATE_TYPE_P (type1); case CPTK_IS_BASE_OF: return (NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2) @@ -9152,34 +9155,34 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2) || DERIVED_FROM_P (type1, type2))); case CPTK_IS_CLASS: - return (NON_UNION_CLASS_TYPE_P (type1)); + return NON_UNION_CLASS_TYPE_P (type1); case CPTK_IS_EMPTY: - return (NON_UNION_CLASS_TYPE_P (type1) && CLASSTYPE_EMPTY_P (type1)); + return NON_UNION_CLASS_TYPE_P (type1) && CLASSTYPE_EMPTY_P (type1); case CPTK_IS_ENUM: - return (type_code1 == ENUMERAL_TYPE); + return type_code1 == ENUMERAL_TYPE; case CPTK_IS_FINAL: - return (CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1)); + return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1); case CPTK_IS_LITERAL_TYPE: - return (literal_type_p (type1)); + return literal_type_p (type1); case CPTK_IS_POD: - return (pod_type_p (type1)); + return pod_type_p (type1); case CPTK_IS_POLYMORPHIC: - return (CLASS_TYPE_P (type1) && TYPE_POLYMORPHIC_P (type1)); + return CLASS_TYPE_P (type1) && TYPE_POLYMORPHIC_P (type1); case CPTK_IS_SAME_AS: return same_type_p (type1, type2); case CPTK_IS_STD_LAYOUT: - return (std_layout_type_p (type1)); + return std_layout_type_p (type1); case CPTK_IS_TRIVIAL: - return (trivial_type_p (type1)); + return trivial_type_p (type1); case CPTK_IS_TRIVIALLY_ASSIGNABLE: return is_trivially_xible (MODIFY_EXPR, type1, type2); @@ -9188,10 +9191,10 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2) return is_trivially_xible (INIT_EXPR, type1, type2); case CPTK_IS_TRIVIALLY_COPYABLE: - return (trivially_copyable_p (type1)); + return trivially_copyable_p (type1); case CPTK_IS_UNION: - return (type_code1 == UNION_TYPE); + return type_code1 == UNION_TYPE; default: gcc_unreachable (); @@ -9253,6 +9256,7 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2) case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS: case CPTK_HAS_VIRTUAL_DESTRUCTOR: case CPTK_IS_ABSTRACT: + case CPTK_IS_AGGREGATE: case CPTK_IS_EMPTY: case CPTK_IS_FINAL: case CPTK_IS_LITERAL_TYPE: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9297d533568..26fdfb3e26b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2017-03-31 Jakub Jelinek + PR libstdc++/80251 + * g++.dg/ext/is_aggregate.C: New test. + PR middle-end/80173 * gcc.target/i386/pr80173.c: New test. diff --git a/gcc/testsuite/g++.dg/ext/is_aggregate.C b/gcc/testsuite/g++.dg/ext/is_aggregate.C new file mode 100644 index 00000000000..8adc6c455f0 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_aggregate.C @@ -0,0 +1,117 @@ +// { dg-do run { target c++11 } } +#include + +template + bool + f() + { return __is_aggregate(T); } + +template + class My + { + public: + bool + f() + { return !!__is_aggregate(T); } + }; + +template + class My2 + { + public: + static const bool trait = __is_aggregate(T); + }; + +template + const bool My2::trait; + +template + struct My3_help + { static const bool trait = b; }; + +template + const bool My3_help::trait; + +template + class My3 + { + public: + bool + f() + { return My3_help::trait; } + }; + +#define PTEST(T) (__is_aggregate(T) && f() \ + && My().f() && My2::trait && My3().f()) + +#define NTEST(T) (!__is_aggregate(T) && !f() \ + && !My().f() && !My2::trait && !My3().f()) + +struct A { int a, b, c; }; +class B { static int a; private: static int b; public: int c; }; +struct C { C () {} int a, b, c; }; +struct D { explicit D (int) {} int a, b, c; }; +struct E : public A { int d, e, f; }; +struct F : public C { using C::C; int d, e, f; }; +class G { int a, b; }; +struct H { private: int a, b; }; +struct I { protected: int a, b; }; +struct J { int a, b; void foo (); }; +struct K { int a, b; virtual void foo (); }; +struct L : virtual public A { int d, e; }; +struct M : protected A { int d, e; }; +struct N : private A { int d, e; }; +typedef int T; +typedef float U; +typedef int V __attribute__((vector_size (4 * sizeof (int)))); +typedef double W __attribute__((vector_size (8 * sizeof (double)))); + +int +main () +{ + assert (NTEST (void)); + assert (NTEST (int)); + assert (NTEST (double)); + assert (NTEST (T)); + assert (NTEST (U)); + assert (PTEST (V)); + assert (PTEST (W)); + assert (PTEST (A)); + assert (PTEST (B)); + assert (NTEST (C)); + assert (NTEST (D)); +#if __cplusplus >= 201703L + assert (PTEST (E)); +#else + assert (NTEST (E)); +#endif + assert (NTEST (F)); + assert (NTEST (G)); + assert (NTEST (H)); + assert (NTEST (I)); + assert (PTEST (J)); + assert (NTEST (K)); + assert (NTEST (L)); + assert (NTEST (M)); + assert (NTEST (N)); + assert (PTEST (int[])); + assert (PTEST (double[])); + assert (PTEST (T[2])); + assert (PTEST (U[])); + assert (PTEST (V[])); + assert (PTEST (W[])); + assert (PTEST (A[19])); + assert (PTEST (B[])); + assert (PTEST (C[])); + assert (PTEST (D[])); + assert (PTEST (E[])); + assert (PTEST (F[])); + assert (PTEST (G[])); + assert (PTEST (H[])); + assert (PTEST (I[])); + assert (PTEST (J[24])); + assert (PTEST (K[])); + assert (PTEST (L[])); + assert (PTEST (M[6])); + assert (PTEST (N[])); +}