From b34459943bbfaf3f6fb32408bec5443b5bd007a9 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Mon, 14 Jul 2003 03:04:29 +0000 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 42 ++ gcc/cp/call.c | 5 +- gcc/cp/cp-tree.h | 28 +- gcc/cp/decl.c | 54 ++- gcc/cp/lex.c | 198 ++------- gcc/cp/parser.c | 400 ++---------------- gcc/cp/pt.c | 323 +++++++------- gcc/cp/semantics.c | 341 +++++++++++++++ gcc/testsuite/ChangeLog | 20 + gcc/testsuite/g++.dg/parse/template9.C | 5 + gcc/testsuite/g++.dg/template/crash4.C | 12 + gcc/testsuite/g++.dg/template/koenig1.C | 8 + .../g++.old-deja/g++.benjamin/tem03.C | 2 +- .../g++.old-deja/g++.benjamin/tem06.C | 2 + .../g++.old-deja/g++.jason/overload33.C | 4 +- .../g++.old-deja/g++.jason/template36.C | 2 +- gcc/testsuite/g++.old-deja/g++.mike/p1989.C | 8 +- gcc/testsuite/g++.old-deja/g++.pt/lookup2.C | 4 +- gcc/testsuite/g++.old-deja/g++.pt/ttp20.C | 2 +- gcc/testsuite/g++.old-deja/g++.pt/ttp21.C | 4 +- .../g++.old-deja/g++.pt/typename13.C | 4 +- gcc/testsuite/g++.old-deja/g++.pt/union2.C | 2 +- 22 files changed, 726 insertions(+), 744 deletions(-) create mode 100644 gcc/testsuite/g++.dg/parse/template9.C create mode 100644 gcc/testsuite/g++.dg/template/crash4.C create mode 100644 gcc/testsuite/g++.dg/template/koenig1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b275e8090d0..c096405890f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,45 @@ +2003-07-13 Mark Mitchell + + * 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 * pt.c (push_access_scope_real): Remove. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 6659592b22d..39f82211b75 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index c713191360e..24fd278c537 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index be2846b7d07..d4c212f3e76 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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: - - 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 { diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 7d63e2c99da..eb0287c9d34 100644 --- a/gcc/cp/lex.c +++ b/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); } -} - -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 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 33c88b16fad..98411a6abdb 100644 --- a/gcc/cp/parser.c +++ b/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; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index d7c56a2d557..37ec8688637 100644 --- a/gcc/cp/pt.c +++ b/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); } - /* 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); @@ -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 diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index db9e4d2791b..ab9376b48a6 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9550b62e69f..1dedd6563d4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,23 @@ +2003-07-13 Mark Mitchell + + 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 * gcc.dg/20030711-1.c: New test. diff --git a/gcc/testsuite/g++.dg/parse/template9.C b/gcc/testsuite/g++.dg/parse/template9.C new file mode 100644 index 00000000000..90ce9fe61ac --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/template9.C @@ -0,0 +1,5 @@ +template +void f() { + g(); // { dg-error "" } + h(3); // { dg-error "" } +} diff --git a/gcc/testsuite/g++.dg/template/crash4.C b/gcc/testsuite/g++.dg/template/crash4.C new file mode 100644 index 00000000000..72b2bb18b9f --- /dev/null +++ b/gcc/testsuite/g++.dg/template/crash4.C @@ -0,0 +1,12 @@ +namespace NS { + struct C {}; + void foo(); +} + +template struct X {}; + +template struct A { + A() { foo (X()); } + void foo(X); +}; +template struct A; diff --git a/gcc/testsuite/g++.dg/template/koenig1.C b/gcc/testsuite/g++.dg/template/koenig1.C new file mode 100644 index 00000000000..850d3882824 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/koenig1.C @@ -0,0 +1,8 @@ +namespace NS { + struct C {}; + void foo(C); +} + +template void bar() { T t; foo (t); } + +template void bar (); diff --git a/gcc/testsuite/g++.old-deja/g++.benjamin/tem03.C b/gcc/testsuite/g++.old-deja/g++.benjamin/tem03.C index 2fc599f73b8..73b99659e12 100644 --- a/gcc/testsuite/g++.old-deja/g++.benjamin/tem03.C +++ b/gcc/testsuite/g++.old-deja/g++.benjamin/tem03.C @@ -195,7 +195,7 @@ struct Xthirteen { if (local_value > value) // { dg-error "" } .* return local_value; else - return value; // { dg-error "" } .* + return value; } }; diff --git a/gcc/testsuite/g++.old-deja/g++.benjamin/tem06.C b/gcc/testsuite/g++.old-deja/g++.benjamin/tem06.C index b56425e2179..3233e0e964d 100644 --- a/gcc/testsuite/g++.old-deja/g++.benjamin/tem06.C +++ b/gcc/testsuite/g++.old-deja/g++.benjamin/tem06.C @@ -14,6 +14,8 @@ public: friend void x (const T &) { } }; +void x(const int &); + template void blah (const T &) { T y; diff --git a/gcc/testsuite/g++.old-deja/g++.jason/overload33.C b/gcc/testsuite/g++.old-deja/g++.jason/overload33.C index 19b4a2edeb7..2cc34c6b209 100644 --- a/gcc/testsuite/g++.old-deja/g++.jason/overload33.C +++ b/gcc/testsuite/g++.old-deja/g++.jason/overload33.C @@ -58,10 +58,10 @@ class SmartPtr : public ConstSmartPtr : ConstSmartPtr(theItem) {} T* item() const - { return _item(); } + { return this->_item(); } operator T*() const - { return _item(); } + { return this->_item(); } }; /* ------------------------------------------------------------ */ diff --git a/gcc/testsuite/g++.old-deja/g++.jason/template36.C b/gcc/testsuite/g++.old-deja/g++.jason/template36.C index a8a9d163c30..23cdb00e6de 100644 --- a/gcc/testsuite/g++.old-deja/g++.jason/template36.C +++ b/gcc/testsuite/g++.old-deja/g++.jason/template36.C @@ -33,7 +33,7 @@ public: int base::* g (); int zowee() const - { return bar(); } + { return this->bar(); } }; template diff --git a/gcc/testsuite/g++.old-deja/g++.mike/p1989.C b/gcc/testsuite/g++.old-deja/g++.mike/p1989.C index 30c7e518c4e..bbecdd8d8a4 100644 --- a/gcc/testsuite/g++.old-deja/g++.mike/p1989.C +++ b/gcc/testsuite/g++.old-deja/g++.mike/p1989.C @@ -195,8 +195,8 @@ template Pix List_DLS::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 bool List_DLSp::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; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/lookup2.C b/gcc/testsuite/g++.old-deja/g++.pt/lookup2.C index 73c2bbbf623..3d9f0605a18 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/lookup2.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/lookup2.C @@ -1,5 +1,5 @@ // { dg-do assemble } -// { dg-options "" } +// { dg-options "-fpermissive" } class A { @@ -15,6 +15,6 @@ protected: template class D : private B { public: - void f2() { f1(); }; + void f2() { f1(); }; // { dg-warning "" } }; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ttp20.C b/gcc/testsuite/g++.old-deja/g++.pt/ttp20.C index c9f7912de41..c54119efda2 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/ttp20.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/ttp20.C @@ -18,7 +18,7 @@ template class D,class E> class C : D template class D,class E> int C::g() { - return f(); + return this->f(); } int main() diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ttp21.C b/gcc/testsuite/g++.old-deja/g++.pt/ttp21.C index c1a4fd0cf36..f0b41bf3f56 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/ttp21.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/ttp21.C @@ -18,13 +18,13 @@ template class D,class E> class C : D template class D,class E> int C::g() { - return f(); + return this->f(); } class E : C { public: - int h() { return g(); } + int h() { return this->g(); } }; int main() diff --git a/gcc/testsuite/g++.old-deja/g++.pt/typename13.C b/gcc/testsuite/g++.old-deja/g++.pt/typename13.C index b0d4b47f3b1..385834b959d 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/typename13.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/typename13.C @@ -1,5 +1,5 @@ // { dg-do assemble } -// { dg-options "" } +// { dg-options "-fpermissive" } template struct B @@ -18,7 +18,7 @@ struct D : public B template void D::f() { - I(); + I(); // { dg-warning "" } } diff --git a/gcc/testsuite/g++.old-deja/g++.pt/union2.C b/gcc/testsuite/g++.old-deja/g++.pt/union2.C index 9eb4a87d068..fdb038f20b0 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/union2.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/union2.C @@ -12,7 +12,7 @@ protected: }; template struct vector : public vector_base { - vector () { def_basep (); } + vector () { this->def_basep (); } }; vector iv; -- 2.30.2