From patchwork Tue Jun 8 09:59:46 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 54958 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 03034B6ED0 for ; Tue, 8 Jun 2010 20:01:19 +1000 (EST) Received: (qmail 17770 invoked by alias); 8 Jun 2010 10:01:18 -0000 Received: (qmail 17618 invoked by uid 22791); 8 Jun 2010 10:01:16 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL, BAYES_00, TW_FN, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 08 Jun 2010 10:01:03 +0000 Received: (qmail 24887 invoked from network); 8 Jun 2010 10:01:01 -0000 Received: from unknown (HELO ?192.168.44.101?) (nathan@127.0.0.2) by mail.codesourcery.com with ESMTPA; 8 Jun 2010 10:01:01 -0000 Message-ID: <4C0E1492.8020506@codesourcery.com> Date: Tue, 08 Jun 2010 10:59:46 +0100 From: Nathan Sidwell User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.9) Gecko/20100423 Thunderbird/3.0.4 MIME-Version: 1.0 To: GCC Patches Subject: [C++] fix alias and members 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 I've committed this patch to fix uses of the alias attribute with member functions. Broken out of the IFUNC patch as these are independent goodness. built and tested on i686-pc-linux-gnu. nathan 2010-06-08 Nathan Sidwell cp/ * decl.c (record_key_method_defined): New, broken out of ... (finish_function): ... here. Call it. (start_decl): Treat aliases as definitions. testsuite/ * g++.dg/ext/attr-alias-1.C: New. * g++.dg/ext/attr-alias-2.C: New. Index: testsuite/g++.dg/ext/attr-alias-1.C =================================================================== --- testsuite/g++.dg/ext/attr-alias-1.C (revision 0) +++ testsuite/g++.dg/ext/attr-alias-1.C (revision 0) @@ -0,0 +1,37 @@ +/* { dg-do run } */ +/* { dg-require-alias "" } */ + +#include + +struct Klass +{ + int implementation () const; + int magic () const; +}; + +int Klass::implementation (void) const +{ + return 0; +} + +int Klass::magic () const + __attribute__ ((alias ("_ZNK5Klass14implementationEv"))); + +int __attribute__ ((noinline)) + Foo (Klass const *ptr) +{ + if (ptr->magic () != 0) + return 1; + + if (typeid (*ptr) != typeid (Klass)) + return 2; + + return 0; +} + +int main () +{ + Klass obj; + + return Foo (&obj); +} Index: testsuite/g++.dg/ext/attr-alias-2.C =================================================================== --- testsuite/g++.dg/ext/attr-alias-2.C (revision 0) +++ testsuite/g++.dg/ext/attr-alias-2.C (revision 0) @@ -0,0 +1,37 @@ +/* { dg-do run } */ +/* { dg-require-alias "" } */ + +#include + +struct Klass +{ + int implementation () const; + virtual int magic () const; +}; + +int Klass::implementation (void) const +{ + return 0; +} + +int Klass::magic () const + __attribute__ ((alias ("_ZNK5Klass14implementationEv"))); + +int __attribute__ ((noinline)) + Foo (Klass const *ptr) +{ + if (ptr->magic () != 0) + return 1; + + if (typeid (*ptr) != typeid (Klass)) + return 2; + + return 0; +} + +int main () +{ + Klass obj; + + return Foo (&obj); +} Index: cp/decl.c =================================================================== --- cp/decl.c (revision 160427) +++ cp/decl.c (working copy) @@ -90,6 +90,7 @@ static void finish_constructor_body (void); static void begin_destructor_body (void); static void finish_destructor_body (void); +static void record_key_method_defined (tree); static tree create_array_type_for_decl (tree, tree, tree); static tree get_atexit_node (void); static tree get_dso_handle_node (void); @@ -4129,6 +4130,7 @@ tree context; bool was_public; int flags; + bool alias; *pushed_scope_p = NULL_TREE; @@ -4190,6 +4192,10 @@ if (toplevel_bindings_p ()) TREE_STATIC (decl) = 1; } + alias = lookup_attribute ("alias", DECL_ATTRIBUTES (decl)) != 0; + + if (alias && TREE_CODE (decl) == FUNCTION_DECL) + record_key_method_defined (decl); /* If this is a typedef that names the class for linkage purposes (7.1.3p8), apply any attributes directly to the type. */ @@ -4292,7 +4298,9 @@ DECL_EXTERNAL (decl) = 1; } - if (DECL_EXTERNAL (decl) && ! DECL_TEMPLATE_SPECIALIZATION (decl)) + if (DECL_EXTERNAL (decl) && ! DECL_TEMPLATE_SPECIALIZATION (decl) + /* Aliases are definitions. */ + && !alias) permerror (input_location, "declaration of %q#D outside of class is not definition", decl); @@ -12502,6 +12510,22 @@ return block; } +/* If FNDECL is a class's key method, add the class to the list of + keyed classes that should be emitted. */ + +static void +record_key_method_defined (tree fndecl) +{ + if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl) + && DECL_VIRTUAL_P (fndecl) + && !processing_template_decl) + { + tree fnclass = DECL_CONTEXT (fndecl); + if (fndecl == CLASSTYPE_KEY_METHOD (fnclass)) + keyed_classes = tree_cons (NULL_TREE, fnclass, keyed_classes); + } +} + /* Finish up a function declaration and compile that function all the way to assembler language output. The free the storage for the function definition. @@ -12528,14 +12552,7 @@ gcc_assert (!defer_mark_used_calls); defer_mark_used_calls = true; - if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl) - && DECL_VIRTUAL_P (fndecl) - && !processing_template_decl) - { - tree fnclass = DECL_CONTEXT (fndecl); - if (fndecl == CLASSTYPE_KEY_METHOD (fnclass)) - keyed_classes = tree_cons (NULL_TREE, fnclass, keyed_classes); - } + record_key_method_defined (fndecl); nested = function_depth > 1; fntype = TREE_TYPE (fndecl);