* 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
+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.
/* 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)
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) \
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);
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);
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);
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);
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);
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:
-
- 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 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.
-
- 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 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 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 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. */
+ reregister_specialization (newdecl,
+ DECL_TI_TEMPLATE (newdecl),
+ olddecl);
}
else
{
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);
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))
SET_IDENTIFIER_NAMESPACE_VALUE (name, error_mark_node);
SET_IDENTIFIER_ERROR_LOCUS (name, current_function_decl);
}
-}
-
-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);
+ return error_mark_node;
}
+/* 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 */
+ return build_min_nt (LOOKUP_EXPR, name);
}
- 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;
- }
-
- /* 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
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
/* 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
(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
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. */
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;
{
tree id_expression;
tree decl;
+ const char *error_msg;
id_expression:
/* Parse the id-expression. */
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;
}
{
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
{
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);
/* Build the ARRAY_REF. */
postfix_expression
= grok_array_decl (postfix_expression, index);
- idk = CP_PARSER_ID_KIND_NONE;
+ idk = CP_ID_KIND_NONE;
}
break;
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)
{
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
|| 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
/*disallow_virtual=*/false);
/* The POSTFIX_EXPRESSION is certainly no longer an id. */
- idk = CP_PARSER_ID_KIND_NONE;
+ idk = CP_ID_KIND_NONE;
}
break;
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
/* 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)
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:
postfix_expression
= finish_increment_expr (postfix_expression,
POSTDECREMENT_EXPR);
- idk = CP_PARSER_ID_KIND_NONE;
+ idk = CP_ID_KIND_NONE;
break;
default:
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
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;
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 *);
}
/* 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;
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;
}
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;
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;
}
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);
{
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
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))
{
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)
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)
{
}
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:
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);
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:
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,
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:
else
{
++skip_evaluation;
- op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
+ op1 = RECUR (op1);
--skip_evaluation;
}
if (TREE_CODE (t) == SIZEOF_EXPR)
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);
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;
&& (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);
}
- /* 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);
+ call_args = RECUR (TREE_OPERAND (t, 1));
if (BASELINK_P (function))
qualified_p = 1;
- if (call_args != NULL_TREE && koenig_name)
- function = lookup_arg_dependent (koenig_name,
- function,
- call_args);
+ 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);
+
+ function = convert_from_reference (function);
if (TREE_CODE (function) == OFFSET_REF)
return build_offset_ref_call_from_tree (function, call_args);
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:
{
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))
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);
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:
{
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);
}
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);
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,
tree args;
tree code_pattern;
tree new_decl;
- int unregistered;
+ bool unregistered;
args = DECL_TI_ARGS (decl);
code_pattern = DECL_TEMPLATE_RESULT (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
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
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. */
+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.
--- /dev/null
+template <typename T>
+void f() {
+ g(); // { dg-error "" }
+ h(3); // { dg-error "" }
+}
--- /dev/null
+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>;
--- /dev/null
+namespace NS {
+ struct C {};
+ void foo(C);
+}
+
+template <class T> void bar() { T t; foo (t); }
+
+template void bar<NS::C> ();
if (local_value > value) // { dg-error "" } .*
return local_value;
else
- return value; // { dg-error "" } .*
+ return value;
}
};
friend void x (const T &) { }
};
+void x(const int &);
+
template<class T>
void blah (const T &) {
T y;
: ConstSmartPtr<T>(theItem) {}
T* item() const
- { return _item(); }
+ { return this->_item(); }
operator T*() const
- { return _item(); }
+ { return this->_item(); }
};
/* ------------------------------------------------------------ */
int base::* g ();
int zowee() const
- { return bar(); }
+ { return this->bar(); }
};
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;
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;
// { dg-do assemble }
-// { dg-options "" }
+// { dg-options "-fpermissive" }
class A
{
template <class T> class D : private B<T>
{
public:
- void f2() { f1(); };
+ void f2() { f1(); }; // { dg-warning "" }
};
template<template<class> class D,class E> int C<D,E>::g()
{
- return f();
+ return this->f();
}
int main()
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()
// { dg-do assemble }
-// { dg-options "" }
+// { dg-options "-fpermissive" }
template <class T>
struct B
template <class T>
void D<T>::f()
{
- I();
+ I(); // { dg-warning "" }
}
};
template<class T> struct vector : public vector_base<T> {
- vector () { def_basep (); }
+ vector () { this->def_basep (); }
};
vector<int> iv;