re PR c++/9388 ([new parser] ICE in cxx_incomplete_type_diagnostic, at cp/typeck2.c:278)

PR c++/9388
	* class.c (currently_open_derived_class): Use dependent_type_p.
	* cp-tree.h (dependent_type_p): New function.
	(dependent_template_arg_p): Likewise.
	(dependent_template_p): Likewise.
	(type_dependent_expression_p): Likewise.
	* parser.c (cp_parser_dependent_type_p): Remove.
	(cp_parser_value_dependent_type_p): Likewise.
	(cp_parser_type_dependent_expression_p): Likewise.
	(cp_parser_dependent_template_arg_p): Likewise.
	(cp_parser_dependent_template_id_p): Likewise.
	(cp_parser_dependent_template_p): Likewise.
	(cp_parser_diagnose_invalid_type_name): Replace
	cp_parser_dependent_type_p with dependent_type_p, etc.
	(cp_parser_primary_expresion): Likewise.
	(cp_parser_nested_name_specifier_opt): Likewise.
	(cp_parser_postfix_expression): Likewise.
	(cp_parser_unary_expression): Likewise.
	(cp_parser_template_name): Likewise.
	(cp_parser_class_name): Likewise.
	(cp_parser_lookup_name): Likewise.
	* pt.c (dependent_type_p): New function.
	(value_dependent_expression_p): Likewise.
	(type_dependent_expression_p): Likewise.
	(dependent_template_arg_p): Likewise.
	(dependent_template_id_p): Likewise.
	(dependent_template_p): Likewise.

	PR c++/9285
	PR c++/9294
	* parser.c (cp_parser_simple_declaration):

	PR c++/9285
	PR c++/9294
	* g++.dg/parse/expr2.C: New test.

	PR c++/9388
	* g++.dg/parse/lookup2.C: Likewise.

From-SVN: r61596
This commit is contained in:
Mark Mitchell 2003-01-22 17:39:15 +00:00 committed by Mark Mitchell
parent 4888ec5d53
commit 1fb3244aad
8 changed files with 391 additions and 313 deletions

View File

@ -1,3 +1,37 @@
2003-01-22 Mark Mitchell <mark@codesourcery.com>
PR c++/9388
* class.c (currently_open_derived_class): Use dependent_type_p.
* cp-tree.h (dependent_type_p): New function.
(dependent_template_arg_p): Likewise.
(dependent_template_p): Likewise.
(type_dependent_expression_p): Likewise.
* parser.c (cp_parser_dependent_type_p): Remove.
(cp_parser_value_dependent_type_p): Likewise.
(cp_parser_type_dependent_expression_p): Likewise.
(cp_parser_dependent_template_arg_p): Likewise.
(cp_parser_dependent_template_id_p): Likewise.
(cp_parser_dependent_template_p): Likewise.
(cp_parser_diagnose_invalid_type_name): Replace
cp_parser_dependent_type_p with dependent_type_p, etc.
(cp_parser_primary_expresion): Likewise.
(cp_parser_nested_name_specifier_opt): Likewise.
(cp_parser_postfix_expression): Likewise.
(cp_parser_unary_expression): Likewise.
(cp_parser_template_name): Likewise.
(cp_parser_class_name): Likewise.
(cp_parser_lookup_name): Likewise.
* pt.c (dependent_type_p): New function.
(value_dependent_expression_p): Likewise.
(type_dependent_expression_p): Likewise.
(dependent_template_arg_p): Likewise.
(dependent_template_id_p): Likewise.
(dependent_template_p): Likewise.
PR c++/9285
PR c++/9294
* parser.c (cp_parser_simple_declaration):
2003-01-21 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
Make-lang.in (cp/decl.o-warn): Add -Wno-error.

View File

