re PR c++/11493 (tree check ICE in error.c)

* cp-tree.h (cp_id_kind): New type.
	(unqualified_name_lookup_error): Change prototype.
	(unqualified_fn_lookup_error): New function.
	(do_identifier): Remove.
	(do_scoped_id): Likewise.
	(tsubst_copy_and_build): Change prototype.
	(reregister_specialization): New function.
	(perform_koenig_lookup): Likewise.
	(finish_id_expression): Likewise.
	* call.c (build_method_call): Adjust call to
	unqualified_name_lookup_error.
	* decl.c (duplicate_decls): Use reregister_specialization.
	* lex.c (is_global): Remove.
	(unqualified_name_lookup_error): Return a value.
	(do_identifier): Remove.
	(do_scoped_id): Likewise.
	(identifier_typedecl_value): Remove.
	(unqualified_fn_lookup_error): New function.
	* parser.c (cp_parser_id_kind): Remove.
	(cp_parser_non_constant_id_expression): Remove.
	(cp_parser_primary_expression): Use finish_id_expression.
	(cp_parser_class_or_namespace_name): Use cp_id_kind, not
	cp_parser_id_kind.
	(cp_parser_postfix_expression): Use perform_koenig_lookup.
	(cp_parser_template_argument): Use cp_id_kind.
	(cp_parser_fold_non_dependent_expr): Adjust call to
	tsubst_copy_and_build.
	* pt.c (unregister_specialization): Rename to ...
	(reregister_specialization): This.
	(tsubst_friend_function): Use it.
	(maybe_fold_nontype_arg): Adjust call to tsubst_copy_and_build.
	(tsubst_qualified_id): Likewise.
	(tsubst_expr): Likewise.
	(tsubst_copy_and_build): Add function_p parameter.  Use
	finish_id_expression.  Introduce RECUR macro.
	(tsubst_non_call_postfix_expression): New function.
	(regenerate_decl_from_template): Use reregister_specialization.
	* semantics.c (perform_koenig_lookup): New function.
	(finish_id_expression): Likewise.

	PR c++/11493
	PR c++/11495
	* g++.dg/parse/template9.C: Likewise.
	* g++.dg/template/crash4.C: New test.
	* g++.dg/template/koenig1.C: Likewise.
	* g++.old-deja/g++.benjamin/tem03.C: Adjust error markers.
	* g++.old-deja/g++.benjamin/tem06.C: Declare "x".
	* g++.old-deja/g++.jason/overload33.C: Use this-> when calling
	functions.
	* g++.old-deja/g++.jason/template36.C: Likewise.
	* g++.old-deja/g++.mike/p1989.C: Likewise.
	* g++.old-deja/g++.pt/lookup2.C: Use -fpermissive when compiling.
	* g++.old-deja/g++.pt/ttp20.C: Use this->.
	* g++.old-deja/g++.pt/ttp21.C: Use this->.
	* g++.old-deja/g++.pt/typename13.C: Use -fpermissive when
	compiling.
	* g++.old-deja/g++.pt/union2.C: Use this->.

From-SVN: r69316
This commit is contained in:
Mark Mitchell 2003-07-14 03:04:29 +00:00 committed by Mark Mitchell
parent f2ffecb112
commit b34459943b
22 changed files with 721 additions and 739 deletions

View File

@ -1,3 +1,45 @@
2003-07-13 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (cp_id_kind): New type.
(unqualified_name_lookup_error): Change prototype.
(unqualified_fn_lookup_error): New function.
(do_identifier): Remove.
(do_scoped_id): Likewise.
(tsubst_copy_and_build): Change prototype.
(reregister_specialization): New function.
(perform_koenig_lookup): Likewise.
(finish_id_expression): Likewise.
* call.c (build_method_call): Adjust call to
unqualified_name_lookup_error.
* decl.c (duplicate_decls): Use reregister_specialization.
* lex.c (is_global): Remove.
(unqualified_name_lookup_error): Return a value.
(do_identifier): Remove.
(do_scoped_id): Likewise.
(identifier_typedecl_value): Remove.
(unqualified_fn_lookup_error): New function.
* parser.c (cp_parser_id_kind): Remove.
(cp_parser_non_constant_id_expression): Remove.
(cp_parser_primary_expression): Use finish_id_expression.
(cp_parser_class_or_namespace_name): Use cp_id_kind, not
cp_parser_id_kind.
(cp_parser_postfix_expression): Use perform_koenig_lookup.
(cp_parser_template_argument): Use cp_id_kind.
(cp_parser_fold_non_dependent_expr): Adjust call to
tsubst_copy_and_build.
* pt.c (unregister_specialization): Rename to ...
(reregister_specialization): This.
(tsubst_friend_function): Use it.
(maybe_fold_nontype_arg): Adjust call to tsubst_copy_and_build.
(tsubst_qualified_id): Likewise.
(tsubst_expr): Likewise.
(tsubst_copy_and_build): Add function_p parameter. Use
finish_id_expression. Introduce RECUR macro.
(tsubst_non_call_postfix_expression): New function.
(regenerate_decl_from_template): Use reregister_specialization.
* semantics.c (perform_koenig_lookup): New function.
(finish_id_expression): Likewise.
2003-07-13 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
* pt.c (push_access_scope_real): Remove.

View File

@ -423,10 +423,7 @@ build_method_call (tree instance, tree name, tree parms,
/* If the name could not be found, issue an error. */
if (!fn)
{
unqualified_name_lookup_error (name);
return error_mark_node;
}
return unqualified_name_lookup_error (name);
if (BASELINK_P (fn) && has_template_args)
BASELINK_FUNCTIONS (fn)

View File

@ -350,6 +350,20 @@ struct tree_wrapper GTY(())
struct z_candidate *z_c;
};
/* The different kinds of ids that we ecounter. */
typedef enum cp_id_kind
{
/* Not an id at all. */
CP_ID_KIND_NONE,
/* An unqualified-id that is not a template-id. */
CP_ID_KIND_UNQUALIFIED,
/* An unqualified template-id. */
CP_ID_KIND_TEMPLATE_ID,
/* A qualified-id. */
CP_ID_KIND_QUALIFIED
} cp_id_kind;
/* Macros for access to language-specific slots in an identifier. */
#define IDENTIFIER_NAMESPACE_BINDINGS(NODE) \
@ -3883,10 +3897,8 @@ extern void snarf_method (tree);
extern void note_got_semicolon (tree);
extern void note_list_got_semicolon (tree);
extern void see_typename (void);
extern void unqualified_name_lookup_error (tree);
extern tree do_identifier (tree, tree);
extern tree do_scoped_id (tree, tree);
extern tree identifier_typedecl_value (tree);
extern tree unqualified_name_lookup_error (tree);
extern tree unqualified_fn_lookup_error (tree);
extern tree build_lang_decl (enum tree_code, tree, tree);
extern void retrofit_lang_decl (tree);
extern tree copy_decl (tree);
@ -3963,7 +3975,7 @@ extern tree most_specialized_instantiation (tree);
extern void print_candidates (tree);
extern int instantiate_pending_templates (void);
extern tree tsubst_default_argument (tree, tree, tree);
extern tree tsubst_copy_and_build (tree, tree, tsubst_flags_t, tree);
extern tree tsubst_copy_and_build (tree, tree, tsubst_flags_t, tree, bool);
extern tree most_general_template (tree);
extern tree get_mostly_instantiated_function_type (tree);
extern int problematic_instantiation_changed (void);
@ -3982,6 +3994,7 @@ extern tree resolve_typename_type (tree, bool);
extern tree template_for_substitution (tree);
extern tree build_non_dependent_expr (tree);
extern tree build_non_dependent_args (tree);
extern bool reregister_specialization (tree, tree, tree);
/* in repo.c */
extern void repo_template_used (tree);
@ -4111,6 +4124,7 @@ extern tree finish_parenthesized_expr (tree);
extern tree finish_non_static_data_member (tree, tree);
extern tree begin_stmt_expr (void);
extern tree finish_stmt_expr (tree);
extern tree perform_koenig_lookup (tree, tree);
extern tree finish_call_expr (tree, tree, bool);
extern tree finish_increment_expr (tree, enum tree_code);
extern tree finish_this_expr (void);
@ -4133,6 +4147,10 @@ extern tree finish_template_type (tree, tree, int);
extern tree finish_base_specifier (tree, tree, bool);
extern void finish_member_declaration (tree);
extern void check_multiple_declarators (void);
extern tree finish_id_expression (tree, tree, tree,
cp_id_kind *, tree *,
bool, bool, bool *,
const char **);
extern tree finish_typeof (tree);
extern tree finish_sizeof (tree);
extern tree finish_alignof (tree);

View File

