summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2010-06-07 08:09:01 -0400
committerJason Merrill <jason@redhat.com>2011-03-30 16:19:30 -0400
commitad334a2e6df70d75d677c33cd3b0b9ea182aa9c2 (patch)
treee10481121c9eb7c9f0a7886b284b8e97b605b394
parent414b72cf0c873a53501888f7fdfb8545ca7f36ad (diff)
downloadgcc-jason/alias-decl.tar.gz
-rw-r--r--gcc/cp/cp-tree.h29
-rw-r--r--gcc/cp/error.c10
-rw-r--r--gcc/cp/parser.c69
-rw-r--r--gcc/cp/pt.c23
-rw-r--r--gcc/cp/semantics.c14
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.