This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Koenig lookup
- To: egcs-patches at cygnus dot com
- Subject: Koenig lookup
- From: "Martin v. Loewis" <loewis at informatik dot hu-berlin dot de>
- Date: Tue, 30 Jun 1998 19:33:21 +0200
After having a close look at the parser, I found that Koenig lookup
isn't that difficult to implement; here's a patch.
Two things need consideration:
1. When parsing, say
IDENTIFIER LEFT_RIGHT
the scanner will perform a lookup of the identifier and store the
result in lastiddecl. With my code, this lookup is lost, as I don't
have a semantic action for $1. I could have done
really_unqualified_id: IDENTIFIER
{ $$ = lastiddecl ? lastiddecl : $1;}
but that would by me a number of reduce/reduce conflicts. As it
stands, I get no new conflicts.
2. The computation of associated namespaces probably does not handle
all 'things'. The code passes the test suite, but there are
certainly parameter types which appear in none of the test cases.
Since the set of associated name space for these is likely
non-obvious, I'd rather wait and see whether they appear in real
life. Once you know what has to be done, doing it in arg_assoc
is easy.
(an example: What is the set of associated namespaces in a call
like:
template<class T>T f1(T&);
...
f2(T);
)
Any comments appreciated.
Martin
1998-06-29 Martin v. Löwis <loewis@informatik.hu-berlin.de>
* decl2.c (build_expr_from_tree): Change calls of do_identifier.
Do Koenig lookup in CALL_EXPR.
(arg_assoc): Handle error_mark.
* lex.c (is_global): New function.
(do_identifier): Expect arguments for Koenig lookup.
* parse.y (primary): Add rules for calls of unqualified function calls.
(do_id): Change call of do_identifier.
* pt.c (finish_stmt_expr): Likewise.
* semantics.c (finish_id_expr): Likewise.
(finish_call_expr): Add integer parameter to indicate
argument-dependent lookup
Index: cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.91
diff -c -p -r1.91 cp-tree.h
*** cp-tree.h 1998/06/25 15:21:36 1.91
--- cp-tree.h 1998/06/30 16:10:25
*************** extern void note_list_got_semicolon PRO
*** 2591,2597 ****
extern void do_pending_lang_change PROTO((void));
extern int identifier_type PROTO((tree));
extern void see_typename PROTO((void));
! extern tree do_identifier PROTO((tree, int));
extern tree do_scoped_id PROTO((tree, int));
extern tree identifier_typedecl_value PROTO((tree));
extern int real_yylex PROTO((void));
--- 2591,2597 ----
extern void do_pending_lang_change PROTO((void));
extern int identifier_type PROTO((tree));
extern void see_typename PROTO((void));
! extern tree do_identifier PROTO((tree, int, tree));
extern tree do_scoped_id PROTO((tree, int));
extern tree identifier_typedecl_value PROTO((tree));
extern int real_yylex PROTO((void));
*************** extern void finish_asm_stmt
*** 2783,2789 ****
extern tree finish_parenthesized_expr PROTO((tree));
extern tree begin_stmt_expr PROTO((void));
extern tree finish_stmt_expr PROTO((tree, tree));
! extern tree finish_call_expr PROTO((tree, tree));
extern tree finish_increment_expr PROTO((tree, enum tree_code));
extern tree finish_this_expr PROTO((void));
extern tree finish_object_call_expr PROTO((tree, tree, tree));
--- 2783,2789 ----
extern tree finish_parenthesized_expr PROTO((tree));
extern tree begin_stmt_expr PROTO((void));
extern tree finish_stmt_expr PROTO((tree, tree));
! extern tree finish_call_expr PROTO((tree, tree, int));
extern tree finish_increment_expr PROTO((tree, enum tree_code));
extern tree finish_this_expr PROTO((void));
extern tree finish_object_call_expr PROTO((tree, tree, tree));
Index: decl2.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl2.c,v
retrieving revision 1.90
diff -c -p -r1.90 decl2.c
*** decl2.c 1998/06/25 14:11:54 1.90
--- decl2.c 1998/06/30 16:10:31
*************** build_expr_from_tree (t)
*** 3468,3480 ****
switch (TREE_CODE (t))
{
case IDENTIFIER_NODE:
! return do_identifier (t, 0);
case LOOKUP_EXPR:
if (LOOKUP_EXPR_GLOBAL (t))
return do_scoped_id (TREE_OPERAND (t, 0), 0);
else
! return do_identifier (TREE_OPERAND (t, 0), 0);
case TEMPLATE_ID_EXPR:
return (lookup_template_function
--- 3468,3480 ----
switch (TREE_CODE (t))
{
case IDENTIFIER_NODE:
! return do_identifier (t, 0, NULL_TREE);
case LOOKUP_EXPR:
if (LOOKUP_EXPR_GLOBAL (t))
return do_scoped_id (TREE_OPERAND (t, 0), 0);
else
! return do_identifier (TREE_OPERAND (t, 0), 0, NULL_TREE);
case TEMPLATE_ID_EXPR:
return (lookup_template_function
*************** build_expr_from_tree (t)
*** 3639,3650 ****
else
{
tree name = TREE_OPERAND (t, 0);
! if (TREE_CODE (name) == TEMPLATE_ID_EXPR
|| ! really_overloaded_fn (name))
name = build_expr_from_tree (name);
! return build_x_function_call
! (name, build_expr_from_tree (TREE_OPERAND (t, 1)),
! current_class_ref);
}
case COND_EXPR:
--- 3639,3659 ----
else
{
tree name = TREE_OPERAND (t, 0);
! tree id;
! tree args = build_expr_from_tree (TREE_OPERAND (t, 1));
! if (args != NULL_TREE && TREE_CODE (name) == LOOKUP_EXPR
! && !LOOKUP_EXPR_GLOBAL (name)
! && TREE_CODE ((id = TREE_OPERAND (name, 0))) == IDENTIFIER_NODE
! && (!current_class_type
! || !lookup_member (current_class_type, id, 0, 0)))
! {
! /* Do Koenig lookup if there are no class members. */
! name = do_identifier (id, 0, args);
! }
! else if (TREE_CODE (name) == TEMPLATE_ID_EXPR
|| ! really_overloaded_fn (name))
name = build_expr_from_tree (name);
! return build_x_function_call (name, args, current_class_ref);
}
case COND_EXPR:
*************** arg_assoc (k, n)
*** 4325,4330 ****
--- 4334,4346 ----
if (arg_assoc_type (k, DECL_CLASS_CONTEXT (n)))
return 1;
return 0;
+ case TEMPLATE_DECL:
+ /* XXX Type of a function template in the context of Koenig lookup?
+ Assume that template parameters are non-deduced for the moment. */
+ n = DECL_RESULT (n);
+ continue;
+ case ERROR_MARK:
+ return 0;
default:
cp_error ("sorry, Koenig lookup for `%s' of type `%T' failed",
tree_code_name [(int)TREE_CODE (n)], TREE_TYPE (n));
Index: lex.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/lex.c,v
retrieving revision 1.52
diff -c -p -r1.52 lex.c
*** lex.c 1998/06/10 10:16:45 1.52
--- lex.c 1998/06/30 16:10:32
*************** see_typename ()
*** 2792,2801 ****
}
}
tree
! do_identifier (token, parsing)
register tree token;
int parsing;
{
register tree id;
--- 2792,2820 ----
}
}
+ /* Return true if d is in a global scope. */
+
+ static int
+ is_global (d)
+ tree d;
+ {
+ while (1)
+ switch (TREE_CODE (d))
+ {
+ case OVERLOAD: d = OVL_FUNCTION (d); continue;
+ case TREE_LIST: d = TREE_VALUE (d); continue;
+ default:
+ my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (d)) == 'd', 980629);
+ d = CP_DECL_CONTEXT (d);
+ return TREE_CODE (d) == NAMESPACE_DECL;
+ }
+ }
+
tree
! do_identifier (token, parsing, args)
register tree token;
int parsing;
+ tree args;
{
register tree id;
*************** do_identifier (token, parsing)
*** 2808,2814 ****
yychar = yylex ();
/* Scope class declarations before global
declarations. */
! if (id == IDENTIFIER_NAMESPACE_VALUE (token)
&& current_class_type != 0
&& TYPE_SIZE (current_class_type) == 0)
{
--- 2827,2833 ----
yychar = yylex ();
/* Scope class declarations before global
declarations. */
! if (id && is_global (id)
&& current_class_type != 0
&& TYPE_SIZE (current_class_type) == 0)
{
*************** do_identifier (token, parsing)
*** 2833,2838 ****
--- 2852,2865 ----
id = error_mark_node;
return id;
}
+ }
+
+ /* Don't do Koenig lookup inside templates, build lookup expressions instead. */
+ if (args && !current_template_parms && (!id || is_global (id)))
+ {
+ /* If we have arguments and we only found global names,
+ do Koenig lookup. */
+ id = lookup_arg_dependent (token, id, args);
}
/* Remember that this name has been used in the class definition, as per
Index: parse.y
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/parse.y,v
retrieving revision 1.65
diff -c -p -r1.65 parse.y
*** parse.y 1998/06/25 03:28:32 1.65
--- parse.y 1998/06/30 16:10:44
*************** notype_unqualified_id:
*** 1240,1246 ****
;
do_id:
! { $$ = do_identifier ($<ttype>-1, 1); }
template_id:
PFUNCNAME '<' do_id template_arg_list_opt template_close_bracket
--- 1240,1246 ----
;
do_id:
! { $$ = do_identifier ($<ttype>-1, 1, NULL_TREE); }
template_id:
PFUNCNAME '<' do_id template_arg_list_opt template_close_bracket
*************** primary:
*** 1327,1336 ****
}
compstmt ')'
{ $$ = finish_stmt_expr ($<ttype>2, $3); }
| primary '(' nonnull_exprlist ')'
! { $$ = finish_call_expr ($1, $3); }
| primary LEFT_RIGHT
! { $$ = finish_call_expr ($1, NULL_TREE); }
| primary '[' expr ']'
{ $$ = grok_array_decl ($$, $3); }
| primary PLUSPLUS
--- 1327,1343 ----
}
compstmt ')'
{ $$ = finish_stmt_expr ($<ttype>2, $3); }
+ /* Koenig lookup support
+ We could store lastiddecl in $1 to avoid another lookup,
+ but that would result in many additional reduce/reduce conflicts. */
+ | IDENTIFIER '(' nonnull_exprlist ')'
+ { $$ = finish_call_expr ($1, $3, 1); }
+ | IDENTIFIER LEFT_RIGHT
+ { $$ = finish_call_expr ($1, NULL_TREE, 1); }
| primary '(' nonnull_exprlist ')'
! { $$ = finish_call_expr ($1, $3, 0); }
| primary LEFT_RIGHT
! { $$ = finish_call_expr ($1, NULL_TREE, 0); }
| primary '[' expr ']'
{ $$ = grok_array_decl ($$, $3); }
| primary PLUSPLUS
Index: pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.159
diff -c -p -r1.159 pt.c
*** pt.c 1998/06/25 03:28:33 1.159
--- pt.c 1998/06/30 16:10:48
*************** tsubst_copy (t, args, in_decl)
*** 5158,5164 ****
switch (code)
{
case PARM_DECL:
! return do_identifier (DECL_NAME (t), 0);
case CONST_DECL:
case FIELD_DECL:
--- 5158,5164 ----
switch (code)
{
case PARM_DECL:
! return do_identifier (DECL_NAME (t), 0, NULL_TREE);
case CONST_DECL:
case FIELD_DECL:
Index: semantics.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/semantics.c,v
retrieving revision 1.13
diff -c -p -r1.13 semantics.c
*** semantics.c 1998/06/23 07:10:28 1.13
--- semantics.c 1998/06/30 16:10:48
*************** finish_stmt_expr (rtl_expr, expr)
*** 836,846 ****
call. */
tree
! finish_call_expr (fn, args)
tree fn;
tree args;
{
! tree result = build_x_function_call (fn, args, current_class_ref);
if (TREE_CODE (result) == CALL_EXPR
&& TREE_TYPE (result) != void_type_node)
--- 836,851 ----
call. */
tree
! finish_call_expr (fn, args, koenig)
tree fn;
tree args;
+ int koenig;
{
! tree result;
!
! if (koenig)
! fn = do_identifier (fn, 0, args);
! result = build_x_function_call (fn, args, current_class_ref);
if (TREE_CODE (result) == CALL_EXPR
&& TREE_TYPE (result) != void_type_node)
*************** finish_id_expr (expr)
*** 1028,1034 ****
tree expr;
{
if (TREE_CODE (expr) == IDENTIFIER_NODE)
! expr = do_identifier (expr, 1);
return expr;
}
--- 1033,1039 ----
tree expr;
{
if (TREE_CODE (expr) == IDENTIFIER_NODE)
! expr = do_identifier (expr, 1, NULL_TREE);
return expr;
}