* [PATCH] C++0x, implement final on classes
@ 2011-05-13 20:03 Ville Voutilainen
2011-05-13 20:19 ` Jason Merrill
0 siblings, 1 reply; 13+ messages in thread
From: Ville Voutilainen @ 2011-05-13 20:03 UTC (permalink / raw)
To: gcc-patches; +Cc: jason
Tested on Linux/X86-32.
2011-05-13 Ville Voutilainen <ville.voutilainen@gmail.com> <ville.voutilainen@symbio.com>
Implement final on class.
* class.c (check_bases): Diagnose derivation from a final class.
* cp-tree.h (lang_type_class): Add is_final and adjust dummy.
* cp-tree.h (CLASSTYPE_FINAL): New.
* parser.c (cp_parser_class_head): Parse class-virt-specifier, set CLASSTYPE_FINAL.
* pt.c (instantiate_class_template_1): Copy the CLASSTYPE_FINAL.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 293dd1c..44b1d8e 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -1268,6 +1268,10 @@ check_bases (tree t,
gcc_assert (COMPLETE_TYPE_P (basetype));
+ if (CLASSTYPE_FINAL (basetype))
+ error ("cannot derive from from final base %qT in derived type %qT",
+ basetype, t);
+
/* If any base class is non-literal, so is the derived class. */
if (!CLASSTYPE_LITERAL_P (basetype))
CLASSTYPE_LITERAL_P (t) = false;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 1705232..901a17d 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1321,6 +1321,7 @@ struct GTY(()) lang_type_class {
unsigned has_complex_move_ctor : 1;
unsigned has_complex_move_assign : 1;
unsigned has_constexpr_ctor : 1;
+ unsigned is_final : 1;
/* When adding a flag here, consider whether or not it ought to
apply to a template instance if it applies to the template. If
@@ -1329,7 +1330,7 @@ struct GTY(()) lang_type_class {
/* There are some bits left to fill out a 32-bit word. Keep track
of this by updating the size of this bitfield whenever you add or
remove a flag. */
- unsigned dummy : 3;
+ unsigned dummy : 2;
tree primary_base;
VEC(tree_pair_s,gc) *vcall_indices;
@@ -1437,6 +1438,11 @@ struct GTY((variable_size)) lang_type {
#define CLASSTYPE_LAZY_DESTRUCTOR(NODE) \
(LANG_TYPE_CLASS_CHECK (NODE)->lazy_destructor)
+/* Nonzero means that NODE (a class type) is final */
+#define CLASSTYPE_FINAL(NODE) \
+ (LANG_TYPE_CLASS_CHECK (NODE)->is_final)
+
+
/* Nonzero means that this _CLASSTYPE node overloads operator=(X&). */
#define TYPE_HAS_COPY_ASSIGN(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_copy_assign)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index fa6cd83..5e9b8a8 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -17117,6 +17117,7 @@ cp_parser_class_head (cp_parser* parser,
tree id = NULL_TREE;
tree type = NULL_TREE;
tree attributes;
+ cp_virt_specifiers virt_specifiers = VIRT_SPEC_UNSPECIFIED;
bool template_id_p = false;
bool qualified_p = false;
bool invalid_nested_name_p = false;
@@ -17260,8 +17261,11 @@ cp_parser_class_head (cp_parser* parser,
pop_deferring_access_checks ();
if (id)
- cp_parser_check_for_invalid_template_id (parser, id,
- type_start_token->location);
+ {
+ virt_specifiers = cp_parser_virt_specifier_seq_opt (parser);
+ cp_parser_check_for_invalid_template_id (parser, id,
+ type_start_token->location);
+ }
/* If it's not a `:' or a `{' then we can't really be looking at a
class-head, since a class-head only appears as part of a
@@ -17493,6 +17497,8 @@ cp_parser_class_head (cp_parser* parser,
if (type)
DECL_SOURCE_LOCATION (TYPE_NAME (type)) = type_start_token->location;
*attributes_p = attributes;
+ if (virt_specifiers & VIRT_SPEC_FINAL)
+ CLASSTYPE_FINAL (type) = 1;
out:
parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
return type;
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 5e24977..5e059e0 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -8209,6 +8209,7 @@ instantiate_class_template_1 (tree type)
CLASSTYPE_VISIBILITY_SPECIFIED (type) = 1;
CLASSTYPE_VISIBILITY (type) = CLASSTYPE_VISIBILITY (pattern);
}
+ CLASSTYPE_FINAL (type) = CLASSTYPE_FINAL (pattern);
pbinfo = TYPE_BINFO (pattern);
diff --git a/gcc/testsuite/g++.dg/inherit/base4.C b/gcc/testsuite/g++.dg/inherit/base4.C
new file mode 100644
index 0000000..5736193
--- /dev/null
+++ b/gcc/testsuite/g++.dg/inherit/base4.C
@@ -0,0 +1,23 @@
+// { dg-do compile }
+// { dg-options "--std=c++0x" }
+struct B1 {};
+
+struct B2 final {};
+
+struct D1 : B1 {};
+
+struct D2 : B2 {}; // { dg-error "cannot derive from from final base" }
+
+template<class T> struct D3 : T {};
+
+template<class T> struct D4 : T {}; // { dg-error "cannot derive from from final base" }
+
+struct B3 final final {}; // { dg-error "duplicate virt-specifier" }
+
+int main()
+{
+ D3<B1> d;
+ D4<B2> d2;
+ struct B2 final{};
+ struct B1 final2{};
+}
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] C++0x, implement final on classes
2011-05-13 20:03 [PATCH] C++0x, implement final on classes Ville Voutilainen
@ 2011-05-13 20:19 ` Jason Merrill
2011-05-13 20:24 ` Ville Voutilainen
0 siblings, 1 reply; 13+ messages in thread
From: Jason Merrill @ 2011-05-13 20:19 UTC (permalink / raw)
To: Ville Voutilainen; +Cc: gcc-patches
On 05/13/2011 01:24 PM, Ville Voutilainen wrote:
> + error ("cannot derive from from final base %qT in derived type %qT",
Let's use %<final%> here.
> if (id)
> - cp_parser_check_for_invalid_template_id (parser, id,
> - type_start_token->location);
> + {
> + virt_specifiers = cp_parser_virt_specifier_seq_opt (parser);
> + cp_parser_check_for_invalid_template_id (parser, id,
> + type_start_token->location);
> + }
Why did you put this before the invalid template-id check, rather than
after?
Also, shouldn't we reject "override" on classes?
The test should include a class template marked final.
Jason
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] C++0x, implement final on classes
2011-05-13 20:19 ` Jason Merrill
@ 2011-05-13 20:24 ` Ville Voutilainen
2011-05-13 20:48 ` Jason Merrill
0 siblings, 1 reply; 13+ messages in thread
From: Ville Voutilainen @ 2011-05-13 20:24 UTC (permalink / raw)
To: Jason Merrill; +Cc: gcc-patches
On 13 May 2011 20:46, Jason Merrill <jason@redhat.com> wrote:
> Why did you put this before the invalid template-id check, rather than
> after?
For no particular reason. Is it significant?
> Also, shouldn't we reject "override" on classes?
You can have stuff like
struct blah override{};
where struct blah is an elaborate-type-specifier, and override is a
variable name.
How do I tell the difference, or more precisely, how do I know when a
class is being defined for
the first time?
> The test should include a class template marked final.
Ok, I'll fix these issues, any guidance for the override question
above is highly appreciated.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] C++0x, implement final on classes
2011-05-13 20:24 ` Ville Voutilainen
@ 2011-05-13 20:48 ` Jason Merrill
2011-05-14 9:50 ` Ville Voutilainen
0 siblings, 1 reply; 13+ messages in thread
From: Jason Merrill @ 2011-05-13 20:48 UTC (permalink / raw)
To: Ville Voutilainen; +Cc: gcc-patches
On 05/13/2011 01:53 PM, Ville Voutilainen wrote:
> On 13 May 2011 20:46, Jason Merrill<jason@redhat.com> wrote:
>> Why did you put this before the invalid template-id check, rather than
>> after?
>
> For no particular reason. Is it significant?
Yes, the order affects the handling of
struct Undeclared<int> final { };
>> Also, shouldn't we reject "override" on classes?
>
> You can have stuff like
> struct blah override{};
>
> where struct blah is an elaborate-type-specifier, and override is a
> variable name.
> How do I tell the difference, or more precisely, how do I know when a
> class is being defined for the first time?
Add the error after the call to cp_parser_commit_to_tentative_parse, at
which point we've decided that we're dealing with a class definition.
Jason
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] C++0x, implement final on classes
2011-05-13 20:48 ` Jason Merrill
@ 2011-05-14 9:50 ` Ville Voutilainen
2011-05-14 14:35 ` Paolo Carlini
0 siblings, 1 reply; 13+ messages in thread
From: Ville Voutilainen @ 2011-05-14 9:50 UTC (permalink / raw)
To: gcc-patches; +Cc: Jason Merrill
At Fri, 13 May 2011 14:13:52 -0400,
Jason Merrill wrote:
> Yes, the order affects the handling of
> struct Undeclared<int> final { };
> Add the error after the call to cp_parser_commit_to_tentative_parse, at
> which point we've decided that we're dealing with a class definition.
Here's a new patch. Hopefully it fixes the issues mentioned
before. Tests still pass, tested on Linux/X86-32.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 293dd1c..40a7643 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -1268,6 +1268,10 @@ check_bases (tree t,
gcc_assert (COMPLETE_TYPE_P (basetype));
+ if (CLASSTYPE_FINAL (basetype))
+ error ("cannot derive from %<final%> base %qT in derived type %qT",
+ basetype, t);
+
/* If any base class is non-literal, so is the derived class. */
if (!CLASSTYPE_LITERAL_P (basetype))
CLASSTYPE_LITERAL_P (t) = false;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 1705232..901a17d 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1321,6 +1321,7 @@ struct GTY(()) lang_type_class {
unsigned has_complex_move_ctor : 1;
unsigned has_complex_move_assign : 1;
unsigned has_constexpr_ctor : 1;
+ unsigned is_final : 1;
/* When adding a flag here, consider whether or not it ought to
apply to a template instance if it applies to the template. If
@@ -1329,7 +1330,7 @@ struct GTY(()) lang_type_class {
/* There are some bits left to fill out a 32-bit word. Keep track
of this by updating the size of this bitfield whenever you add or
remove a flag. */
- unsigned dummy : 3;
+ unsigned dummy : 2;
tree primary_base;
VEC(tree_pair_s,gc) *vcall_indices;
@@ -1437,6 +1438,11 @@ struct GTY((variable_size)) lang_type {
#define CLASSTYPE_LAZY_DESTRUCTOR(NODE) \
(LANG_TYPE_CLASS_CHECK (NODE)->lazy_destructor)
+/* Nonzero means that NODE (a class type) is final */
+#define CLASSTYPE_FINAL(NODE) \
+ (LANG_TYPE_CLASS_CHECK (NODE)->is_final)
+
+
/* Nonzero means that this _CLASSTYPE node overloads operator=(X&). */
#define TYPE_HAS_COPY_ASSIGN(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_copy_assign)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index fa6cd83..30cdb88 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -17082,10 +17082,13 @@ cp_parser_class_specifier (cp_parser* parser)
class-head:
class-key identifier [opt] base-clause [opt]
- class-key nested-name-specifier identifier base-clause [opt]
+ class-key nested-name-specifier identifier class-virt-specifier[opt] base-clause [opt]
class-key nested-name-specifier [opt] template-id
base-clause [opt]
+ class-virt-specifier:
+ final
+
GNU Extensions:
class-key attributes identifier [opt] base-clause [opt]
class-key attributes nested-name-specifier identifier base-clause [opt]
@@ -17117,6 +17120,7 @@ cp_parser_class_head (cp_parser* parser,
tree id = NULL_TREE;
tree type = NULL_TREE;
tree attributes;
+ cp_virt_specifiers virt_specifiers = VIRT_SPEC_UNSPECIFIED;
bool template_id_p = false;
bool qualified_p = false;
bool invalid_nested_name_p = false;
@@ -17260,8 +17264,11 @@ cp_parser_class_head (cp_parser* parser,
pop_deferring_access_checks ();
if (id)
- cp_parser_check_for_invalid_template_id (parser, id,
- type_start_token->location);
+ {
+ cp_parser_check_for_invalid_template_id (parser, id,
+ type_start_token->location);
+ virt_specifiers = cp_parser_virt_specifier_seq_opt (parser);
+ }
/* If it's not a `:' or a `{' then we can't really be looking at a
class-head, since a class-head only appears as part of a
@@ -17277,6 +17284,13 @@ cp_parser_class_head (cp_parser* parser,
/* At this point, we're going ahead with the class-specifier, even
if some other problem occurs. */
cp_parser_commit_to_tentative_parse (parser);
+ if (virt_specifiers & VIRT_SPEC_OVERRIDE)
+ {
+ cp_parser_error (parser,
+ "cannot specify %<override%> for a class");
+ type = error_mark_node;
+ goto out;
+ }
/* Issue the error about the overly-qualified name now. */
if (qualified_p)
{
@@ -17493,6 +17507,8 @@ cp_parser_class_head (cp_parser* parser,
if (type)
DECL_SOURCE_LOCATION (TYPE_NAME (type)) = type_start_token->location;
*attributes_p = attributes;
+ if (type && (virt_specifiers & VIRT_SPEC_FINAL))
+ CLASSTYPE_FINAL (type) = 1;
out:
parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
return type;
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 5e24977..5e059e0 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -8209,6 +8209,7 @@ instantiate_class_template_1 (tree type)
CLASSTYPE_VISIBILITY_SPECIFIED (type) = 1;
CLASSTYPE_VISIBILITY (type) = CLASSTYPE_VISIBILITY (pattern);
}
+ CLASSTYPE_FINAL (type) = CLASSTYPE_FINAL (pattern);
pbinfo = TYPE_BINFO (pattern);
diff --git a/gcc/testsuite/g++.dg/inherit/base4.C b/gcc/testsuite/g++.dg/inherit/base4.C
new file mode 100644
index 0000000..7f17504
--- /dev/null
+++ b/gcc/testsuite/g++.dg/inherit/base4.C
@@ -0,0 +1,47 @@
+// { dg-do compile }
+// { dg-options "--std=c++0x" }
+struct B1 {};
+
+struct B2 final {};
+
+struct D1 : B1 {};
+
+struct D2 : B2 {}; // { dg-error "cannot derive from 'final' base" }
+
+template<class T> struct D3 : T {};
+
+template<class T> struct D4 : T {}; // { dg-error "cannot derive from 'final' base" }
+
+template <class T> struct B3 {};
+
+template <class T> struct B4 final {};
+
+template <class T> struct B5 final {};
+
+struct undeclared<int> final { }; // { dg-error "not a template" }
+
+struct D5 : B3<D5> {};
+
+struct D6 : B4<D6> {}; // { dg-error "cannot derive from 'final' base" }
+
+struct B6 final final {}; // { dg-error "duplicate virt-specifier" }
+
+struct B7 override {}; // { dg-error "cannot specify 'override' for a class" }
+
+int main()
+{
+ D3<B1> d;
+ D4<B2> d2;
+ struct B2 final{}; // { dg-error "previous definition" }
+ B2 final; // { dg-error "has a previous declaration|previously declared here" }
+ B2 final2 = final;
+ struct B2 {}; // { dg-error "redefinition" }
+ struct B2 final; // { dg-error "redeclaration" }
+ struct B2 override; // { dg-error "previously declared here" }
+ struct B2 final {}; // { dg-error "redefinition" }
+ struct B2 override {}; // { dg-error "cannot specify 'override' for a class" }
+ B2 override{}; // { dg-error "redeclaration" }
+ struct foo final {}; // { dg-error "previous definition" }
+ struct foo final {}; // { dg-error "redefinition" }
+ foo final; // { dg-error "conflicting declaration" }
+}
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] C++0x, implement final on classes
2011-05-14 9:50 ` Ville Voutilainen
@ 2011-05-14 14:35 ` Paolo Carlini
2011-05-14 18:15 ` Ville Voutilainen
0 siblings, 1 reply; 13+ messages in thread
From: Paolo Carlini @ 2011-05-14 14:35 UTC (permalink / raw)
To: Ville Voutilainen; +Cc: gcc-patches, Jason Merrill
... I'm wondering if wouldn't be more appropriate for the new testcase to be in /cpp0x, with a name like final.C
Paolo
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] C++0x, implement final on classes
2011-05-14 14:35 ` Paolo Carlini
@ 2011-05-14 18:15 ` Ville Voutilainen
2011-05-14 22:50 ` Jason Merrill
0 siblings, 1 reply; 13+ messages in thread
From: Ville Voutilainen @ 2011-05-14 18:15 UTC (permalink / raw)
To: gcc-patches; +Cc: Jason Merrill
At Sat, 14 May 2011 09:01:39 +0200,
Paolo Carlini wrote:
> ... I'm wondering if wouldn't be more appropriate for the new testcase to be in /cpp0x, with a name like final.C
There are probably other tests there that need moving too,
if such moving is done. I don't have a strong opinion
either way, but maybe the moving should be done separately?
The last patch contained a ligature in the grammar comment
for class-virt-specifier.. fixed below.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 293dd1c..40a7643 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -1268,6 +1268,10 @@ check_bases (tree t,
gcc_assert (COMPLETE_TYPE_P (basetype));
+ if (CLASSTYPE_FINAL (basetype))
+ error ("cannot derive from %<final%> base %qT in derived type %qT",
+ basetype, t);
+
/* If any base class is non-literal, so is the derived class. */
if (!CLASSTYPE_LITERAL_P (basetype))
CLASSTYPE_LITERAL_P (t) = false;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 1705232..901a17d 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1321,6 +1321,7 @@ struct GTY(()) lang_type_class {
unsigned has_complex_move_ctor : 1;
unsigned has_complex_move_assign : 1;
unsigned has_constexpr_ctor : 1;
+ unsigned is_final : 1;
/* When adding a flag here, consider whether or not it ought to
apply to a template instance if it applies to the template. If
@@ -1329,7 +1330,7 @@ struct GTY(()) lang_type_class {
/* There are some bits left to fill out a 32-bit word. Keep track
of this by updating the size of this bitfield whenever you add or
remove a flag. */
- unsigned dummy : 3;
+ unsigned dummy : 2;
tree primary_base;
VEC(tree_pair_s,gc) *vcall_indices;
@@ -1437,6 +1438,11 @@ struct GTY((variable_size)) lang_type {
#define CLASSTYPE_LAZY_DESTRUCTOR(NODE) \
(LANG_TYPE_CLASS_CHECK (NODE)->lazy_destructor)
+/* Nonzero means that NODE (a class type) is final */
+#define CLASSTYPE_FINAL(NODE) \
+ (LANG_TYPE_CLASS_CHECK (NODE)->is_final)
+
+
/* Nonzero means that this _CLASSTYPE node overloads operator=(X&). */
#define TYPE_HAS_COPY_ASSIGN(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_copy_assign)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index fa6cd83..a77d4ff 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -17082,10 +17082,13 @@ cp_parser_class_specifier (cp_parser* parser)
class-head:
class-key identifier [opt] base-clause [opt]
- class-key nested-name-specifier identifier base-clause [opt]
+ class-key nested-name-specifier identifier class-virt-specifier [opt] base-clause [opt]
class-key nested-name-specifier [opt] template-id
base-clause [opt]
+ class-virt-specifier:
+ final
+
GNU Extensions:
class-key attributes identifier [opt] base-clause [opt]
class-key attributes nested-name-specifier identifier base-clause [opt]
@@ -17117,6 +17120,7 @@ cp_parser_class_head (cp_parser* parser,
tree id = NULL_TREE;
tree type = NULL_TREE;
tree attributes;
+ cp_virt_specifiers virt_specifiers = VIRT_SPEC_UNSPECIFIED;
bool template_id_p = false;
bool qualified_p = false;
bool invalid_nested_name_p = false;
@@ -17260,8 +17264,11 @@ cp_parser_class_head (cp_parser* parser,
pop_deferring_access_checks ();
if (id)
- cp_parser_check_for_invalid_template_id (parser, id,
- type_start_token->location);
+ {
+ cp_parser_check_for_invalid_template_id (parser, id,
+ type_start_token->location);
+ virt_specifiers = cp_parser_virt_specifier_seq_opt (parser);
+ }
/* If it's not a `:' or a `{' then we can't really be looking at a
class-head, since a class-head only appears as part of a
@@ -17277,6 +17284,13 @@ cp_parser_class_head (cp_parser* parser,
/* At this point, we're going ahead with the class-specifier, even
if some other problem occurs. */
cp_parser_commit_to_tentative_parse (parser);
+ if (virt_specifiers & VIRT_SPEC_OVERRIDE)
+ {
+ cp_parser_error (parser,
+ "cannot specify %<override%> for a class");
+ type = error_mark_node;
+ goto out;
+ }
/* Issue the error about the overly-qualified name now. */
if (qualified_p)
{
@@ -17493,6 +17507,8 @@ cp_parser_class_head (cp_parser* parser,
if (type)
DECL_SOURCE_LOCATION (TYPE_NAME (type)) = type_start_token->location;
*attributes_p = attributes;
+ if (type && (virt_specifiers & VIRT_SPEC_FINAL))
+ CLASSTYPE_FINAL (type) = 1;
out:
parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
return type;
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 5e24977..5e059e0 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -8209,6 +8209,7 @@ instantiate_class_template_1 (tree type)
CLASSTYPE_VISIBILITY_SPECIFIED (type) = 1;
CLASSTYPE_VISIBILITY (type) = CLASSTYPE_VISIBILITY (pattern);
}
+ CLASSTYPE_FINAL (type) = CLASSTYPE_FINAL (pattern);
pbinfo = TYPE_BINFO (pattern);
diff --git a/gcc/testsuite/g++.dg/inherit/base4.C b/gcc/testsuite/g++.dg/inherit/base4.C
new file mode 100644
index 0000000..7f17504
--- /dev/null
+++ b/gcc/testsuite/g++.dg/inherit/base4.C
@@ -0,0 +1,47 @@
+// { dg-do compile }
+// { dg-options "--std=c++0x" }
+struct B1 {};
+
+struct B2 final {};
+
+struct D1 : B1 {};
+
+struct D2 : B2 {}; // { dg-error "cannot derive from 'final' base" }
+
+template<class T> struct D3 : T {};
+
+template<class T> struct D4 : T {}; // { dg-error "cannot derive from 'final' base" }
+
+template <class T> struct B3 {};
+
+template <class T> struct B4 final {};
+
+template <class T> struct B5 final {};
+
+struct undeclared<int> final { }; // { dg-error "not a template" }
+
+struct D5 : B3<D5> {};
+
+struct D6 : B4<D6> {}; // { dg-error "cannot derive from 'final' base" }
+
+struct B6 final final {}; // { dg-error "duplicate virt-specifier" }
+
+struct B7 override {}; // { dg-error "cannot specify 'override' for a class" }
+
+int main()
+{
+ D3<B1> d;
+ D4<B2> d2;
+ struct B2 final{}; // { dg-error "previous definition" }
+ B2 final; // { dg-error "has a previous declaration|previously declared here" }
+ B2 final2 = final;
+ struct B2 {}; // { dg-error "redefinition" }
+ struct B2 final; // { dg-error "redeclaration" }
+ struct B2 override; // { dg-error "previously declared here" }
+ struct B2 final {}; // { dg-error "redefinition" }
+ struct B2 override {}; // { dg-error "cannot specify 'override' for a class" }
+ B2 override{}; // { dg-error "redeclaration" }
+ struct foo final {}; // { dg-error "previous definition" }
+ struct foo final {}; // { dg-error "redefinition" }
+ foo final; // { dg-error "conflicting declaration" }
+}
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] C++0x, implement final on classes
2011-05-14 18:15 ` Ville Voutilainen
@ 2011-05-14 22:50 ` Jason Merrill
2011-05-14 22:52 ` Ville Voutilainen
0 siblings, 1 reply; 13+ messages in thread
From: Jason Merrill @ 2011-05-14 22:50 UTC (permalink / raw)
To: Ville Voutilainen; +Cc: gcc-patches
On 05/14/2011 10:56 AM, Ville Voutilainen wrote:
> At Sat, 14 May 2011 09:01:39 +0200,
> Paolo Carlini wrote:
>> ... I'm wondering if wouldn't be more appropriate for the new testcase to be in /cpp0x, with a name like final.C
>
> There are probably other tests there that need moving too,
> if such moving is done. I don't have a strong opinion
> either way, but maybe the moving should be done separately?
Paolo is right, C++0x tests go in cpp0x. I'll move this and your
earlier one.
Jason
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] C++0x, implement final on classes
2011-05-14 22:50 ` Jason Merrill
@ 2011-05-14 22:52 ` Ville Voutilainen
2011-05-15 9:35 ` Jason Merrill
0 siblings, 1 reply; 13+ messages in thread
From: Ville Voutilainen @ 2011-05-14 22:52 UTC (permalink / raw)
To: Jason Merrill; +Cc: gcc-patches
On 14 May 2011 19:41, Jason Merrill <jason@redhat.com> wrote:
> Paolo is right, C++0x tests go in cpp0x. I'll move this and your earlier
> one.
Duly noted, I'll keep that in mind for subsequent ones. Is the patch
otherwise ok?
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] C++0x, implement final on classes
2011-05-14 22:52 ` Ville Voutilainen
@ 2011-05-15 9:35 ` Jason Merrill
2011-05-15 10:25 ` Ville Voutilainen
0 siblings, 1 reply; 13+ messages in thread
From: Jason Merrill @ 2011-05-15 9:35 UTC (permalink / raw)
To: Ville Voutilainen; +Cc: gcc-patches
On 05/14/2011 12:42 PM, Ville Voutilainen wrote:
> On 14 May 2011 19:41, Jason Merrill<jason@redhat.com> wrote:
>> Paolo is right, C++0x tests go in cpp0x. I'll move this and your earlier
>> one.
>
> Duly noted, I'll keep that in mind for subsequent ones. Is the patch
> otherwise ok?
Yes, and I've applied it.
Jason
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] C++0x, implement final on classes
2011-05-15 9:35 ` Jason Merrill
@ 2011-05-15 10:25 ` Ville Voutilainen
2011-05-15 14:08 ` Jason Merrill
0 siblings, 1 reply; 13+ messages in thread
From: Ville Voutilainen @ 2011-05-15 10:25 UTC (permalink / raw)
To: gcc-patches; +Cc: Jason Merrill
On 14 May 2011 21:15, Jason Merrill <jason@redhat.com> wrote:
> On 05/14/2011 12:42 PM, Ville Voutilainen wrote:
>> Duly noted, I'll keep that in mind for subsequent ones. Is the patch
>> otherwise ok?
> Yes, and I've applied it.
Cool, thanks! I'm not quite sure whether there are ambiguities in the case
of elaborate-specifiers, but I suppose those can be fixed later. Should these
facilities be somehow flagged 0x-only? I haven't done that at all..
Somebody should probably update the C++0x status page, and refer to N3206
rather than to N2928 for explicit virtual overrides, and mark it done?
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] C++0x, implement final on classes
2011-05-15 10:25 ` Ville Voutilainen
@ 2011-05-15 14:08 ` Jason Merrill
2011-05-15 15:43 ` Jason Merrill
0 siblings, 1 reply; 13+ messages in thread
From: Jason Merrill @ 2011-05-15 14:08 UTC (permalink / raw)
To: Ville Voutilainen; +Cc: gcc-patches
On 05/14/2011 02:19 PM, Ville Voutilainen wrote:
> Cool, thanks! I'm not quite sure whether there are ambiguities in the case
> of elaborate-specifiers, but I suppose those can be fixed later.
Good point. In the case that
!cp_parser_next_token_starts_class_definition_p, we should rewind to
before what we parsed as virt-specifiers.
> Should these
> facilities be somehow flagged 0x-only? I haven't done that at all..
Yes, we should maybe_warn_cpp0x about them.
> Somebody should probably update the C++0x status page, and refer to N3206
> rather than to N2928 for explicit virtual overrides, and mark it done?
Will do.
Jason
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] C++0x, implement final on classes
2011-05-15 14:08 ` Jason Merrill
@ 2011-05-15 15:43 ` Jason Merrill
0 siblings, 0 replies; 13+ messages in thread
From: Jason Merrill @ 2011-05-15 15:43 UTC (permalink / raw)
To: Ville Voutilainen; +Cc: gcc-patches
On 05/14/2011 06:49 PM, Jason Merrill wrote:
> On 05/14/2011 02:19 PM, Ville Voutilainen wrote:
>> Cool, thanks! I'm not quite sure whether there are ambiguities in the
>> case
>> of elaborate-specifiers, but I suppose those can be fixed later.
>
> Good point. In the case that
> !cp_parser_next_token_starts_class_definition_p, we should rewind to
> before what we parsed as virt-specifiers.
cp_lexer_token_position and cp_lexer_set_token_position should be useful
for this.
Jason
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2011-05-14 22:52 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-13 20:03 [PATCH] C++0x, implement final on classes Ville Voutilainen
2011-05-13 20:19 ` Jason Merrill
2011-05-13 20:24 ` Ville Voutilainen
2011-05-13 20:48 ` Jason Merrill
2011-05-14 9:50 ` Ville Voutilainen
2011-05-14 14:35 ` Paolo Carlini
2011-05-14 18:15 ` Ville Voutilainen
2011-05-14 22:50 ` Jason Merrill
2011-05-14 22:52 ` Ville Voutilainen
2011-05-15 9:35 ` Jason Merrill
2011-05-15 10:25 ` Ville Voutilainen
2011-05-15 14:08 ` Jason Merrill
2011-05-15 15:43 ` Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).