@ -3558,36 +3558,30 @@ duplicate_decls (tree newdecl, tree olddecl)
function_size - sizeof (struct tree_common));
if (DECL_TEMPLATE_INSTANTIATION (newdecl))
{
/* If newdecl is a template instantiation, it is possible that
the following sequence of events has occurred:
/* If newdecl is a template instantiation, it is possible that
the following sequence of events has occurred:
o A friend function was declared in a class template. The
class template was instantiated.
o A friend function was declared in a class template. The
class template was instantiated.
o The instantiation of the friend declaration was
recorded on the instantiation list, and is newdecl.
o The instantiation of the friend declaration was
recorded on the instantiation list, and is newdecl.
o Later, however, instantiate_class_template called pushdecl
on the newdecl to perform name injection. But, pushdecl in
turn called duplicate_decls when it discovered that another
declaration of a global function with the same name already
existed.
o Later, however, instantiate_class_template called pushdecl
on the newdecl to perform name injection. But, pushdecl in
turn called duplicate_decls when it discovered that another
declaration of a global function with the same name already
existed.
o Here, in duplicate_decls, we decided to clobber newdecl.
o Here, in duplicate_decls, we decided to clobber newdecl.
If we're going to do that, we'd better make sure that
olddecl, and not newdecl, is on the list of
instantiations so that if we try to do the instantiation
again we won't get the clobbered declaration. */
tree tmpl = DECL_TI_TEMPLATE (newdecl);
tree decls = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
for (; decls; decls = TREE_CHAIN (decls))
if (TREE_VALUE (decls) == newdecl)
TREE_VALUE (decls) = olddecl;
}
If we're going to do that, we'd better make sure that
olddecl, and not newdecl, is on the list of
instantiations so that if we try to do the instantiation
again we won't get the clobbered declaration. */
reregister_specialization (newdecl,
DECL_TI_TEMPLATE (newdecl),
olddecl);
}
else
{

View File

@ -49,7 +49,6 @@ static void handle_pragma_interface (cpp_reader *);
static void handle_pragma_implementation (cpp_reader *);
static void handle_pragma_java_exceptions (cpp_reader *);
static int is_global (tree);
static void init_operators (void);
static void copy_lang_type (tree);
@ -662,30 +661,10 @@ handle_pragma_java_exceptions (cpp_reader* dfile ATTRIBUTE_UNUSED )
choose_personality_routine (lang_java);
}
/* Return true if d is in a global scope. */
static int
is_global (tree d)
{
while (1)
switch (TREE_CODE (d))
{
case ERROR_MARK:
return 1;
case OVERLOAD: d = OVL_FUNCTION (d); continue;
case TREE_LIST: d = TREE_VALUE (d); continue;
default:
my_friendly_assert (DECL_P (d), 980629);
return DECL_NAMESPACE_SCOPE_P (d);
}
}
/* Issue an error message indicating that the lookup of NAME (an
IDENTIFIER_NODE) failed. */
IDENTIFIER_NODE) failed. Returns the ERROR_MARK_NODE. */
void
tree
unqualified_name_lookup_error (tree name)
{
if (IDENTIFIER_OPNAME_P (name))
@ -714,164 +693,43 @@ unqualified_name_lookup_error (tree name)
SET_IDENTIFIER_NAMESPACE_VALUE (name, error_mark_node);
SET_IDENTIFIER_ERROR_LOCUS (name, current_function_decl);
}
return error_mark_node;
}
tree
do_identifier (register tree token, tree args)
{
register tree id;
timevar_push (TV_NAME_LOOKUP);
id = lookup_name (token, 0);
/* Do Koenig lookup if appropriate (inside templates we build lookup
expressions instead).
[basic.lookup.koenig]: If the ordinary unqualified lookup of the name
finds the declaration of a class member function, the associated
namespaces and classes are not considered. */
if (args && !current_template_parms && (!id || is_global (id)))
id = lookup_arg_dependent (token, id, args);
if (id == error_mark_node)
{
/* lookup_name quietly returns error_mark_node if we're parsing,
as we don't want to complain about an identifier that ends up
being used as a declarator. So we call it again to get the error
message. */
id = lookup_name (token, 0);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
if (!id || (TREE_CODE (id) == FUNCTION_DECL
&& DECL_ANTICIPATED (id)))
{
if (current_template_parms)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
build_min_nt (LOOKUP_EXPR, token));
else if (IDENTIFIER_TYPENAME_P (token))
/* A templated conversion operator might exist. */
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, token);
else
{
unqualified_name_lookup_error (token);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
}
id = check_for_out_of_scope_variable (id);
/* TREE_USED is set in `hack_identifier'. */
if (TREE_CODE (id) == CONST_DECL)
{
/* Check access. */
if (IDENTIFIER_CLASS_VALUE (token) == id)
perform_or_defer_access_check (TYPE_BINFO (DECL_CONTEXT (id)), id);
if (!processing_template_decl || DECL_TEMPLATE_PARM_P (id))
id = DECL_INITIAL (id);
}
else
id = hack_identifier (id, token);
/* We must look up dependent names when the template is
instantiated, not while parsing it. For now, we don't
distinguish between dependent and independent names. So, for
example, we look up all overloaded functions at
instantiation-time, even though in some cases we should just use
the DECL we have here. We also use LOOKUP_EXPRs to find things
like local variables, rather than creating TEMPLATE_DECLs for the
local variables and then finding matching instantiations. */
if (current_template_parms
&& (is_overloaded_fn (id)
|| (TREE_CODE (id) == VAR_DECL
&& CP_DECL_CONTEXT (id)
&& TREE_CODE (CP_DECL_CONTEXT (id)) == FUNCTION_DECL)
|| TREE_CODE (id) == PARM_DECL
|| TREE_CODE (id) == RESULT_DECL
|| TREE_CODE (id) == USING_DECL))
id = build_min_nt (LOOKUP_EXPR, token);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, id);
}
/* Like unqualified_name_lookup_error, but NAME is an unqualified-id
used as a function. Returns an appropriate expression for
NAME. */
tree
do_scoped_id (tree token, tree id)
unqualified_fn_lookup_error (tree name)
{
timevar_push (TV_NAME_LOOKUP);
if (!id || (TREE_CODE (id) == FUNCTION_DECL
&& DECL_ANTICIPATED (id)))
{
if (processing_template_decl)
{
id = build_min_nt (LOOKUP_EXPR, token);
LOOKUP_EXPR_GLOBAL (id) = 1;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, id);
}
if (IDENTIFIER_NAMESPACE_VALUE (token) != error_mark_node)
error ("`::%D' undeclared (first use here)", token);
id = error_mark_node;
/* Prevent repeated error messages. */
SET_IDENTIFIER_NAMESPACE_VALUE (token, error_mark_node);
}
else
{
if (TREE_CODE (id) == ADDR_EXPR)
mark_used (TREE_OPERAND (id, 0));
else if (TREE_CODE (id) != OVERLOAD)
mark_used (id);
}
if (TREE_CODE (id) == CONST_DECL && ! processing_template_decl)
{
/* XXX CHS - should we set TREE_USED of the constant? */
id = DECL_INITIAL (id);
/* This is to prevent an enum whose value is 0
from being considered a null pointer constant. */
id = build1 (NOP_EXPR, TREE_TYPE (id), id);
TREE_CONSTANT (id) = 1;
}
if (processing_template_decl)
{
if (is_overloaded_fn (id))
/* In a template, it is invalid to write "f()" or "f(3)" if no
declaration of "f" is available. Historically, G++ and most
other compilers accepted that usage; explain to the user what
is going wrong. */
(flag_permissive ? warning : error)
("there are no arguments to `%D' that depend on a template "
"parameter, so a declaration of `%D' must be available", name,
name);
if (!flag_permissive)
{
id = build_min_nt (LOOKUP_EXPR, token);
LOOKUP_EXPR_GLOBAL (id) = 1;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, id);
static bool hint;
if (!hint)
{
error ("(if you use `-fpermissive', G++ will accept your code, "
"but allowing the use of an undeclared name is "
"deprecated)");
hint = true;
}
}
/* else just use the decl */
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, convert_from_reference (id));
}
tree
identifier_typedecl_value (tree node)
{
tree t, type;
type = IDENTIFIER_TYPE_VALUE (node);
if (type == NULL_TREE)
return NULL_TREE;
if (IDENTIFIER_BINDING (node))
{
t = IDENTIFIER_VALUE (node);
if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type)
return t;
}
if (IDENTIFIER_NAMESPACE_VALUE (node))
{
t = IDENTIFIER_NAMESPACE_VALUE (node);
if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type)
return t;
return build_min_nt (LOOKUP_EXPR, name);
}
/* Will this one ever happen? */
if (TYPE_MAIN_DECL (type))
return TYPE_MAIN_DECL (type);
/* We used to do an internal error of 62 here, but instead we will
handle the return of a null appropriately in the callers. */
return NULL_TREE;
return unqualified_name_lookup_error (name);
}
#ifdef GATHER_STATISTICS

