From 653cc74afc6785458eee2791fde774fb23ec3d8f Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 25 Sep 1997 18:56:40 +0000 Subject: [PATCH] Handle multi-level typenames and implicit typename in base list. * parse.y (typename_sub{,[0-2]}): New rules. (structsp, rule TYPENAME_KEYWORD): Use typename_sub. (nonnested_type): New rule. (complete_type_name): Use it. (base_class.1): Use typename_sub and nonnested_type. (nested_name_specifier): Don't elide std:: here. * decl.c (make_typename_type): Handle getting a type for NAME. (lookup_name_real): Turn std:: into :: here. Rvalue conversions were removed in London. * call.c (is_subseq): Don't consider lvalue transformations. (build_conv): LVALUE_CONV and RVALUE_CONV get IDENTITY_RANK. (joust): Reenable ?: kludge. From-SVN: r15715 --- gcc/cp/ChangeLog | 17 +++++++++ gcc/cp/call.c | 14 ++++---- gcc/cp/decl.c | 8 ++++- gcc/cp/parse.y | 90 ++++++++++++++++++++++++++++++++++++++---------- 4 files changed, 104 insertions(+), 25 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b33c99617b8..c5e34ac4b24 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,20 @@ +Thu Sep 25 11:11:13 1997 Jason Merrill + + Handle multi-level typenames and implicit typename in base list. + * parse.y (typename_sub{,[0-2]}): New rules. + (structsp, rule TYPENAME_KEYWORD): Use typename_sub. + (nonnested_type): New rule. + (complete_type_name): Use it. + (base_class.1): Use typename_sub and nonnested_type. + (nested_name_specifier): Don't elide std:: here. + * decl.c (make_typename_type): Handle getting a type for NAME. + (lookup_name_real): Turn std:: into :: here. + + Rvalue conversions were removed in London. + * call.c (is_subseq): Don't consider lvalue transformations. + (build_conv): LVALUE_CONV and RVALUE_CONV get IDENTITY_RANK. + (joust): Reenable ?: kludge. + 1997-09-22 Brendan Kehoe * decl.c (start_function): Up warning of no return type to be a diff --git a/gcc/cp/call.c b/gcc/cp/call.c index a080c045ef2..6855181cef4 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -3021,9 +3021,7 @@ build_conv (code, type, from) rank = STD_RANK; break; - case LVALUE_CONV: case QUAL_CONV: - case RVALUE_CONV: if (rank < EXACT_RANK) rank = EXACT_RANK; @@ -5649,6 +5647,11 @@ static int is_subseq (ics1, ics2) tree ics1, ics2; { + /* Do not consider lvalue transformations here. */ + if (TREE_CODE (ics2) == RVALUE_CONV + || TREE_CODE (ics2) == LVALUE_CONV) + return 0; + for (;; ics2 = TREE_OPERAND (ics2, 0)) { if (TREE_CODE (ics2) == TREE_CODE (ics1) @@ -6084,10 +6087,10 @@ joust (cand1, cand2) break; if (i == TREE_VEC_LENGTH (cand1->convs)) return 1; -#if 0 + /* Kludge around broken overloading rules whereby - bool ? void *const & : void *const & is ambiguous. */ - /* Huh? Explain the problem better. */ + Integer a, b; test ? a : b; is ambiguous, since there's a builtin + that takes references and another that takes values. */ if (cand1->fn == ansi_opname[COND_EXPR]) { tree c1 = TREE_VEC_ELT (cand1->convs, 1); @@ -6103,7 +6106,6 @@ joust (cand1, cand2) return -1; } } -#endif } tweak: diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index e60cef6bc9a..df8066b1078 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -4317,7 +4317,9 @@ make_typename_type (context, name) { tree t, d; - if (TREE_CODE (name) == TYPE_DECL) + if (TREE_CODE_CLASS (TREE_CODE (name)) == 't') + name = TYPE_IDENTIFIER (name); + else if (TREE_CODE (name) == TYPE_DECL) name = DECL_NAME (name); else if (TREE_CODE (name) != IDENTIFIER_NODE) my_friendly_abort (2000); @@ -4378,6 +4380,10 @@ lookup_name_real (name, prefer_type, nonclass) yylex = 1; prefer_type = looking_for_typename; + /* std:: becomes :: for now. */ + if (got_scope == std_node) + got_scope = void_type_node; + if (got_scope) type = got_scope; else if (got_object != error_mark_node) diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index 7d9d5db7a34..16e5db99160 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -258,12 +258,12 @@ empty_parms () %type template_type template_arg_list template_arg %type condition xcond paren_cond_or_null %type type_name nested_name_specifier nested_type ptr_to_mem -%type complete_type_name notype_identifier +%type complete_type_name notype_identifier nonnested_type %type complex_type_name nested_name_specifier_1 %type nomods_initdecls nomods_initdcl0 %type new_initializer new_placement %type using_decl .poplevel - +%type typename_sub typename_sub0 typename_sub1 typename_sub2 /* in order to recognize aggr tags as defining and thus shadowing. */ %token TYPENAME_DEFN IDENTIFIER_DEFN PTYPENAME_DEFN %type named_class_head_sans_basetype_defn @@ -2190,11 +2190,8 @@ structsp: | ENUM complex_type_name { $$.t = xref_tag (enum_type_node, $2, NULL_TREE, 1); $$.new_type_flag = 0; } - | TYPENAME_KEYWORD nested_name_specifier identifier - { $$.t = make_typename_type ($2, $3); - $$.new_type_flag = 0; } - | TYPENAME_KEYWORD global_scope nested_name_specifier identifier - { $$.t = make_typename_type ($3, $4); + | TYPENAME_KEYWORD typename_sub + { $$.t = $2; $$.new_type_flag = 0; } /* C++ extensions, merged with C to avoid shift/reduce conflicts */ | class_head left_curly opt.component_decl_list '}' maybe_attribute @@ -2437,11 +2434,8 @@ base_class: ; base_class.1: - complete_type_name - | TYPENAME_KEYWORD nested_name_specifier identifier - { $$ = TYPE_MAIN_DECL (make_typename_type ($2, $3)); } - | TYPENAME_KEYWORD global_scope nested_name_specifier identifier - { $$ = TYPE_MAIN_DECL (make_typename_type ($3, $4)); } + typename_sub + | nonnested_type | SIGOF '(' expr ')' { if (current_aggr == signature_type_node) @@ -2945,7 +2939,7 @@ after_type_declarator: | direct_after_type_declarator ; -complete_type_name: +nonnested_type: type_name %prec EMPTY { if (TREE_CODE ($1) == IDENTIFIER_NODE) @@ -2974,6 +2968,10 @@ complete_type_name: $$ = $2; got_scope = NULL_TREE; } + ; + +complete_type_name: + nonnested_type | nested_type | global_scope nested_type { $$ = $2; } @@ -3119,11 +3117,7 @@ nested_name_specifier_1: { if (TREE_CODE ($$) == IDENTIFIER_NODE) $$ = lastiddecl; - if (TREE_CODE ($$) == NAMESPACE_DECL - && DECL_NAME ($$) == get_identifier ("std")) - got_scope = void_type_node; - else - got_scope = $$; + got_scope = $$; } | template_type SCOPE { got_scope = $$ = complete_type (TREE_TYPE ($1)); } @@ -3139,6 +3133,66 @@ nested_name_specifier_1: { goto failed_scope; } */ ; +typename_sub: + typename_sub0 + | global_scope typename_sub0 + { $$ = $2; } + ; + +typename_sub0: + typename_sub1 identifier + { + if (TREE_CODE_CLASS (TREE_CODE ($1)) == 't') + $$ = make_typename_type ($1, $2); + else if (TREE_CODE ($2) == IDENTIFIER_NODE) + cp_error ("`%T' is not a class or namespace", $2); + else + $$ = $2; + } + ; + +typename_sub1: + typename_sub2 + { + if (TREE_CODE ($1) == IDENTIFIER_NODE) + cp_error ("`%T' is not a class or namespace", $1); + } + | typename_sub1 typename_sub2 + { + if (TREE_CODE_CLASS (TREE_CODE ($1)) == 't') + $$ = make_typename_type ($1, $2); + else if (TREE_CODE ($2) == IDENTIFIER_NODE) + cp_error ("`%T' is not a class or namespace", $2); + else + $$ = $2; + } + ; + +typename_sub2: + TYPENAME SCOPE + { + if (TREE_CODE ($1) != IDENTIFIER_NODE) + $$ = lastiddecl; + got_scope = $$ = complete_type (TREE_TYPE ($$)); + } + | SELFNAME SCOPE + { + if (TREE_CODE ($1) != IDENTIFIER_NODE) + $$ = lastiddecl; + got_scope = $$ = complete_type (TREE_TYPE ($$)); + } + | template_type SCOPE + { got_scope = $$ = complete_type (TREE_TYPE ($$)); } + | PTYPENAME SCOPE + | IDENTIFIER SCOPE + | NSNAME SCOPE + { + if (TREE_CODE ($$) == IDENTIFIER_NODE) + $$ = lastiddecl; + got_scope = $$; + } + ; + complex_type_name: global_scope type_name { -- 2.30.2