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:
parent
f2ffecb112
commit
b34459943b
22 changed files with 721 additions and 739 deletions
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
198
gcc/cp/lex.c
198
gcc/cp/lex.c
|
@ -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
|
||||
|
|
400
gcc/cp/parser.c
400
gcc/cp/parser.c
|
@ -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;
|
||||
|
|
323
gcc/cp/pt.c
323
gcc/cp/pt.c
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
5
gcc/testsuite/g++.dg/parse/template9.C
Normal file
5
gcc/testsuite/g++.dg/parse/template9.C
Normal file
|
@ -0,0 +1,5 @@
|
|||
template <typename T>
|
||||
void f() {
|
||||
g(); // { dg-error "" }
|
||||
h(3); // { dg-error "" }
|
||||
}
|
12
gcc/testsuite/g++.dg/template/crash4.C
Normal file
12
gcc/testsuite/g++.dg/template/crash4.C
Normal 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>;
|
8
gcc/testsuite/g++.dg/template/koenig1.C
Normal file
8
gcc/testsuite/g++.dg/template/koenig1.C
Normal 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> ();
|
|
@ -195,7 +195,7 @@ struct Xthirteen {
|
|||
if (local_value > value) // { dg-error "" } .*
|
||||
return local_value;
|
||||
else
|
||||
return value; // { dg-error "" } .*
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -14,6 +14,8 @@ public:
|
|||
friend void x (const T &) { }
|
||||
};
|
||||
|
||||
void x(const int &);
|
||||
|
||||
template<class T>
|
||||
void blah (const T &) {
|
||||
T y;
|
||||
|
|
|
@ -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(); }
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
int base::* g ();
|
||||
|
||||
int zowee() const
|
||||
{ return bar(); }
|
||||
{ return this->bar(); }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 "" }
|
||||
};
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 "" }
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ protected:
|
|||
};
|
||||
|
||||
template<class T> struct vector : public vector_base<T> {
|
||||
vector () { def_basep (); }
|
||||
vector () { this->def_basep (); }
|
||||
};
|
||||
|
||||
vector<int> iv;
|
||||
|
|
Loading…
Add table
Reference in a new issue