View File

@ -1047,20 +1047,6 @@ typedef enum cp_parser_flags
CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES = 0x2
} cp_parser_flags;
/* The different kinds of ids that we ecounter. */
typedef enum cp_parser_id_kind
{
/* Not an id at all. */
CP_PARSER_ID_KIND_NONE,
/* An unqualified-id that is not a template-id. */
CP_PARSER_ID_KIND_UNQUALIFIED,
/* An unqualified template-id. */
CP_PARSER_ID_KIND_TEMPLATE_ID,
/* A qualified-id. */
CP_PARSER_ID_KIND_QUALIFIED
} cp_parser_id_kind;
/* The different kinds of declarators we want to parse. */
typedef enum cp_parser_declarator_kind
@ -1311,7 +1297,7 @@ static bool cp_parser_translation_unit
/* Expressions [gram.expr] */
static tree cp_parser_primary_expression
(cp_parser *, cp_parser_id_kind *, tree *);
(cp_parser *, cp_id_kind *, tree *);
static tree cp_parser_id_expression
(cp_parser *, bool, bool, bool *);
static tree cp_parser_unqualified_id
@ -1695,8 +1681,6 @@ static void cp_parser_check_type_definition
(cp_parser *);
static tree cp_parser_non_constant_expression
(const char *);
static tree cp_parser_non_constant_id_expression
(tree);
static bool cp_parser_diagnose_invalid_type_name
(cp_parser *);
static int cp_parser_skip_to_closing_parenthesis
@ -1794,16 +1778,6 @@ cp_parser_non_constant_expression (const char *thing)
return error_mark_node;
}
/* Issue an eror message about the fact that DECL appeared in a
constant-expression. Returns ERROR_MARK_NODE. */
static tree
cp_parser_non_constant_id_expression (tree decl)
{
error ("`%D' cannot appear in a constant-expression", decl);
return error_mark_node;
}
/* Check for a common situation where a type-name should be present,
but is not, and issue a sensible error message. Returns true if an
invalid type-name was detected. */
@ -2215,13 +2189,13 @@ cp_parser_translation_unit (cp_parser* parser)
static tree
cp_parser_primary_expression (cp_parser *parser,
cp_parser_id_kind *idk,
cp_id_kind *idk,
tree *qualifying_class)
{
cp_token *token;
/* Assume the primary expression is not an id-expression. */
*idk = CP_PARSER_ID_KIND_NONE;
*idk = CP_ID_KIND_NONE;
/* And that it cannot be used as pointer-to-member. */
*qualifying_class = NULL_TREE;
@ -2397,6 +2371,7 @@ cp_parser_primary_expression (cp_parser *parser,
{
tree id_expression;
tree decl;
const char *error_msg;
id_expression:
/* Parse the id-expression. */
@ -2457,281 +2432,16 @@ cp_parser_primary_expression (cp_parser *parser,
return error_mark_node;
}
}
if (decl == error_mark_node)
{
/* Name lookup failed. */
if (!parser->scope
&& processing_template_decl)
{
/* Unqualified name lookup failed while processing a
template. */
*idk = CP_PARSER_ID_KIND_UNQUALIFIED;
/* If the next token is a parenthesis, assume that
Koenig lookup will succeed when instantiating the
template. */
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
return build_min_nt (LOOKUP_EXPR, id_expression);
/* If we're not doing Koenig lookup, issue an error. */
error ("`%D' has not been declared", id_expression);
return error_mark_node;
}
else if (parser->scope
&& (!TYPE_P (parser->scope)
|| !dependent_type_p (parser->scope)))
{
/* Qualified name lookup failed, and the
qualifying name was not a dependent type. That
is always an error. */
if (TYPE_P (parser->scope)
&& !COMPLETE_TYPE_P (parser->scope))
error ("incomplete type `%T' used in nested name "
"specifier",
parser->scope);
else if (parser->scope != global_namespace)
error ("`%D' is not a member of `%D'",
id_expression, parser->scope);
else
error ("`::%D' has not been declared", id_expression);
return error_mark_node;
}
else if (!parser->scope && !processing_template_decl)
{
/* It may be resolvable as a koenig lookup function
call. */
*idk = CP_PARSER_ID_KIND_UNQUALIFIED;
return id_expression;
}
}
/* If DECL is a variable that would be out of scope under
ANSI/ISO rules, but in scope in the ARM, name lookup
will succeed. Issue a diagnostic here. */
else
decl = check_for_out_of_scope_variable (decl);
/* Remember that the name was used in the definition of
the current class so that we can check later to see if
the meaning would have been different after the class
was entirely defined. */
if (!parser->scope && decl != error_mark_node)
maybe_note_name_used_in_class (id_expression, decl);
}
/* If we didn't find anything, or what we found was a type,
then this wasn't really an id-expression. */
if (TREE_CODE (decl) == TEMPLATE_DECL
&& !DECL_FUNCTION_TEMPLATE_P (decl))
{
cp_parser_error (parser, "missing template arguments");
return error_mark_node;
}
else if (TREE_CODE (decl) == TYPE_DECL
|| TREE_CODE (decl) == NAMESPACE_DECL)
{
cp_parser_error (parser,
"expected primary-expression");
return error_mark_node;
}
/* If the name resolved to a template parameter, there is no
need to look it up again later. Similarly, we resolve
enumeration constants to their underlying values. */
if (TREE_CODE (decl) == CONST_DECL)
{
*idk = CP_PARSER_ID_KIND_NONE;
if (DECL_TEMPLATE_PARM_P (decl) || !processing_template_decl)
return DECL_INITIAL (decl);
return decl;
}
else
{
bool dependent_p;
/* If the declaration was explicitly qualified indicate
that. The semantics of `A::f(3)' are different than
`f(3)' if `f' is virtual. */
*idk = (parser->scope
? CP_PARSER_ID_KIND_QUALIFIED
: (TREE_CODE (decl) == TEMPLATE_ID_EXPR
? CP_PARSER_ID_KIND_TEMPLATE_ID
: CP_PARSER_ID_KIND_UNQUALIFIED));
/* [temp.dep.expr]
An id-expression is type-dependent if it contains an
identifier that was declared with a dependent type.
As an optimization, we could choose not to create a
LOOKUP_EXPR for a name that resolved to a local
variable in the template function that we are currently
declaring; such a name cannot ever resolve to anything
else. If we did that we would not have to look up
these names at instantiation time.
The standard is not very specific about an
id-expression that names a set of overloaded functions.
What if some of them have dependent types and some of
them do not? Presumably, such a name should be treated
as a dependent name. */
/* Assume the name is not dependent. */
dependent_p = false;
if (!processing_template_decl)
/* No names are dependent outside a template. */
;
/* A template-id where the name of the template was not
resolved is definitely dependent. */
else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
&& (TREE_CODE (TREE_OPERAND (decl, 0))
== IDENTIFIER_NODE))
dependent_p = true;
/* For anything except an overloaded function, just check
its type. */
else if (!is_overloaded_fn (decl))
dependent_p
= dependent_type_p (TREE_TYPE (decl));
/* For a set of overloaded functions, check each of the
functions. */
else
{
tree fns = decl;
if (BASELINK_P (fns))
fns = BASELINK_FUNCTIONS (fns);
/* For a template-id, check to see if the template
arguments are dependent. */
if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
{
tree args = TREE_OPERAND (fns, 1);
dependent_p = any_dependent_template_arguments_p (args);
/* The functions are those referred to by the
template-id. */
fns = TREE_OPERAND (fns, 0);
}
/* If there are no dependent template arguments, go
through the overlaoded functions. */
while (fns && !dependent_p)
{
tree fn = OVL_CURRENT (fns);
/* Member functions of dependent classes are
dependent. */
if (TREE_CODE (fn) == FUNCTION_DECL
&& type_dependent_expression_p (fn))
dependent_p = true;
else if (TREE_CODE (fn) == TEMPLATE_DECL
&& dependent_template_p (fn))
dependent_p = true;
fns = OVL_NEXT (fns);
}
}
/* If the name was dependent on a template parameter,
we will resolve the name at instantiation time. */
if (dependent_p)
{
/* Create a SCOPE_REF for qualified names, if the
scope is dependent. */
if (parser->scope)
{
if (TYPE_P (parser->scope))
*qualifying_class = parser->scope;
/* Since this name was dependent, the expression isn't
constant -- yet. No error is issued because it
might be constant when things are instantiated. */
if (parser->constant_expression_p)
parser->non_constant_expression_p = true;
if (TYPE_P (parser->scope)
&& dependent_type_p (parser->scope))
return build_nt (SCOPE_REF,
parser->scope,
id_expression);
else if (TYPE_P (parser->scope)
&& DECL_P (decl))
return build (SCOPE_REF,
TREE_TYPE (decl),
parser->scope,
id_expression);
else
return decl;
}
/* A TEMPLATE_ID already contains all the information
we need. */
if (TREE_CODE (id_expression) == TEMPLATE_ID_EXPR)
return id_expression;
/* Since this name was dependent, the expression isn't
constant -- yet. No error is issued because it
might be constant when things are instantiated. */
if (parser->constant_expression_p)
parser->non_constant_expression_p = true;
/* Create a LOOKUP_EXPR for other unqualified names. */
return build_min_nt (LOOKUP_EXPR, id_expression);
}
/* Only certain kinds of names are allowed in constant
expression. Enumerators have already been handled
above. */
if (parser->constant_expression_p)
{
/* Non-type template parameters of integral or
enumeration type are OK. */
if (TREE_CODE (decl) == TEMPLATE_PARM_INDEX
&& INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl)))
;
/* Const variables or static data members of integral
or enumeration types initialized with constant
expressions are OK. We also accept dependent
initializers; they may turn out to be constant at
instantiation-time. */
else if (TREE_CODE (decl) == VAR_DECL
&& CP_TYPE_CONST_P (TREE_TYPE (decl))
&& INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl))
&& DECL_INITIAL (decl)
&& (TREE_CONSTANT (DECL_INITIAL (decl))
|| type_dependent_expression_p (DECL_INITIAL
(decl))
|| value_dependent_expression_p (DECL_INITIAL
(decl))))
;
else
{
if (!parser->allow_non_constant_expression_p)
return cp_parser_non_constant_id_expression (decl);
parser->non_constant_expression_p = true;
}
}
if (parser->scope)
{
decl = (adjust_result_of_qualified_name_lookup
(decl, parser->scope, current_class_type));
if (TREE_CODE (decl) == FIELD_DECL || BASELINK_P (decl))
*qualifying_class = parser->scope;
else if (!processing_template_decl)
decl = convert_from_reference (decl);
else if (TYPE_P (parser->scope))
decl = build (SCOPE_REF,
TREE_TYPE (decl),
parser->scope,
decl);
}
else
/* Transform references to non-static data members into
COMPONENT_REFs. */
decl = hack_identifier (decl, id_expression);
/* Resolve references to variables of anonymous unions
into COMPONENT_REFs. */
if (TREE_CODE (decl) == ALIAS_DECL)
decl = DECL_INITIAL (decl);
}
if (TREE_DEPRECATED (decl))
warn_deprecated_use (decl);
decl = finish_id_expression (id_expression, decl, parser->scope,
idk, qualifying_class,
parser->constant_expression_p,
parser->allow_non_constant_expression_p,
&parser->non_constant_expression_p,
&error_msg);
if (error_msg)
cp_parser_error (parser, error_msg);
return decl;
}
@ -3463,7 +3173,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
{
cp_token *token;
enum rid keyword;
cp_parser_id_kind idk = CP_PARSER_ID_KIND_NONE;
cp_id_kind idk = CP_ID_KIND_NONE;
tree postfix_expression = NULL_TREE;
/* Non-NULL only if the current postfix-expression can be used to
form a pointer-to-member. In that case, QUALIFYING_CLASS is the
@ -3730,11 +3440,9 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
{
if (TREE_CODE (postfix_expression) == IDENTIFIER_NODE
&& cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN))
{
/* It is not a Koenig lookup function call. */
unqualified_name_lookup_error (postfix_expression);
postfix_expression = error_mark_node;
}
/* It is not a Koenig lookup function call. */
postfix_expression
= unqualified_name_lookup_error (postfix_expression);
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
@ -3756,7 +3464,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
/* Build the ARRAY_REF. */
postfix_expression
= grok_array_decl (postfix_expression, index);
idk = CP_PARSER_ID_KIND_NONE;
idk = CP_ID_KIND_NONE;
}
break;
@ -3780,58 +3488,17 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
parser->non_constant_expression_p = true;
}
if (idk == CP_PARSER_ID_KIND_UNQUALIFIED
if (idk == CP_ID_KIND_UNQUALIFIED
&& (is_overloaded_fn (postfix_expression)
|| DECL_P (postfix_expression)
|| TREE_CODE (postfix_expression) == IDENTIFIER_NODE)
&& args)
{
tree identifier = NULL_TREE;
tree functions = NULL_TREE;
/* Find the name of the overloaded function. */
if (TREE_CODE (postfix_expression) == IDENTIFIER_NODE)
identifier = postfix_expression;
else if (is_overloaded_fn (postfix_expression))
{
functions = postfix_expression;
identifier = DECL_NAME (get_first_fn (functions));
}
else if (DECL_P (postfix_expression))
{
functions = postfix_expression;
identifier = DECL_NAME (postfix_expression);
}
/* A call to a namespace-scope function using an
unqualified name.
Do Koenig lookup -- unless any of the arguments are
type-dependent. */
if (!any_type_dependent_arguments_p (args))
{
postfix_expression
= lookup_arg_dependent (identifier, functions, args);
if (!postfix_expression)
{
/* The unqualified name could not be resolved. */
unqualified_name_lookup_error (identifier);
postfix_expression = error_mark_node;
break;
}
}
else
postfix_expression = build_min_nt (LOOKUP_EXPR,
identifier);
}
else if (idk == CP_PARSER_ID_KIND_UNQUALIFIED
postfix_expression
= perform_koenig_lookup (postfix_expression, args);
else if (idk == CP_ID_KIND_UNQUALIFIED
&& TREE_CODE (postfix_expression) == IDENTIFIER_NODE)
{
/* The unqualified name could not be resolved. */
unqualified_name_lookup_error (postfix_expression);
postfix_expression = error_mark_node;
break;
}
postfix_expression
= unqualified_fn_lookup_error (postfix_expression);
if (TREE_CODE (postfix_expression) == COMPONENT_REF)
{
@ -3853,7 +3520,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
postfix_expression
= (build_new_method_call
(instance, fn, args, NULL_TREE,
(idk == CP_PARSER_ID_KIND_QUALIFIED
(idk == CP_ID_KIND_QUALIFIED
? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL)));
}
else if (TREE_CODE (postfix_expression) == OFFSET_REF
@ -3861,7 +3528,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
|| TREE_CODE (postfix_expression) == DOTSTAR_EXPR)
postfix_expression = (build_offset_ref_call_from_tree
(postfix_expression, args));
else if (idk == CP_PARSER_ID_KIND_QUALIFIED)
else if (idk == CP_ID_KIND_QUALIFIED)
/* A call to a static class member, or a namespace-scope
function. */
postfix_expression
@ -3874,7 +3541,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
/*disallow_virtual=*/false);
/* The POSTFIX_EXPRESSION is certainly no longer an id. */
idk = CP_PARSER_ID_KIND_NONE;
idk = CP_ID_KIND_NONE;
}
break;
@ -3901,7 +3568,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
parser->scope = NULL_TREE;
parser->qualifying_scope = NULL_TREE;
parser->object_scope = NULL_TREE;
idk = CP_PARSER_ID_KIND_NONE;
idk = CP_ID_KIND_NONE;
/* Enter the scope corresponding to the type of the object
given by the POSTFIX_EXPRESSION. */
if (!dependent_p
@ -3969,7 +3636,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
/* But we do need to remember that there was an explicit
scope for virtual function calls. */
if (parser->scope)
idk = CP_PARSER_ID_KIND_QUALIFIED;
idk = CP_ID_KIND_QUALIFIED;
if (name != error_mark_node
&& !BASELINK_P (name)
@ -4019,7 +3686,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
postfix_expression
= finish_increment_expr (postfix_expression,
POSTINCREMENT_EXPR);
idk = CP_PARSER_ID_KIND_NONE;
idk = CP_ID_KIND_NONE;
break;
case CPP_MINUS_MINUS:
@ -4037,7 +3704,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
postfix_expression
= finish_increment_expr (postfix_expression,
POSTDECREMENT_EXPR);
idk = CP_PARSER_ID_KIND_NONE;
idk = CP_ID_KIND_NONE;
break;
default:
@ -8065,7 +7732,7 @@ cp_parser_template_argument (cp_parser* parser)
bool template_p;
bool address_p;
cp_token *token;
cp_parser_id_kind idk;
cp_id_kind idk;
tree qualifying_class;
/* There's really no way to know what we're looking at, so we just
@ -14184,7 +13851,8 @@ cp_parser_fold_non_dependent_expr (tree expr)
expr = tsubst_copy_and_build (expr,
/*args=*/NULL_TREE,
tf_error,
/*in_decl=*/NULL_TREE);
/*in_decl=*/NULL_TREE,
/*function_p=*/false);
processing_template_decl = saved_processing_template_decl;
}
return expr;

