From patchwork Thu Oct 13 17:35:28 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Spertus X-Patchwork-Id: 119575 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id EFE2AB7091 for ; Fri, 14 Oct 2011 04:36:00 +1100 (EST) Received: (qmail 24716 invoked by alias); 13 Oct 2011 17:35:56 -0000 Received: (qmail 24410 invoked by uid 22791); 13 Oct 2011 17:35:50 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL, BAYES_00, TW_CX, TW_NV X-Spam-Check-By: sourceware.org Received: from mail171.messagelabs.com (HELO mail171.messagelabs.com) (216.82.253.243) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 13 Oct 2011 17:35:33 +0000 X-Env-Sender: mike_spertus@symantec.com X-Msg-Ref: server-3.tower-171.messagelabs.com!1318526931!33801027!9 X-StarScan-Version: 6.3.6; banners=-,-,- X-VirusChecked: Checked Received: (qmail 12708 invoked from network); 13 Oct 2011 17:35:32 -0000 Received: from tus1smtoutpex01.symantec.com (HELO tus1smtoutpex01.symantec.com) (216.10.195.241) by server-3.tower-171.messagelabs.com with DHE-RSA-AES256-SHA encrypted SMTP; 13 Oct 2011 17:35:32 -0000 Received: from tus1smtintpin02.ges.symantec.com (TUS1SMTINTPIN02.ges.symantec.com [192.168.215.102]) by tus1smtoutpex01.symantec.com (Symantec Brightmail Gateway out) with SMTP id B1.C0.30071.361279E4; Thu, 13 Oct 2011 10:35:31 -0700 (MST) Received: from [155.64.220.139] (helo=TUS1XCHHUBPIN03.SYMC.SYMANTEC.COM) by tus1smtintpin02.ges.symantec.com with esmtp (Exim 4.76) (envelope-from ) id 1REPBr-0005o4-7K; Thu, 13 Oct 2011 10:35:31 -0700 Received: from TUS1XCHEVSPIN34.SYMC.SYMANTEC.COM ([155.64.220.149]) by TUS1XCHHUBPIN03.SYMC.SYMANTEC.COM ([155.64.220.139]) with mapi; Thu, 13 Oct 2011 10:35:31 -0700 From: Michael Spertus To: Jason Merrill CC: Benjamin Kosnik , Jonathan Wakely , "gcc-patches@gcc.gnu.org" , "libstdc++@gcc.gnu.org" Date: Thu, 13 Oct 2011 10:35:28 -0700 Subject: RE: Intrinsics for N2965: Type traits and base classes Message-ID: References: <20110913154324.4be22faf@shotwell> <4E809F45.2010908@symantec.com> <20110927195930.54e0d0df@shotwell> <4E830B10.8020802@symantec.com> <4E831DF8.9080700@symantec.com> <20110929102215.33af0ba9@shotwell> <20111003214035.2cbbcaf8@shotwell> <20111003220353.7d511557@shotwell> <4E91F45E.3000706@redhat.com> In-Reply-To: <4E91F45E.3000706@redhat.com> MIME-Version: 1.0 X-RouteViaML: true Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Addressing Jason's comments: Index: libstdc++-v3/include/tr2/type_traits =================================================================== --- libstdc++-v3/include/tr2/type_traits (revision 0) +++ libstdc++-v3/include/tr2/type_traits (revision 0) @@ -0,0 +1,96 @@ +// TR2 type_traits -*- C++ -*- + +// Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 +// Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file tr2/type_traits + * This is a TR2 C++ Library header. + */ + +#ifndef _GLIBCXX_TR2_TYPE_TRAITS +#define _GLIBCXX_TR2_TYPE_TRAITS 1 + +#pragma GCC system_header +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +namespace tr2 +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup metaprogramming Type Traits + * @ingroup utilities + * + * Compile time type transformation and information. + * @{ + */ + + template struct typelist; + template<> + struct typelist<> + { + typedef std::true_type empty; + }; + + template + struct typelist<_First, _Rest...> + { + struct first + { + typedef _First type; + }; + + struct rest + { + typedef typelist<_Rest...> type; + }; + + typedef std::false_type empty; + }; + + // Sequence abstraction metafunctions default to looking in the type + template struct first : public T::first {}; + template struct rest : public T::rest {}; + template struct empty : public T::empty {}; + + + template + struct bases + { + typedef typelist<__bases(T)...> type; + }; + + template + struct direct_bases + { + typedef typelist<__direct_bases(T)...> type; + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} +} + +#endif // _GLIBCXX_TR2_TYPE_TRAITS Index: gcc/c-family/c-common.c =================================================================== --- gcc/c-family/c-common.c (revision 178892) +++ gcc/c-family/c-common.c (working copy) @@ -423,6 +423,7 @@ { "__asm__", RID_ASM, 0 }, { "__attribute", RID_ATTRIBUTE, 0 }, { "__attribute__", RID_ATTRIBUTE, 0 }, + { "__bases", RID_BASES, D_CXXONLY }, { "__builtin_choose_expr", RID_CHOOSE_EXPR, D_CONLY }, { "__builtin_complex", RID_BUILTIN_COMPLEX, D_CONLY }, { "__builtin_offsetof", RID_OFFSETOF, 0 }, @@ -433,6 +434,7 @@ { "__const", RID_CONST, 0 }, { "__const__", RID_CONST, 0 }, { "__decltype", RID_DECLTYPE, D_CXXONLY }, + { "__direct_bases", RID_DIRECT_BASES, D_CXXONLY }, { "__extension__", RID_EXTENSION, 0 }, { "__func__", RID_C99_FUNCTION_NAME, 0 }, { "__has_nothrow_assign", RID_HAS_NOTHROW_ASSIGN, D_CXXONLY }, Index: gcc/c-family/c-common.h =================================================================== --- gcc/c-family/c-common.h (revision 178892) +++ gcc/c-family/c-common.h (working copy) @@ -129,12 +129,13 @@ RID_CONSTCAST, RID_DYNCAST, RID_REINTCAST, RID_STATCAST, /* C++ extensions */ + RID_BASES, RID_DIRECT_BASES, 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_CLASS, RID_IS_CONVERTIBLE_TO, RID_IS_EMPTY, RID_IS_ENUM, RID_IS_LITERAL_TYPE, RID_IS_POD, RID_IS_POLYMORPHIC, RID_IS_STD_LAYOUT, Index: gcc/testsuite/g++.dg/ext/bases.C =================================================================== --- gcc/testsuite/g++.dg/ext/bases.C (revision 0) +++ gcc/testsuite/g++.dg/ext/bases.C (revision 0) @@ -0,0 +1,29 @@ +// { dg-do run } +#include +#include +// A simple typelist +template struct types {}; + +// Simple bases implementation +template struct b { + typedef types<__bases(T)...> type; +}; + +// Simple direct_bases implementation +template struct db { + typedef types<__direct_bases(T)...> type; +}; +struct A {}; +struct C : virtual A {}; +struct D : public C {}; +struct B : D, virtual A {}; +struct E : C, virtual D, B {}; +struct F : A, B, E {}; + +int main() { + assert(typeid(b::type) + == typeid(types)); + assert(typeid(db::type) == typeid(types)); + assert(typeid(db::type) == typeid(types<>)); + return 0; +} Index: gcc/cp/pt.c =================================================================== --- gcc/cp/pt.c (revision 178892) +++ gcc/cp/pt.c (working copy) @@ -2976,6 +2976,9 @@ } break; + case BASES: + parameter_pack_p = true; + break; default: /* Not a parameter pack. */ break; @@ -9123,6 +9126,15 @@ tree arg_pack = NULL_TREE; tree orig_arg = NULL_TREE; + if (TREE_CODE (parm_pack) == BASES) + { + if (BASES_DIRECT (parm_pack)) + return calculate_direct_bases (tsubst_expr (BASES_TYPE (parm_pack), + args, complain, in_decl, false)); + else + return calculate_bases (tsubst_expr (BASES_TYPE (parm_pack), + args, complain, in_decl, false)); + } if (TREE_CODE (parm_pack) == PARM_DECL) { if (!cp_unevaluated_operand) Index: gcc/cp/semantics.c =================================================================== --- gcc/cp/semantics.c (revision 178892) +++ gcc/cp/semantics.c (working copy) @@ -3407,6 +3407,149 @@ return underlying_type; } +/* Implement the __direct_bases keyword: Return the direct base classes + of type */ + +tree +calculate_direct_bases (tree type) +{ + VEC(tree, gc) *vector = make_tree_vector(); + tree bases_vec = NULL_TREE; + VEC(tree, none) *base_binfos; + tree binfo; + unsigned i; + + complete_type (type); + + if (!NON_UNION_CLASS_TYPE_P (type)) + return make_tree_vec (0); + + base_binfos = BINFO_BASE_BINFOS (TYPE_BINFO (type)); + + /* Virtual bases are initialized first */ + for (i = 0; VEC_iterate (tree, base_binfos, i, binfo); i++) + { + if (BINFO_VIRTUAL_P (binfo)) + { + VEC_safe_push (tree, gc, vector, binfo); + } + } + + /* Now non-virtuals */ + for (i = 0; VEC_iterate (tree, base_binfos, i, binfo); i++) + { + if (!BINFO_VIRTUAL_P (binfo)) + { + VEC_safe_push (tree, gc, vector, binfo); + } + } + + + bases_vec = make_tree_vec (VEC_length (tree, vector)); + + for (i = 0; i < VEC_length (tree, vector); ++i) + { + TREE_VEC_ELT (bases_vec, i) = BINFO_TYPE (VEC_index (tree, vector, i)); + } + return bases_vec; +} + +/* Implement the __bases keyword: Return the base classes + of type */ + +/* Find morally non-virtual base classes by walking binfo hierarchy */ +/* Virtual base classes are handled separately in finish_bases */ + +static tree +dfs_calculate_bases_pre (tree binfo, ATTRIBUTE_UNUSED void *data_) +{ + /* Don't walk bases of virtual bases */ + return BINFO_VIRTUAL_P (binfo) ? dfs_skip_bases : NULL_TREE; +} + +static tree +dfs_calculate_bases_post (tree binfo, void *data_) +{ + VEC(tree, gc) **data = (VEC(tree, gc) **) data_; + if (!BINFO_VIRTUAL_P (binfo)) + { + VEC_safe_push (tree, gc, *data, BINFO_TYPE (binfo)); + } + return NULL_TREE; +} + +/* Calculates the morally non-virtual base classes of a class */ +static VEC(tree, gc) * +calculate_bases_helper (tree type) +{ + VEC(tree, gc) *vector = make_tree_vector(); + + /* Now add non-virtual base classes in order of construction */ + dfs_walk_all (TYPE_BINFO (type), + dfs_calculate_bases_pre, dfs_calculate_bases_post, &vector); + return vector; +} + +tree +calculate_bases (tree type) +{ + VEC(tree, gc) *vector = make_tree_vector(); + tree bases_vec = NULL_TREE; + unsigned i; + VEC(tree, gc) *vbases; + VEC(tree, gc) *nonvbases; + tree binfo; + + complete_type (type); + + if (!NON_UNION_CLASS_TYPE_P (type)) + return make_tree_vec (0); + + /* First go through virtual base classes */ + for (vbases = CLASSTYPE_VBASECLASSES (type), i = 0; + VEC_iterate (tree, vbases, i, binfo); i++) + { + VEC(tree, gc) *vbase_bases = calculate_bases_helper (BINFO_TYPE (binfo)); + VEC_safe_splice (tree, gc, vector, vbase_bases); + release_tree_vector (vbase_bases); + } + + /* Now for the non-virtual bases */ + nonvbases = calculate_bases_helper (type); + VEC_safe_splice (tree, gc, vector, nonvbases); + release_tree_vector (nonvbases); + + /* Last element is entire class, so don't copy */ + bases_vec = make_tree_vec (VEC_length (tree, vector) - 1); + + for (i = 0; i < VEC_length (tree, vector) - 1; ++i) + { + TREE_VEC_ELT (bases_vec, i) = VEC_index (tree, vector, i); + } + release_tree_vector (vector); + return bases_vec; +} + +tree +finish_bases (tree type, bool direct) +{ + tree bases = NULL_TREE; + + if (!processing_template_decl) + { + /* Parameter packs can only be used in templates */ + error ("Parameter pack __bases only valid in template declaration"); + return error_mark_node; + } + + bases = cxx_make_type (BASES); + BASES_TYPE (bases) = type; + BASES_DIRECT (bases) = direct; + SET_TYPE_STRUCTURAL_EQUALITY (bases); + + return bases; +} + /* Perform C++-specific checks for __builtin_offsetof before calling fold_offsetof. */ Index: gcc/cp/parser.c =================================================================== --- gcc/cp/parser.c (revision 178892) +++ gcc/cp/parser.c (working copy) @@ -7295,6 +7295,12 @@ case RID_UNDERLYING_TYPE: kind = CPTK_UNDERLYING_TYPE; break; + case RID_BASES: + kind = CPTK_BASES; + break; + case RID_DIRECT_BASES: + kind = CPTK_DIRECT_BASES; + break; default: gcc_unreachable (); } @@ -7339,9 +7345,17 @@ /* Complete the trait expression, which may mean either processing the trait expr now or saving it for template instantiation. */ - return kind != CPTK_UNDERLYING_TYPE - ? finish_trait_expr (kind, type1, type2) - : finish_underlying_type (type1); + switch(kind) + { + case CPTK_UNDERLYING_TYPE: + return finish_underlying_type (type1); + case CPTK_BASES: + return finish_bases (type1, false); + case CPTK_DIRECT_BASES: + return finish_bases (type1, true); + default: + return finish_trait_expr (kind, type1, type2); + } } /* Lambdas that appear in variable initializer or default argument scope @@ -12010,6 +12024,7 @@ parser->integral_constant_expression_p = false; saved_non_ice_p = parser->non_integral_constant_expression_p; parser->non_integral_constant_expression_p = false; + /* Parse the arguments. */ do { @@ -12827,7 +12842,6 @@ case RID_UNDERLYING_TYPE: type = cp_parser_trait_expr (parser, RID_UNDERLYING_TYPE); - if (decl_specs) cp_parser_set_decl_spec_type (decl_specs, type, token->location, @@ -12835,6 +12849,14 @@ return type; + case RID_BASES: + case RID_DIRECT_BASES: + type = cp_parser_trait_expr (parser, token->keyword); + if (decl_specs) + cp_parser_set_decl_spec_type (decl_specs, type, + token->location, + /*type_definition_p=*/false); + return type; default: break; } @@ -20534,7 +20556,7 @@ } /* Parse a template-argument-list, as well as the trailing ">" (but - not the opening ">"). See cp_parser_template_argument_list for the + not the opening "<"). See cp_parser_template_argument_list for the return value. */ static tree Index: gcc/cp/cp-tree.def =================================================================== --- gcc/cp/cp-tree.def (revision 178892) +++ gcc/cp/cp-tree.def (working copy) @@ -461,6 +461,10 @@ UNDERLYING_TYPE_TYPE is the type in question. */ DEFTREECODE (UNDERLYING_TYPE, "underlying_type", tcc_type, 0) +/* A type designated by one of the bases type traits. + BASES_TYPE is the type in question. */ +DEFTREECODE (BASES, "bases", tcc_type, 0) + /* Used to represent the template information stored by template specializations. The accessors are: Index: gcc/cp/cp-tree.h =================================================================== --- gcc/cp/cp-tree.h (revision 178892) +++ gcc/cp/cp-tree.h (working copy) @@ -558,6 +558,8 @@ typedef enum cp_trait_kind { + CPTK_BASES, + CPTK_DIRECT_BASES, CPTK_HAS_NOTHROW_ASSIGN, CPTK_HAS_NOTHROW_CONSTRUCTOR, CPTK_HAS_NOTHROW_COPY, @@ -3416,6 +3418,13 @@ #define UNDERLYING_TYPE_TYPE(NODE) \ (TYPE_VALUES_RAW (UNDERLYING_TYPE_CHECK (NODE))) +/* The type in question for BASES. */ +#define BASES_TYPE(NODE) \ + (TYPE_VALUES_RAW (BASES_CHECK (NODE))) + +#define BASES_DIRECT(NODE) \ + TREE_LANG_FLAG_0 (BASES_CHECK (NODE)) + /* The expression in question for a DECLTYPE_TYPE. */ #define DECLTYPE_TYPE_EXPR(NODE) (TYPE_VALUES_RAW (DECLTYPE_TYPE_CHECK (NODE))) @@ -5430,6 +5439,9 @@ location_t); extern tree finish_typeof (tree); extern tree finish_underlying_type (tree); +extern tree calculate_bases (tree); +extern tree finish_bases (tree, bool); +extern tree calculate_direct_bases (tree); extern tree finish_offsetof (tree); extern void finish_decl_cleanup (tree, tree); extern void finish_eh_cleanup (tree);