diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3f04054cd8a..3e7abcc0a35 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2011-12-13 Fabien ChĂȘne + + PR c++/14258 + * cp-tree.h (USING_DECL_TYPENAME_P): New macro. + * parser.c (cp_parser_nonclass_name): Handle using declarations + that refer to a dependent type. + (cp_parser_using_declaration): Set USING_DECL_TYPENAME_P to 1 if + the using declaration refers to a dependent type. + 2011-12-12 Jakub Jelinek PR c++/51496 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index f4438165b4b..a96adbb17b2 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -130,6 +130,7 @@ c-common.h, not after. DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL) DECL_MEMBER_TEMPLATE_P (in TEMPLATE_DECL) FUNCTION_PARAMETER_PACK_P (in PARM_DECL) + USING_DECL_TYPENAME_P (in USING_DECL) 2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL). DECL_IMPLICIT_TYPEDEF_P (in a TYPE_DECL) 3: DECL_IN_AGGR_P. @@ -2521,6 +2522,9 @@ extern void decl_shadowed_for_var_insert (tree, tree); /* The decls named by a using decl. */ #define USING_DECL_DECLS(NODE) DECL_INITIAL (USING_DECL_CHECK (NODE)) +/* Non zero if the using decl refers to a dependent type. */ +#define USING_DECL_TYPENAME_P(NODE) DECL_LANG_FLAG_1 (USING_DECL_CHECK (NODE)) + /* In a VAR_DECL, true if we have a shadowed local variable in the shadowed var table for this VAR_DECL. */ #define DECL_HAS_SHADOWED_FOR_VAR_P(NODE) \ diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 2bd91ec9656..91280b785a2 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -13807,9 +13807,26 @@ cp_parser_nonclass_name (cp_parser* parser) /* Look up the type-name. */ type_decl = cp_parser_lookup_name_simple (parser, identifier, token->location); - /* If it is a using decl, use its underlying decl. */ - type_decl = strip_using_decl (type_decl); - + if (TREE_CODE (type_decl) == USING_DECL) + { + if (!DECL_DEPENDENT_P (type_decl)) + type_decl = strip_using_decl (type_decl); + else if (USING_DECL_TYPENAME_P (type_decl)) + { + /* We have found a type introduced by a using + declaration at class scope that refers to a dependent + type. + + using typename :: [opt] nested-name-specifier unqualified-id ; + */ + type_decl = make_typename_type (TREE_TYPE (type_decl), + DECL_NAME (type_decl), + typename_type, tf_error); + if (type_decl != error_mark_node) + type_decl = TYPE_NAME (type_decl); + } + } + if (TREE_CODE (type_decl) != TYPE_DECL && (objc_is_id (identifier) || objc_is_class_name (identifier))) { @@ -14947,6 +14964,9 @@ cp_parser_using_declaration (cp_parser* parser, /* Create the USING_DECL. */ decl = do_class_using_decl (parser->scope, identifier); + if (typename_p) + USING_DECL_TYPENAME_P (decl) = 1; + if (check_for_bare_parameter_packs (decl)) return false; else @@ -18900,7 +18920,11 @@ cp_parser_member_declaration (cp_parser* parser) parser->colon_corrects_to_scope_p = false; if (cp_parser_using_declaration (parser, /*access_declaration=*/true)) - goto out; + { + warning (OPT_Wdeprecated, "access declarations are deprecated; " + "employ using declarations instead"); + goto out; + } /* Parse the decl-specifier-seq. */ decl_spec_token_start = cp_lexer_peek_token (parser->lexer); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e5fa8ba4ee0..50595b29dba 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2011-12-11 Fabien ChĂȘne + + PR c++/14258 + * g++.dg/template/using16.C: New. + * g++.dg/template/using17.C: New. + 2011-12-13 Martin Jambor PR tree-optimization/51362 diff --git a/gcc/testsuite/g++.dg/template/using16.C b/gcc/testsuite/g++.dg/template/using16.C new file mode 100644 index 00000000000..589f7f18f52 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/using16.C @@ -0,0 +1,42 @@ +// { dg-do compile } + +template +struct A +{ + typedef T type; +}; + +template +struct B +{ + class type + { + type(); // { dg-error "private" } + }; +}; + +template +struct C : A, B +{ + using typename B::type; + + void f() + { + type j; // { dg-error "context" } + } +}; + +template class C; // { dg-message "required" } + +template +struct D +{ + typedef T type; +}; + +template +class E : D +{ + using typename D::type; // { dg-message "previous" } + using typename D::type; // { dg-error "redeclaration" } +}; diff --git a/gcc/testsuite/g++.dg/template/using17.C b/gcc/testsuite/g++.dg/template/using17.C new file mode 100644 index 00000000000..1af1dc71e4e --- /dev/null +++ b/gcc/testsuite/g++.dg/template/using17.C @@ -0,0 +1,44 @@ +// PR c++/14258 +// { dg-do run } + +template +struct A +{ + typedef T type; + typedef A type2; +}; + +template +struct B : A +{ + using typename A::type; + type t; + + using typename A::type2; + + type f() + { + type i = 1; + return i; + } +}; + +int main() +{ + B::type t = 4; + if (t != 4) + __builtin_abort(); + + B b; + b.t = 3; + if (b.t != 3) + __builtin_abort(); + + B b2; + if (b2.f() != 1) + __builtin_abort(); + + B::type2::type tt = 12; + if (tt != 12) + __builtin_abort(); +}