View File

@ -125,7 +125,6 @@ static tree retrieve_specialization (tree, tree);
static tree retrieve_local_specialization (tree);
static tree register_specialization (tree, tree, tree);
static void register_local_specialization (tree, tree);
static int unregister_specialization (tree, tree);
static tree reduce_template_parm_level (tree, tree, int);
static tree build_template_decl (tree, tree);
static int mark_template_parm (tree, void *);
@ -987,11 +986,11 @@ register_specialization (tree spec, tree tmpl, tree args)
}
/* Unregister the specialization SPEC as a specialization of TMPL.
Returns nonzero if the SPEC was listed as a specialization of
TMPL. */
Replace it with NEW_SPEC, if NEW_SPEC is non-NULL. Returns true
if the SPEC was listed as a specialization of TMPL. */
static int
unregister_specialization (tree spec, tree tmpl)
bool
reregister_specialization (tree spec, tree tmpl, tree new_spec)
{
tree* s;
@ -1000,7 +999,10 @@ unregister_specialization (tree spec, tree tmpl)
s = &TREE_CHAIN (*s))
if (TREE_VALUE (*s) == spec)
{
*s = TREE_CHAIN (*s);
if (!new_spec)
*s = TREE_CHAIN (*s);
else
TREE_VALUE (*s) == new_spec;
return 1;
}
@ -4910,8 +4912,17 @@ tsubst_friend_function (tree decl, tree args)
DECL_TEMPLATE_INFO (old_decl) = new_friend_template_info;
if (TREE_CODE (old_decl) != TEMPLATE_DECL)
/* duplicate_decls will take care of this case. */
;
{
tree t;
tree spec;
t = most_general_template (old_decl);
for (spec = DECL_TEMPLATE_SPECIALIZATIONS (t);
spec;
spec = TREE_CHAIN (spec))
if (TREE_VALUE (spec) == new_friend)
TREE_VALUE (spec) = old_decl;
}
else
{
tree t;
@ -5503,7 +5514,8 @@ maybe_fold_nontype_arg (tree arg)
arg = tsubst_copy_and_build (arg,
/*args=*/NULL_TREE,
tf_error,
/*in_decl=*/NULL_TREE);
/*in_decl=*/NULL_TREE,
/*function_p=*/false);
processing_template_decl = saved_processing_template_decl;
}
@ -7071,7 +7083,8 @@ tsubst_baselink (tree baselink, tree object_type,
template_args = TREE_OPERAND (fns, 1);
fns = TREE_OPERAND (fns, 0);
template_args = tsubst_copy_and_build (template_args, args,
complain, in_decl);
complain, in_decl,
/*function_p=*/false);
}
name = DECL_NAME (get_first_fn (fns));
baselink = lookup_fnfields (qualifying_scope, name, /*protect=*/1);
@ -7112,7 +7125,8 @@ tsubst_qualified_id (tree qualified_id, tree args,
{
is_template = true;
template_args = tsubst_copy_and_build (TREE_OPERAND (name, 1),
args, complain, in_decl);
args, complain, in_decl,
/*function_p=*/false);
name = TREE_OPERAND (name, 0);
}
else
@ -7549,7 +7563,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
return tsubst_copy (t, args, complain, in_decl);
if (!STATEMENT_CODE_P (TREE_CODE (t)))
return tsubst_copy_and_build (t, args, complain, in_decl);
return tsubst_copy_and_build (t, args, complain, in_decl,
/*function_p=*/false);
switch (TREE_CODE (t))
{
@ -7857,15 +7872,37 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
return tsubst_expr (TREE_CHAIN (t), args, complain, in_decl);
}
/* T is a postfix-expression that is not being used in a function
call. Return the substituted version of T. */
static tree
tsubst_non_call_postfix_expression (tree t, tree args,
tsubst_flags_t complain,
tree in_decl)
{
if (TREE_CODE (t) == SCOPE_REF)
t = tsubst_qualified_id (t, args, complain, in_decl,
/*done=*/false, /*address_p=*/false);
else
t = tsubst_copy_and_build (t, args, complain, in_decl,
/*function_p=*/false);
return t;
}
/* Like tsubst but deals with expressions and performs semantic
analysis. */
analysis. FUNCTION_P is true if T is the "F" in "F (ARGS)". */
tree
tsubst_copy_and_build (tree t,
tree args,
tsubst_flags_t complain,
tree in_decl)
tree in_decl,
bool function_p)
{
#define RECUR(NODE) \
tsubst_copy_and_build (NODE, args, complain, in_decl, /*function_p=*/false)
tree op1;
if (t == NULL_TREE || t == error_mark_node)
@ -7873,45 +7910,62 @@ tsubst_copy_and_build (tree t,
switch (TREE_CODE (t))
{
case IDENTIFIER_NODE:
if (IDENTIFIER_TYPENAME_P (t))
{
tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
return do_identifier (mangle_conv_op_name_for_type (new_type),
NULL_TREE);
}
else
return do_identifier (t, NULL_TREE);
case LOOKUP_EXPR:
case IDENTIFIER_NODE:
{
if (LOOKUP_EXPR_GLOBAL (t))
{
tree token
= tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
return do_scoped_id (token, IDENTIFIER_GLOBAL_VALUE (token));
}
tree decl;
tree scope;
cp_id_kind idk;
tree qualifying_class;
bool non_constant_expression_p;
const char *error_msg;
/* Remember whether this identifier was explicitly qualified
with "::". */
if (TREE_CODE (t) == LOOKUP_EXPR && LOOKUP_EXPR_GLOBAL (t))
scope = global_namespace;
else
scope = NULL_TREE;
/* Get at the underlying identifier. */
if (TREE_CODE (t) == LOOKUP_EXPR)
t = TREE_OPERAND (t, 0);
if (IDENTIFIER_TYPENAME_P (t))
{
t = do_identifier
(tsubst_copy
(TREE_OPERAND (t, 0), args, complain, in_decl),
NULL_TREE);
if (TREE_CODE (t) == ALIAS_DECL)
t = DECL_INITIAL (t);
return t;
tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
t = mangle_conv_op_name_for_type (new_type);
}
/* Look up the name. */
if (scope == global_namespace)
decl = IDENTIFIER_GLOBAL_VALUE (t);
else
decl = lookup_name (t, 0);
/* By convention, expressions use ERROR_MARK_NODE to indicate
failure, not NULL_TREE. */
if (decl == NULL_TREE)
decl = error_mark_node;
decl = finish_id_expression (t, decl, scope,
&idk,
&qualifying_class,
/*constant_expression_p=*/false,
/*allow_non_constant_expression_p=*/false,
&non_constant_expression_p,
&error_msg);
if (error_msg)
error (error_msg);
if (!function_p && TREE_CODE (decl) == IDENTIFIER_NODE)
decl = unqualified_name_lookup_error (decl);
return decl;
}
case TEMPLATE_ID_EXPR:
{
tree object;
tree template
= tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
in_decl);
tree targs
= tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
in_decl);
tree template = RECUR (TREE_OPERAND (t, 0));
tree targs = RECUR (TREE_OPERAND (t, 1));
if (TREE_CODE (template) == COMPONENT_REF)
{
@ -7930,46 +7984,37 @@ tsubst_copy_and_build (tree t,
}
case INDIRECT_REF:
return build_x_indirect_ref
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
"unary *");
return build_x_indirect_ref (RECUR (TREE_OPERAND (t, 0)), "unary *");
case CAST_EXPR:
return build_functional_cast
(tsubst (TREE_TYPE (t), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
RECUR (TREE_OPERAND (t, 0)));
case REINTERPRET_CAST_EXPR:
return build_reinterpret_cast
(tsubst (TREE_TYPE (t), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
RECUR (TREE_OPERAND (t, 0)));
case CONST_CAST_EXPR:
return build_const_cast
(tsubst (TREE_TYPE (t), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
RECUR (TREE_OPERAND (t, 0)));
case DYNAMIC_CAST_EXPR:
return build_dynamic_cast
(tsubst (TREE_TYPE (t), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
RECUR (TREE_OPERAND (t, 0)));
case STATIC_CAST_EXPR:
return build_static_cast
(tsubst (TREE_TYPE (t), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
RECUR (TREE_OPERAND (t, 0)));
case POSTDECREMENT_EXPR:
case POSTINCREMENT_EXPR:
op1 = TREE_OPERAND (t, 0);
if (TREE_CODE (op1) == SCOPE_REF)
op1 = tsubst_qualified_id (TREE_OPERAND (t, 0),
args, complain,
in_decl,
/*done=*/false,
/*address_p=*/false);
else
op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0),
args, complain, in_decl);
return build_x_unary_op (TREE_CODE (t), op1);
case PREDECREMENT_EXPR:
@ -7981,10 +8026,7 @@ tsubst_copy_and_build (tree t,
case CONVERT_EXPR: /* Unary + */
case REALPART_EXPR:
case IMAGPART_EXPR:
return (build_x_unary_op
(TREE_CODE (t),
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
in_decl)));
return build_x_unary_op (TREE_CODE (t), RECUR (TREE_OPERAND (t, 0)));
case ADDR_EXPR:
op1 = TREE_OPERAND (t, 0);
@ -7992,7 +8034,8 @@ tsubst_copy_and_build (tree t,
op1 = tsubst_qualified_id (op1, args, complain, in_decl,
/*done=*/true, /*address_p=*/true);
else
op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
op1 = tsubst_non_call_postfix_expression (op1, args, complain,
in_decl);
return build_x_unary_op (ADDR_EXPR, op1);
case PLUS_EXPR:
@ -8026,15 +8069,11 @@ tsubst_copy_and_build (tree t,
case LT_EXPR:
case GT_EXPR:
case MEMBER_REF:
case DOTSTAR_EXPR:
return build_x_binary_op
(TREE_CODE (t),
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl));
case DOTSTAR_EXPR:
return build_m_component_ref
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl));
RECUR (TREE_OPERAND (t, 0)),
RECUR (TREE_OPERAND (t, 1)));
case SCOPE_REF:
return tsubst_qualified_id (t, args, complain, in_decl, /*done=*/true,
@ -8044,24 +8083,14 @@ tsubst_copy_and_build (tree t,
if (tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl)
== NULL_TREE)
/* new-type-id */
return build_nt
(ARRAY_REF, NULL_TREE,
tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
in_decl));
return build_nt (ARRAY_REF, NULL_TREE, RECUR (TREE_OPERAND (t, 1)));
op1 = TREE_OPERAND (t, 0);
if (TREE_CODE (op1) == SCOPE_REF)
op1 = tsubst_qualified_id (op1, args, complain, in_decl,
/*done=*/false, /*address_p=*/false);
else
op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0),
args, complain, in_decl);
/* Remember that there was a reference to this entity. */
if (DECL_P (op1))
mark_used (op1);
return grok_array_decl (op1,
tsubst_copy_and_build (TREE_OPERAND (t, 1),
args, complain,
in_decl));
return grok_array_decl (op1, RECUR (TREE_OPERAND (t, 1)));
case SIZEOF_EXPR:
case ALIGNOF_EXPR:
@ -8077,7 +8106,7 @@ tsubst_copy_and_build (tree t,
else
{
++skip_evaluation;
op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
op1 = RECUR (op1);
--skip_evaluation;
}
if (TREE_CODE (t) == SIZEOF_EXPR)
@ -8087,17 +8116,13 @@ tsubst_copy_and_build (tree t,
case MODOP_EXPR:
return build_x_modify_expr
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
(RECUR (TREE_OPERAND (t, 0)),
TREE_CODE (TREE_OPERAND (t, 1)),
tsubst_copy_and_build (TREE_OPERAND (t, 2), args, complain, in_decl));
RECUR (TREE_OPERAND (t, 2)));
case ARROW_EXPR:
op1 = TREE_OPERAND (t, 0);
if (TREE_CODE (op1) == SCOPE_REF)
op1 = tsubst_qualified_id (op1, args, complain, in_decl,
/*done=*/false, /*address_p=*/false);
else
op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0),
args, complain, in_decl);
/* Remember that there was a reference to this entity. */
if (DECL_P (op1))
mark_used (op1);
@ -8105,38 +8130,29 @@ tsubst_copy_and_build (tree t,
case NEW_EXPR:
return build_new
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 2), args, complain, in_decl),
(RECUR (TREE_OPERAND (t, 0)),
RECUR (TREE_OPERAND (t, 1)),
RECUR (TREE_OPERAND (t, 2)),
NEW_EXPR_USE_GLOBAL (t));
case DELETE_EXPR:
return delete_sanity
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl),
(RECUR (TREE_OPERAND (t, 0)),
RECUR (TREE_OPERAND (t, 1)),
DELETE_EXPR_USE_VEC (t),
DELETE_EXPR_USE_GLOBAL (t));
case COMPOUND_EXPR:
return (build_x_compound_expr
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
in_decl)));
return build_x_compound_expr (RECUR (TREE_OPERAND (t, 0)),
RECUR (TREE_OPERAND (t, 1)));
case CALL_EXPR:
{
tree function;
tree call_args;
tree koenig_name;
bool qualified_p;
function = TREE_OPERAND (t, 0);
if (TREE_CODE (function) == LOOKUP_EXPR
&& !LOOKUP_EXPR_GLOBAL (function))
koenig_name = TREE_OPERAND (function, 0);
else
koenig_name = NULL_TREE;
if (TREE_CODE (function) == SCOPE_REF)
{
qualified_p = true;
@ -8150,24 +8166,32 @@ tsubst_copy_and_build (tree t,
&& (TREE_CODE (TREE_OPERAND (function, 1))
== SCOPE_REF));
function = tsubst_copy_and_build (function, args, complain,
in_decl);
function = convert_from_reference (function);
in_decl,
!qualified_p);
}
call_args = RECUR (TREE_OPERAND (t, 1));
if (BASELINK_P (function))
qualified_p = 1;
if (!qualified_p
&& TREE_CODE (function) != TEMPLATE_ID_EXPR
&& (is_overloaded_fn (function)
|| DECL_P (function)
|| TREE_CODE (function) == IDENTIFIER_NODE))
{
if (call_args)
function = perform_koenig_lookup (function, call_args);
else if (TREE_CODE (function) == IDENTIFIER_NODE)
function = unqualified_name_lookup_error (function);
}
/* Remember that there was a reference to this entity. */
if (DECL_P (function))
mark_used (function);
call_args = tsubst_copy_and_build (TREE_OPERAND (t, 1), args,
complain, in_decl);
if (BASELINK_P (function))
qualified_p = 1;
if (call_args != NULL_TREE && koenig_name)
function = lookup_arg_dependent (koenig_name,
function,
call_args);
function = convert_from_reference (function);
if (TREE_CODE (function) == OFFSET_REF)
return build_offset_ref_call_from_tree (function, call_args);
@ -8183,15 +8207,15 @@ tsubst_copy_and_build (tree t,
case COND_EXPR:
return build_x_conditional_expr
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 2), args, complain, in_decl));
(RECUR (TREE_OPERAND (t, 0)),
RECUR (TREE_OPERAND (t, 1)),
RECUR (TREE_OPERAND (t, 2)));
case PSEUDO_DTOR_EXPR:
return finish_pseudo_destructor_expr
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 2), args, complain, in_decl));
(RECUR (TREE_OPERAND (t, 0)),
RECUR (TREE_OPERAND (t, 1)),
RECUR (TREE_OPERAND (t, 2)));
case TREE_LIST:
{
@ -8202,13 +8226,13 @@ tsubst_copy_and_build (tree t,
purpose = TREE_PURPOSE (t);
if (purpose)
purpose = tsubst_copy_and_build (purpose, args, complain, in_decl);
purpose = RECUR (purpose);
value = TREE_VALUE (t);
if (value)
value = tsubst_copy_and_build (value, args, complain, in_decl);
value = RECUR (value);
chain = TREE_CHAIN (t);
if (chain && chain != void_type_node)
chain = tsubst_copy_and_build (chain, args, complain, in_decl);
chain = RECUR (chain);
if (purpose == TREE_PURPOSE (t)
&& value == TREE_VALUE (t)
&& chain == TREE_CHAIN (t))
@ -8221,13 +8245,8 @@ tsubst_copy_and_build (tree t,
tree object;
tree member;
object = TREE_OPERAND (t, 0);
if (TREE_CODE (object) == SCOPE_REF)
object = tsubst_qualified_id (object, args, complain, in_decl,
/*done=*/false, /*address_p=*/false);
else
object = tsubst_copy_and_build (object, args, complain, in_decl);
object = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0),
args, complain, in_decl);
/* Remember that there was a reference to this entity. */
if (DECL_P (object))
mark_used (object);
@ -8282,7 +8301,7 @@ tsubst_copy_and_build (tree t,
case THROW_EXPR:
return build_throw
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
(RECUR (TREE_OPERAND (t, 0)));
case CONSTRUCTOR:
{
@ -8308,9 +8327,8 @@ tsubst_copy_and_build (tree t,
tree value = TREE_VALUE (elts);
if (purpose && purpose_p)
purpose
= tsubst_copy_and_build (purpose, args, complain, in_decl);
value = tsubst_copy_and_build (value, args, complain, in_decl);
purpose = RECUR (purpose);
value = RECUR (value);
r = tree_cons (purpose, value, r);
}
@ -8324,10 +8342,7 @@ tsubst_copy_and_build (tree t,
case TYPEID_EXPR:
{
tree operand_0
= tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
in_decl);
tree operand_0 = RECUR (TREE_OPERAND (t, 0));
if (TYPE_P (operand_0))
return get_typeid (operand_0);
return build_typeid (operand_0);
@ -8347,14 +8362,15 @@ tsubst_copy_and_build (tree t,
return convert_from_reference (t);
case VA_ARG_EXPR:
return build_x_va_arg
(tsubst_copy_and_build
(TREE_OPERAND (t, 0), args, complain, in_decl),
tsubst_copy (TREE_TYPE (t), args, complain, in_decl));
return build_x_va_arg (RECUR (TREE_OPERAND (t, 0)),
tsubst_copy (TREE_TYPE (t), args, complain,
in_decl));
default:
return tsubst_copy (t, args, complain, in_decl);
}
#undef RECUR
}
/* Verify that the instantiated ARGS are valid. For type arguments,
@ -10576,7 +10592,7 @@ regenerate_decl_from_template (tree decl, tree tmpl)
tree args;
tree code_pattern;
tree new_decl;
int unregistered;
bool unregistered;
args = DECL_TI_ARGS (decl);
code_pattern = DECL_TEMPLATE_RESULT (tmpl);
@ -10587,7 +10603,8 @@ regenerate_decl_from_template (tree decl, tree tmpl)
instantiation of a specialization, which it isn't: it's a full
instantiation. */
gen_tmpl = most_general_template (tmpl);
unregistered = unregister_specialization (decl, gen_tmpl);
unregistered = reregister_specialization (decl, gen_tmpl,
/*new_spec=*/NULL_TREE);
/* If the DECL was not unregistered then something peculiar is
happening: we created a specialization but did not call

View File

@ -1473,6 +1473,47 @@ finish_stmt_expr (tree rtl_expr)
return result;
}
/* Perform Koenig lookup. FN is the postfix-expression representing
the call; ARGS are the arguments to the call. Returns the
functions to be considered by overload resolution. */
tree
perform_koenig_lookup (tree fn, tree args)
{
tree identifier = NULL_TREE;
tree functions = NULL_TREE;
/* Find the name of the overloaded function. */
if (TREE_CODE (fn) == IDENTIFIER_NODE)
identifier = fn;
else if (is_overloaded_fn (fn))
{
functions = fn;
identifier = DECL_NAME (get_first_fn (functions));
}
else if (DECL_P (fn))
{
functions = fn;
identifier = DECL_NAME (fn);
}
/* A call to a namespace-scope function using an unqualified name.
Do Koenig lookup -- unless any of the arguments are
type-dependent. */
if (!any_type_dependent_arguments_p (args))
{
fn = lookup_arg_dependent (identifier, functions, args);
if (!fn)
/* The unqualified name could not be resolved. */
fn = unqualified_fn_lookup_error (identifier);
}
else
fn = build_min_nt (LOOKUP_EXPR, identifier);
return fn;
}
/* Generate an expression for `FN (ARGS)'.
If DISALLOW_VIRTUAL is true, the call to FN will be not generated
@ -2191,6 +2232,306 @@ check_multiple_declarators (void)
error ("multiple declarators in template declaration");
}
/* ID_EXPRESSION is a representation of parsed, but unprocessed,
id-expression. (See cp_parser_id_expression for details.) SCOPE,
if non-NULL, is the type or namespace used to explicitly qualify
ID_EXPRESSION. DECL is the entity to which that name has been
resolved.
*CONSTANT_EXPRESSION_P is true if we are presently parsing a
constant-expression. In that case, *NON_CONSTANT_EXPRESSION_P will
be set to true if this expression isn't permitted in a
constant-expression, but it is otherwise not set by this function.
*ALLOW_NON_CONSTANT_EXPRESSION_P is true if we are parsing a
constant-expression, but a non-constant expression is also
permissible.
If an error occurs, and it is the kind of error that might cause
the parser to abort a tentative parse, *ERROR_MSG is filled in. It
is the caller's responsibility to issue the message. *ERROR_MSG
will be a string with static storage duration, so the caller need
not "free" it.
Return an expression for the entity, after issuing appropriate
diagnostics. This function is also responsible for transforming a
reference to a non-static member into a COMPONENT_REF that makes
the use of "this" explicit.
Upon return, *IDK will be filled in appropriately. */
tree
finish_id_expression (tree id_expression,
tree decl,
tree scope,
cp_id_kind *idk,
tree *qualifying_class,
bool constant_expression_p,
bool allow_non_constant_expression_p,
bool *non_constant_expression_p,
const char **error_msg)
{
/* Initialize the output parameters. */
*idk = CP_ID_KIND_NONE;
*error_msg = NULL;
if (id_expression == error_mark_node)
return error_mark_node;
/* If we have a template-id, then no further lookup is
required. If the template-id was for a template-class, we
will sometimes have a TYPE_DECL at this point. */
else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
|| TREE_CODE (decl) == TYPE_DECL)
;
/* Look up the name. */
else
{
if (decl == error_mark_node)
{
/* Name lookup failed. */
if (scope && (!TYPE_P (scope) || !dependent_type_p (scope)))
{
/* Qualified name lookup failed, and the qualifying name
was not a dependent type. That is always an
error. */
if (TYPE_P (scope) && !COMPLETE_TYPE_P (scope))
error ("incomplete type `%T' used in nested name "
"specifier",
scope);
else if (scope != global_namespace)
error ("`%D' is not a member of `%D'",
id_expression, scope);
else
error ("`::%D' has not been declared", id_expression);
return error_mark_node;
}
else if (!scope)
{
/* It may be resolved via Koenig lookup. */
*idk = CP_ID_KIND_UNQUALIFIED;
return id_expression;
}
}
/* If DECL is a variable that would be out of scope under
ANSI/ISO rules, but in scope in the ARM, name lookup
will succeed. Issue a diagnostic here. */
else
decl = check_for_out_of_scope_variable (decl);
/* Remember that the name was used in the definition of
the current class so that we can check later to see if
the meaning would have been different after the class
was entirely defined. */
if (!scope && decl != error_mark_node)
maybe_note_name_used_in_class (id_expression, decl);
}
/* If we didn't find anything, or what we found was a type,
then this wasn't really an id-expression. */
if (TREE_CODE (decl) == TEMPLATE_DECL
&& !DECL_FUNCTION_TEMPLATE_P (decl))
{
*error_msg = "missing template arguments";
return error_mark_node;
}
else if (TREE_CODE (decl) == TYPE_DECL
|| TREE_CODE (decl) == NAMESPACE_DECL)
{
*error_msg = "expected primary-expression";
return error_mark_node;
}
/* If the name resolved to a template parameter, there is no
need to look it up again later. Similarly, we resolve
enumeration constants to their underlying values. */
if (TREE_CODE (decl) == CONST_DECL)
{
*idk = CP_ID_KIND_NONE;
if (DECL_TEMPLATE_PARM_P (decl) || !processing_template_decl)
return DECL_INITIAL (decl);
return decl;
}
else
{
bool dependent_p;
/* If the declaration was explicitly qualified indicate
that. The semantics of `A::f(3)' are different than
`f(3)' if `f' is virtual. */
*idk = (scope
? CP_ID_KIND_QUALIFIED
: (TREE_CODE (decl) == TEMPLATE_ID_EXPR
? CP_ID_KIND_TEMPLATE_ID
: CP_ID_KIND_UNQUALIFIED));
/* [temp.dep.expr]
An id-expression is type-dependent if it contains an
identifier that was declared with a dependent type.
As an optimization, we could choose not to create a
LOOKUP_EXPR for a name that resolved to a local variable in
the template function that we are currently declaring; such a
name cannot ever resolve to anything else. If we did that we
would not have to look up these names at instantiation time.
The standard is not very specific about an id-expression that
names a set of overloaded functions. What if some of them
have dependent types and some of them do not? Presumably,
such a name should be treated as a dependent name. */
/* Assume the name is not dependent. */
dependent_p = false;
if (!processing_template_decl)
/* No names are dependent outside a template. */
;
/* A template-id where the name of the template was not resolved
is definitely dependent. */
else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
&& (TREE_CODE (TREE_OPERAND (decl, 0))
== IDENTIFIER_NODE))
dependent_p = true;
/* For anything except an overloaded function, just check its
type. */
else if (!is_overloaded_fn (decl))
dependent_p
= dependent_type_p (TREE_TYPE (decl));
/* For a set of overloaded functions, check each of the
functions. */
else
{
tree fns = decl;
if (BASELINK_P (fns))
fns = BASELINK_FUNCTIONS (fns);
/* For a template-id, check to see if the template
arguments are dependent. */
if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
{
tree args = TREE_OPERAND (fns, 1);
dependent_p = any_dependent_template_arguments_p (args);
/* The functions are those referred to by the
template-id. */
fns = TREE_OPERAND (fns, 0);
}
/* If there are no dependent template arguments, go through
the overlaoded functions. */
while (fns && !dependent_p)
{
tree fn = OVL_CURRENT (fns);
/* Member functions of dependent classes are
dependent. */
if (TREE_CODE (fn) == FUNCTION_DECL
&& type_dependent_expression_p (fn))
dependent_p = true;
else if (TREE_CODE (fn) == TEMPLATE_DECL
&& dependent_template_p (fn))
dependent_p = true;
fns = OVL_NEXT (fns);
}
}
/* If the name was dependent on a template parameter, we will
resolve the name at instantiation time. */
if (dependent_p)
{
/* Create a SCOPE_REF for qualified names, if the scope is
dependent. */
if (scope)
{
if (TYPE_P (scope))
*qualifying_class = scope;
/* Since this name was dependent, the expression isn't
constant -- yet. No error is issued because it might
be constant when things are instantiated. */
if (constant_expression_p)
*non_constant_expression_p = true;
if (TYPE_P (scope) && dependent_type_p (scope))
return build_nt (SCOPE_REF, scope, id_expression);
else if (TYPE_P (scope) && DECL_P (decl))
return build (SCOPE_REF, TREE_TYPE (decl), scope,
id_expression);
else
return decl;
}
/* A TEMPLATE_ID already contains all the information we
need. */
if (TREE_CODE (id_expression) == TEMPLATE_ID_EXPR)
return id_expression;
/* Since this name was dependent, the expression isn't
constant -- yet. No error is issued because it might be
constant when things are instantiated. */
if (constant_expression_p)
*non_constant_expression_p = true;
/* Create a LOOKUP_EXPR for other unqualified names. */
return build_min_nt (LOOKUP_EXPR, id_expression);
}
/* Only certain kinds of names are allowed in constant
expression. Enumerators have already been handled above. */
if (constant_expression_p)
{
/* Non-type template parameters of integral or enumeration
type are OK. */
if (TREE_CODE (decl) == TEMPLATE_PARM_INDEX
&& INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl)))
;
/* Const variables or static data members of integral or
enumeration types initialized with constant expressions
are OK. We also accept dependent initializers; they may
turn out to be constant at instantiation-time. */
else if (TREE_CODE (decl) == VAR_DECL
&& CP_TYPE_CONST_P (TREE_TYPE (decl))
&& INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl))
&& DECL_INITIAL (decl)
&& (TREE_CONSTANT (DECL_INITIAL (decl))
|| type_dependent_expression_p (DECL_INITIAL
(decl))
|| value_dependent_expression_p (DECL_INITIAL
(decl))))
;
else
{
if (!allow_non_constant_expression_p)
{
error ("`%D' cannot appear in a constant-expression", decl);
return error_mark_node;
}
*non_constant_expression_p = true;
}
}
if (scope)
{
decl = (adjust_result_of_qualified_name_lookup
(decl, scope, current_class_type));
if (TREE_CODE (decl) == FIELD_DECL || BASELINK_P (decl))
*qualifying_class = scope;
else if (!processing_template_decl)
decl = convert_from_reference (decl);
else if (TYPE_P (scope))
decl = build (SCOPE_REF, TREE_TYPE (decl), scope, decl);
}
else
/* Transform references to non-static data members into
COMPONENT_REFs. */
decl = hack_identifier (decl, id_expression);
/* Resolve references to variables of anonymous unions
into COMPONENT_REFs. */
if (TREE_CODE (decl) == ALIAS_DECL)
decl = DECL_INITIAL (decl);
}
if (TREE_DEPRECATED (decl))
warn_deprecated_use (decl);
return decl;
}
/* Implement the __typeof keyword: Return the type of EXPR, suitable for
use as a type-specifier. */