@ -6001,6 +6001,10 @@ currently_open_derived_class (t)
{
int i;
/* The bases of a dependent type are unknown. */
if (dependent_type_p (t))
return NULL_TREE;
if (DERIVED_FROM_P (t, current_class_type))
return current_class_type;

View File

@ -4088,6 +4088,10 @@ extern void record_last_problematic_instantiation (void);
extern tree current_instantiation (void);
extern tree maybe_get_template_decl_from_type_decl (tree);
extern int processing_template_parmlist;
extern bool dependent_type_p (tree);
extern bool dependent_template_arg_p (tree);
extern bool dependent_template_p (tree);
extern bool type_dependent_expression_p (tree);
/* in repo.c */
extern void repo_template_used (tree);

View File

@ -1780,18 +1780,6 @@ static bool cp_parser_is_string_literal
PARAMS ((cp_token *));
static bool cp_parser_is_keyword
PARAMS ((cp_token *, enum rid));
static bool cp_parser_dependent_type_p
(tree);
static bool cp_parser_value_dependent_expression_p
(tree);
static bool cp_parser_type_dependent_expression_p
(tree);
static bool cp_parser_dependent_template_arg_p
(tree);
static bool cp_parser_dependent_template_id_p
(tree, tree);
static bool cp_parser_dependent_template_p
(tree);
static tree cp_parser_scope_through_which_access_occurs
(tree, tree, tree);
@ -1823,283 +1811,6 @@ cp_parser_is_keyword (token, keyword)
return token->keyword == keyword;
}
/* Returns TRUE if TYPE is dependent, in the sense of
[temp.dep.type]. */
static bool
cp_parser_dependent_type_p (type)
tree type;
{
tree scope;
if (!processing_template_decl)
return false;
/* If the type is NULL, we have not computed a type for the entity
in question; in that case, the type is dependent. */
if (!type)
return true;
/* Erroneous types can be considered non-dependent. */
if (type == error_mark_node)
return false;
/* [temp.dep.type]
A type is dependent if it is:
-- a template parameter. */
if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
return true;
/* -- a qualified-id with a nested-name-specifier which contains a
class-name that names a dependent type or whose unqualified-id
names a dependent type. */
if (TREE_CODE (type) == TYPENAME_TYPE)
return true;
/* -- a cv-qualified type where the cv-unqualified type is
dependent. */
type = TYPE_MAIN_VARIANT (type);
/* -- a compound type constructed from any dependent type. */
if (TYPE_PTRMEM_P (type) || TYPE_PTRMEMFUNC_P (type))
return (cp_parser_dependent_type_p (TYPE_PTRMEM_CLASS_TYPE (type))
|| cp_parser_dependent_type_p (TYPE_PTRMEM_POINTED_TO_TYPE
(type)));
else if (TREE_CODE (type) == POINTER_TYPE
|| TREE_CODE (type) == REFERENCE_TYPE)
return cp_parser_dependent_type_p (TREE_TYPE (type));
else if (TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE)
{
tree arg_type;
if (cp_parser_dependent_type_p (TREE_TYPE (type)))
return true;
for (arg_type = TYPE_ARG_TYPES (type);
arg_type;
arg_type = TREE_CHAIN (arg_type))
if (cp_parser_dependent_type_p (TREE_VALUE (arg_type)))
return true;
return false;
}
/* -- an array type constructed from any dependent type or whose
size is specified by a constant expression that is
value-dependent. */
if (TREE_CODE (type) == ARRAY_TYPE)
{
if (TYPE_DOMAIN (type)
&& ((cp_parser_value_dependent_expression_p
(TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
|| (cp_parser_type_dependent_expression_p
(TYPE_MAX_VALUE (TYPE_DOMAIN (type))))))
return true;
return cp_parser_dependent_type_p (TREE_TYPE (type));
}
/* -- a template-id in which either the template name is a template
parameter or any of the template arguments is a dependent type or
an expression that is type-dependent or value-dependent.
This language seems somewhat confused; for example, it does not
discuss template template arguments. Therefore, we use the
definition for dependent template arguments in [temp.dep.temp]. */
if (CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_INFO (type)
&& (cp_parser_dependent_template_id_p
(CLASSTYPE_TI_TEMPLATE (type),
CLASSTYPE_TI_ARGS (type))))
return true;
else if (TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
return true;
/* All TYPEOF_TYPEs are dependent; if the argument of the `typeof'
expression is not type-dependent, then it should already been
have resolved. */
if (TREE_CODE (type) == TYPEOF_TYPE)
return true;
/* The standard does not specifically mention types that are local
to template functions or local classes, but they should be
considered dependent too. For example:
template <int I> void f() {
enum E { a = I };
S<sizeof (E)> s;
}
The size of `E' cannot be known until the value of `I' has been
determined. Therefore, `E' must be considered dependent. */
scope = TYPE_CONTEXT (type);
if (scope && TYPE_P (scope))
return cp_parser_dependent_type_p (scope);
else if (scope && TREE_CODE (scope) == FUNCTION_DECL)
return cp_parser_type_dependent_expression_p (scope);
/* Other types are non-dependent. */
return false;
}
/* Returns TRUE if the EXPRESSION is value-dependent. */
static bool
cp_parser_value_dependent_expression_p (tree expression)
{
if (!processing_template_decl)
return false;
/* A name declared with a dependent type. */
if (DECL_P (expression)
&& cp_parser_dependent_type_p (TREE_TYPE (expression)))
return true;
/* A non-type template parameter. */
if ((TREE_CODE (expression) == CONST_DECL
&& DECL_TEMPLATE_PARM_P (expression))
|| TREE_CODE (expression) == TEMPLATE_PARM_INDEX)
return true;
/* A constant with integral or enumeration type and is initialized
with an expression that is value-dependent. */
if (TREE_CODE (expression) == VAR_DECL
&& DECL_INITIAL (expression)
&& (CP_INTEGRAL_TYPE_P (TREE_TYPE (expression))
|| TREE_CODE (TREE_TYPE (expression)) == ENUMERAL_TYPE)
&& cp_parser_value_dependent_expression_p (DECL_INITIAL (expression)))
return true;
/* These expressions are value-dependent if the type to which the
cast occurs is dependent. */
if ((TREE_CODE (expression) == DYNAMIC_CAST_EXPR
|| TREE_CODE (expression) == STATIC_CAST_EXPR
|| TREE_CODE (expression) == CONST_CAST_EXPR
|| TREE_CODE (expression) == REINTERPRET_CAST_EXPR
|| TREE_CODE (expression) == CAST_EXPR)
&& cp_parser_dependent_type_p (TREE_TYPE (expression)))
return true;
/* A `sizeof' expression where the sizeof operand is a type is
value-dependent if the type is dependent. If the type was not
dependent, we would no longer have a SIZEOF_EXPR, so any
SIZEOF_EXPR is dependent. */
if (TREE_CODE (expression) == SIZEOF_EXPR)
return true;
/* A constant expression is value-dependent if any subexpression is
value-dependent. */
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (expression))))
{
switch (TREE_CODE_CLASS (TREE_CODE (expression)))
{
case '1':
return (cp_parser_value_dependent_expression_p
(TREE_OPERAND (expression, 0)));
case '<':
case '2':
return ((cp_parser_value_dependent_expression_p
(TREE_OPERAND (expression, 0)))
|| (cp_parser_value_dependent_expression_p
(TREE_OPERAND (expression, 1))));
case 'e':
{
int i;
for (i = 0;
i < TREE_CODE_LENGTH (TREE_CODE (expression));
++i)
if (cp_parser_value_dependent_expression_p
(TREE_OPERAND (expression, i)))
return true;
return false;
}
}
}
/* The expression is not value-dependent. */
return false;
}
/* Returns TRUE if the EXPRESSION is type-dependent, in the sense of
[temp.dep.expr]. */
static bool
cp_parser_type_dependent_expression_p (expression)
tree expression;
{
if (!processing_template_decl)
return false;
/* Some expression forms are never type-dependent. */
if (TREE_CODE (expression) == PSEUDO_DTOR_EXPR
|| TREE_CODE (expression) == SIZEOF_EXPR
|| TREE_CODE (expression) == ALIGNOF_EXPR
|| TREE_CODE (expression) == TYPEID_EXPR
|| TREE_CODE (expression) == DELETE_EXPR
|| TREE_CODE (expression) == VEC_DELETE_EXPR
|| TREE_CODE (expression) == THROW_EXPR)
return false;
/* The types of these expressions depends only on the type to which
the cast occurs. */
if (TREE_CODE (expression) == DYNAMIC_CAST_EXPR
|| TREE_CODE (expression) == STATIC_CAST_EXPR
|| TREE_CODE (expression) == CONST_CAST_EXPR
|| TREE_CODE (expression) == REINTERPRET_CAST_EXPR
|| TREE_CODE (expression) == CAST_EXPR)
return cp_parser_dependent_type_p (TREE_TYPE (expression));
/* The types of these expressions depends only on the type created
by the expression. */
else if (TREE_CODE (expression) == NEW_EXPR
|| TREE_CODE (expression) == VEC_NEW_EXPR)
return cp_parser_dependent_type_p (TREE_OPERAND (expression, 1));
if (TREE_CODE (expression) == FUNCTION_DECL
&& DECL_LANG_SPECIFIC (expression)
&& DECL_TEMPLATE_INFO (expression)
&& (cp_parser_dependent_template_id_p
(DECL_TI_TEMPLATE (expression),
INNERMOST_TEMPLATE_ARGS (DECL_TI_ARGS (expression)))))
return true;
return (cp_parser_dependent_type_p (TREE_TYPE (expression)));
}
/* Returns TRUE if the ARG (a template argument) is dependent. */
static bool
cp_parser_dependent_template_arg_p (tree arg)
{
if (!processing_template_decl)
return false;
if (TREE_CODE (arg) == TEMPLATE_DECL
|| TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
return cp_parser_dependent_template_p (arg);
else if (TYPE_P (arg))
return cp_parser_dependent_type_p (arg);
else
return (cp_parser_type_dependent_expression_p (arg)
|| cp_parser_value_dependent_expression_p (arg));
}
/* Returns TRUE if the specialization TMPL<ARGS> is dependent. */
static bool
cp_parser_dependent_template_id_p (tree tmpl, tree args)
{
int i;
if (cp_parser_dependent_template_p (tmpl))
return true;
for (i = 0; i < TREE_VEC_LENGTH (args); ++i)
if (cp_parser_dependent_template_arg_p (TREE_VEC_ELT (args, i)))
return true;
return false;
}
/* Returns TRUE if the template TMPL is dependent. */
static bool
cp_parser_dependent_template_p (tree tmpl)
{
/* Template template parameters are dependent. */
if (DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)
|| TREE_CODE (tmpl) == TEMPLATE_TEMPLATE_PARM)
return true;
/* So are member templates of dependent classes. */
if (TYPE_P (CP_DECL_CONTEXT (tmpl)))
return cp_parser_dependent_type_p (DECL_CONTEXT (tmpl));
return false;
}
/* Returns the scope through which DECL is being accessed, or
NULL_TREE if DECL is not a member. If OBJECT_TYPE is non-NULL, we
have just seen `x->' or `x.' and OBJECT_TYPE is the type of `*x',
@ -2244,7 +1955,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser)
{
tree base_type = BINFO_TYPE (b);
if (CLASS_TYPE_P (base_type)
&& cp_parser_dependent_type_p (base_type))
&& dependent_type_p (base_type))
{
tree field;
/* Go from a particular instantiation of the
@ -2941,7 +2652,7 @@ cp_parser_primary_expression (cp_parser *parser,
its type. */
else if (!is_overloaded_fn (decl))
dependent_p
= cp_parser_dependent_type_p (TREE_TYPE (decl));
= dependent_type_p (TREE_TYPE (decl));
/* For a set of overloaded functions, check each of the
functions. */
else
@ -2961,8 +2672,7 @@ cp_parser_primary_expression (cp_parser *parser,
{
while (args)
{
if (cp_parser_dependent_template_arg_p
(TREE_VALUE (args)))
if (dependent_template_arg_p (TREE_VALUE (args)))
{
dependent_p = true;
break;
@ -2974,8 +2684,7 @@ cp_parser_primary_expression (cp_parser *parser,
{
int i;
for (i = 0; i < TREE_VEC_LENGTH (args); ++i)
if (cp_parser_dependent_template_arg_p
(TREE_VEC_ELT (args, i)))
if (dependent_template_arg_p (TREE_VEC_ELT (args, i)))
{
dependent_p = true;
break;
@ -2996,10 +2705,10 @@ cp_parser_primary_expression (cp_parser *parser,
/* Member functions of dependent classes are
dependent. */
if (TREE_CODE (fn) == FUNCTION_DECL
&& cp_parser_type_dependent_expression_p (fn))
&& type_dependent_expression_p (fn))
dependent_p = true;
else if (TREE_CODE (fn) == TEMPLATE_DECL
&& cp_parser_dependent_template_p (fn))
&& dependent_template_p (fn))
dependent_p = true;
fns = OVL_NEXT (fns);
@ -3611,7 +3320,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
avoid doing it if the type is already complete. */
&& !COMPLETE_TYPE_P (parser->scope)
/* Do not try to complete dependent types. */
&& !cp_parser_dependent_type_p (parser->scope))
&& !dependent_type_p (parser->scope))
complete_type (parser->scope);
}
@ -4160,7 +3869,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
Do Koenig lookup -- unless any of the arguments are
type-dependent. */
for (arg = args; arg; arg = TREE_CHAIN (arg))
if (cp_parser_type_dependent_expression_p (TREE_VALUE (arg)))
if (type_dependent_expression_p (TREE_VALUE (arg)))
break;
if (!arg)
{
@ -4244,8 +3953,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
postfix_expression = build_x_arrow (postfix_expression);
/* Check to see whether or not the expression is
type-dependent. */
dependent_p = (cp_parser_type_dependent_expression_p
(postfix_expression));
dependent_p = (type_dependent_expression_p (postfix_expression));
/* The identifier following the `->' or `.' is not
qualified. */
parser->scope = NULL_TREE;
@ -4554,8 +4262,8 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p)
/* If the type of the operand cannot be determined build a
SIZEOF_EXPR. */
if (TYPE_P (operand)
? cp_parser_dependent_type_p (operand)
: cp_parser_type_dependent_expression_p (operand))
? dependent_type_p (operand)
: type_dependent_expression_p (operand))
return build_min (SIZEOF_EXPR, size_type_node, operand);
/* Otherwise, compute the constant value. */
else
@ -6776,6 +6484,15 @@ cp_parser_simple_declaration (parser, function_definition_allowed_p)
function_definition_allowed_p,
/*member_p=*/false,
&function_definition_p);
/* If an error occurred while parsing tentatively, exit quickly.
(That usually happens when in the body of a function; each
statement is treated as a declaration-statement until proven
otherwise.) */
if (cp_parser_error_occurred (parser))
{
pop_deferring_access_checks ();
return;
}
/* Handle function definitions specially. */
if (function_definition_p)
{
@ -8344,7 +8061,7 @@ cp_parser_template_name (parser, template_keyword_p, check_dependency_p)
if (DECL_FUNCTION_TEMPLATE_P (decl) || !DECL_P (decl))
{
tree scope = CP_DECL_CONTEXT (get_first_fn (decl));
if (TYPE_P (scope) && cp_parser_dependent_type_p (scope))
if (TYPE_P (scope) && dependent_type_p (scope))
return identifier;
}
@ -11507,7 +11224,7 @@ cp_parser_class_name (cp_parser *parser,
/* Any name names a type if we're following the `typename' keyword
in a qualified name where the enclosing scope is type-dependent. */
typename_p = (typename_keyword_p && scope && TYPE_P (scope)
&& cp_parser_dependent_type_p (scope));
&& dependent_type_p (scope));
/* Handle the common case (an identifier, but not a template-id)
efficiently. */
if (token->type == CPP_NAME
@ -13456,7 +13173,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name, bool check_access,
/* Perform the lookup. */
if (parser->scope)
{
bool dependent_type_p;
bool dependent_p;
if (parser->scope == error_mark_node)
return error_mark_node;
@ -13466,12 +13183,12 @@ cp_parser_lookup_name (cp_parser *parser, tree name, bool check_access,
looking up names in uninstantiated templates. Even then, we
cannot look up the name if the scope is not a class type; it
might, for example, be a template type parameter. */
dependent_type_p = (TYPE_P (parser->scope)
&& !(parser->in_declarator_p
&& currently_open_class (parser->scope))
&& cp_parser_dependent_type_p (parser->scope));
dependent_p = (TYPE_P (parser->scope)
&& !(parser->in_declarator_p
&& currently_open_class (parser->scope))
&& dependent_type_p (parser->scope));
if ((check_dependency || !CLASS_TYPE_P (parser->scope))
&& dependent_type_p)
&& dependent_p)
{
if (!is_type)
decl = build_nt (SCOPE_REF, parser->scope, name);
@ -13490,7 +13207,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name, bool check_access,
otherwise, we would have processed this lookup above. So
that PARSER->SCOPE is not considered a dependent base by
lookup_member, we must enter the scope here. */
if (dependent_type_p)
if (dependent_p)
push_scope (parser->scope);
/* If the PARSER->SCOPE is a a template specialization, it
may be instantiated during name lookup. In that case,
@ -13498,7 +13215,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name, bool check_access,
tentative parse, those errors are valid. */
decl = lookup_qualified_name (parser->scope, name, is_type,
/*flags=*/0);
if (dependent_type_p)
if (dependent_p)
pop_scope (parser->scope);
}
parser->qualifying_scope = parser->scope;

View File

@ -171,6 +171,8 @@ static void copy_default_args_to_explicit_spec PARAMS ((tree));
static int invalid_nontype_parm_type_p PARAMS ((tree, tsubst_flags_t));
static int eq_local_specializations (const void *, const void *);
static tree template_for_substitution (tree);
static bool value_dependent_expression_p (tree);
static bool dependent_template_id_p (tree, tree);
/* Make the current scope suitable for access checking when we are
processing T. T can be FUNCTION_DECL for instantiated function
@ -11187,4 +11189,283 @@ invalid_nontype_parm_type_p (type, complain)
return 1;
}
/* Returns TRUE if TYPE is dependent, in the sense of
[temp.dep.type]. */
bool
dependent_type_p (type)
tree type;
{
tree scope;
/* If there are no template parameters in scope, then there can't be
any dependent types. */
if (!processing_template_decl)
return false;
/* If the type is NULL, we have not computed a type for the entity
in question; in that case, the type is dependent. */
if (!type)
return true;
/* Erroneous types can be considered non-dependent. */
if (type == error_mark_node)
return false;
/* [temp.dep.type]
A type is dependent if it is:
-- a template parameter. */
if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
return true;
/* -- a qualified-id with a nested-name-specifier which contains a
class-name that names a dependent type or whose unqualified-id
names a dependent type. */
if (TREE_CODE (type) == TYPENAME_TYPE)
return true;
/* -- a cv-qualified type where the cv-unqualified type is
dependent. */
type = TYPE_MAIN_VARIANT (type);
/* -- a compound type constructed from any dependent type. */
if (TYPE_PTRMEM_P (type) || TYPE_PTRMEMFUNC_P (type))
return (dependent_type_p (TYPE_PTRMEM_CLASS_TYPE (type))
|| dependent_type_p (TYPE_PTRMEM_POINTED_TO_TYPE
(type)));
else if (TREE_CODE (type) == POINTER_TYPE
|| TREE_CODE (type) == REFERENCE_TYPE)
return dependent_type_p (TREE_TYPE (type));
else if (TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE)
{
tree arg_type;
if (dependent_type_p (TREE_TYPE (type)))
return true;
for (arg_type = TYPE_ARG_TYPES (type);
arg_type;
arg_type = TREE_CHAIN (arg_type))
if (dependent_type_p (TREE_VALUE (arg_type)))
return true;
return false;
}
/* -- an array type constructed from any dependent type or whose
size is specified by a constant expression that is
value-dependent. */
if (TREE_CODE (type) == ARRAY_TYPE)
{
if (TYPE_DOMAIN (type)
&& ((value_dependent_expression_p
(TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
|| (type_dependent_expression_p
(TYPE_MAX_VALUE (TYPE_DOMAIN (type))))))
return true;
return dependent_type_p (TREE_TYPE (type));
}
/* -- a template-id in which either the template name is a template
parameter or any of the template arguments is a dependent type or
an expression that is type-dependent or value-dependent.
This language seems somewhat confused; for example, it does not
discuss template template arguments. Therefore, we use the
definition for dependent template arguments in [temp.dep.temp]. */
if (CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_INFO (type)
&& (dependent_template_id_p
(CLASSTYPE_TI_TEMPLATE (type),
CLASSTYPE_TI_ARGS (type))))
return true;
else if (TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
return true;
/* All TYPEOF_TYPEs are dependent; if the argument of the `typeof'
expression is not type-dependent, then it should already been
have resolved. */
if (TREE_CODE (type) == TYPEOF_TYPE)
return true;
/* The standard does not specifically mention types that are local
to template functions or local classes, but they should be
considered dependent too. For example:
template <int I> void f() {
enum E { a = I };
S<sizeof (E)> s;
}
The size of `E' cannot be known until the value of `I' has been
determined. Therefore, `E' must be considered dependent. */
scope = TYPE_CONTEXT (type);
if (scope && TYPE_P (scope))
return dependent_type_p (scope);
else if (scope && TREE_CODE (scope) == FUNCTION_DECL)
return type_dependent_expression_p (scope);
/* Other types are non-dependent. */
return false;
}
/* Returns TRUE if the EXPRESSION is value-dependent. */
static bool
value_dependent_expression_p (tree expression)
{
if (!processing_template_decl)
return false;
/* A name declared with a dependent type. */
if (DECL_P (expression)
&& dependent_type_p (TREE_TYPE (expression)))
return true;
/* A non-type template parameter. */
if ((TREE_CODE (expression) == CONST_DECL
&& DECL_TEMPLATE_PARM_P (expression))
|| TREE_CODE (expression) == TEMPLATE_PARM_INDEX)
return true;
/* A constant with integral or enumeration type and is initialized
with an expression that is value-dependent. */
if (TREE_CODE (expression) == VAR_DECL
&& DECL_INITIAL (expression)
&& (CP_INTEGRAL_TYPE_P (TREE_TYPE (expression))
|| TREE_CODE (TREE_TYPE (expression)) == ENUMERAL_TYPE)
&& value_dependent_expression_p (DECL_INITIAL (expression)))
return true;
/* These expressions are value-dependent if the type to which the
cast occurs is dependent. */
if ((TREE_CODE (expression) == DYNAMIC_CAST_EXPR
|| TREE_CODE (expression) == STATIC_CAST_EXPR
|| TREE_CODE (expression) == CONST_CAST_EXPR
|| TREE_CODE (expression) == REINTERPRET_CAST_EXPR
|| TREE_CODE (expression) == CAST_EXPR)
&& dependent_type_p (TREE_TYPE (expression)))
return true;
/* A `sizeof' expression where the sizeof operand is a type is
value-dependent if the type is dependent. If the type was not
dependent, we would no longer have a SIZEOF_EXPR, so any
SIZEOF_EXPR is dependent. */
if (TREE_CODE (expression) == SIZEOF_EXPR)
return true;
/* A constant expression is value-dependent if any subexpression is
value-dependent. */
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (expression))))
{
switch (TREE_CODE_CLASS (TREE_CODE (expression)))
{
case '1':
return (value_dependent_expression_p
(TREE_OPERAND (expression, 0)));
case '<':
case '2':
return ((value_dependent_expression_p
(TREE_OPERAND (expression, 0)))
|| (value_dependent_expression_p
(TREE_OPERAND (expression, 1))));
case 'e':
{
int i;
for (i = 0;
i < TREE_CODE_LENGTH (TREE_CODE (expression));
++i)
if (value_dependent_expression_p
(TREE_OPERAND (expression, i)))
return true;
return false;
}
}
}
/* The expression is not value-dependent. */
return false;
}
/* Returns TRUE if the EXPRESSION is type-dependent, in the sense of
[temp.dep.expr]. */
bool
type_dependent_expression_p (expression)
tree expression;
{
if (!processing_template_decl)
return false;
/* Some expression forms are never type-dependent. */
if (TREE_CODE (expression) == PSEUDO_DTOR_EXPR
|| TREE_CODE (expression) == SIZEOF_EXPR
|| TREE_CODE (expression) == ALIGNOF_EXPR
|| TREE_CODE (expression) == TYPEID_EXPR
|| TREE_CODE (expression) == DELETE_EXPR
|| TREE_CODE (expression) == VEC_DELETE_EXPR
|| TREE_CODE (expression) == THROW_EXPR)
return false;
/* The types of these expressions depends only on the type to which
the cast occurs. */
if (TREE_CODE (expression) == DYNAMIC_CAST_EXPR
|| TREE_CODE (expression) == STATIC_CAST_EXPR
|| TREE_CODE (expression) == CONST_CAST_EXPR
|| TREE_CODE (expression) == REINTERPRET_CAST_EXPR
|| TREE_CODE (expression) == CAST_EXPR)
return dependent_type_p (TREE_TYPE (expression));
/* The types of these expressions depends only on the type created
by the expression. */
else if (TREE_CODE (expression) == NEW_EXPR
|| TREE_CODE (expression) == VEC_NEW_EXPR)
return dependent_type_p (TREE_OPERAND (expression, 1));
if (TREE_CODE (expression) == FUNCTION_DECL
&& DECL_LANG_SPECIFIC (expression)
&& DECL_TEMPLATE_INFO (expression)
&& (dependent_template_id_p
(DECL_TI_TEMPLATE (expression),
INNERMOST_TEMPLATE_ARGS (DECL_TI_ARGS (expression)))))
return true;
return (dependent_type_p (TREE_TYPE (expression)));
}
/* Returns TRUE if the ARG (a template argument) is dependent. */
bool
dependent_template_arg_p (tree arg)
{
if (!processing_template_decl)
return false;
if (TREE_CODE (arg) == TEMPLATE_DECL
|| TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
return dependent_template_p (arg);
else if (TYPE_P (arg))
return dependent_type_p (arg);
else
return (type_dependent_expression_p (arg)
|| value_dependent_expression_p (arg));
}
/* Returns TRUE if the specialization TMPL<ARGS> is dependent. */
static bool
dependent_template_id_p (tree tmpl, tree args)
{
int i;
if (dependent_template_p (tmpl))
return true;
for (i = 0; i < TREE_VEC_LENGTH (args); ++i)
if (dependent_template_arg_p (TREE_VEC_ELT (args, i)))
return true;
return false;
}
/* Returns TRUE if the template TMPL is dependent. */
bool
dependent_template_p (tree tmpl)
{
/* Template template parameters are dependent. */
if (DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)
|| TREE_CODE (tmpl) == TEMPLATE_TEMPLATE_PARM)
return true;
/* So are member templates of dependent classes. */
if (TYPE_P (CP_DECL_CONTEXT (tmpl)))
return dependent_type_p (DECL_CONTEXT (tmpl));
return false;
}
#include "gt-cp-pt.h"

View File

@ -1,3 +1,12 @@
2003-01-22 Mark Mitchell <mark@codesourcery.com>
PR c++/9285
PR c++/9294
* g++.dg/parse/expr2.C: New test.
PR c++/9388
* g++.dg/parse/lookup2.C: Likewise.
Tue Jan 21 18:01:35 CET 2003 Jan Hubicka <jh@suse.cz>
* gcc.c-torture/execute/990208-1.c: Add noinline attributes as needed.

View File

@ -0,0 +1,8 @@
struct X {
X(double *data, double d0, double d1);
};
int foo(double d0) {
double * data;
X(data,d0,d0);
}

View File

@ -0,0 +1,21 @@
template <typename T> struct A
{
typedef int X;
};
template <typename T> struct B
{
typename A<T>::X x;
};
template <typename T> struct C
{
void foo(int);
B<A<T>*> b;
};
template <typename T> struct D
{
enum { e };
void bar() { C<T*>::foo(e); }
};