Commit b3908fcc by Jonathan Wakely Committed by Jonathan Wakely

re PR libstdc++/51365 (cannot use final empty class in std::tuple)

c-family:
	PR libstdc++/51365
	* c-common.c (RID_IS_FINAL): Add.
	* c-common.h (RID_IS_FINAL): Add.
cp:
	PR libstdc++/51365
	* cp-tree.h (CPTK_IS_FINAL): Add.
	* parser.c (cp_parser_translation_unit): Handle RID_IS_FINAL.
	(cp_parser_primary_expression, cp_parser_trait_expr): Likewise.
	* semantics.c (trait_expr_value, finish_trait_expr): Handle
	CPTK_IS_FINAL.
	* cxx-pretty-print.c (pp_cxx_trait_expression): Likewise.
testsuite:
	PR libstdc++/51365
	* g++.dg/ext/is_final.C: New.

From-SVN: r182360
parent d36971dd
2011-12-15 Jonathan Wakely <jwakely.gcc@gmail.com>
PR libstdc++/51365
* c-common.c (RID_IS_FINAL): Add.
* c-common.h (RID_IS_FINAL): Add.
2011-11-30 Iain Sandoe <iains@gcc.gnu.org> 2011-11-30 Iain Sandoe <iains@gcc.gnu.org>
* c.opt (fgnu-runtime): Provide full description. * c.opt (fgnu-runtime): Provide full description.
......
...@@ -462,6 +462,7 @@ const struct c_common_resword c_common_reswords[] = ...@@ -462,6 +462,7 @@ const struct c_common_resword c_common_reswords[] =
{ "__is_convertible_to", RID_IS_CONVERTIBLE_TO, D_CXXONLY }, { "__is_convertible_to", RID_IS_CONVERTIBLE_TO, D_CXXONLY },
{ "__is_empty", RID_IS_EMPTY, D_CXXONLY }, { "__is_empty", RID_IS_EMPTY, D_CXXONLY },
{ "__is_enum", RID_IS_ENUM, D_CXXONLY }, { "__is_enum", RID_IS_ENUM, D_CXXONLY },
{ "__is_final", RID_IS_FINAL, D_CXXONLY },
{ "__is_literal_type", RID_IS_LITERAL_TYPE, D_CXXONLY }, { "__is_literal_type", RID_IS_LITERAL_TYPE, D_CXXONLY },
{ "__is_pod", RID_IS_POD, D_CXXONLY }, { "__is_pod", RID_IS_POD, D_CXXONLY },
{ "__is_polymorphic", RID_IS_POLYMORPHIC, D_CXXONLY }, { "__is_polymorphic", RID_IS_POLYMORPHIC, D_CXXONLY },
......
...@@ -134,7 +134,7 @@ enum rid ...@@ -134,7 +134,7 @@ enum rid
RID_CONSTCAST, RID_DYNCAST, RID_REINTCAST, RID_STATCAST, RID_CONSTCAST, RID_DYNCAST, RID_REINTCAST, RID_STATCAST,
/* C++ extensions */ /* C++ extensions */
RID_BASES, RID_DIRECT_BASES, RID_BASES, RID_DIRECT_BASES,
RID_HAS_NOTHROW_ASSIGN, RID_HAS_NOTHROW_CONSTRUCTOR, RID_HAS_NOTHROW_ASSIGN, RID_HAS_NOTHROW_CONSTRUCTOR,
RID_HAS_NOTHROW_COPY, RID_HAS_TRIVIAL_ASSIGN, RID_HAS_NOTHROW_COPY, RID_HAS_TRIVIAL_ASSIGN,
RID_HAS_TRIVIAL_CONSTRUCTOR, RID_HAS_TRIVIAL_COPY, RID_HAS_TRIVIAL_CONSTRUCTOR, RID_HAS_TRIVIAL_COPY,
...@@ -142,12 +142,12 @@ enum rid ...@@ -142,12 +142,12 @@ enum rid
RID_IS_ABSTRACT, RID_IS_BASE_OF, RID_IS_ABSTRACT, RID_IS_BASE_OF,
RID_IS_CLASS, RID_IS_CONVERTIBLE_TO, RID_IS_CLASS, RID_IS_CONVERTIBLE_TO,
RID_IS_EMPTY, RID_IS_ENUM, RID_IS_EMPTY, RID_IS_ENUM,
RID_IS_LITERAL_TYPE, RID_IS_POD, RID_IS_FINAL, RID_IS_LITERAL_TYPE,
RID_IS_POLYMORPHIC, RID_IS_STD_LAYOUT, RID_IS_POD, RID_IS_POLYMORPHIC,
RID_IS_TRIVIAL, RID_IS_UNION, RID_IS_STD_LAYOUT, RID_IS_TRIVIAL,
RID_UNDERLYING_TYPE, RID_IS_UNION, RID_UNDERLYING_TYPE,
/* C++0x */ /* C++11 */
RID_CONSTEXPR, RID_DECLTYPE, RID_NOEXCEPT, RID_NULLPTR, RID_STATIC_ASSERT, RID_CONSTEXPR, RID_DECLTYPE, RID_NOEXCEPT, RID_NULLPTR, RID_STATIC_ASSERT,
/* Objective-C ("AT" reserved words - they are only keywords when /* Objective-C ("AT" reserved words - they are only keywords when
......
2011-12-15 Jonathan Wakely <jwakely.gcc@gmail.com>
PR libstdc++/51365
* cp-tree.h (CPTK_IS_FINAL): Add.
* parser.c (cp_parser_translation_unit): Handle RID_IS_FINAL.
(cp_parser_primary_expression, cp_parser_trait_expr): Likewise.
* semantics.c (trait_expr_value, finish_trait_expr): Handle
CPTK_IS_FINAL.
* cxx-pretty-print.c (pp_cxx_trait_expression): Likewise.
2011-12-14 Jason Merrill <jason@redhat.com> 2011-12-14 Jason Merrill <jason@redhat.com>
PR c++/51554 PR c++/51554
......
...@@ -587,6 +587,7 @@ typedef enum cp_trait_kind ...@@ -587,6 +587,7 @@ typedef enum cp_trait_kind
CPTK_IS_CONVERTIBLE_TO, CPTK_IS_CONVERTIBLE_TO,
CPTK_IS_EMPTY, CPTK_IS_EMPTY,
CPTK_IS_ENUM, CPTK_IS_ENUM,
CPTK_IS_FINAL,
CPTK_IS_LITERAL_TYPE, CPTK_IS_LITERAL_TYPE,
CPTK_IS_POD, CPTK_IS_POD,
CPTK_IS_POLYMORPHIC, CPTK_IS_POLYMORPHIC,
......
...@@ -2380,6 +2380,9 @@ pp_cxx_trait_expression (cxx_pretty_printer *pp, tree t) ...@@ -2380,6 +2380,9 @@ pp_cxx_trait_expression (cxx_pretty_printer *pp, tree t)
case CPTK_IS_ENUM: case CPTK_IS_ENUM:
pp_cxx_ws_string (pp, "__is_enum"); pp_cxx_ws_string (pp, "__is_enum");
break; break;
case CPTK_IS_FINAL:
pp_cxx_ws_string (pp, "__is_final");
break;
case CPTK_IS_POD: case CPTK_IS_POD:
pp_cxx_ws_string (pp, "__is_pod"); pp_cxx_ws_string (pp, "__is_pod");
break; break;
......
...@@ -3854,6 +3854,7 @@ cp_parser_translation_unit (cp_parser* parser) ...@@ -3854,6 +3854,7 @@ cp_parser_translation_unit (cp_parser* parser)
__is_convertible_to ( type-id , type-id ) __is_convertible_to ( type-id , type-id )
__is_empty ( type-id ) __is_empty ( type-id )
__is_enum ( type-id ) __is_enum ( type-id )
__is_final ( type-id )
__is_literal_type ( type-id ) __is_literal_type ( type-id )
__is_pod ( type-id ) __is_pod ( type-id )
__is_polymorphic ( type-id ) __is_polymorphic ( type-id )
...@@ -4199,6 +4200,7 @@ cp_parser_primary_expression (cp_parser *parser, ...@@ -4199,6 +4200,7 @@ cp_parser_primary_expression (cp_parser *parser,
case RID_IS_CONVERTIBLE_TO: case RID_IS_CONVERTIBLE_TO:
case RID_IS_EMPTY: case RID_IS_EMPTY:
case RID_IS_ENUM: case RID_IS_ENUM:
case RID_IS_FINAL:
case RID_IS_LITERAL_TYPE: case RID_IS_LITERAL_TYPE:
case RID_IS_POD: case RID_IS_POD:
case RID_IS_POLYMORPHIC: case RID_IS_POLYMORPHIC:
...@@ -7868,6 +7870,9 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword) ...@@ -7868,6 +7870,9 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
case RID_IS_ENUM: case RID_IS_ENUM:
kind = CPTK_IS_ENUM; kind = CPTK_IS_ENUM;
break; break;
case RID_IS_FINAL:
kind = CPTK_IS_FINAL;
break;
case RID_IS_LITERAL_TYPE: case RID_IS_LITERAL_TYPE:
kind = CPTK_IS_LITERAL_TYPE; kind = CPTK_IS_LITERAL_TYPE;
break; break;
......
...@@ -5434,6 +5434,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2) ...@@ -5434,6 +5434,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
case CPTK_IS_ENUM: case CPTK_IS_ENUM:
return (type_code1 == ENUMERAL_TYPE); return (type_code1 == ENUMERAL_TYPE);
case CPTK_IS_FINAL:
return (CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1));
case CPTK_IS_LITERAL_TYPE: case CPTK_IS_LITERAL_TYPE:
return (literal_type_p (type1)); return (literal_type_p (type1));
...@@ -5493,6 +5496,7 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2) ...@@ -5493,6 +5496,7 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
|| kind == CPTK_IS_CONVERTIBLE_TO || kind == CPTK_IS_CONVERTIBLE_TO
|| kind == CPTK_IS_EMPTY || kind == CPTK_IS_EMPTY
|| kind == CPTK_IS_ENUM || kind == CPTK_IS_ENUM
|| kind == CPTK_IS_FINAL
|| kind == CPTK_IS_LITERAL_TYPE || kind == CPTK_IS_LITERAL_TYPE
|| kind == CPTK_IS_POD || kind == CPTK_IS_POD
|| kind == CPTK_IS_POLYMORPHIC || kind == CPTK_IS_POLYMORPHIC
...@@ -5533,6 +5537,7 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2) ...@@ -5533,6 +5537,7 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
case CPTK_HAS_VIRTUAL_DESTRUCTOR: case CPTK_HAS_VIRTUAL_DESTRUCTOR:
case CPTK_IS_ABSTRACT: case CPTK_IS_ABSTRACT:
case CPTK_IS_EMPTY: case CPTK_IS_EMPTY:
case CPTK_IS_FINAL:
case CPTK_IS_LITERAL_TYPE: case CPTK_IS_LITERAL_TYPE:
case CPTK_IS_POD: case CPTK_IS_POD:
case CPTK_IS_POLYMORPHIC: case CPTK_IS_POLYMORPHIC:
......
2011-12-15 Jonathan Wakely <jwakely.gcc@gmail.com>
PR libstdc++/51365
* g++.dg/ext/is_final.C: New.
2012-12-15 Richard Guenther <rguenther@suse.de> 2012-12-15 Richard Guenther <rguenther@suse.de>
PR lto/48508 PR lto/48508
......
// PR c++/51365
// { dg-do compile }
// { dg-options "-std=c++0x" }
struct A { };
static_assert( ! __is_final (A), "A not final" );
struct Af final { };
static_assert( __is_final (Af), "Af is final" );
class B { };
static_assert( ! __is_final (B), "B not final" );
class Bf final { };
static_assert( __is_final (Bf), "Bf is final" );
struct C : private A, private B { };
static_assert( ! __is_final (C), "C not final" );
struct Cf final : private A, private B { };
static_assert( __is_final (Cf), "Cf is final" );
struct D { virtual ~D() final { } };
static_assert( ! __is_final (D), "D not final" );
struct Df final { virtual ~Df() final { } };
static_assert( __is_final (Df), "Df is final" );
template<typename> struct E { };
static_assert( ! __is_final (E<int>), "E<int> not final" );
static_assert( ! __is_final (E<Af>), "E<Af> not final" );
template<typename> struct Ef final { };
static_assert( __is_final (Ef<int>), "Ef<int> is final" );
static_assert( __is_final (Ef<A>), "Ef<A> is final" );
static_assert( __is_final (Ef<Af>), "Ef<Af> is final" );
template<typename> struct F { virtual ~F() final { }; };
static_assert( ! __is_final (F<int>), "F<int> not final" );
static_assert( ! __is_final (F<Af>), "F<Af> not final" );
template<typename> struct Ff final { virtual ~Ff() final { }; };
static_assert( __is_final (Ff<int>), "Ff<int> is final" );
static_assert( __is_final (Ff<A>), "Ff<A> is final" );
static_assert( __is_final (Ff<Af>), "Ff<Af> is final" );
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