diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 931cbe141ebee3e7ec2c777b7203bad0d120af42..3bb19a09af086224e803bb4e875b21968fbbb26c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2010-06-08 Nathan Sidwell <nathan@codesourcery.com> + + * decl.c (record_key_method_defined): New, broken out of ... + (finish_function): ... here. Call it. + (start_decl): Treat aliases as definitions. + 2010-06-08 Laurynas Biveinis <laurynas.biveinis@gmail.com> * typeck2.c (abstract_virtuals_error): Use typed GC allocation. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 706eee9b6669085cd2aedf19b6ac1995915cd6bf..ca3152f9caf6b6abb8f759c0c8fb34bfdbedf769 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -90,6 +90,7 @@ static void check_function_type (tree, tree); 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 @@ start_decl (const cp_declarator *declarator, tree context; bool was_public; int flags; + bool alias; *pushed_scope_p = NULL_TREE; @@ -4190,6 +4192,10 @@ start_decl (const cp_declarator *declarator, 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 @@ start_decl (const cp_declarator *declarator, 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 @@ outer_curly_brace_block (tree fndecl) 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 @@ finish_function (int flags) 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); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 239ef3eead6e18c97a7b8a42304803bbcacde902..284bbc951fbb0664a1d4f9cf6fd7a02c6c461a34 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-06-08 Nathan Sidwell <nathan@codesourcery.com> + + * g++.dg/ext/attr-alias-1.C: New. + * g++.dg/ext/attr-alias-2.C: New. + 2010-06-07 Tobias Burnus <burnus@net-b.de> PR fortran/44446 diff --git a/gcc/testsuite/g++.dg/ext/attr-alias-1.C b/gcc/testsuite/g++.dg/ext/attr-alias-1.C new file mode 100644 index 0000000000000000000000000000000000000000..1427267e5173954bf8410aeef5d21edc4aba09c4 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/attr-alias-1.C @@ -0,0 +1,37 @@ +/* { dg-do run } */ +/* { dg-require-alias "" } */ + +#include <typeinfo> + +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); +} diff --git a/gcc/testsuite/g++.dg/ext/attr-alias-2.C b/gcc/testsuite/g++.dg/ext/attr-alias-2.C new file mode 100644 index 0000000000000000000000000000000000000000..61a132f77a7b02107af0da5c256fb180925dd4f3 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/attr-alias-2.C @@ -0,0 +1,37 @@ +/* { dg-do run } */ +/* { dg-require-alias "" } */ + +#include <typeinfo> + +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); +}