decl.c (record_key_method_defined): New, broken out of ...

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.

From-SVN: r160431
This commit is contained in:
Nathan Sidwell 2010-06-08 09:59:10 +00:00 committed by Nathan Sidwell
parent 4b9c045f7e
commit 3bb1ed661a
5 changed files with 111 additions and 9 deletions

View File

@ -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> 2010-06-08 Laurynas Biveinis <laurynas.biveinis@gmail.com>
* typeck2.c (abstract_virtuals_error): Use typed GC allocation. * typeck2.c (abstract_virtuals_error): Use typed GC allocation.

View File

@ -90,6 +90,7 @@ static void check_function_type (tree, tree);
static void finish_constructor_body (void); static void finish_constructor_body (void);
static void begin_destructor_body (void); static void begin_destructor_body (void);
static void finish_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 create_array_type_for_decl (tree, tree, tree);
static tree get_atexit_node (void); static tree get_atexit_node (void);
static tree get_dso_handle_node (void); static tree get_dso_handle_node (void);
@ -4129,6 +4130,7 @@ start_decl (const cp_declarator *declarator,
tree context; tree context;
bool was_public; bool was_public;
int flags; int flags;
bool alias;
*pushed_scope_p = NULL_TREE; *pushed_scope_p = NULL_TREE;
@ -4190,6 +4192,10 @@ start_decl (const cp_declarator *declarator,
if (toplevel_bindings_p ()) if (toplevel_bindings_p ())
TREE_STATIC (decl) = 1; 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 /* If this is a typedef that names the class for linkage purposes
(7.1.3p8), apply any attributes directly to the type. */ (7.1.3p8), apply any attributes directly to the type. */
@ -4292,7 +4298,9 @@ start_decl (const cp_declarator *declarator,
DECL_EXTERNAL (decl) = 1; 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", permerror (input_location, "declaration of %q#D outside of class is not definition",
decl); decl);
@ -12502,6 +12510,22 @@ outer_curly_brace_block (tree fndecl)
return block; 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 /* Finish up a function declaration and compile that function
all the way to assembler language output. The free the storage all the way to assembler language output. The free the storage
for the function definition. for the function definition.
@ -12528,14 +12552,7 @@ finish_function (int flags)
gcc_assert (!defer_mark_used_calls); gcc_assert (!defer_mark_used_calls);
defer_mark_used_calls = true; defer_mark_used_calls = true;
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl) record_key_method_defined (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);
}
nested = function_depth > 1; nested = function_depth > 1;
fntype = TREE_TYPE (fndecl); fntype = TREE_TYPE (fndecl);

View File

@ -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> 2010-06-07 Tobias Burnus <burnus@net-b.de>
PR fortran/44446 PR fortran/44446

View File

@ -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);
}

View File

@ -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);
}