Commit 9e259dd1 by Mark Mitchell Committed by Mark Mitchell

call.c (standard_conversion): Use build_ptrmem_type.

	* call.c (standard_conversion): Use build_ptrmem_type.
	* cp-tree.h (build_ptrmem_type): New function.
	(adjust_result_of_qualified_name_lookup): Likewise.
	* decl.c (grokvardecl): Do not look for OFFSET_TYPEs to indicate
	static data members.
	(build_ptrmem_type): New function.
	(grokdeclarator): Do not use build_offset_type when encountering a
	qualified name.
	* parse.y (parse_finish_call_expr): Use
	adjust_result_of_qualified_name_lookup.
	* search.c (adjust_result_of_qualified_name_lookup): New function.
	* typeck.c (qualify_type_recursive): Use TYPE_PTRMEM_* rather than
	accessing OFFSET_TYPEs directly.

	* g++.dg/template/crash1.C: New test.

From-SVN: r56169
parent c512fd7b
2002-08-09 Mark Mitchell <mark@codesourcery.com>
* call.c (standard_conversion): Use build_ptrmem_type.
* cp-tree.h (build_ptrmem_type): New function.
(adjust_result_of_qualified_name_lookup): Likewise.
* decl.c (grokvardecl): Do not look for OFFSET_TYPEs to indicate
static data members.
(build_ptrmem_type): New function.
(grokdeclarator): Do not use build_offset_type when encountering a
qualified name.
* parse.y (parse_finish_call_expr): Use
adjust_result_of_qualified_name_lookup.
* search.c (adjust_result_of_qualified_name_lookup): New function.
* typeck.c (qualify_type_recursive): Use TYPE_PTRMEM_* rather than
accessing OFFSET_TYPEs directly.
2002-08-08 Mike Stump <mrs@apple.com> 2002-08-08 Mike Stump <mrs@apple.com>
* call.c (add_builtin_candidate): legal -> valid, illegal -> invalid. * call.c (add_builtin_candidate): legal -> valid, illegal -> invalid.
......
...@@ -838,8 +838,7 @@ standard_conversion (to, from, expr) ...@@ -838,8 +838,7 @@ standard_conversion (to, from, expr)
(TREE_TYPE (TREE_TYPE (from)), (TREE_TYPE (TREE_TYPE (from)),
TREE_TYPE (TREE_TYPE (to))))) TREE_TYPE (TREE_TYPE (to)))))
{ {
from = build_offset_type (tbase, TREE_TYPE (TREE_TYPE (from))); from = build_ptrmem_type (tbase, TREE_TYPE (TREE_TYPE (from)));
from = build_pointer_type (from);
conv = build_conv (PMEM_CONV, from, conv); conv = build_conv (PMEM_CONV, from, conv);
} }
} }
......
...@@ -3682,6 +3682,7 @@ extern void expand_static_init PARAMS ((tree, tree)); ...@@ -3682,6 +3682,7 @@ extern void expand_static_init PARAMS ((tree, tree));
extern tree start_handler_parms PARAMS ((tree, tree)); extern tree start_handler_parms PARAMS ((tree, tree));
extern int complete_array_type PARAMS ((tree, tree, int)); extern int complete_array_type PARAMS ((tree, tree, int));
extern tree build_ptrmemfunc_type PARAMS ((tree)); extern tree build_ptrmemfunc_type PARAMS ((tree));
extern tree build_ptrmem_type (tree, tree);
/* the grokdeclarator prototype is in decl.h */ /* the grokdeclarator prototype is in decl.h */
extern int parmlist_is_exprlist PARAMS ((tree)); extern int parmlist_is_exprlist PARAMS ((tree));
extern int copy_fn_p PARAMS ((tree)); extern int copy_fn_p PARAMS ((tree));
...@@ -4056,7 +4057,8 @@ extern tree find_vbase_instance PARAMS ((tree, tree)); ...@@ -4056,7 +4057,8 @@ extern tree find_vbase_instance PARAMS ((tree, tree));
extern tree binfo_for_vbase PARAMS ((tree, tree)); extern tree binfo_for_vbase PARAMS ((tree, tree));
extern tree binfo_via_virtual PARAMS ((tree, tree)); extern tree binfo_via_virtual PARAMS ((tree, tree));
extern tree build_baselink (tree, tree, tree, tree); extern tree build_baselink (tree, tree, tree, tree);
extern tree adjust_result_of_qualified_name_lookup
(tree, tree, tree);
/* in semantics.c */ /* in semantics.c */
extern void init_cp_semantics PARAMS ((void)); extern void init_cp_semantics PARAMS ((void));
extern tree finish_expr_stmt PARAMS ((tree)); extern tree finish_expr_stmt PARAMS ((tree));
......
...@@ -9137,64 +9137,68 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals, ...@@ -9137,64 +9137,68 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
return decl; return decl;
} }
/* Create a VAR_DECL named NAME with the indicated TYPE.
If SCOPE is non-NULL, it is the class type or namespace containing
the variable. If SCOPE is NULL, the variable should is created in
the innermost enclosings scope. */
static tree static tree
grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace) grokvardecl (type, name, specbits_in, initialized, constp, scope)
tree type; tree type;
tree declarator; tree name;
RID_BIT_TYPE *specbits_in; RID_BIT_TYPE *specbits_in;
int initialized; int initialized;
int constp; int constp;
tree in_namespace; tree scope;
{ {
tree decl; tree decl;
RID_BIT_TYPE specbits; RID_BIT_TYPE specbits;
my_friendly_assert (!name || TREE_CODE (name) == IDENTIFIER_NODE,
20020808);
specbits = *specbits_in; specbits = *specbits_in;
if (TREE_CODE (type) == OFFSET_TYPE) /* Compute the scope in which to place the variable. */
if (!scope)
{ {
/* If you declare a static member so that it /* An explicit "extern" specifier indicates a namespace-scope
can be initialized, the code will reach here. */ variable. */
tree basetype = TYPE_OFFSET_BASETYPE (type); if (RIDBIT_SETP (RID_EXTERN, specbits))
type = TREE_TYPE (type); scope = current_namespace;
decl = build_lang_decl (VAR_DECL, declarator, type); else if (!at_function_scope_p ())
DECL_CONTEXT (decl) = basetype; {
} scope = current_scope ();
if (!scope)
scope = current_namespace;
}
}
if (scope
&& (/* If the variable is a namespace-scope variable declared in a
template, we need DECL_LANG_SPECIFIC. */
(TREE_CODE (scope) == NAMESPACE_DECL && processing_template_decl)
/* Similarly for namespace-scope variables with language linkage
other than C++. */
|| (TREE_CODE (scope) == NAMESPACE_DECL
&& current_lang_name != lang_name_cplusplus)
/* Similarly for static data members. */
|| TYPE_P (scope)))
decl = build_lang_decl (VAR_DECL, name, type);
else else
{ decl = build_decl (VAR_DECL, name, type);
tree context;
if (in_namespace)
context = in_namespace;
else if (namespace_bindings_p () || RIDBIT_SETP (RID_EXTERN, specbits))
context = current_namespace;
else
context = NULL_TREE;
/* For namespace-scope variables, declared in a template, we
need the full lang_decl. The same is true for
namespace-scope variables that do not have C++ language
linkage. */
if (context
&& (processing_template_decl
|| current_lang_name != lang_name_cplusplus))
decl = build_lang_decl (VAR_DECL, declarator, type);
else
decl = build_decl (VAR_DECL, declarator, type);
if (context)
set_decl_namespace (decl, context, 0);
context = DECL_CONTEXT (decl); if (scope && TREE_CODE (scope) == NAMESPACE_DECL)
if (declarator && context && current_lang_name != lang_name_c) set_decl_namespace (decl, scope, 0);
/* We can't mangle lazily here because we don't have any else
way to recover whether or not a variable was `extern DECL_CONTEXT (decl) = scope;
"C"' later. */
mangle_decl (decl);
}
if (in_namespace) if (name && scope && current_lang_name != lang_name_c)
set_decl_namespace (decl, in_namespace, 0); /* We can't mangle lazily here because we don't have any
way to recover whether or not a variable was `extern
"C"' later. */
mangle_decl (decl);
if (RIDBIT_SETP (RID_EXTERN, specbits)) if (RIDBIT_SETP (RID_EXTERN, specbits))
{ {
...@@ -9320,6 +9324,14 @@ build_ptrmemfunc_type (type) ...@@ -9320,6 +9324,14 @@ build_ptrmemfunc_type (type)
return t; return t;
} }
/* Create and return a pointer to data member type. */
tree
build_ptrmem_type (tree class_type, tree member_type)
{
return build_pointer_type (build_offset_type (class_type, member_type));
}
/* DECL is a VAR_DECL defined in-class, whose TYPE is also given. /* DECL is a VAR_DECL defined in-class, whose TYPE is also given.
Check to see that the definition is valid. Issue appropriate error Check to see that the definition is valid. Issue appropriate error
messages. Return 1 if the definition is particularly bad, or 0 messages. Return 1 if the definition is particularly bad, or 0
...@@ -9811,6 +9823,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ...@@ -9811,6 +9823,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
tree attributes; tree attributes;
if (decl_context != NORMAL)
{
error ("variable declaration is not allowed here");
return error_mark_node;
}
*next = TREE_OPERAND (decl, 0); *next = TREE_OPERAND (decl, 0);
init = CALL_DECLARATOR_PARMS (decl); init = CALL_DECLARATOR_PARMS (decl);
...@@ -9835,7 +9853,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ...@@ -9835,7 +9853,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
} }
else else
error ("invalid declarator"); error ("invalid declarator");
return 0; return NULL_TREE;
} }
innermost_code = TREE_CODE (decl); innermost_code = TREE_CODE (decl);
if (decl_context == FIELD && ctype == NULL_TREE) if (decl_context == FIELD && ctype == NULL_TREE)
...@@ -10580,7 +10598,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ...@@ -10580,7 +10598,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
/* Now figure out the structure of the declarator proper. /* Now figure out the structure of the declarator proper.
Descend through it, creating more complex types, until we reach Descend through it, creating more complex types, until we reach
the declared identifier (or NULL_TREE, in an absolute declarator). */ the declared identifier (or NULL_TREE, in an abstract declarator). */
while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE
&& TREE_CODE (declarator) != TEMPLATE_ID_EXPR) && TREE_CODE (declarator) != TEMPLATE_ID_EXPR)
...@@ -10892,9 +10910,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ...@@ -10892,9 +10910,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
continue; continue;
} }
if (TREE_CODE (type) == OFFSET_TYPE if (ctype
&& (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE && (TREE_CODE (type) == VOID_TYPE
|| TREE_CODE (TREE_TYPE (type)) == REFERENCE_TYPE)) || TREE_CODE (type) == REFERENCE_TYPE))
{ {
error ("cannot declare pointer to `%#T' member", error ("cannot declare pointer to `%#T' member",
TREE_TYPE (type)); TREE_TYPE (type));
...@@ -10917,6 +10935,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ...@@ -10917,6 +10935,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
} }
else if (TREE_CODE (type) == METHOD_TYPE) else if (TREE_CODE (type) == METHOD_TYPE)
type = build_ptrmemfunc_type (build_pointer_type (type)); type = build_ptrmemfunc_type (build_pointer_type (type));
else if (ctype)
type = build_ptrmem_type (ctype, type);
else else
type = build_pointer_type (type); type = build_pointer_type (type);
...@@ -11102,7 +11122,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ...@@ -11102,7 +11122,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
ctype, name, current_class_type); ctype, name, current_class_type);
return void_type_node; return void_type_node;
} }
type = build_offset_type (ctype, type);
} }
else else
{ {
...@@ -11121,14 +11140,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ...@@ -11121,14 +11140,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (declarator && TREE_CODE (declarator) == CALL_EXPR) if (declarator && TREE_CODE (declarator) == CALL_EXPR)
/* In this case, we will deal with it later. */ /* In this case, we will deal with it later. */
; ;
else else if (TREE_CODE (type) == FUNCTION_TYPE)
{ type = build_cplus_method_type (ctype, TREE_TYPE (type),
if (TREE_CODE (type) == FUNCTION_TYPE) TYPE_ARG_TYPES (type));
type = build_cplus_method_type (ctype, TREE_TYPE (type),
TYPE_ARG_TYPES (type));
else
type = build_offset_type (ctype, type);
}
} }
} }
break; break;
...@@ -11846,7 +11860,7 @@ friend declaration requires class-key, i.e. `friend %#T'", ...@@ -11846,7 +11860,7 @@ friend declaration requires class-key, i.e. `friend %#T'",
decl = grokvardecl (type, declarator, &specbits, decl = grokvardecl (type, declarator, &specbits,
initialized, initialized,
(type_quals & TYPE_QUAL_CONST) != 0, (type_quals & TYPE_QUAL_CONST) != 0,
in_namespace); ctype ? ctype : in_namespace);
bad_specifiers (decl, "variable", virtualp, quals != NULL_TREE, bad_specifiers (decl, "variable", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE); inlinep, friendp, raises != NULL_TREE);
......
...@@ -4156,22 +4156,9 @@ parse_finish_call_expr (tree fn, tree args, int koenig) ...@@ -4156,22 +4156,9 @@ parse_finish_call_expr (tree fn, tree args, int koenig)
BASELINK_FUNCTIONS (fn), BASELINK_FUNCTIONS (fn),
template_args); template_args);
} }
if (BASELINK_P (fn) if (current_class_type)
&& current_class_type fn = (adjust_result_of_qualified_name_lookup
&& DERIVED_FROM_P (scope, current_class_type)) (fn, scope, current_class_type));
{
scope = lookup_base (current_class_type, scope,
ba_ignore | ba_quiet, NULL);
if (scope)
{
BASELINK_ACCESS_BINFO (fn) = scope;
BASELINK_BINFO (fn)
= lookup_base (scope,
BINFO_TYPE (BASELINK_BINFO (fn)),
ba_ignore | ba_quiet,
NULL);
}
}
} }
} }
disallow_virtual = true; disallow_virtual = true;
......
...@@ -1640,6 +1640,50 @@ lookup_fnfields_1 (type, name) ...@@ -1640,6 +1640,50 @@ lookup_fnfields_1 (type, name)
return -1; return -1;
} }
/* DECL is the result of a qualified name lookup. QUALIFYING_CLASS
was the class used to qualify the name. CONTEXT_CLASS is the class
corresponding to the object in which DECL will be used. Return a
possibly modified version of DECL that takes into account the
CONTEXT_CLASS.
In particular, consider an expression like `B::m' in the context of
a derived class `D'. If `B::m' has been resolved to a BASELINK,
then the most derived class indicated by the BASELINK_BINFO will be
`B', not `D'. This function makes that adjustment. */
tree
adjust_result_of_qualified_name_lookup (tree decl,
tree qualifying_class,
tree context_class)
{
my_friendly_assert (CLASS_TYPE_P (qualifying_class), 20020808);
my_friendly_assert (CLASS_TYPE_P (context_class), 20020808);
if (BASELINK_P (decl)
&& DERIVED_FROM_P (qualifying_class, context_class))
{
tree base;
/* Look for the QUALIFYING_CLASS as a base of the
CONTEXT_CLASS. If QUALIFYING_CLASS is ambiguous, we cannot
be sure yet than an error has occurred; perhaps the function
chosen by overload resolution will be static. */
base = lookup_base (context_class, qualifying_class,
ba_ignore | ba_quiet, NULL);
if (base)
{
BASELINK_ACCESS_BINFO (decl) = base;
BASELINK_BINFO (decl)
= lookup_base (base, BINFO_TYPE (BASELINK_BINFO (decl)),
ba_ignore | ba_quiet,
NULL);
}
}
return decl;
}
/* Walk the class hierarchy dominated by TYPE. FN is called for each /* Walk the class hierarchy dominated by TYPE. FN is called for each
type in the hierarchy, in a breadth-first preorder traversal. type in the hierarchy, in a breadth-first preorder traversal.
......
...@@ -203,28 +203,33 @@ qualify_type_recursive (t1, t2) ...@@ -203,28 +203,33 @@ qualify_type_recursive (t1, t2)
if ((TYPE_PTR_P (t1) && TYPE_PTR_P (t2)) if ((TYPE_PTR_P (t1) && TYPE_PTR_P (t2))
|| (TYPE_PTRMEM_P (t1) && TYPE_PTRMEM_P (t2))) || (TYPE_PTRMEM_P (t1) && TYPE_PTRMEM_P (t2)))
{ {
tree tt1 = TREE_TYPE (t1); tree tt1;
tree tt2 = TREE_TYPE (t2); tree tt2;
tree b1; tree b1;
int type_quals; int type_quals;
tree tgt; tree tgt;
tree attributes = (*targetm.merge_type_attributes) (t1, t2); tree attributes = (*targetm.merge_type_attributes) (t1, t2);
if (TREE_CODE (tt1) == OFFSET_TYPE) if (TYPE_PTRMEM_P (t1))
{ {
b1 = TYPE_OFFSET_BASETYPE (tt1); b1 = TYPE_PTRMEM_CLASS_TYPE (t1);
tt1 = TREE_TYPE (tt1); tt1 = TYPE_PTRMEM_POINTED_TO_TYPE (t1);
tt2 = TREE_TYPE (tt2); tt2 = TYPE_PTRMEM_POINTED_TO_TYPE (t2);
} }
else else
b1 = NULL_TREE; {
b1 = NULL_TREE;
tt1 = TREE_TYPE (t1);
tt2 = TREE_TYPE (t2);
}
type_quals = (cp_type_quals (tt1) | cp_type_quals (tt2)); type_quals = (cp_type_quals (tt1) | cp_type_quals (tt2));
tgt = qualify_type_recursive (tt1, tt2); tgt = qualify_type_recursive (tt1, tt2);
tgt = cp_build_qualified_type (tgt, type_quals); tgt = cp_build_qualified_type (tgt, type_quals);
if (b1) if (b1)
tgt = build_offset_type (b1, tgt); t1 = build_ptrmem_type (b1, tgt);
t1 = build_pointer_type (tgt); else
t1 = build_pointer_type (tgt);
t1 = build_type_attribute_variant (t1, attributes); t1 = build_type_attribute_variant (t1, attributes);
} }
return t1; return t1;
...@@ -4390,9 +4395,7 @@ unary_complex_lvalue (code, arg) ...@@ -4390,9 +4395,7 @@ unary_complex_lvalue (code, arg)
return error_mark_node; return error_mark_node;
} }
type = build_offset_type (DECL_FIELD_CONTEXT (t), TREE_TYPE (t)); type = build_ptrmem_type (DECL_FIELD_CONTEXT (t), TREE_TYPE (t));
type = build_pointer_type (type);
t = make_ptrmem_cst (type, TREE_OPERAND (arg, 1)); t = make_ptrmem_cst (type, TREE_OPERAND (arg, 1));
return t; return t;
} }
......
2002-08-09 Mark Mitchell <mark@codesourcery.com>
* g++.dg/template/crash1.C: New test.
2002-08-08 Jakub Jelinek <jakub@redhat.com> 2002-08-08 Jakub Jelinek <jakub@redhat.com>
* gcc.dg/tls/opt-2.c: New test. * gcc.dg/tls/opt-2.c: New test.
......
// { dg-do compile } // { dg-do compile }
// Copyright (C) 2001 Free Software Foundation, Inc. // Copyright (C) 2001, 2002 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 29 Dec 2001 <nathan@nathan@codesourcery.com> // Contributed by Nathan Sidwell 29 Dec 2001 <nathan@codesourcery.com>
// PR 5125. ICE // PR 5125. ICE
...@@ -13,5 +13,5 @@ class S ...@@ -13,5 +13,5 @@ class S
template <class I> template <class I>
void S::Foo(int (*f)(TYPO&o) ) void S::Foo(int (*f)(TYPO&o) )
{ // { dg-error "template definition of non-template|prototype" "" } { // { dg-error "template definition|variable declaration|prototype" "" }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment