aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2010-06-08 09:59:10 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2010-06-08 09:59:10 +0000
commit3bb1ed661a7dc49c4536613d430699d124641b10 (patch)
tree906559e4176cecbde6bf18a6a401846d2ff55bce
parent4b9c045f7e3afb16f845649c04fa62634098a885 (diff)
downloadgcc-3bb1ed661a7dc49c4536613d430699d124641b10.zip
gcc-3bb1ed661a7dc49c4536613d430699d124641b10.tar.gz
gcc-3bb1ed661a7dc49c4536613d430699d124641b10.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/decl.c35
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-alias-1.C37
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-alias-2.C37
5 files changed, 111 insertions, 9 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 931cbe1..3bb19a0 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 706eee9..ca3152f 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 239ef3e..284bbc9 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 0000000..1427267
--- /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 0000000..61a132f
--- /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);
+}