Commit 3bb1ed66 by Nathan Sidwell Committed by Nathan Sidwell

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
parent 4b9c045f
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.
......
...@@ -90,6 +90,7 @@ static void check_function_type (tree, tree); ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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);
......
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
......
/* { 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);
}
/* { 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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment