mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-13 18:30:59 +08:00
PR c++/45114 - Support C++11 alias-declaration
gcc/cp/ * cp-tree.h (TYPE_DECL_ALIAS_P, TYPE_ALIAS_P) (DECL_TYPE_TEMPLATE_P, DECL_ALIAS_TEMPLATE_P): New accessor macros. (TYPE_TEMPLATE_INFO): Get template info of an alias template specializations from its TYPE_DECL. (SET_TYPE_TEMPLATE_INFO): Set template info of alias template specializations into its TYPE_DECL. (DECL_CLASS_TEMPLATE_P): Re-write using the new DECL_TYPE_TEMPLATE_P. (enum cp_decl_spec): Add new ds_alias enumerator. (alias_type_or_template_p, alias_template_specialization_p): Declare new functions. * parser.c (cp_parser_alias_declaration): New static function. (cp_parser_check_decl_spec): Add "using" name for the `alias' declspec. (cp_parser_type_name): Update comment. Support simple-template-id representing alias template specializations in c++0x mode. (cp_parser_qualifying_entity): Update comment. Use cp_parser_type_name. (cp_parser_block_declaration): Handle alias-declaration in c++11. Update comment. (cp_parser_template_id): Handle specializations of alias templates. (cp_parser_member_declaration): Add alias-declaration production to comment. Support alias-declarations. (cp_parser_template_declaration_after_export): Handle alias templates in c++11. * decl.c (make_typename_type, make_unbound_class_template): Accept alias templates. (grokdeclarator): Set TYPE_DECL_ALIAS_P on alias declarations. * decl2.c (grokfield): Move template creation after setting up the TYPE_DECL of the alias, so that the TEMPLATE_DECL of the alias template actually carries the right type-id of the alias declaration. * pt.c (alias_type_or_template_p) (alias_template_specialization_p): Define new public functions. (maybe_process_partial_specialization): Reject partial specializations of alias templates. (primary_template_instantiation_p): Consider alias template instantiations. (push_template_decl_real): Assert that TYPE_DECLs of alias templates are different from those of class template. Store template info onto the TYPE_DECL of the alias template. (convert_template_argument): Strip aliases from template arguments. (lookup_template_class_1): Handle the creation of the specialization of an alias template. (tsubst_decl): Create a substituted copy of the TYPE_DECL of an member alias template. (tsubst): Handle substituting into the type of an alias template. Handle substituting UNBOUND_CLASS_TEMPLATE into BOUND_TEMPLATE_TEMPLATE_PARM. (do_type_instantiation): Better diagnostics when trying to explicitely instantiate a non-class template. * search.c (lookup_field_1, lookup_field_r): Support looking up alias templates. * semantics.c (finish_template_type): For instantiations of alias templates, return the TYPE_DECL of the actual alias and not the one of the aliased type. * error.c (dump_alias_template_specialization): New static function. (dump_type): Handle printing of alias templates and their specializations. templates. (dump_aggr_type): For specialization of alias templates, fetch arguments from the right place. (dump_decl): Print an alias-declaration like `using decl = type;' (dump_template_decl): Support printing of alias templates. gcc/testsuite/ * g++.dg/cpp0x/alias-decl-0.C: New test case. * g++.dg/cpp0x/alias-decl-1.C: Likewise. * g++.dg/cpp0x/alias-decl-3.C: Likewise. * g++.dg/cpp0x/alias-decl-4.C: Likewise. * g++.dg/cpp0x/alias-decl-6.C: Likewise. * g++.dg/cpp0x/alias-decl-7.C: Likewise. * g++.dg/cpp0x/alias-decl-8.C: Likewise. * g++.dg/cpp0x/alias-decl-9.C: Likewise. * g++.dg/cpp0x/alias-decl-10.C: Likewise. * g++.dg/ext/alias-decl-attr1.C: Likewise. * g++.dg/ext/alias-decl-attr2.C: Likewise. * g++.dg/ext/alias-decl-attr3.C: Likewise. * g++.dg/ext/alias-decl-attr4.C: Likewise. From-SVN: r181118
This commit is contained in:
parent
bfd08c8902
commit
2870428932
@ -1,3 +1,77 @@
|
||||
2011-11-07 Jason Merrill <jason@redhat.com>
|
||||
Dodji Seketeli <dodji@redhat.com>
|
||||
|
||||
Support C++11 alias-declaration
|
||||
PR c++/45114
|
||||
* cp-tree.h (TYPE_DECL_ALIAS_P, TYPE_ALIAS_P)
|
||||
(DECL_TYPE_TEMPLATE_P, DECL_ALIAS_TEMPLATE_P): New accessor
|
||||
macros.
|
||||
(TYPE_TEMPLATE_INFO): Get template info of an alias template
|
||||
specializations from its TYPE_DECL.
|
||||
(SET_TYPE_TEMPLATE_INFO): Set template info of alias template
|
||||
specializations into its TYPE_DECL.
|
||||
(DECL_CLASS_TEMPLATE_P): Re-write using the new
|
||||
DECL_TYPE_TEMPLATE_P.
|
||||
(enum cp_decl_spec): Add new ds_alias enumerator.
|
||||
(alias_type_or_template_p, alias_template_specialization_p):
|
||||
Declare new functions.
|
||||
* parser.c (cp_parser_alias_declaration): New static function.
|
||||
(cp_parser_check_decl_spec): Add "using" name for the `alias'
|
||||
declspec.
|
||||
(cp_parser_type_name): Update comment. Support simple-template-id
|
||||
representing alias template specializations in c++0x mode.
|
||||
(cp_parser_qualifying_entity): Update comment. Use
|
||||
cp_parser_type_name.
|
||||
(cp_parser_block_declaration): Handle alias-declaration in c++11.
|
||||
Update comment.
|
||||
(cp_parser_template_id): Handle specializations of alias
|
||||
templates.
|
||||
(cp_parser_member_declaration): Add alias-declaration production
|
||||
to comment. Support alias-declarations.
|
||||
(cp_parser_template_declaration_after_export): Handle alias
|
||||
templates in c++11.
|
||||
* decl.c (make_typename_type, make_unbound_class_template): Accept
|
||||
alias templates.
|
||||
(grokdeclarator): Set TYPE_DECL_ALIAS_P on alias
|
||||
declarations.
|
||||
* decl2.c (grokfield): Move template creation after setting up the
|
||||
TYPE_DECL of the alias, so that the TEMPLATE_DECL of the alias
|
||||
template actually carries the right type-id of the alias
|
||||
declaration.
|
||||
* pt.c (alias_type_or_template_p)
|
||||
(alias_template_specialization_p): Define new public functions.
|
||||
(maybe_process_partial_specialization): Reject partial
|
||||
specializations of alias templates.
|
||||
(primary_template_instantiation_p): Consider alias template
|
||||
instantiations.
|
||||
(push_template_decl_real): Assert that TYPE_DECLs of alias
|
||||
templates are different from those of class template. Store
|
||||
template info onto the TYPE_DECL of the alias template.
|
||||
(convert_template_argument): Strip aliases from template
|
||||
arguments.
|
||||
(lookup_template_class_1): Handle the creation of the
|
||||
specialization of an alias template.
|
||||
(tsubst_decl): Create a substituted copy of the TYPE_DECL of an
|
||||
member alias template.
|
||||
(tsubst): Handle substituting into the type of an alias template.
|
||||
Handle substituting UNBOUND_CLASS_TEMPLATE into
|
||||
BOUND_TEMPLATE_TEMPLATE_PARM.
|
||||
(do_type_instantiation): Better diagnostics when trying to
|
||||
explicitely instantiate a non-class template.
|
||||
* search.c (lookup_field_1, lookup_field_r): Support looking up
|
||||
alias templates.
|
||||
* semantics.c (finish_template_type): For instantiations of alias
|
||||
templates, return the TYPE_DECL of the actual alias and not the
|
||||
one of the aliased type.
|
||||
* error.c (dump_alias_template_specialization): New static
|
||||
function.
|
||||
(dump_type): Handle printing of alias templates and their
|
||||
specializations. templates.
|
||||
(dump_aggr_type): For specialization of alias templates, fetch
|
||||
arguments from the right place.
|
||||
(dump_decl): Print an alias-declaration like `using decl = type;'
|
||||
(dump_template_decl): Support printing of alias templates.
|
||||
|
||||
2011-11-07 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/35688
|
||||
|
@ -139,6 +139,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)
|
||||
@ -2541,6 +2542,17 @@ extern void decl_shadowed_for_var_insert (tree, tree);
|
||||
#define DECL_PENDING_INLINE_INFO(NODE) \
|
||||
(LANG_DECL_FN_CHECK (NODE)->u.pending_inline_info)
|
||||
|
||||
/* 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 a type which is an alias for another type; i.e, a type
|
||||
which declaration was written 'using name-of-type =
|
||||
another-type'. */
|
||||
#define TYPE_ALIAS_P(NODE) \
|
||||
(TYPE_P (NODE) \
|
||||
&& TYPE_DECL_ALIAS_P (TYPE_NAME (NODE)))
|
||||
|
||||
/* For a class type: if this structure has many fields, we'll sort them
|
||||
and put them into a TREE_VEC. */
|
||||
#define CLASSTYPE_SORTED_FIELDS(NODE) \
|
||||
@ -2597,16 +2609,20 @@ 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) && !TYPE_ALIAS_P (NODE)) \
|
||||
? CLASSTYPE_TEMPLATE_INFO (NODE) \
|
||||
: NULL_TREE)))
|
||||
: (DECL_LANG_SPECIFIC (TYPE_NAME (NODE)) \
|
||||
? (DECL_TEMPLATE_INFO (TYPE_NAME (NODE))) \
|
||||
: NULL_TREE))))
|
||||
|
||||
/* 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) && !TYPE_ALIAS_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))
|
||||
@ -3620,12 +3636,23 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
|
||||
&& !DECL_UNBOUND_CLASS_TEMPLATE_P (NODE) \
|
||||
&& TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == FUNCTION_DECL)
|
||||
|
||||
/* Nonzero for a DECL that represents a template class. */
|
||||
#define DECL_CLASS_TEMPLATE_P(NODE) \
|
||||
/* Nonzero for a DECL that represents a class template or alias
|
||||
template. */
|
||||
#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)
|
||||
|
||||
/* Nonzero for a DECL that represents a class template. */
|
||||
#define DECL_CLASS_TEMPLATE_P(NODE) \
|
||||
(DECL_TYPE_TEMPLATE_P (NODE) \
|
||||
&& DECL_IMPLICIT_TYPEDEF_P (DECL_TEMPLATE_RESULT (NODE)))
|
||||
|
||||
/* Nonzero for a TEMPLATE_DECL that represents an alias template. */
|
||||
#define DECL_ALIAS_TEMPLATE_P(NODE) \
|
||||
(DECL_TYPE_TEMPLATE_P (NODE) \
|
||||
&& !DECL_ARTIFICIAL (DECL_TEMPLATE_RESULT (NODE)))
|
||||
|
||||
/* Nonzero for a NODE which declares a type. */
|
||||
#define DECL_DECLARES_TYPE_P(NODE) \
|
||||
(TREE_CODE (NODE) == TYPE_DECL || DECL_CLASS_TEMPLATE_P (NODE))
|
||||
@ -4580,6 +4607,7 @@ typedef enum cp_decl_spec {
|
||||
ds_explicit,
|
||||
ds_friend,
|
||||
ds_typedef,
|
||||
ds_alias,
|
||||
ds_constexpr,
|
||||
ds_complex,
|
||||
ds_thread,
|
||||
@ -5283,6 +5311,8 @@ extern tree build_non_dependent_expr (tree);
|
||||
extern void make_args_non_dependent (VEC(tree,gc) *);
|
||||
extern bool reregister_specialization (tree, tree, tree);
|
||||
extern tree fold_non_dependent_expr (tree);
|
||||
extern bool alias_type_or_template_p (tree);
|
||||
extern bool alias_template_specialization_p (tree);
|
||||
extern bool explicit_class_specialization_p (tree);
|
||||
extern int push_tinst_level (tree);
|
||||
extern void pop_tinst_level (void);
|
||||
|
@ -3270,7 +3270,7 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
if (want_template && !DECL_CLASS_TEMPLATE_P (t))
|
||||
if (want_template && !DECL_TYPE_TEMPLATE_P (t))
|
||||
{
|
||||
if (complain & tf_error)
|
||||
error ("%<typename %T::%D%> names %q#T, which is not a class template",
|
||||
@ -3338,7 +3338,7 @@ make_unbound_class_template (tree context, tree name, tree parm_list,
|
||||
if (tmpl && TREE_CODE (tmpl) == TYPE_DECL)
|
||||
tmpl = maybe_get_template_decl_from_type_decl (tmpl);
|
||||
|
||||
if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
|
||||
if (!tmpl || !DECL_TYPE_TEMPLATE_P (tmpl))
|
||||
{
|
||||
if (complain & tf_error)
|
||||
error ("no class template named %q#T in %q#T", name, context);
|
||||
@ -9747,6 +9747,11 @@ grokdeclarator (const cp_declarator *declarator,
|
||||
memfn_quals != TYPE_UNQUALIFIED,
|
||||
inlinep, friendp, raises != NULL_TREE);
|
||||
|
||||
if (declspecs->specs[(int)ds_alias])
|
||||
/* Acknowledge that this was written:
|
||||
`using analias = atype;'. */
|
||||
TYPE_DECL_ALIAS_P (decl) = 1;
|
||||
|
||||
return decl;
|
||||
}
|
||||
|
||||
|
@ -848,9 +848,6 @@ grokfield (const cp_declarator *declarator,
|
||||
DECL_NONLOCAL (value) = 1;
|
||||
DECL_CONTEXT (value) = current_class_type;
|
||||
|
||||
if (processing_template_decl)
|
||||
value = push_template_decl (value);
|
||||
|
||||
if (attrlist)
|
||||
{
|
||||
int attrflags = 0;
|
||||
@ -869,6 +866,12 @@ grokfield (const cp_declarator *declarator,
|
||||
&& TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
|
||||
set_underlying_type (value);
|
||||
|
||||
/* It's important that push_template_decl below follows
|
||||
set_underlying_type above so that the created template
|
||||
carries the properly set type of VALUE. */
|
||||
if (processing_template_decl)
|
||||
value = push_template_decl (value);
|
||||
|
||||
record_locally_defined_typedef (value);
|
||||
return value;
|
||||
}
|
||||
|
@ -61,6 +61,7 @@ static const char *op_to_string (enum tree_code);
|
||||
static const char *parm_to_string (int);
|
||||
static const char *type_to_string (tree, int);
|
||||
|
||||
static void dump_alias_template_specialization (tree, int);
|
||||
static void dump_type (tree, int);
|
||||
static void dump_typename (tree, int);
|
||||
static void dump_simple_decl (tree, tree, int);
|
||||
@ -330,6 +331,23 @@ dump_template_bindings (tree parms, tree args, VEC(tree,gc)* typenames)
|
||||
}
|
||||
}
|
||||
|
||||
/* Dump a human-readable equivalent of the alias template
|
||||
specialization of T. */
|
||||
|
||||
static void
|
||||
dump_alias_template_specialization (tree t, int flags)
|
||||
{
|
||||
tree name;
|
||||
|
||||
gcc_assert (alias_template_specialization_p (t));
|
||||
|
||||
name = TYPE_IDENTIFIER (t);
|
||||
pp_cxx_tree_identifier (cxx_pp, name);
|
||||
dump_template_parms (TYPE_TEMPLATE_INFO (t),
|
||||
/*primary=*/false,
|
||||
flags & ~TFF_TEMPLATE_HEADER);
|
||||
}
|
||||
|
||||
/* Dump a human-readable equivalent of TYPE. FLAGS controls the
|
||||
format. */
|
||||
|
||||
@ -344,10 +362,15 @@ dump_type (tree t, int flags)
|
||||
{
|
||||
tree decl = TYPE_NAME (t);
|
||||
if ((flags & TFF_CHASE_TYPEDEF)
|
||||
|| DECL_SELF_REFERENCE_P (decl)
|
||||
|| (!flag_pretty_templates
|
||||
&& DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)))
|
||||
|| DECL_SELF_REFERENCE_P (decl)
|
||||
|| (!flag_pretty_templates
|
||||
&& DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)))
|
||||
t = strip_typedefs (t);
|
||||
else if (alias_template_specialization_p (t))
|
||||
{
|
||||
dump_alias_template_specialization (t, flags);
|
||||
return;
|
||||
}
|
||||
else if (same_type_p (t, TREE_TYPE (decl)))
|
||||
t = decl;
|
||||
else
|
||||
@ -588,7 +611,10 @@ dump_aggr_type (tree t, int flags)
|
||||
|
||||
if (name)
|
||||
{
|
||||
typdef = !DECL_ARTIFICIAL (name);
|
||||
typdef = (!DECL_ARTIFICIAL (name)
|
||||
/* An alias specialization is not considered to be a
|
||||
typedef. */
|
||||
&& !alias_template_specialization_p (t));
|
||||
|
||||
if ((typdef
|
||||
&& ((flags & TFF_CHASE_TYPEDEF)
|
||||
@ -613,7 +639,7 @@ dump_aggr_type (tree t, int flags)
|
||||
{
|
||||
/* Because the template names are mangled, we have to locate
|
||||
the most general template, and use that name. */
|
||||
tree tpl = CLASSTYPE_TI_TEMPLATE (t);
|
||||
tree tpl = TYPE_TI_TEMPLATE (t);
|
||||
|
||||
while (DECL_TEMPLATE_INFO (tpl))
|
||||
tpl = DECL_TI_TEMPLATE (tpl);
|
||||
@ -952,6 +978,18 @@ dump_decl (tree t, int flags)
|
||||
dump_type (TREE_TYPE (t), flags);
|
||||
break;
|
||||
}
|
||||
if (TYPE_DECL_ALIAS_P (t)
|
||||
&& (flags & TFF_DECL_SPECIFIERS
|
||||
|| flags & TFF_CLASS_KEY_OR_ENUM))
|
||||
{
|
||||
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");
|
||||
@ -1196,13 +1234,14 @@ dump_template_decl (tree t, int flags)
|
||||
}
|
||||
}
|
||||
|
||||
if (DECL_TEMPLATE_RESULT (t)
|
||||
&& TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL)
|
||||
if (DECL_CLASS_TEMPLATE_P (t))
|
||||
dump_type (TREE_TYPE (t),
|
||||
((flags & ~TFF_CLASS_KEY_OR_ENUM) | TFF_TEMPLATE_NAME
|
||||
| (flags & TFF_DECL_SPECIFIERS ? TFF_CLASS_KEY_OR_ENUM : 0)));
|
||||
else if (DECL_TEMPLATE_RESULT (t)
|
||||
&& TREE_CODE (DECL_TEMPLATE_RESULT (t)) == VAR_DECL)
|
||||
&& (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == VAR_DECL
|
||||
/* Alias template. */
|
||||
|| DECL_TYPE_TEMPLATE_P (t)))
|
||||
dump_decl (DECL_TEMPLATE_RESULT (t), flags | TFF_TEMPLATE_NAME);
|
||||
else
|
||||
{
|
||||
|
141
gcc/cp/parser.c
141
gcc/cp/parser.c
@ -1935,6 +1935,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
|
||||
@ -2509,6 +2511,7 @@ cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs,
|
||||
"explicit",
|
||||
"friend",
|
||||
"typedef",
|
||||
"using",
|
||||
"constexpr",
|
||||
"__complex",
|
||||
"__thread"
|
||||
@ -5135,7 +5138,7 @@ cp_parser_nested_name_specifier (cp_parser *parser,
|
||||
this is either a class-name or a namespace-name (which corresponds
|
||||
to the class-or-namespace-name production in the grammar). For
|
||||
C++0x, it can also be a type-name that refers to an enumeration
|
||||
type.
|
||||
type or a simple-template-id.
|
||||
|
||||
TYPENAME_KEYWORD_P is TRUE iff the `typename' keyword is in effect.
|
||||
TEMPLATE_KEYWORD_P is TRUE iff the `template' keyword is in effect.
|
||||
@ -5211,8 +5214,8 @@ cp_parser_qualifying_entity (cp_parser *parser,
|
||||
/* Parse tentatively. */
|
||||
cp_parser_parse_tentatively (parser);
|
||||
|
||||
/* Parse a typedef-name or enum-name. */
|
||||
scope = cp_parser_nonclass_name (parser);
|
||||
/* Parse a type-name */
|
||||
scope = cp_parser_type_name (parser);
|
||||
|
||||
/* "If the name found does not designate a namespace or a class,
|
||||
enumeration, or dependent type, the program is ill-formed."
|
||||
@ -10150,8 +10153,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;
|
||||
@ -10163,6 +10166,14 @@ 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_lexer_peek_nth_token (parser->lexer, 3)->keyword
|
||||
== RID_ATTRIBUTE)))
|
||||
cp_parser_alias_declaration (parser);
|
||||
/* Otherwise, it's a using-declaration. */
|
||||
else
|
||||
cp_parser_using_declaration (parser,
|
||||
@ -12343,7 +12354,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;
|
||||
@ -13611,6 +13622,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
|
||||
class-name
|
||||
enum-name
|
||||
typedef-name
|
||||
simple-template-id [in c++0x]
|
||||
|
||||
enum-name:
|
||||
identifier
|
||||
@ -13638,8 +13650,37 @@ cp_parser_type_name (cp_parser* parser)
|
||||
/* If it's not a class-name, keep looking. */
|
||||
if (!cp_parser_parse_definitely (parser))
|
||||
{
|
||||
/* It must be a typedef-name or an enum-name. */
|
||||
return cp_parser_nonclass_name (parser);
|
||||
if (cxx_dialect < cxx0x)
|
||||
/* It must be a typedef-name or an enum-name. */
|
||||
return cp_parser_nonclass_name (parser);
|
||||
|
||||
cp_parser_parse_tentatively (parser);
|
||||
/* It is either a simple-template-id representing an
|
||||
instantiation of an alias template... */
|
||||
type_decl = cp_parser_template_id (parser,
|
||||
/*template_keyword_p=*/false,
|
||||
/*check_dependency_p=*/false,
|
||||
/*is_declaration=*/false);
|
||||
/* Note that this must be an instantiation of an alias template
|
||||
because [temp.names]/6 says:
|
||||
|
||||
A template-id that names an alias template specialization
|
||||
is a type-name.
|
||||
|
||||
Whereas [temp.names]/7 says:
|
||||
|
||||
A simple-template-id that names a class template
|
||||
specialization is a class-name. */
|
||||
if (type_decl != NULL_TREE
|
||||
&& TREE_CODE (type_decl) == TYPE_DECL
|
||||
&& TYPE_DECL_ALIAS_P (type_decl))
|
||||
gcc_assert (DECL_TEMPLATE_INSTANTIATION (type_decl));
|
||||
else
|
||||
cp_parser_simulate_error (parser);
|
||||
|
||||
if (!cp_parser_parse_definitely (parser))
|
||||
/* ... Or a typedef-name or an enum-name. */
|
||||
return cp_parser_nonclass_name (parser);
|
||||
}
|
||||
|
||||
return type_decl;
|
||||
@ -14835,6 +14876,63 @@ cp_parser_using_declaration (cp_parser* parser,
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Parse an alias-declaration.
|
||||
|
||||
alias-declaration:
|
||||
using identifier attribute-specifier-seq [opt] = type-id */
|
||||
|
||||
static tree
|
||||
cp_parser_alias_declaration (cp_parser* parser)
|
||||
{
|
||||
tree id, type, decl, dummy, attributes;
|
||||
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);
|
||||
attributes = cp_parser_attributes_opt (parser);
|
||||
cp_parser_require (parser, CPP_EQ, RT_EQ);
|
||||
|
||||
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.attributes = attributes;
|
||||
++decl_specs.specs[(int) ds_typedef];
|
||||
++decl_specs.specs[(int) ds_alias];
|
||||
|
||||
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, attributes);
|
||||
else
|
||||
decl = start_decl (declarator, &decl_specs, 0,
|
||||
attributes, NULL_TREE, &dummy);
|
||||
if (decl == error_mark_node)
|
||||
return decl;
|
||||
|
||||
cp_finish_decl (decl, NULL_TREE, 0, NULL_TREE, 0);
|
||||
|
||||
/* If decl is a template, return its TEMPLATE_DECL so that it gets
|
||||
added into the symbol table; otherwise, return the TYPE_DECL. */
|
||||
if (DECL_LANG_SPECIFIC (decl)
|
||||
&& DECL_TEMPLATE_INFO (decl)
|
||||
&& PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl)))
|
||||
decl = DECL_TI_TEMPLATE (decl);
|
||||
return decl;
|
||||
}
|
||||
|
||||
/* Parse a using-directive.
|
||||
|
||||
using-directive:
|
||||
@ -18532,6 +18630,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
|
||||
@ -18599,10 +18698,25 @@ cp_parser_member_declaration (cp_parser* parser)
|
||||
/* Check for a using-declaration. */
|
||||
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_USING))
|
||||
{
|
||||
/* Parse the using-declaration. */
|
||||
cp_parser_using_declaration (parser,
|
||||
/*access_declaration_p=*/false);
|
||||
return;
|
||||
if (cxx_dialect < cxx0x)
|
||||
{
|
||||
/* Parse the using-declaration. */
|
||||
cp_parser_using_declaration (parser,
|
||||
/*access_declaration_p=*/false);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
tree decl;
|
||||
cp_parser_parse_tentatively (parser);
|
||||
decl = cp_parser_alias_declaration (parser);
|
||||
if (cp_parser_parse_definitely (parser))
|
||||
finish_member_declaration (decl);
|
||||
else
|
||||
cp_parser_using_declaration (parser,
|
||||
/*access_declaration_p=*/false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for @defs. */
|
||||
@ -20893,6 +21007,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
|
||||
|
210
gcc/cp/pt.c
210
gcc/cp/pt.c
@ -814,7 +814,13 @@ maybe_process_partial_specialization (tree type)
|
||||
|
||||
context = TYPE_CONTEXT (type);
|
||||
|
||||
if (CLASS_TYPE_P (type) && CLASSTYPE_USE_TEMPLATE (type))
|
||||
if ((CLASS_TYPE_P (type) && CLASSTYPE_USE_TEMPLATE (type))
|
||||
/* Consider non-class instantiations of alias templates as
|
||||
well. */
|
||||
|| (TYPE_P (type)
|
||||
&& TYPE_TEMPLATE_INFO (type)
|
||||
&& DECL_LANG_SPECIFIC (TYPE_NAME (type))
|
||||
&& DECL_USE_TEMPLATE (TYPE_NAME (type))))
|
||||
{
|
||||
/* This is for ordinary explicit specialization and partial
|
||||
specialization of a template class such as:
|
||||
@ -827,7 +833,8 @@ maybe_process_partial_specialization (tree type)
|
||||
|
||||
Make sure that `C<int>' and `C<T*>' are implicit instantiations. */
|
||||
|
||||
if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)
|
||||
if (CLASS_TYPE_P (type)
|
||||
&& CLASSTYPE_IMPLICIT_INSTANTIATION (type)
|
||||
&& !COMPLETE_TYPE_P (type))
|
||||
{
|
||||
check_specialization_namespace (CLASSTYPE_TI_TEMPLATE (type));
|
||||
@ -839,8 +846,16 @@ maybe_process_partial_specialization (tree type)
|
||||
return error_mark_node;
|
||||
}
|
||||
}
|
||||
else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type))
|
||||
else if (CLASS_TYPE_P (type)
|
||||
&& CLASSTYPE_TEMPLATE_INSTANTIATION (type))
|
||||
error ("specialization of %qT after instantiation", type);
|
||||
|
||||
if (DECL_ALIAS_TEMPLATE_P (TYPE_TI_TEMPLATE (type)))
|
||||
{
|
||||
error ("partial specialization of alias template %qD",
|
||||
TYPE_TI_TEMPLATE (type));
|
||||
return error_mark_node;
|
||||
}
|
||||
}
|
||||
else if (CLASS_TYPE_P (type)
|
||||
&& !CLASSTYPE_USE_TEMPLATE (type)
|
||||
@ -2842,8 +2857,8 @@ make_ith_pack_parameter_name (tree name, int i)
|
||||
return get_identifier (newname);
|
||||
}
|
||||
|
||||
/* Return true if T is a primary function
|
||||
or class template instantiation. */
|
||||
/* Return true if T is a primary function, class or alias template
|
||||
instantiation. */
|
||||
|
||||
bool
|
||||
primary_template_instantiation_p (const_tree t)
|
||||
@ -2858,6 +2873,11 @@ primary_template_instantiation_p (const_tree t)
|
||||
else if (CLASS_TYPE_P (t))
|
||||
return CLASSTYPE_TEMPLATE_INSTANTIATION (t)
|
||||
&& PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t));
|
||||
else if (TYPE_P (t)
|
||||
&& TYPE_TEMPLATE_INFO (t)
|
||||
&& PRIMARY_TEMPLATE_P (TYPE_TI_TEMPLATE (t))
|
||||
&& DECL_TEMPLATE_INSTANTIATION (TYPE_NAME (t)))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -4831,6 +4851,10 @@ 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
|
||||
&& TYPE_DECL_ALIAS_P (decl))
|
||||
/* alias-declaration */
|
||||
gcc_assert (!DECL_ARTIFICIAL (decl));
|
||||
else
|
||||
{
|
||||
error ("template declaration of %q#D", decl);
|
||||
@ -5095,8 +5119,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);
|
||||
}
|
||||
@ -5259,6 +5288,32 @@ fold_non_dependent_expr (tree expr)
|
||||
return fold_non_dependent_expr_sfinae (expr, tf_error);
|
||||
}
|
||||
|
||||
/* Return TRUE iff T is a type alias, a TEMPLATE_DECL for an alias
|
||||
template declaration, or a TYPE_DECL for an alias declaration. */
|
||||
|
||||
bool
|
||||
alias_type_or_template_p (tree t)
|
||||
{
|
||||
if (t == NULL_TREE)
|
||||
return false;
|
||||
return ((TREE_CODE (t) == TYPE_DECL && TYPE_DECL_ALIAS_P (t))
|
||||
|| (TYPE_P (t)
|
||||
&& TYPE_NAME (t)
|
||||
&& TYPE_DECL_ALIAS_P (TYPE_NAME (t)))
|
||||
|| DECL_ALIAS_TEMPLATE_P (t));
|
||||
}
|
||||
|
||||
/* Return TRUE iff is a specialization of an alias template. */
|
||||
|
||||
bool
|
||||
alias_template_specialization_p (tree t)
|
||||
{
|
||||
if (t == NULL_TREE)
|
||||
return false;
|
||||
return (primary_template_instantiation_p (t)
|
||||
&& DECL_ALIAS_TEMPLATE_P (TYPE_TI_TEMPLATE (t)));
|
||||
}
|
||||
|
||||
/* Subroutine of convert_nontype_argument. Converts EXPR to TYPE, which
|
||||
must be a function or a pointer-to-function type, as specified
|
||||
in [temp.arg.nontype]: disambiguate EXPR if it is an overload set,
|
||||
@ -7355,7 +7410,31 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
|
||||
ENUM_FIXED_UNDERLYING_TYPE_P (t)
|
||||
= ENUM_FIXED_UNDERLYING_TYPE_P (template_type);
|
||||
}
|
||||
else
|
||||
else if (DECL_ALIAS_TEMPLATE_P (gen_tmpl))
|
||||
{
|
||||
/* The user referred to a specialization of an alias
|
||||
template represented by GEN_TMPL.
|
||||
|
||||
[temp.alias]/2 says:
|
||||
|
||||
When a template-id refers to the specialization of an
|
||||
alias template, it is equivalent to the associated
|
||||
type obtained by substitution of its
|
||||
template-arguments for the template-parameters in the
|
||||
type-id of the alias template. */
|
||||
|
||||
t = tsubst (TREE_TYPE (gen_tmpl), arglist, complain, in_decl);
|
||||
/* Note that the call above (by indirectly calling
|
||||
register_specialization in tsubst_decl) registers the
|
||||
TYPE_DECL representing the specialization of the alias
|
||||
template. So next time someone substitutes ARGLIST for
|
||||
the template parms into the alias template (GEN_TMPL),
|
||||
she'll get that TYPE_DECL back. */
|
||||
|
||||
if (t == error_mark_node)
|
||||
return t;
|
||||
}
|
||||
else if (CLASS_TYPE_P (template_type))
|
||||
{
|
||||
t = make_class_type (TREE_CODE (template_type));
|
||||
CLASSTYPE_DECLARED_CLASS (t)
|
||||
@ -7378,6 +7457,8 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
|
||||
structural equality testing. */
|
||||
SET_TYPE_STRUCTURAL_EQUALITY (t);
|
||||
}
|
||||
else
|
||||
gcc_unreachable ();
|
||||
|
||||
/* If we called start_enum or pushtag above, this information
|
||||
will already be set up. */
|
||||
@ -7393,14 +7474,17 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
|
||||
else
|
||||
type_decl = TYPE_NAME (t);
|
||||
|
||||
TREE_PRIVATE (type_decl)
|
||||
= TREE_PRIVATE (TYPE_STUB_DECL (template_type));
|
||||
TREE_PROTECTED (type_decl)
|
||||
= TREE_PROTECTED (TYPE_STUB_DECL (template_type));
|
||||
if (CLASSTYPE_VISIBILITY_SPECIFIED (template_type))
|
||||
if (CLASS_TYPE_P (template_type))
|
||||
{
|
||||
DECL_VISIBILITY_SPECIFIED (type_decl) = 1;
|
||||
DECL_VISIBILITY (type_decl) = CLASSTYPE_VISIBILITY (template_type);
|
||||
TREE_PRIVATE (type_decl)
|
||||
= TREE_PRIVATE (TYPE_STUB_DECL (template_type));
|
||||
TREE_PROTECTED (type_decl)
|
||||
= TREE_PROTECTED (TYPE_STUB_DECL (template_type));
|
||||
if (CLASSTYPE_VISIBILITY_SPECIFIED (template_type))
|
||||
{
|
||||
DECL_VISIBILITY_SPECIFIED (type_decl) = 1;
|
||||
DECL_VISIBILITY (type_decl) = CLASSTYPE_VISIBILITY (template_type);
|
||||
}
|
||||
}
|
||||
|
||||
/* Let's consider the explicit specialization of a member
|
||||
@ -7456,7 +7540,7 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
|
||||
++processing_template_decl;
|
||||
partial_inst_args =
|
||||
tsubst (INNERMOST_TEMPLATE_ARGS
|
||||
(CLASSTYPE_TI_ARGS (TREE_TYPE (gen_tmpl))),
|
||||
(TYPE_TI_ARGS (TREE_TYPE (gen_tmpl))),
|
||||
arglist, complain, NULL_TREE);
|
||||
--processing_template_decl;
|
||||
TREE_VEC_LENGTH (arglist)++;
|
||||
@ -7480,7 +7564,15 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
|
||||
TREE_VEC_LENGTH (arglist)--;
|
||||
found = tsubst (gen_tmpl, arglist, complain, NULL_TREE);
|
||||
TREE_VEC_LENGTH (arglist)++;
|
||||
found = CLASSTYPE_TI_TEMPLATE (found);
|
||||
/* FOUND is either a proper class type, or an alias
|
||||
template specialization. In the later case, it's a
|
||||
TYPE_DECL, resulting from the substituting of arguments
|
||||
for parameters in the TYPE_DECL of the alias template
|
||||
done earlier. So be careful while getting the template
|
||||
of FOUND. */
|
||||
found = TREE_CODE (found) == TYPE_DECL
|
||||
? TYPE_TI_TEMPLATE (TREE_TYPE (found))
|
||||
: CLASSTYPE_TI_TEMPLATE (found);
|
||||
}
|
||||
|
||||
SET_TYPE_TEMPLATE_INFO (t, build_template_info (found, arglist));
|
||||
@ -7508,7 +7600,7 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
|
||||
the instantiation and exit above. */
|
||||
tsubst_enum (template_type, t, arglist);
|
||||
|
||||
if (is_dependent_type)
|
||||
if (CLASS_TYPE_P (template_type) && is_dependent_type)
|
||||
/* If the type makes use of template parameters, the
|
||||
code that generates debugging information will crash. */
|
||||
DECL_IGNORED_P (TYPE_STUB_DECL (t)) = 1;
|
||||
@ -9845,7 +9937,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
|
||||
|
||||
DECL_TEMPLATE_INFO (r) = build_template_info (t, args);
|
||||
|
||||
if (TREE_CODE (decl) == TYPE_DECL)
|
||||
if (TREE_CODE (decl) == TYPE_DECL
|
||||
&& !TYPE_DECL_ALIAS_P (decl))
|
||||
{
|
||||
tree new_type;
|
||||
++processing_template_decl;
|
||||
@ -10378,8 +10471,15 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
|
||||
referencing a static data member within in its own
|
||||
class. We can use pointer equality, rather than
|
||||
same_type_p, because DECL_CONTEXT is always
|
||||
canonical. */
|
||||
if (ctx == DECL_CONTEXT (t))
|
||||
canonical... */
|
||||
if (ctx == DECL_CONTEXT (t)
|
||||
&& (TREE_CODE (t) != TYPE_DECL
|
||||
/* ... unless T is a member template; in which
|
||||
case our caller can be willing to create a
|
||||
specialization of that template represented
|
||||
by T. */
|
||||
|| !(DECL_TI_TEMPLATE (t)
|
||||
&& DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (t)))))
|
||||
spec = t;
|
||||
}
|
||||
|
||||
@ -10860,7 +10960,7 @@ tree
|
||||
tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
|
||||
{
|
||||
enum tree_code code;
|
||||
tree type, r;
|
||||
tree type, r = NULL_TREE;
|
||||
|
||||
if (t == NULL_TREE || t == error_mark_node
|
||||
|| t == integer_type_node
|
||||
@ -10892,10 +10992,21 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
|
||||
&& typedef_variant_p (t))
|
||||
{
|
||||
tree decl = TYPE_NAME (t);
|
||||
|
||||
if (DECL_CLASS_SCOPE_P (decl)
|
||||
&& CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (decl))
|
||||
&& uses_template_parms (DECL_CONTEXT (decl)))
|
||||
|
||||
if (TYPE_DECL_ALIAS_P (decl)
|
||||
&& DECL_LANG_SPECIFIC (decl)
|
||||
&& DECL_TEMPLATE_INFO (decl)
|
||||
&& PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl)))
|
||||
{
|
||||
/* DECL represents an alias template and we want to
|
||||
instantiate it. Let's substitute our arguments for the
|
||||
template parameters into the declaration and get the
|
||||
resulting type. */
|
||||
r = tsubst (decl, args, complain, decl);
|
||||
}
|
||||
else if (DECL_CLASS_SCOPE_P (decl)
|
||||
&& CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (decl))
|
||||
&& uses_template_parms (DECL_CONTEXT (decl)))
|
||||
{
|
||||
tree tmpl = most_general_template (DECL_TI_TEMPLATE (decl));
|
||||
tree gen_args = tsubst (DECL_TI_ARGS (decl), args, complain, in_decl);
|
||||
@ -11045,6 +11156,46 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
|
||||
if (argvec == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
gcc_assert (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
|
||||
|| TREE_CODE (arg) == TEMPLATE_DECL
|
||||
|| TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE);
|
||||
|
||||
if (TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE)
|
||||
/* Consider this code:
|
||||
|
||||
template <template <class> class Template>
|
||||
struct Internal {
|
||||
template <class Arg> using Bind = Template<Arg>;
|
||||
};
|
||||
|
||||
template <template <class> class Template, class Arg>
|
||||
using Instantiate = Template<Arg>; //#0
|
||||
|
||||
template <template <class> class Template,
|
||||
class Argument>
|
||||
using Bind =
|
||||
Instantiate<Internal<Template>::template Bind,
|
||||
Argument>; //#1
|
||||
|
||||
When #1 is parsed, the
|
||||
BOUND_TEMPLATE_TEMPLATE_PARM representing the
|
||||
parameter `Template' in #0 matches the
|
||||
UNBOUND_CLASS_TEMPLATE representing the argument
|
||||
`Internal<Template>::template Bind'; We then want
|
||||
to assemble the type `Bind<Argument>' that can't
|
||||
be fully created right now, because
|
||||
`Internal<Template>' not being complete, the Bind
|
||||
template cannot be looked up in that context. So
|
||||
we need to "store" `Bind<Argument>' for later
|
||||
when the context of Bind becomes complete. Let's
|
||||
store that in a TYPENAME_TYPE. */
|
||||
return make_typename_type (TYPE_CONTEXT (arg),
|
||||
build_nt (TEMPLATE_ID_EXPR,
|
||||
TYPE_IDENTIFIER (arg),
|
||||
argvec),
|
||||
typename_type,
|
||||
complain);
|
||||
|
||||
/* We can get a TEMPLATE_TEMPLATE_PARM here when we
|
||||
are resolving nested-types in the signature of a
|
||||
member function templates. Otherwise ARG is a
|
||||
@ -17610,7 +17761,12 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
|
||||
|
||||
if (! CLASS_TYPE_P (t) || ! CLASSTYPE_TEMPLATE_INFO (t))
|
||||
{
|
||||
error ("explicit instantiation of non-template type %qT", t);
|
||||
tree tmpl =
|
||||
(TYPE_TEMPLATE_INFO (t)) ? TYPE_TI_TEMPLATE (t) : NULL;
|
||||
if (tmpl)
|
||||
error ("explicit instantiation of non-class template %qD", tmpl);
|
||||
else
|
||||
error ("explicit instantiation of non-template type %qT", t);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -427,7 +427,7 @@ lookup_field_1 (tree type, tree name, bool want_type)
|
||||
field = fields[i--];
|
||||
while (i >= lo && DECL_NAME (fields[i]) == name);
|
||||
if (TREE_CODE (field) != TYPE_DECL
|
||||
&& !DECL_CLASS_TEMPLATE_P (field))
|
||||
&& !DECL_TYPE_TEMPLATE_P (field))
|
||||
field = NULL_TREE;
|
||||
}
|
||||
else
|
||||
@ -478,7 +478,7 @@ lookup_field_1 (tree type, tree name, bool want_type)
|
||||
if (DECL_NAME (field) == name
|
||||
&& (!want_type
|
||||
|| TREE_CODE (field) == TYPE_DECL
|
||||
|| DECL_CLASS_TEMPLATE_P (field)))
|
||||
|| DECL_TYPE_TEMPLATE_P (field)))
|
||||
return field;
|
||||
}
|
||||
/* Not found. */
|
||||
@ -1046,7 +1046,7 @@ lookup_field_r (tree binfo, void *data)
|
||||
/* If we're looking up a type (as with an elaborated type specifier)
|
||||
we ignore all non-types we find. */
|
||||
if (lfi->want_type && TREE_CODE (nval) != TYPE_DECL
|
||||
&& !DECL_CLASS_TEMPLATE_P (nval))
|
||||
&& !DECL_TYPE_TEMPLATE_P (nval))
|
||||
{
|
||||
if (lfi->name == TYPE_IDENTIFIER (type))
|
||||
{
|
||||
|
@ -2733,15 +2733,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) && !alias_type_or_template_p (type))
|
||||
return TYPE_STUB_DECL (type);
|
||||
else
|
||||
return TYPE_NAME (type);
|
||||
}
|
||||
|
||||
/* Finish processing a BASE_CLASS with the indicated ACCESS_SPECIFIER.
|
||||
|
@ -1,3 +1,21 @@
|
||||
2011-11-07 Dodji Seketeli <dodji@redhat.com>
|
||||
|
||||
Support C++11 alias-declaration
|
||||
PR c++/45114
|
||||
* g++.dg/cpp0x/alias-decl-0.C: New test case.
|
||||
* g++.dg/cpp0x/alias-decl-1.C: Likewise.
|
||||
* g++.dg/cpp0x/alias-decl-3.C: Likewise.
|
||||
* g++.dg/cpp0x/alias-decl-4.C: Likewise.
|
||||
* g++.dg/cpp0x/alias-decl-6.C: Likewise.
|
||||
* g++.dg/cpp0x/alias-decl-7.C: Likewise.
|
||||
* g++.dg/cpp0x/alias-decl-8.C: Likewise.
|
||||
* g++.dg/cpp0x/alias-decl-9.C: Likewise.
|
||||
* g++.dg/cpp0x/alias-decl-10.C: Likewise.
|
||||
* g++.dg/ext/alias-decl-attr1.C: Likewise.
|
||||
* g++.dg/ext/alias-decl-attr2.C: Likewise.
|
||||
* g++.dg/ext/alias-decl-attr3.C: Likewise.
|
||||
* g++.dg/ext/alias-decl-attr4.C: Likewise.
|
||||
|
||||
2011-11-07 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* gcc.dg/pragma-align-2.c: Compile with -std=gnu99.
|
||||
|
37
gcc/testsuite/g++.dg/cpp0x/alias-decl-0.C
Normal file
37
gcc/testsuite/g++.dg/cpp0x/alias-decl-0.C
Normal file
@ -0,0 +1,37 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
template<template<class> class TT> struct X { };
|
||||
template<class> struct Y { };
|
||||
template<class T> using Z = Y<T>;
|
||||
|
||||
void f(X<Y>);
|
||||
void g(X<Z>);
|
||||
|
||||
void
|
||||
foo()
|
||||
{
|
||||
// Below x and y don't have the same type, because Y and Z don't
|
||||
// designate the same template ...
|
||||
X<Y> y;
|
||||
X<Z> z;
|
||||
|
||||
// ... So these must fail to compile.
|
||||
f(z); // { dg-error "" }
|
||||
g(y); // { dg-error "" }
|
||||
}
|
||||
|
||||
template<class> struct A0 {};
|
||||
template<class T> using AA0 = A0<T>;
|
||||
template<class T> using AAA0 = AA0<T>;
|
||||
|
||||
void f0(A0<int>);
|
||||
void
|
||||
g0()
|
||||
{
|
||||
AA0<int> a;
|
||||
AAA0<int> b;
|
||||
f0(a);
|
||||
f0(b);
|
||||
}
|
||||
|
||||
|
15
gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C
Normal file
15
gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C
Normal file
@ -0,0 +1,15 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
// These also represent tests for printing alias declarations and
|
||||
// their instantiations.
|
||||
|
||||
template<class T, class U> struct A0 {};
|
||||
template<class T, class U> using AA0 = A0<T, U>;
|
||||
template<class T> struct AA0<int, T> {}; // { dg-error "partial specialization" }
|
||||
|
||||
template <class U> using Ptr = U*;
|
||||
template<class U> struct Ptr<U*> {}; // { dg-error "partial specialization" }
|
||||
|
||||
struct A {
|
||||
using A = int;//{ dg-error "nested|has|same name as|class|in which|declared" }
|
||||
};
|
18
gcc/testsuite/g++.dg/cpp0x/alias-decl-10.C
Normal file
18
gcc/testsuite/g++.dg/cpp0x/alias-decl-10.C
Normal file
@ -0,0 +1,18 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
template <class T> using Ptr = T*;
|
||||
Ptr<unsigned>; // { dg-error "does not declare anything" }
|
||||
Ptr<char><int>; // { dg-error "not a template|does not declare anything" }
|
||||
template class Ptr<int>;//{ dg-error "explicit instantiation|non-class templ|does not decl|anything" }
|
||||
|
||||
template <class T> using Arg = T;
|
||||
struct A {};
|
||||
template class Arg<A>;// { dg-error "explicit instantiation|non-class templ" }
|
||||
|
||||
template <template <class> class TT, class T> using Instantiate = TT<T>;
|
||||
template <class> struct Vector {};
|
||||
template class Instantiate<Vector, int>; // OK Vector<int> can be explicitely instantiated
|
||||
|
||||
template <class T> struct S {};
|
||||
template<class T> using SFor = S<T>;
|
||||
template class SFor<int>; // OK, S<int> can be explicitely instantiated
|
33
gcc/testsuite/g++.dg/cpp0x/alias-decl-2.C
Normal file
33
gcc/testsuite/g++.dg/cpp0x/alias-decl-2.C
Normal file
@ -0,0 +1,33 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
template<class T> struct S0 {};
|
||||
template<class T> using AS0 = S0<T>;
|
||||
|
||||
template<template<class> class TT>
|
||||
void f(TT<int>);
|
||||
|
||||
template class AS0<char>;
|
||||
|
||||
void
|
||||
foo()
|
||||
{
|
||||
AS0<int> a;
|
||||
f(a);
|
||||
}
|
||||
|
||||
template<class T, class U> struct Vector{};
|
||||
template<class T> struct Alloc {};
|
||||
|
||||
template<class T> using Vec = Vector<T, Alloc<T> >;
|
||||
|
||||
template<class T> void g(Vector<T, Alloc<T> >);
|
||||
|
||||
template<template<class T> class TT> void h(TT<int>); // { dg-error "provided for" }
|
||||
|
||||
void
|
||||
bar()
|
||||
{
|
||||
Vec<int> a;
|
||||
g(a);
|
||||
h(a); // { dg-error "no matching function|wrong number of template arguments" }
|
||||
}
|
42
gcc/testsuite/g++.dg/cpp0x/alias-decl-3.C
Normal file
42
gcc/testsuite/g++.dg/cpp0x/alias-decl-3.C
Normal file
@ -0,0 +1,42 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
// Exercise some member alias templates ...
|
||||
|
||||
template<class T, class U> class A0 {};
|
||||
|
||||
template<class T>
|
||||
struct A1 {
|
||||
template<class U> struct S {};
|
||||
template<class U> using AA0 = A0<T, U>;
|
||||
|
||||
void f(A0<T, int>);
|
||||
|
||||
void
|
||||
foo()
|
||||
{
|
||||
AA0<int> a;
|
||||
const AA0<int> b;
|
||||
f(a);
|
||||
f(b);
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
bar()
|
||||
{
|
||||
A1<int> a1;
|
||||
a1.foo();
|
||||
A1<int>::AA0<int> a1aa0;
|
||||
a1.f(a1aa0);
|
||||
}
|
||||
|
||||
// ... some simple member alias ...
|
||||
struct B {
|
||||
using A = int;
|
||||
};
|
||||
|
||||
B::A a;
|
||||
|
||||
// ... and some simple alias
|
||||
|
||||
using Int = int;
|
14
gcc/testsuite/g++.dg/cpp0x/alias-decl-4.C
Normal file
14
gcc/testsuite/g++.dg/cpp0x/alias-decl-4.C
Normal file
@ -0,0 +1,14 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
// [temp.alias]/3:
|
||||
// The type-id in an alias template declaration shall not refer
|
||||
// to the alias template being declared. The type produced by an
|
||||
// alias template specialization shall not directly or indirectly
|
||||
// make use of that specialization.
|
||||
|
||||
template <class T> struct A;
|
||||
template <class T> using B = typename A<T>::U; // { dg-error "type" }
|
||||
template <class T> struct A {
|
||||
typedef B<T> U;
|
||||
};
|
||||
B<short> b; // { dg-error "invalid type" }
|
34
gcc/testsuite/g++.dg/cpp0x/alias-decl-5.C
Normal file
34
gcc/testsuite/g++.dg/cpp0x/alias-decl-5.C
Normal file
@ -0,0 +1,34 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
// alias template of a partial specialization
|
||||
|
||||
template<class T, class U, class W> struct S0 {};
|
||||
template<class T, class U> struct S0<T, U, char> {};
|
||||
template<class T> using AS0 = S0<T, int, char>;
|
||||
void foo(S0<bool, int, char>);
|
||||
|
||||
AS0<bool> a; // OK
|
||||
|
||||
void
|
||||
f()
|
||||
{
|
||||
foo(a); //OK
|
||||
}
|
||||
|
||||
// alias template of an explicit specialization of a member template
|
||||
|
||||
template<class T>
|
||||
struct S1 {
|
||||
template<class U>
|
||||
struct M {};
|
||||
};
|
||||
template<class T> using AM = S1<int>::M<T>;
|
||||
void bar(S1<int>::M<bool>);
|
||||
|
||||
AM<bool> b; //OK.
|
||||
|
||||
void
|
||||
g()
|
||||
{
|
||||
bar(b); //OK
|
||||
}
|
12
gcc/testsuite/g++.dg/cpp0x/alias-decl-6.C
Normal file
12
gcc/testsuite/g++.dg/cpp0x/alias-decl-6.C
Normal file
@ -0,0 +1,12 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
// Alias template of non-class types.
|
||||
|
||||
template <class T, class U> struct same;
|
||||
template <class T> struct same<T,T> {};
|
||||
|
||||
template <class T> using Ptr = T*;
|
||||
template <template <class> class T> struct A {
|
||||
template <class U> using X = T<U>;
|
||||
};
|
||||
same<A<Ptr>::X<int>,int*> s;
|
23
gcc/testsuite/g++.dg/cpp0x/alias-decl-7.C
Normal file
23
gcc/testsuite/g++.dg/cpp0x/alias-decl-7.C
Normal file
@ -0,0 +1,23 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
// Add arguments to unbound template template parameter.
|
||||
|
||||
template <template <class> class Template>
|
||||
struct Internal {
|
||||
template <class Arg> using Bind = Template<Arg>;
|
||||
};
|
||||
|
||||
template <template <class> class Template, class Arg>
|
||||
using Instantiate = Template<Arg>; // After parsing #1, the
|
||||
// BOUND_TEMPLATE_TEMPLATE_PARM
|
||||
// parameter Template gets
|
||||
// the UNBOUND_CLASS_TEMPLATE
|
||||
// Internal<Template>::template Bind
|
||||
// as an argument, and the
|
||||
// parameter Arg gets Argument as
|
||||
// an argument. And we build
|
||||
// 'Bind<Argument>'.
|
||||
|
||||
template <template <class> class Template, class Argument>
|
||||
using Bind = Instantiate<Internal<Template>::template Bind, Argument>; //#1
|
||||
|
32
gcc/testsuite/g++.dg/cpp0x/alias-decl-8.C
Normal file
32
gcc/testsuite/g++.dg/cpp0x/alias-decl-8.C
Normal file
@ -0,0 +1,32 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
struct A {
|
||||
template <class U> using C = U;
|
||||
};
|
||||
|
||||
// The particularity of the below struct is to have more than 7
|
||||
// fields. In this case, looking up a member here should exercise
|
||||
// cp/search.c:lookup_field_1 in such a way that it finds it in the
|
||||
// CLASSTYPE_SORTED_FIELDS of struct A7.
|
||||
struct A7 {
|
||||
int f0;
|
||||
int f1;
|
||||
int f2;
|
||||
int f3;
|
||||
int f4;
|
||||
int f5;
|
||||
int f6;
|
||||
int f7;
|
||||
template <class U> using C = U;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct B {
|
||||
typename T::template C<int> n; //#0
|
||||
};
|
||||
|
||||
// These should trigger the lookup
|
||||
// of template C inside class A or
|
||||
// A7, via #0.
|
||||
B<A> b;
|
||||
B<A7> c;
|
9
gcc/testsuite/g++.dg/cpp0x/alias-decl-9.C
Normal file
9
gcc/testsuite/g++.dg/cpp0x/alias-decl-9.C
Normal file
@ -0,0 +1,9 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
template <class T>
|
||||
struct A {
|
||||
using Result = T;
|
||||
};
|
||||
template <class A> using Arg = typename A::Result;
|
||||
Arg<A<int>> b;
|
||||
|
19
gcc/testsuite/g++.dg/ext/alias-decl-attr1.C
Normal file
19
gcc/testsuite/g++.dg/ext/alias-decl-attr1.C
Normal file
@ -0,0 +1,19 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
template <unsigned Len, unsigned Align>
|
||||
struct aligned_storage
|
||||
{
|
||||
using type __attribute__((aligned((Align)))) =
|
||||
char[Len];
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct X
|
||||
{
|
||||
typename aligned_storage<sizeof(T),__alignof(T)>::type data;
|
||||
};
|
||||
|
||||
template<bool> struct StaticAssert;
|
||||
template<> struct StaticAssert<true> {};
|
||||
|
||||
StaticAssert<__alignof (X<double>) == __alignof (double)> dummy;
|
42
gcc/testsuite/g++.dg/ext/alias-decl-attr2.C
Normal file
42
gcc/testsuite/g++.dg/ext/alias-decl-attr2.C
Normal file
@ -0,0 +1,42 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
template<typename T>
|
||||
struct X {
|
||||
using layout_type __attribute ((aligned(__alignof(double)))) =
|
||||
char[sizeof(T)];
|
||||
layout_type data;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Y {
|
||||
using layout_type __attribute ((aligned(__alignof(T)))) =
|
||||
char[sizeof(T)];
|
||||
layout_type data;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Z {
|
||||
using layout_type __attribute ((aligned(__alignof(T)))) =
|
||||
char[sizeof(T)];
|
||||
struct Z2 {
|
||||
layout_type data;
|
||||
} in;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct A;
|
||||
|
||||
template <typename T>
|
||||
struct A<T*> {
|
||||
using layout_type __attribute ((aligned(__alignof(T)))) =
|
||||
char[sizeof(T)];
|
||||
layout_type data;
|
||||
};
|
||||
|
||||
template<bool> struct StaticAssert;
|
||||
template<> struct StaticAssert<true> {};
|
||||
|
||||
StaticAssert<__alignof(X<double>) == __alignof(double)> d1;
|
||||
StaticAssert<__alignof(Y<double>) == __alignof(double)> d2;
|
||||
StaticAssert<__alignof(Z<double>) == __alignof(double)> d3;
|
||||
StaticAssert<__alignof(A<double*>) == __alignof(double)> d4;
|
21
gcc/testsuite/g++.dg/ext/alias-decl-attr3.C
Normal file
21
gcc/testsuite/g++.dg/ext/alias-decl-attr3.C
Normal file
@ -0,0 +1,21 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
// { dg-do run }
|
||||
|
||||
template <class T>
|
||||
int
|
||||
align_of_type_wide_array()
|
||||
{
|
||||
using type_wide_array __attribute((aligned(__alignof(T))))
|
||||
= unsigned char[sizeof (T)];
|
||||
|
||||
return __alignof(type_wide_array);
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
if (align_of_type_wide_array<int>() == __alignof(int))
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
34
gcc/testsuite/g++.dg/ext/alias-decl-attr4.C
Normal file
34
gcc/testsuite/g++.dg/ext/alias-decl-attr4.C
Normal file
@ -0,0 +1,34 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
// { dg-do run }
|
||||
|
||||
using global_vector_type __attribute__((vector_size(16))) = float;
|
||||
|
||||
template <class T> struct A
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template < typename Val > struct S
|
||||
{
|
||||
using vector_type __attribute__((vector_size(16))) =
|
||||
typename A<Val>::type
|
||||
typedef Val vector_type2 __attribute__((vector_size(16)));
|
||||
int pr_size() { return sizeof(vector_type); }
|
||||
int pr_size2() { return sizeof(vector_type2); }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
if (sizeof (S<float>::vector_type) != sizeof (global_vector_type))
|
||||
return 1;
|
||||
if (sizeof (S<float>::vector_type2) != sizeof (global_vector_type))
|
||||
return 2;
|
||||
|
||||
S<float> x;
|
||||
if (x.pr_size() != sizeof (global_vector_type))
|
||||
return 3;
|
||||
if (x.pr_size2() != sizeof (global_vector_type))
|
||||
return 4;
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user