static void expand_static_init (tree, tree);
static tree next_initializable_field (tree);
static tree reshape_init (tree, tree *);
-static tree build_typename_type (tree, tree, tree);
/* Erroneous argument lists can use this *IFF* they do not modify it. */
tree error_mark_list;
return hash;
}
+typedef struct typename_info {
+ tree scope;
+ tree name;
+ tree template_id;
+ bool enum_p;
+ bool class_p;
+} typename_info;
+
/* Compare two TYPENAME_TYPEs. K1 and K2 are really of type `tree'. */
static int
typename_compare (const void * k1, const void * k2)
{
tree t1;
- tree t2;
- tree d1;
- tree d2;
+ const typename_info *t2;
t1 = (tree) k1;
- t2 = (tree) k2;
- d1 = TYPE_NAME (t1);
- d2 = TYPE_NAME (t2);
+ t2 = (const typename_info *) k2;
- return (DECL_NAME (d1) == DECL_NAME (d2)
- && TYPE_CONTEXT (t1) == TYPE_CONTEXT (t2)
- && ((TREE_TYPE (t1) != NULL_TREE)
- == (TREE_TYPE (t2) != NULL_TREE))
- && same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
- && TYPENAME_TYPE_FULLNAME (t1) == TYPENAME_TYPE_FULLNAME (t2));
+ return (DECL_NAME (TYPE_NAME (t1)) == t2->name
+ && TYPE_CONTEXT (t1) == t2->scope
+ && TYPENAME_TYPE_FULLNAME (t1) == t2->template_id
+ && TYPENAME_IS_ENUM_P (t1) == t2->enum_p
+ && TYPENAME_IS_CLASS_P (t1) == t2->class_p);
}
/* Build a TYPENAME_TYPE. If the type is `typename T::t', CONTEXT is
- the type of `T', NAME is the IDENTIFIER_NODE for `t'. If BASE_TYPE
- is non-NULL, this type is being created by the implicit typename
- extension, and BASE_TYPE is a type named `t' in some base class of
- `T' which depends on template parameters.
-
+ the type of `T', NAME is the IDENTIFIER_NODE for `t'.
+
Returns the new TYPENAME_TYPE. */
static GTY ((param_is (union tree_node))) htab_t typename_htab;
static tree
-build_typename_type (tree context, tree name, tree fullname)
+build_typename_type (tree context, tree name, tree fullname,
+ enum tag_types tag_type)
{
tree t;
tree d;
+ typename_info ti;
void **e;
+ hashval_t hash;
if (typename_htab == NULL)
- {
- typename_htab = htab_create_ggc (61, &typename_hash,
- &typename_compare, NULL);
- }
-
- /* Build the TYPENAME_TYPE. */
- t = make_aggr_type (TYPENAME_TYPE);
- TYPE_CONTEXT (t) = FROB_CONTEXT (context);
- TYPENAME_TYPE_FULLNAME (t) = fullname;
-
- /* Build the corresponding TYPE_DECL. */
- d = build_decl (TYPE_DECL, name, t);
- TYPE_NAME (TREE_TYPE (d)) = d;
- TYPE_STUB_DECL (TREE_TYPE (d)) = d;
- DECL_CONTEXT (d) = FROB_CONTEXT (context);
- DECL_ARTIFICIAL (d) = 1;
+ typename_htab = htab_create_ggc (61, &typename_hash,
+ &typename_compare, NULL);
+
+ ti.scope = FROB_CONTEXT (context);
+ ti.name = name;
+ ti.template_id = fullname;
+ ti.enum_p = tag_type == enum_type;
+ ti.class_p = (tag_type == class_type
+ || tag_type == record_type
+ || tag_type == union_type);
+ hash = (htab_hash_pointer (ti.scope)
+ ^ htab_hash_pointer (ti.name));
/* See if we already have this type. */
- e = htab_find_slot (typename_htab, t, INSERT);
+ e = htab_find_slot_with_hash (typename_htab, &ti, hash, INSERT);
if (*e)
t = (tree) *e;
else
- *e = t;
+ {
+ /* Build the TYPENAME_TYPE. */
+ t = make_aggr_type (TYPENAME_TYPE);
+ TYPE_CONTEXT (t) = ti.scope;
+ TYPENAME_TYPE_FULLNAME (t) = ti.template_id;
+ TYPENAME_IS_ENUM_P (t) = ti.enum_p;
+ TYPENAME_IS_CLASS_P (t) = ti.class_p;
+
+ /* Build the corresponding TYPE_DECL. */
+ d = build_decl (TYPE_DECL, name, t);
+ TYPE_NAME (TREE_TYPE (d)) = d;
+ TYPE_STUB_DECL (TREE_TYPE (d)) = d;
+ DECL_CONTEXT (d) = FROB_CONTEXT (context);
+ DECL_ARTIFICIAL (d) = 1;
+ /* Store it in the hash table. */
+ *e = t;
+ }
+
return t;
}
-/* Resolve `typename CONTEXT::NAME'. Returns an appropriate type,
- unless an error occurs, in which case error_mark_node is returned.
- If we locate a non-artificial TYPE_DECL and TF_KEEP_TYPE_DECL is
- set, we return that, rather than the _TYPE it corresponds to, in
- other cases we look through the type decl. If TF_ERROR is set,
- complain about errors, otherwise be quiet. */
+/* Resolve `typename CONTEXT::NAME'. TAG_TYPE indicates the tag
+ provided to name the type. Returns an appropriate type, unless an
+ error occurs, in which case error_mark_node is returned. If we
+ locate a non-artificial TYPE_DECL and TF_KEEP_TYPE_DECL is set, we
+ return that, rather than the _TYPE it corresponds to, in other
+ cases we look through the type decl. If TF_ERROR is set, complain
+ about errors, otherwise be quiet. */
tree
-make_typename_type (tree context, tree name, tsubst_flags_t complain)
+make_typename_type (tree context, tree name, enum tag_types tag_type,
+ tsubst_flags_t complain)
{
tree fullname;
return error_mark_node;
}
- return build_typename_type (context, name, fullname);
+ return build_typename_type (context, name, fullname, tag_type);
}
/* Resolve `CONTEXT::template NAME'. Returns a TEMPLATE_DECL if the name
/* Classes [gram.class] */
static tree cp_parser_class_name
- (cp_parser *, bool, bool, bool, bool, bool, bool);
+ (cp_parser *, bool, bool, enum tag_types, bool, bool, bool);
static tree cp_parser_class_specifier
(cp_parser *);
static tree cp_parser_class_head
/* Utility Routines */
static tree cp_parser_lookup_name
- (cp_parser *, tree, bool, bool, bool, bool, bool *);
+ (cp_parser *, tree, enum tag_types, bool, bool, bool, bool *);
static tree cp_parser_lookup_name_simple
(cp_parser *, tree);
static tree cp_parser_maybe_treat_template_as_class
static void cp_parser_check_type_definition
(cp_parser *);
static void cp_parser_check_for_definition_in_return_type
- (cp_declarator *, int);
+ (cp_declarator *, tree);
static void cp_parser_check_for_invalid_template_id
(cp_parser *, tree);
static bool cp_parser_non_integral_constant_expression
error ("%s", parser->type_definition_forbidden_message);
}
-/* This function is called when a declaration is parsed. If
- DECLARATOR is a function declarator and DECLARES_CLASS_OR_ENUM
- indicates that a type was defined in the decl-specifiers for DECL,
- then an error is issued. */
+/* This function is called when the DECLARATOR is processed. The TYPE
+ was a type definied in the decl-specifiers. If it is invalid to
+ define a type in the decl-specifiers for DECLARATOR, an error is
+ issued. */
static void
cp_parser_check_for_definition_in_return_type (cp_declarator *declarator,
- int declares_class_or_enum)
+ tree type)
{
/* [dcl.fct] forbids type definitions in return types.
Unfortunately, it's not easy to know whether or not we are
|| declarator->kind == cdk_ptrmem))
declarator = declarator->declarator;
if (declarator
- && declarator->kind == cdk_function
- && declares_class_or_enum & 2)
- error ("new types may not be defined in a return type");
+ && declarator->kind == cdk_function)
+ {
+ error ("new types may not be defined in a return type");
+ inform ("(perhaps a semicolon is missing after the definition of %qT)",
+ type);
+ }
}
/* A type-specifier (TYPE) has been parsed which cannot be followed by
tree result;
if (TREE_CODE (id) == IDENTIFIER_NODE)
{
- result = make_typename_type (scope, id, /*complain=*/0);
+ result = make_typename_type (scope, id, typename_type,
+ /*complain=*/0);
if (result == error_mark_node)
cp_parser_diagnose_invalid_type_name (parser, scope, id);
return result;
}
- return make_typename_type (scope, id, tf_error);
+ return make_typename_type (scope, id, typename_type, tf_error);
}
bool ambiguous_p;
decl = cp_parser_lookup_name (parser, id_expression,
- /*is_type=*/false,
+ none_type,
/*is_template=*/false,
/*is_namespace=*/false,
/*check_dependency=*/true,
type_decl = cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
- /*type_p=*/false,
+ none_type,
/*check_dependency=*/false,
/*class_head_p=*/false,
declarator_p);
= cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
- /*type_p=*/false,
+ none_type,
/*check_dependency=*/false,
/*class_head_p=*/false,
declarator_p);
= cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
- /*type_p=*/false,
+ none_type,
/*check_dependency=*/false,
/*class_head_p=*/false,
declarator_p);
= cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
- /*type_p=*/false,
+ none_type,
/*check_dependency=*/false,
/*class_head_p=*/false,
declarator_p);
scope = cp_parser_class_name (parser,
typename_keyword_p,
template_keyword_p,
- type_p,
+ type_p ? class_type : none_type,
check_dependency_p,
/*class_head_p=*/false,
is_declaration);
functional cast is being performed. */
else
type = make_typename_type (parser->scope, id,
+ typename_type,
/*complain=*/1);
postfix_expression = cp_parser_functional_cast (parser, type);
if (parser->scope)
*idk = CP_ID_KIND_QUALIFIED;
- if (name != error_mark_node && !BASELINK_P (name) && parser->scope)
+ /* If the name is a template-id that names a type, we will get a
+ TYPE_DECL here. That is invalid code. */
+ if (TREE_CODE (name) == TYPE_DECL)
{
- name = build_nt (SCOPE_REF, parser->scope, name);
- parser->scope = NULL_TREE;
- parser->qualifying_scope = NULL_TREE;
- parser->object_scope = NULL_TREE;
+ error ("invalid use of %qD", name);
+ postfix_expression = error_mark_node;
+ }
+ else
+ {
+ if (name != error_mark_node && !BASELINK_P (name) && parser->scope)
+ {
+ name = build_nt (SCOPE_REF, parser->scope, name);
+ parser->scope = NULL_TREE;
+ parser->qualifying_scope = NULL_TREE;
+ parser->object_scope = NULL_TREE;
+ }
+ if (scope && name && BASELINK_P (name))
+ adjust_result_of_qualified_name_lookup
+ (name, BINFO_TYPE (BASELINK_BINFO (name)), scope);
+ postfix_expression
+ = finish_class_member_access_expr (postfix_expression, name);
}
- if (scope && name && BASELINK_P (name))
- adjust_result_of_qualified_name_lookup
- (name, BINFO_TYPE (BASELINK_BINFO (name)), scope);
- postfix_expression
- = finish_class_member_access_expr (postfix_expression, name);
}
/* We no longer need to look up names in the scope of the object on
return cp_parser_class_name (parser,
/*typename_keyword_p=*/true,
/*template_keyword_p=*/template_p,
- /*type_p=*/false,
+ none_type,
/*check_dependency_p=*/true,
/*class_head_p=*/false,
/*is_declaration=*/true);
id = cp_parser_class_name (parser,
/*typename_keyword_p=*/true,
/*template_keyword_p=*/false,
- /*type_p=*/false,
+ none_type,
/*check_dependency_p=*/true,
/*class_head_p=*/false,
/*is_declaration=*/true);
/* Look up the name. */
default_argument
= cp_parser_lookup_name (parser, default_argument,
- /*is_type=*/false,
- /*is_template=*/is_template,
- /*is_namespace=*/false,
- /*check_dependency=*/true,
- /*ambiguous_p=*/NULL);
+ none_type,
+ /*is_template=*/is_template,
+ /*is_namespace=*/false,
+ /*check_dependency=*/true,
+ /*ambiguous_p=*/NULL);
/* See if the default argument is valid. */
default_argument
= check_template_template_default_arg (default_argument);
/* Look up the name. */
decl = cp_parser_lookup_name (parser, identifier,
- /*is_type=*/false,
+ none_type,
/*is_template=*/false,
/*is_namespace=*/false,
check_dependency_p,
at this point in that case. */
if (TREE_CODE (argument) != TYPE_DECL)
argument = cp_parser_lookup_name (parser, argument,
- /*is_type=*/false,
+ none_type,
/*is_template=*/template_p,
/*is_namespace=*/false,
/*check_dependency=*/true,
/*ctor_dtor_or_conv_p=*/NULL,
/*parenthesized_p=*/NULL,
/*member_p=*/false);
- cp_parser_check_for_definition_in_return_type (declarator,
- declares_class_or_enum);
+ if (declares_class_or_enum & 2)
+ cp_parser_check_for_definition_in_return_type (declarator,
+ decl_specifiers.type);
if (declarator != cp_error_declarator)
{
decl = grokdeclarator (declarator, &decl_specifiers,
type_decl = cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
- /*type_p=*/false,
+ none_type,
/*check_dependency_p=*/true,
/*class_head_p=*/false,
/*is_declaration=*/false);
else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
&& tag_type == typename_type)
type = make_typename_type (parser->scope, decl,
+ typename_type,
/*complain=*/1);
else
type = TREE_TYPE (decl);
types, so we set IS_TYPE to TRUE when calling
cp_parser_lookup_name. */
decl = cp_parser_lookup_name (parser, identifier,
- /*is_type=*/true,
+ tag_type,
/*is_template=*/false,
/*is_namespace=*/false,
/*check_dependency=*/true,
function if the token after the name is the scope resolution
operator.) */
namespace_decl = cp_parser_lookup_name (parser, identifier,
- /*is_type=*/false,
+ none_type,
/*is_template=*/false,
/*is_namespace=*/true,
/*check_dependency=*/true,
if (declarator == cp_error_declarator)
return error_mark_node;
- cp_parser_check_for_definition_in_return_type (declarator,
- declares_class_or_enum);
+ if (declares_class_or_enum & 2)
+ cp_parser_check_for_definition_in_return_type (declarator,
+ decl_specifiers->type);
/* Figure out what scope the entity declared by the DECLARATOR is
located in. `grokdeclarator' sometimes changes the scope, so
to indicate that names looked up in dependent types should be
assumed to be types. TEMPLATE_KEYWORD_P is true iff the `template'
keyword has been used to indicate that the name that appears next
- is a template. TYPE_P is true iff the next name should be treated
- as class-name, even if it is declared to be some other kind of name
- as well. If CHECK_DEPENDENCY_P is FALSE, names are looked up in
- dependent scopes. If CLASS_HEAD_P is TRUE, this class is the class
- being defined in a class-head.
+ is a template. TAG_TYPE indicates the explicit tag given before
+ the type name, if any. If CHECK_DEPENDENCY_P is FALSE, names are
+ looked up in dependent scopes. If CLASS_HEAD_P is TRUE, this class
+ is the class being defined in a class-head.
Returns the TYPE_DECL representing the class. */
cp_parser_class_name (cp_parser *parser,
bool typename_keyword_p,
bool template_keyword_p,
- bool type_p,
+ enum tag_types tag_type,
bool check_dependency_p,
bool class_head_p,
bool is_declaration)
resolution operator, object, function, and enumerator
names are ignored. */
if (cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))
- type_p = true;
+ tag_type = typename_type;
/* Look up the name. */
decl = cp_parser_lookup_name (parser, identifier,
- type_p,
+ tag_type,
/*is_template=*/false,
/*is_namespace=*/false,
check_dependency_p,
/* If this is a typename, create a TYPENAME_TYPE. */
if (typename_p && decl != error_mark_node)
{
- decl = make_typename_type (scope, decl, /*complain=*/1);
+ decl = make_typename_type (scope, decl, typename_type, /*complain=*/1);
if (decl != error_mark_node)
decl = TYPE_NAME (decl);
}
standard does not seem to be definitive, but there is no other
valid interpretation of the following `::'. Therefore, those
names are considered class-names. */
- decl = TYPE_NAME (make_typename_type (scope, decl, tf_error));
+ decl = TYPE_NAME (make_typename_type (scope, decl, tag_type, tf_error));
else if (decl == error_mark_node
|| TREE_CODE (decl) != TYPE_DECL
|| !IS_AGGR_TYPE (TREE_TYPE (decl)))
type = cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
- /*type_p=*/true,
+ class_type,
/*check_dependency_p=*/false,
/*class_head_p=*/true,
/*is_declaration=*/false);
return;
}
- cp_parser_check_for_definition_in_return_type
- (declarator, declares_class_or_enum);
+ if (declares_class_or_enum & 2)
+ cp_parser_check_for_definition_in_return_type
+ (declarator, decl_specifiers.type);
/* Look for an asm-specification. */
asm_specification = cp_parser_asm_specification_opt (parser);
cp_parser_nested_name_specifier_opt (parser,
/*typename_keyword_p=*/true,
/*check_dependency_p=*/true,
- /*type_p=*/true,
+ typename_type,
/*is_declaration=*/true);
/* If the base class is given by a qualified name, assume that names
we see are type names or templates, as appropriate. */
type = cp_parser_class_name (parser,
class_scope_p,
template_p,
- /*type_p=*/true,
+ typename_type,
/*check_dependency_p=*/true,
/*class_head_p=*/false,
/*is_declaration=*/true);
If there was no entity with the indicated NAME, the ERROR_MARK_NODE
is returned.
- If IS_TYPE is TRUE, bindings that do not refer to types are
- ignored.
+ If TAG_TYPE is not NONE_TYPE, it inidcates an explicit type keyword
+ (e.g., "struct") that was used. In that case bindings that do not
+ refer to types are ignored.
If IS_TEMPLATE is TRUE, bindings that do not refer to templates are
ignored.
static tree
cp_parser_lookup_name (cp_parser *parser, tree name,
- bool is_type, bool is_template, bool is_namespace,
+ enum tag_types tag_type,
+ bool is_template, bool is_namespace,
bool check_dependency,
bool *ambiguous_p)
{
if ((check_dependency || !CLASS_TYPE_P (parser->scope))
&& dependent_p)
{
- if (is_type)
- /* The resolution to Core Issue 180 says that `struct A::B'
- should be considered a type-name, even if `A' is
- dependent. */
- decl = TYPE_NAME (make_typename_type (parser->scope,
- name,
- /*complain=*/1));
+ if (tag_type)
+ {
+ tree type;
+
+ /* The resolution to Core Issue 180 says that `struct
+ A::B' should be considered a type-name, even if `A'
+ is dependent. */
+ type = make_typename_type (parser->scope, name, tag_type,
+ /*complain=*/1);
+ if (tag_type == enum_type)
+ TYPENAME_IS_ENUM_P (type) = 1;
+ else if (tag_type != typename_type)
+ TYPENAME_IS_CLASS_P (type) = 1;
+ decl = TYPE_NAME (type);
+ }
else if (is_template)
decl = make_unbound_class_template (parser->scope,
name, NULL_TREE,
may be instantiated during name lookup. In that case,
errors may be issued. Even if we rollback the current
tentative parse, those errors are valid. */
- decl = lookup_qualified_name (parser->scope, name, is_type,
+ decl = lookup_qualified_name (parser->scope, name,
+ tag_type != none_type,
/*complain=*/true);
if (pop_p)
pop_scope (parser->scope);
parse, those errors are valid. */
object_decl = lookup_member (object_type,
name,
- /*protect=*/0, is_type);
+ /*protect=*/0,
+ tag_type != none_type);
/* Look it up in the enclosing context, too. */
- decl = lookup_name_real (name, is_type, /*nonclass=*/0,
+ decl = lookup_name_real (name, tag_type != none_type,
+ /*nonclass=*/0,
/*block_p=*/true, is_namespace,
/*flags=*/0);
parser->object_scope = object_type;
}
else
{
- decl = lookup_name_real (name, is_type, /*nonclass=*/0,
+ decl = lookup_name_real (name, tag_type != none_type,
+ /*nonclass=*/0,
/*block_p=*/true, is_namespace,
/*flags=*/0);
parser->qualifying_scope = NULL_TREE;
cp_parser_lookup_name_simple (cp_parser* parser, tree name)
{
return cp_parser_lookup_name (parser, name,
- /*is_type=*/false,
+ none_type,
/*is_template=*/false,
/*is_namespace=*/false,
/*check_dependency=*/true,
type_decl = cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
- /*type_p=*/false,
+ none_type,
/*check_dependency_p=*/false,
/*class_head_p=*/false,
/*is_declaration=*/false);
static tree most_specialized_class (tree, tree);
static int template_class_depth_real (tree, int);
static tree tsubst_aggr_type (tree, tree, tsubst_flags_t, tree, int);
-static tree tsubst_decl (tree, tree, tree, tsubst_flags_t);
static tree tsubst_arg_types (tree, tree, tsubst_flags_t, tree);
static tree tsubst_function_type (tree, tree, tsubst_flags_t, tree);
static void check_specialization_scope (void);
arg = make_typename_type (TREE_OPERAND (arg, 0),
TREE_OPERAND (arg, 1),
+ typename_type,
complain & tf_error);
is_type = 1;
}
TREE_PURPOSE (arg));
}
-/* Substitute the ARGS into the T, which is a _DECL. TYPE is the
- (already computed) substitution of ARGS into TREE_TYPE (T), if
- appropriate. Return the result of the substitution. Issue error
- and warning messages under control of COMPLAIN. */
+/* Substitute the ARGS into the T, which is a _DECL. Return the
+ result of the substitution. Issue error and warning messages under
+ control of COMPLAIN. */
static tree
-tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
+tsubst_decl (tree t, tree args, tsubst_flags_t complain)
{
location_t saved_loc;
tree r = NULL_TREE;
tree argvec = NULL_TREE;
tree *friends;
tree gen_tmpl;
+ tree type;
int member;
int args_depth;
int parms_depth;
member = 0;
ctx = DECL_CONTEXT (t);
}
- type = tsubst (type, args, complain, in_decl);
+ type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (type == error_mark_node)
return error_mark_node;
case PARM_DECL:
{
+ tree type;
+
r = copy_node (t);
if (DECL_TEMPLATE_PARM_P (t))
SET_DECL_TEMPLATE_PARM_P (r);
+ type = tsubst (TREE_TYPE (t), args, complain, in_decl);
TREE_TYPE (r) = type;
c_apply_type_quals_to_decl (cp_type_quals (type), r);
case FIELD_DECL:
{
+ tree type;
+
r = copy_decl (t);
+ type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ if (type == error_mark_node)
+ return error_mark_node;
TREE_TYPE (r) = type;
c_apply_type_quals_to_decl (cp_type_quals (type), r);
break;
case TYPE_DECL:
- if (TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM
- || t == TYPE_MAIN_DECL (TREE_TYPE (t)))
- {
- /* If this is the canonical decl, we don't have to mess with
- instantiations, and often we can't (for typename, template
- type parms and such). Note that TYPE_NAME is not correct for
- the above test if we've copied the type for a typedef. */
- r = TYPE_NAME (type);
- break;
- }
-
- /* Fall through. */
-
case VAR_DECL:
{
tree argvec = NULL_TREE;
tree spec;
tree tmpl = NULL_TREE;
tree ctx;
+ tree type = NULL_TREE;
int local_p;
+ if (TREE_CODE (t) == TYPE_DECL)
+ {
+ type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ if (TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM
+ || t == TYPE_MAIN_DECL (TREE_TYPE (t)))
+ {
+ /* If this is the canonical decl, we don't have to
+ mess with instantiations, and often we can't (for
+ typename, template type parms and such). Note that
+ TYPE_NAME is not correct for the above test if
+ we've copied the type for a typedef. */
+ r = TYPE_NAME (type);
+ break;
+ }
+ }
+
/* Assume this is a non-local variable. */
local_p = 0;
r = copy_decl (t);
if (TREE_CODE (r) == VAR_DECL)
{
+ type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ if (type == error_mark_node)
+ return error_mark_node;
type = complete_type (type);
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r)
= DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (t);
|| TREE_CODE (t) == NAMESPACE_DECL)
return t;
+ if (DECL_P (t))
+ return tsubst_decl (t, args, complain);
+
if (TREE_CODE (t) == IDENTIFIER_NODE)
type = IDENTIFIER_TYPE_VALUE (t);
else
gcc_assert (type != unknown_type_node);
- if (type && TREE_CODE (t) != FUNCTION_DECL
+ if (type
&& TREE_CODE (t) != TYPENAME_TYPE
- && TREE_CODE (t) != TEMPLATE_DECL
&& TREE_CODE (t) != IDENTIFIER_NODE
&& TREE_CODE (t) != FUNCTION_TYPE
&& TREE_CODE (t) != METHOD_TYPE)
if (type == error_mark_node)
return error_mark_node;
- if (DECL_P (t))
- return tsubst_decl (t, args, type, complain);
-
switch (TREE_CODE (t))
{
case RECORD_TYPE:
}
}
- f = make_typename_type (ctx, f,
+ f = make_typename_type (ctx, f, typename_type,
(complain & tf_error) | tf_keep_type_decl);
if (f == error_mark_node)
return f;
f = TREE_TYPE (f);
}
+ if (TREE_CODE (f) != TYPENAME_TYPE)
+ {
+ if (TYPENAME_IS_ENUM_P (t) && TREE_CODE (f) != ENUMERAL_TYPE)
+ error ("%qT resolves to %qT, which is not an enumeration type",
+ t, f);
+ else if (TYPENAME_IS_CLASS_P (t) && !CLASS_TYPE_P (f))
+ error ("%qT resolves to %qT, which is is not a class type",
+ t, f);
+ }
+
return cp_build_qualified_type_real
(f, cp_type_quals (f) | cp_type_quals (t), complain);
}