View File

@ -1,3 +1,23 @@
2003-07-13 Mark Mitchell <mark@codesourcery.com>
PR c++/11493
PR c++/11495
* g++.dg/parse/template9.C: Likewise.
* g++.dg/template/crash4.C: New test.
* g++.dg/template/koenig1.C: Likewise.
* g++.old-deja/g++.benjamin/tem03.C: Adjust error markers.
* g++.old-deja/g++.benjamin/tem06.C: Declare "x".
* g++.old-deja/g++.jason/overload33.C: Use this-> when calling
functions.
* g++.old-deja/g++.jason/template36.C: Likewise.
* g++.old-deja/g++.mike/p1989.C: Likewise.
* g++.old-deja/g++.pt/lookup2.C: Use -fpermissive when compiling.
* g++.old-deja/g++.pt/ttp20.C: Use this->.
* g++.old-deja/g++.pt/ttp21.C: Use this->.
* g++.old-deja/g++.pt/typename13.C: Use -fpermissive when
compiling.
* g++.old-deja/g++.pt/union2.C: Use this->.
2003-07-11 Jakub Jelinek <jakub@redhat.com>
* gcc.dg/20030711-1.c: New test.

View File

@ -0,0 +1,5 @@
template <typename T>
void f() {
g(); // { dg-error "" }
h(3); // { dg-error "" }
}

