===================================================================
@@ -462,6 +462,7 @@ const struct c_common_resword c_common_r
{ "__is_convertible_to", RID_IS_CONVERTIBLE_TO, D_CXXONLY },
{ "__is_empty", RID_IS_EMPTY, 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_pod", RID_IS_POD, D_CXXONLY },
{ "__is_polymorphic", RID_IS_POLYMORPHIC, D_CXXONLY },
===================================================================
@@ -134,7 +134,7 @@ enum rid
RID_CONSTCAST, RID_DYNCAST, RID_REINTCAST, RID_STATCAST,
/* C++ extensions */
- RID_BASES, RID_DIRECT_BASES,
+ RID_BASES, RID_DIRECT_BASES,
RID_HAS_NOTHROW_ASSIGN, RID_HAS_NOTHROW_CONSTRUCTOR,
RID_HAS_NOTHROW_COPY, RID_HAS_TRIVIAL_ASSIGN,
RID_HAS_TRIVIAL_CONSTRUCTOR, RID_HAS_TRIVIAL_COPY,
@@ -142,12 +142,12 @@ enum rid
RID_IS_ABSTRACT, RID_IS_BASE_OF,
RID_IS_CLASS, RID_IS_CONVERTIBLE_TO,
RID_IS_EMPTY, RID_IS_ENUM,
- RID_IS_LITERAL_TYPE, RID_IS_POD,
- RID_IS_POLYMORPHIC, RID_IS_STD_LAYOUT,
- RID_IS_TRIVIAL, RID_IS_UNION,
- RID_UNDERLYING_TYPE,
+ RID_IS_FINAL, RID_IS_LITERAL_TYPE,
+ RID_IS_POD, RID_IS_POLYMORPHIC,
+ RID_IS_STD_LAYOUT, RID_IS_TRIVIAL,
+ RID_IS_UNION, RID_UNDERLYING_TYPE,
- /* C++0x */
+ /* C++11 */
RID_CONSTEXPR, RID_DECLTYPE, RID_NOEXCEPT, RID_NULLPTR, RID_STATIC_ASSERT,
/* Objective-C ("AT" reserved words - they are only keywords when
===================================================================
@@ -584,6 +584,7 @@ typedef enum cp_trait_kind
CPTK_IS_CONVERTIBLE_TO,
CPTK_IS_EMPTY,
CPTK_IS_ENUM,
+ CPTK_IS_FINAL,
CPTK_IS_LITERAL_TYPE,
CPTK_IS_POD,
CPTK_IS_POLYMORPHIC,
===================================================================
@@ -3854,6 +3854,7 @@ cp_parser_translation_unit (cp_parser* p
__is_convertible_to ( type-id , type-id )
__is_empty ( type-id )
__is_enum ( type-id )
+ __is_final ( type-id )
__is_literal_type ( type-id )
__is_pod ( type-id )
__is_polymorphic ( type-id )
@@ -4199,6 +4200,7 @@ cp_parser_primary_expression (cp_parser
case RID_IS_CONVERTIBLE_TO:
case RID_IS_EMPTY:
case RID_IS_ENUM:
+ case RID_IS_FINAL:
case RID_IS_LITERAL_TYPE:
case RID_IS_POD:
case RID_IS_POLYMORPHIC:
@@ -7868,6 +7870,9 @@ cp_parser_trait_expr (cp_parser* parser,
case RID_IS_ENUM:
kind = CPTK_IS_ENUM;
break;
+ case RID_IS_FINAL:
+ kind = CPTK_IS_FINAL;
+ break;
case RID_IS_LITERAL_TYPE:
kind = CPTK_IS_LITERAL_TYPE;
break;
===================================================================
@@ -5412,6 +5412,9 @@ trait_expr_value (cp_trait_kind kind, tr
case CPTK_IS_ENUM:
return (type_code1 == ENUMERAL_TYPE);
+ case CPTK_IS_FINAL:
+ return (CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1));
+
case CPTK_IS_LITERAL_TYPE:
return (literal_type_p (type1));
@@ -5471,6 +5474,7 @@ finish_trait_expr (cp_trait_kind kind, t
|| kind == CPTK_IS_CONVERTIBLE_TO
|| kind == CPTK_IS_EMPTY
|| kind == CPTK_IS_ENUM
+ || kind == CPTK_IS_FINAL
|| kind == CPTK_IS_LITERAL_TYPE
|| kind == CPTK_IS_POD
|| kind == CPTK_IS_POLYMORPHIC
@@ -5511,6 +5515,7 @@ finish_trait_expr (cp_trait_kind kind, t
case CPTK_HAS_VIRTUAL_DESTRUCTOR:
case CPTK_IS_ABSTRACT:
case CPTK_IS_EMPTY:
+ case CPTK_IS_FINAL:
case CPTK_IS_LITERAL_TYPE:
case CPTK_IS_POD:
case CPTK_IS_POLYMORPHIC:
===================================================================
@@ -2380,6 +2380,9 @@ pp_cxx_trait_expression (cxx_pretty_prin
case CPTK_IS_ENUM:
pp_cxx_ws_string (pp, "__is_enum");
break;
+ case CPTK_IS_FINAL:
+ pp_cxx_ws_string (pp, "__is_final");
+ break;
case CPTK_IS_POD:
pp_cxx_ws_string (pp, "__is_pod");
break;
===================================================================
@@ -15164,6 +15164,10 @@ of unknown bound.
If @code{type} is a cv enumeration type ([basic.compound]) the trait is
true, else it is false.
+@item __is_final (type)
+If @code{type} is a cv class type marked @code{final} ([class]) the trait
+is true, else it is false.
+
@item __is_literal_type (type)
If @code{type} is a literal type ([basic.types]) the trait is
true, else it is false. Requires: @code{type} shall be a complete type,
===================================================================
@@ -0,0 +1,46 @@
+// 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" );
+