diff options
author | Jason Merrill <jason@redhat.com> | 2010-06-07 08:09:01 -0400 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2011-03-30 16:19:30 -0400 |
commit | ad334a2e6df70d75d677c33cd3b0b9ea182aa9c2 (patch) | |
tree | e10481121c9eb7c9f0a7886b284b8e97b605b394 | |
parent | 414b72cf0c873a53501888f7fdfb8545ca7f36ad (diff) | |
download | gcc-jason/alias-decl.tar.gz |
alias-decljason/alias-decl
-rw-r--r-- | gcc/cp/cp-tree.h | 29 | ||||
-rw-r--r-- | gcc/cp/error.c | 10 | ||||
-rw-r--r-- | gcc/cp/parser.c | 69 | ||||
-rw-r--r-- | gcc/cp/pt.c | 23 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 14 |
5 files changed, 126 insertions, 19 deletions
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 6ef6e6eb3ec..0131a27aaa4 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -138,6 +138,7 @@ c-common.h, not after. 5: DECL_INTERFACE_KNOWN. 6: DECL_THIS_STATIC (in VAR_DECL or FUNCTION_DECL). DECL_FIELD_IS_BASE (in FIELD_DECL) + TYPE_DECL_ALIAS_P (in TYPE_DECL) 7: DECL_DEAD_FOR_LOCAL (in VAR_DECL). DECL_THUNK_P (in a member FUNCTION_DECL) DECL_NORMAL_CAPTURE_P (in FIELD_DECL) @@ -2529,16 +2530,17 @@ extern void decl_shadowed_for_var_insert (tree, tree); ? ENUM_TEMPLATE_INFO (NODE) : \ (TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM \ ? TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (NODE) : \ - (TYPE_LANG_SPECIFIC (NODE) \ + (CLASS_TYPE_P (NODE) \ ? CLASSTYPE_TEMPLATE_INFO (NODE) \ - : NULL_TREE))) + : (DECL_TEMPLATE_INFO (TYPE_NAME (NODE)))))) /* Set the template information for an ENUMERAL_, RECORD_, or UNION_TYPE to VAL. */ -#define SET_TYPE_TEMPLATE_INFO(NODE, VAL) \ - (TREE_CODE (NODE) == ENUMERAL_TYPE \ - ? (ENUM_TEMPLATE_INFO (NODE) = (VAL)) \ - : (CLASSTYPE_TEMPLATE_INFO (NODE) = (VAL))) +#define SET_TYPE_TEMPLATE_INFO(NODE, VAL) \ + (TREE_CODE (NODE) == ENUMERAL_TYPE \ + ? (ENUM_TEMPLATE_INFO (NODE) = (VAL)) \ + : CLASS_TYPE_P (NODE) ? (CLASSTYPE_TEMPLATE_INFO (NODE) = (VAL)) \ + : (DECL_TEMPLATE_INFO (TYPE_NAME (NODE)) = (VAL))) #define TI_TEMPLATE(NODE) TREE_TYPE (TEMPLATE_INFO_CHECK (NODE)) #define TI_ARGS(NODE) TREE_CHAIN (TEMPLATE_INFO_CHECK (NODE)) @@ -3391,6 +3393,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) #define DECL_FIELD_IS_BASE(NODE) \ DECL_LANG_FLAG_6 (FIELD_DECL_CHECK (NODE)) +/* Nonzero for TYPE_DECL means that it was written 'using name = type'. */ +#define TYPE_DECL_ALIAS_P(NODE) \ + DECL_LANG_FLAG_6 (TYPE_DECL_CHECK (NODE)) + /* Nonzero for FIELD_DECL node means that this field is a simple (no explicit initializer) lambda capture field, making it invisible to name lookup in unevaluated contexts. */ @@ -3530,11 +3536,19 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) && TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == FUNCTION_DECL) /* Nonzero for a DECL that represents a template class. */ -#define DECL_CLASS_TEMPLATE_P(NODE) \ +#define DECL_TYPE_TEMPLATE_P(NODE) \ (TREE_CODE (NODE) == TEMPLATE_DECL \ && DECL_TEMPLATE_RESULT (NODE) != NULL_TREE \ + && TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == TYPE_DECL) + +#define DECL_CLASS_TEMPLATE_P(NODE) \ + (DECL_TYPE_TEMPLATE_P (NODE) \ && DECL_IMPLICIT_TYPEDEF_P (DECL_TEMPLATE_RESULT (NODE))) +#define DECL_ALIAS_TEMPLATE_P(NODE) \ + (DECL_TYPE_TEMPLATE_P (NODE) \ + && !DECL_ARTIFICIAL (DECL_TEMPLATE_RESULT (NODE))) + /* Nonzero if NODE which declares a type. */ #define DECL_DECLARES_TYPE_P(NODE) \ (TREE_CODE (NODE) == TYPE_DECL || DECL_CLASS_TEMPLATE_P (NODE)) @@ -4442,6 +4456,7 @@ typedef enum cp_decl_spec { ds_explicit, ds_friend, ds_typedef, + ds_alias, ds_constexpr, ds_complex, ds_thread, diff --git a/gcc/cp/error.c b/gcc/cp/error.c index ec9b9fe85af..fd94ebae8f5 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -933,6 +933,16 @@ dump_decl (tree t, int flags) dump_type (TREE_TYPE (t), flags); break; } + if (TYPE_DECL_ALIAS_P (t)) + { + pp_cxx_ws_string (cxx_pp, "using"); + dump_decl (DECL_NAME (t), flags); + pp_cxx_whitespace (cxx_pp); + pp_cxx_ws_string (cxx_pp, "="); + pp_cxx_whitespace (cxx_pp); + dump_type (DECL_ORIGINAL_TYPE (t), flags); + break; + } if ((flags & TFF_DECL_SPECIFIERS) && !DECL_SELF_REFERENCE_P (t)) pp_cxx_ws_string (cxx_pp, "typedef"); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 3a60d0f81ea..48cdbacbe44 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1664,6 +1664,8 @@ static bool cp_parser_using_declaration (cp_parser *, bool); static void cp_parser_using_directive (cp_parser *); +static tree cp_parser_alias_declaration + (cp_parser *); static void cp_parser_asm_definition (cp_parser *); static void cp_parser_linkage_specification @@ -9298,8 +9300,8 @@ cp_parser_block_declaration (cp_parser *parser, namespace-alias-definition. */ else if (token1->keyword == RID_NAMESPACE) cp_parser_namespace_alias_definition (parser); - /* If the next keyword is `using', we have either a - using-declaration or a using-directive. */ + /* If the next keyword is `using', we have a + using-declaration, a using-directive, or an alias-declaration. */ else if (token1->keyword == RID_USING) { cp_token *token2; @@ -9311,6 +9313,12 @@ cp_parser_block_declaration (cp_parser *parser, token2 = cp_lexer_peek_nth_token (parser->lexer, 2); if (token2->keyword == RID_NAMESPACE) cp_parser_using_directive (parser); + /* If the second token after 'using' is '=', then we have an + alias-declaration. */ + else if (cxx_dialect >= cxx0x + && token2->type == CPP_NAME + && cp_lexer_peek_nth_token (parser->lexer, 3)->type == CPP_EQ) + cp_parser_alias_declaration (parser); /* Otherwise, it's a using-declaration. */ else cp_parser_using_declaration (parser, @@ -11436,7 +11444,7 @@ cp_parser_template_id (cp_parser *parser, /* Build a representation of the specialization. */ if (TREE_CODE (templ) == IDENTIFIER_NODE) template_id = build_min_nt (TEMPLATE_ID_EXPR, templ, arguments); - else if (DECL_CLASS_TEMPLATE_P (templ) + else if (DECL_TYPE_TEMPLATE_P (templ) || DECL_TEMPLATE_TEMPLATE_PARM_P (templ)) { bool entering_scope; @@ -13881,6 +13889,57 @@ cp_parser_using_declaration (cp_parser* parser, return true; } +/* Parse an alias-declaration. + + alias-declaration: + using identifier = type-id */ + +static tree +cp_parser_alias_declaration (cp_parser* parser) +{ + tree id, type, decl, dummy; + location_t id_location; + cp_declarator *declarator; + cp_decl_specifier_seq decl_specs; + + /* Look for the `using' keyword. */ + cp_parser_require_keyword (parser, RID_USING, RT_USING); + id_location = cp_lexer_peek_token (parser->lexer)->location; + id = cp_parser_identifier (parser); + cp_parser_require (parser, CPP_EQ, RT_EQ); + + decl = build_decl (id_location, TYPE_DECL, id, unknown_type_node); + if (at_class_scope () || template_parm_scope_p ()) + retrofit_lang_decl (decl); + + type = cp_parser_type_id (parser); + + /* A typedef-name can also be introduced by an alias-declaration. The + identifier following the using keyword becomes a typedef-name. It has + the same semantics as if it were introduced by the typedef + specifier. In particular, it does not define a new type and it shall + not appear in the type-id. */ + + clear_decl_specs (&decl_specs); + decl_specs.type = type; + ++decl_specs.specs[(int) ds_typedef]; + + declarator = make_id_declarator (NULL_TREE, id, sfk_none); + declarator->id_loc = id_location; + + if (at_class_scope_p ()) + decl = grokfield (declarator, &decl_specs, NULL_TREE, false, + NULL_TREE, NULL_TREE); + else + decl = start_decl (declarator, &decl_specs, 0, + NULL_TREE, NULL_TREE, &dummy); + if (decl == error_mark_node) + return decl; + cp_finish_decl (decl, NULL_TREE, 0, NULL_TREE, 0); + + return decl; +} + /* Parse a using-directive. using-directive: @@ -17395,6 +17454,7 @@ cp_parser_member_specification_opt (cp_parser* parser) :: [opt] nested-name-specifier template [opt] unqualified-id ; using-declaration template-declaration + alias-declaration member-declarator-list: member-declarator @@ -19704,6 +19764,9 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE)) cp_parser_template_declaration_after_export (parser, member_p); + else if (cxx_dialect >= cxx0x + && cp_lexer_next_token_is_keyword (parser->lexer, RID_USING)) + decl = cp_parser_alias_declaration (parser); else { /* There are no access checks when parsing a template, as we do not diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 5960e4624b6..50080b0947a 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -4749,6 +4749,11 @@ push_template_decl_real (tree decl, bool is_friend) else if (DECL_IMPLICIT_TYPEDEF_P (decl) && CLASS_TYPE_P (TREE_TYPE (decl))) /* OK */; + else if (TREE_CODE (decl) == TYPE_DECL) + { + /* alias-declaration */ + gcc_assert (!DECL_ARTIFICIAL (decl)); + } else { error ("template declaration of %q#D", decl); @@ -5013,8 +5018,13 @@ template arguments to %qD do not match original template %qD", if (DECL_IMPLICIT_TYPEDEF_P (decl)) SET_TYPE_TEMPLATE_INFO (TREE_TYPE (tmpl), info); - else if (DECL_LANG_SPECIFIC (decl)) - DECL_TEMPLATE_INFO (decl) = info; + else + { + if (primary && !DECL_LANG_SPECIFIC (decl)) + retrofit_lang_decl (decl); + if (DECL_LANG_SPECIFIC (decl)) + DECL_TEMPLATE_INFO (decl) = info; + } return DECL_TEMPLATE_RESULT (tmpl); } @@ -7001,7 +7011,7 @@ lookup_template_class (tree d1, ENUM_FIXED_UNDERLYING_TYPE_P (t) = ENUM_FIXED_UNDERLYING_TYPE_P (template_type); } - else + else if (CLASS_TYPE_P (template_type)) { t = make_class_type (TREE_CODE (template_type)); CLASSTYPE_DECLARED_CLASS (t) @@ -7024,6 +7034,13 @@ lookup_template_class (tree d1, structural equality testing. */ SET_TYPE_STRUCTURAL_EQUALITY (t); } + else + { + /* A template alias. */ + type_decl = tsubst (DECL_TEMPLATE_RESULT (templ), arglist, + complain, in_decl); + t = TREE_TYPE (type_decl); + } /* If we called start_enum or pushtag above, this information will already be set up. */ diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 3300c3f5b3a..444f5eaad2e 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2684,15 +2684,17 @@ finish_template_decl (tree parms) tree finish_template_type (tree name, tree args, int entering_scope) { - tree decl; + tree type; - decl = lookup_template_class (name, args, + type = lookup_template_class (name, args, NULL_TREE, NULL_TREE, entering_scope, tf_warning_or_error | tf_user); - if (decl != error_mark_node) - decl = TYPE_STUB_DECL (decl); - - return decl; + if (type == error_mark_node) + return type; + else if (CLASS_TYPE_P (type)) + return TYPE_STUB_DECL (type); + else + return TYPE_NAME (type); } /* Finish processing a BASE_CLASS with the indicated ACCESS_SPECIFIER. |