aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@yorick.cygnus.com>1997-09-25 18:56:40 +0000
committerJason Merrill <jason@gcc.gnu.org>1997-09-25 14:56:40 -0400
commit653cc74afc6785458eee2791fde774fb23ec3d8f (patch)
tree0e2ab47b18732e9a6b88e92e405a180726d99a24
parent6d4312ddbf30f452fd9c93254e0be63c4fcbda9a (diff)
downloadgcc-653cc74afc6785458eee2791fde774fb23ec3d8f.zip
gcc-653cc74afc6785458eee2791fde774fb23ec3d8f.tar.gz
gcc-653cc74afc6785458eee2791fde774fb23ec3d8f.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog17
-rw-r--r--gcc/cp/call.c14
-rw-r--r--gcc/cp/decl.c8
-rw-r--r--gcc/cp/parse.y90
4 files changed, 104 insertions, 25 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index b33c996..c5e34ac 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,20 @@
+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
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index a080c04..6855181 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 e60cef6..df8066b 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 7d9d5db..16e5db9 100644
--- a/gcc/cp/parse.y
+++ b/gcc/cp/parse.y
@@ -258,12 +258,12 @@ empty_parms ()
%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
@@ -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
{