+Thu Sep 25 11:11:13 1997 Jason Merrill <jason@yorick.cygnus.com>
+
+ 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 <brendan@lisa.cygnus.com>
* decl.c (start_function): Up warning of no return type to be a
rank = STD_RANK;
break;
- case LVALUE_CONV:
case QUAL_CONV:
- case RVALUE_CONV:
if (rank < EXACT_RANK)
rank = EXACT_RANK;
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)
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);
return -1;
}
}
-#endif
}
tweak:
%type <ttype> template_type template_arg_list template_arg
%type <ttype> condition xcond paren_cond_or_null
%type <ttype> type_name nested_name_specifier nested_type ptr_to_mem
-%type <ttype> complete_type_name notype_identifier
+%type <ttype> complete_type_name notype_identifier nonnested_type
%type <ttype> complex_type_name nested_name_specifier_1
%type <itype> nomods_initdecls nomods_initdcl0
%type <ttype> new_initializer new_placement
%type <ttype> using_decl .poplevel
-
+%type <ttype> 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 <ttype> named_class_head_sans_basetype_defn
| 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
;
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)
| direct_after_type_declarator
;
-complete_type_name:
+nonnested_type:
type_name %prec EMPTY
{
if (TREE_CODE ($1) == IDENTIFIER_NODE)
$$ = $2;
got_scope = NULL_TREE;
}
+ ;
+
+complete_type_name:
+ nonnested_type
| nested_type
| global_scope nested_type
{ $$ = $2; }
{
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)); }
{ 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
{