From patchwork Fri May 13 17:24:44 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ville Voutilainen X-Patchwork-Id: 95502 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 93124B6EF3 for ; Sat, 14 May 2011 03:25:16 +1000 (EST) Received: (qmail 6792 invoked by alias); 13 May 2011 17:25:14 -0000 Received: (qmail 6758 invoked by uid 22791); 13 May 2011 17:25:12 -0000 X-SWARE-Spam-Status: No, hits=-2.6 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, RFC_ABUSE_POST, T_TO_NO_BRKTS_FREEMAIL X-Spam-Check-By: sourceware.org Received: from mail-ey0-f175.google.com (HELO mail-ey0-f175.google.com) (209.85.215.175) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 13 May 2011 17:24:55 +0000 Received: by eye27 with SMTP id 27so881055eye.20 for ; Fri, 13 May 2011 10:24:54 -0700 (PDT) Received: by 10.213.114.1 with SMTP id c1mr7985ebq.54.1305307494219; Fri, 13 May 2011 10:24:54 -0700 (PDT) Received: from ville-laptop.gmail.com ([88.193.47.74]) by mx.google.com with ESMTPS id x5sm1575415eea.14.2011.05.13.10.24.52 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 13 May 2011 10:24:53 -0700 (PDT) Date: Fri, 13 May 2011 20:24:44 +0300 Message-ID: <87liyav7hf.wl%ville@ville-laptop> From: Ville Voutilainen To: gcc-patches@gcc.gnu.org Cc: jason@redhat.com Subject: [PATCH] C++0x, implement final on classes User-Agent: Wanderlust/2.14.0 (Africa) SEMI/1.14.6 (Maruoka) FLIM/1.14.9 (=?UTF-8?B?R29qxY0=?=) APEL/10.7 Emacs/23.1 (i486-pc-linux-gnu) MULE/6.0 (HANACHIRUSATO) MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") 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 Tested on Linux/X86-32. 2011-05-13 Ville Voutilainen Implement final on class. * class.c (check_bases): Diagnose derivation from a final class. * cp-tree.h (lang_type_class): Add is_final and adjust dummy. * cp-tree.h (CLASSTYPE_FINAL): New. * parser.c (cp_parser_class_head): Parse class-virt-specifier, set CLASSTYPE_FINAL. * pt.c (instantiate_class_template_1): Copy the CLASSTYPE_FINAL. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 293dd1c..44b1d8e 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -1268,6 +1268,10 @@ check_bases (tree t, gcc_assert (COMPLETE_TYPE_P (basetype)); + if (CLASSTYPE_FINAL (basetype)) + error ("cannot derive from from final base %qT in derived type %qT", + basetype, t); + /* If any base class is non-literal, so is the derived class. */ if (!CLASSTYPE_LITERAL_P (basetype)) CLASSTYPE_LITERAL_P (t) = false; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 1705232..901a17d 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1321,6 +1321,7 @@ struct GTY(()) lang_type_class { unsigned has_complex_move_ctor : 1; unsigned has_complex_move_assign : 1; unsigned has_constexpr_ctor : 1; + unsigned is_final : 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 @@ -1329,7 +1330,7 @@ struct GTY(()) lang_type_class { /* 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 : 3; + unsigned dummy : 2; tree primary_base; VEC(tree_pair_s,gc) *vcall_indices; @@ -1437,6 +1438,11 @@ struct GTY((variable_size)) lang_type { #define CLASSTYPE_LAZY_DESTRUCTOR(NODE) \ (LANG_TYPE_CLASS_CHECK (NODE)->lazy_destructor) +/* Nonzero means that NODE (a class type) is final */ +#define CLASSTYPE_FINAL(NODE) \ + (LANG_TYPE_CLASS_CHECK (NODE)->is_final) + + /* Nonzero means that this _CLASSTYPE node overloads operator=(X&). */ #define TYPE_HAS_COPY_ASSIGN(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_copy_assign) diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index fa6cd83..5e9b8a8 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -17117,6 +17117,7 @@ cp_parser_class_head (cp_parser* parser, tree id = NULL_TREE; tree type = NULL_TREE; tree attributes; + cp_virt_specifiers virt_specifiers = VIRT_SPEC_UNSPECIFIED; bool template_id_p = false; bool qualified_p = false; bool invalid_nested_name_p = false; @@ -17260,8 +17261,11 @@ cp_parser_class_head (cp_parser* parser, pop_deferring_access_checks (); if (id) - cp_parser_check_for_invalid_template_id (parser, id, - type_start_token->location); + { + virt_specifiers = cp_parser_virt_specifier_seq_opt (parser); + cp_parser_check_for_invalid_template_id (parser, id, + type_start_token->location); + } /* If it's not a `:' or a `{' then we can't really be looking at a class-head, since a class-head only appears as part of a @@ -17493,6 +17497,8 @@ cp_parser_class_head (cp_parser* parser, if (type) DECL_SOURCE_LOCATION (TYPE_NAME (type)) = type_start_token->location; *attributes_p = attributes; + if (virt_specifiers & VIRT_SPEC_FINAL) + CLASSTYPE_FINAL (type) = 1; out: parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; return type; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 5e24977..5e059e0 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -8209,6 +8209,7 @@ instantiate_class_template_1 (tree type) CLASSTYPE_VISIBILITY_SPECIFIED (type) = 1; CLASSTYPE_VISIBILITY (type) = CLASSTYPE_VISIBILITY (pattern); } + CLASSTYPE_FINAL (type) = CLASSTYPE_FINAL (pattern); pbinfo = TYPE_BINFO (pattern); diff --git a/gcc/testsuite/g++.dg/inherit/base4.C b/gcc/testsuite/g++.dg/inherit/base4.C new file mode 100644 index 0000000..5736193 --- /dev/null +++ b/gcc/testsuite/g++.dg/inherit/base4.C @@ -0,0 +1,23 @@ +// { dg-do compile } +// { dg-options "--std=c++0x" } +struct B1 {}; + +struct B2 final {}; + +struct D1 : B1 {}; + +struct D2 : B2 {}; // { dg-error "cannot derive from from final base" } + +template struct D3 : T {}; + +template struct D4 : T {}; // { dg-error "cannot derive from from final base" } + +struct B3 final final {}; // { dg-error "duplicate virt-specifier" } + +int main() +{ + D3 d; + D4 d2; + struct B2 final{}; + struct B1 final2{}; +}