View File

@ -0,0 +1,12 @@
namespace NS {
struct C {};
void foo();
}
template <class T> struct X {};
template <class T> struct A {
A() { foo (X<T>()); }
void foo(X<T>);
};
template struct A<NS::C>;

View File

@ -0,0 +1,8 @@
namespace NS {
struct C {};
void foo(C);
}
template <class T> void bar() { T t; foo (t); }
template void bar<NS::C> ();

View File

@ -195,7 +195,7 @@ struct Xthirteen {
if (local_value > value) // { dg-error "" } .*
return local_value;
else
return value; // { dg-error "" } .*
return value;
}
};

View File

@ -14,6 +14,8 @@ public:
friend void x (const T &) { }
};
void x(const int &);
template<class T>
void blah (const T &) {
T y;

View File

@ -58,10 +58,10 @@ class SmartPtr : public ConstSmartPtr<T>
: ConstSmartPtr<T>(theItem) {}
T* item() const
{ return _item(); }
{ return this->_item(); }
operator T*() const
{ return _item(); }
{ return this->_item(); }
};
/* ------------------------------------------------------------ */

View File

@ -33,7 +33,7 @@ public:
int base::* g ();
int zowee() const
{ return bar(); }
{ return this->bar(); }
};
template <class T>

View File

@ -195,8 +195,8 @@ template<class T>
Pix
List_DLS<T>::search(const T& item) const
{
for (Pix x=first(); 0 != x; next(x)) {
if (item == operator()(x)) // { dg-error "" } const subversion
for (Pix x=this->first(); 0 != x; this->next(x)) {
if (item == this->operator()(x)) // { dg-error "" } const subversion
return x;
}
return 0;
@ -223,8 +223,8 @@ template<class T>
bool
List_DLSp<T>::contains(const T& item) const
{
for (Pix x=first(); 0 != x; next(x)) {
if (*item == *operator()(x))
for (Pix x=this->first(); 0 != x; this->next(x)) {
if (*item == *(this->operator()(x)))
return TRUE;
}
return FALSE;

View File

@ -1,5 +1,5 @@
// { dg-do assemble }
// { dg-options "" }
// { dg-options "-fpermissive" }
class A
{
@ -15,6 +15,6 @@ protected:
template <class T> class D : private B<T>
{
public:
void f2() { f1(); };
void f2() { f1(); }; // { dg-warning "" }
};

View File

@ -18,7 +18,7 @@ template<template<class> class D,class E> class C : D<E>
template<template<class> class D,class E> int C<D,E>::g()
{
return f();
return this->f();
}
int main()

View File

@ -18,13 +18,13 @@ template<template<class> class D,class E> class C : D<E>
template<template<class> class D,class E> int C<D,E>::g()
{
return f();
return this->f();
}
class E : C<D,int>
{
public:
int h() { return g(); }
int h() { return this->g(); }
};
int main()

View File

@ -1,5 +1,5 @@
// { dg-do assemble }
// { dg-options "" }
// { dg-options "-fpermissive" }
template <class T>
struct B
@ -18,7 +18,7 @@ struct D : public B<T>
template <class T>
void D<T>::f()
{
I();
I(); // { dg-warning "" }
}

View File

@ -12,7 +12,7 @@ protected:
};
template<class T> struct vector : public vector_base<T> {
vector () { def_basep (); }
vector () { this->def_basep (); }
};
vector<int> iv;