summaryrefslogtreecommitdiffstats
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog42
-rw-r--r--gcc/cp/class.c30
-rw-r--r--gcc/cp/cvt.c31
-rw-r--r--gcc/cp/decl.c218
-rw-r--r--gcc/cp/decl2.c29
-rw-r--r--gcc/cp/pt.c33
-rw-r--r--gcc/cp/tree.c17
-rw-r--r--gcc/testsuite/g++.old-deja/g++.eh/tmpl3.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.ns/crash3.C10
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/expr1.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/lookup8.C14
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/array2.C14
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/memtemp81.C24
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/overload11.C27
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/ptrmem4.C28
15 files changed, 399 insertions, 126 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 84cc28fa1b7..78658fd0169 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,45 @@
+1998-12-14 Mark Mitchell <mark@markmitchell.com>
+
+ * class.c (pushclass): Tweak handling of class-level bindings.
+ (resolve_address_of_overloaded_function): Update pointer-to-member
+ handling.
+ (instantiate_type): Likewise.
+ * cvt.c (cp_convert_to_pointer): Likewise.
+ * decl.c (pop_binding): Take the DECL to pop, not just the name.
+ Deal with `struct stat' hack.
+ (binding_level): Add to documentation.
+ (push_binding): Clear BINDING_TYPE.
+ (add_binding): New function.
+ (push_local_binding): Use it.
+ (push_class_binding): Likewise.
+ (poplevel): Adjust calls to pop_binding.
+ (poplevel_class): Likewise.
+ (pushdecl): Adjust handling of TYPE_DECLs; add bindings for hidden
+ declarations to current binding level.
+ (push_class_level_binding): Likewise.
+ (push_overloaded_decl): Adjust handling of OVERLOADs in local
+ bindings.
+ (lookup_namespace_name): Don't crash when confronted with a
+ TEMPLATE_DECL.
+ (lookup_name_real): Do `struct stat' hack in local binding
+ contexts.
+ (build_ptrmemfunc_type): Adjust documentation.
+ (grokdeclarator): Don't avoid building real array types when
+ processing templates unless really necessary.
+ (finish_method): Adjust calls to pop_binding.
+ * decl2.c (reparse_absdcl_as_expr): Recursively call ourselves,
+ not reparse_decl_as_expr.
+ (build_expr_from_tree): Deal with a template-id as the function to
+ call in a METHOD_CALL_EXPR.
+ * pt.c (convert_nontype_argument): Tweak pointer-to-member handling.
+ (maybe_adjust_types_For_deduction): Don't do peculiar things with
+ METHOD_TYPEs here.
+ (resolve_overloaded_unification): Handle COMPONENT_REFs. Build
+ pointer-to-member types where necessary.
+ * tree.c (build_cplus_array_type_1): Don't avoid building real
+ array types when processing templates unless really necessary.
+ (build_exception_variant): Compare the exception lists correctly.
+
1998-12-13 Mark Mitchell <mark@markmitchell.com>
* cp-tree.def (CPLUS_BINDING): Update documentation.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 5031b556917..e3f4544481b 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -4789,7 +4789,7 @@ pushclass (type, modify)
for (item = previous_class_values; item; item = TREE_CHAIN (item))
{
tree id = TREE_PURPOSE (item);
- tree decl = IDENTIFIER_CLASS_VALUE (id);
+ tree decl = TREE_TYPE (item);
push_class_binding (id, decl);
if (TREE_CODE (decl) == TYPE_DECL)
@@ -4808,8 +4808,6 @@ pushclass (type, modify)
if (! (IS_AGGR_TYPE_CODE (TREE_CODE (tag_type))
&& CLASSTYPE_IS_TEMPLATE (tag_type)))
pushtag (TREE_PURPOSE (tags), tag_type, 0);
- else
- pushdecl_class_level (CLASSTYPE_TI_TEMPLATE (tag_type));
}
current_function_decl = this_fndecl;
@@ -5028,11 +5026,12 @@ resolve_address_of_overloaded_function (target_type,
interoperability with most_specialized_instantiation. */
tree matches = NULL_TREE;
- /* If the TARGET_TYPE is a pointer-to-a-method, we convert it to
- proper pointer-to-member type here. */
- if (TREE_CODE (target_type) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (target_type)) == METHOD_TYPE)
- target_type = build_ptrmemfunc_type (target_type);
+ /* By the time we get here, we should be seeing only real
+ pointer-to-member types, not the internal POINTER_TYPE to
+ METHOD_TYPE representation. */
+ my_friendly_assert (!(TREE_CODE (target_type) == POINTER_TYPE
+ && (TREE_CODE (TREE_TYPE (target_type))
+ == METHOD_TYPE)), 0);
/* Check that the TARGET_TYPE is reasonable. */
if (TYPE_PTRFN_P (target_type))
@@ -5475,15 +5474,20 @@ instantiate_type (lhstype, rhs, complain)
if (fn == error_mark_node)
return error_mark_node;
mark_addressable (fn);
- TREE_TYPE (rhs) = lhstype;
TREE_OPERAND (rhs, 0) = fn;
TREE_CONSTANT (rhs) = staticp (fn);
- if (TREE_CODE (lhstype) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (lhstype)) == METHOD_TYPE)
+ if (TYPE_PTRMEMFUNC_P (lhstype))
{
- build_ptrmemfunc_type (lhstype);
- rhs = build_ptrmemfunc (lhstype, rhs, 0);
+ /* We must use the POINTER_TYPE to METHOD_TYPE on RHS here
+ so that build_ptrmemfunc knows that RHS we have is not
+ already a pointer-to-member constant. Instead, it is
+ just a ADDR_EXPR over a FUNCTION_DECL. */
+ TREE_TYPE (rhs) = TYPE_PTRMEMFUNC_FN_TYPE (lhstype);
+ rhs = build_ptrmemfunc (TREE_TYPE (rhs), rhs, 0);
}
+ else
+ /* Here, things our simple; we have exactly what we need. */
+ TREE_TYPE (rhs) = lhstype;
}
return rhs;
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index a5a91c16238..c8f9fcc57e9 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -95,9 +95,6 @@ cp_convert_to_pointer (type, expr)
}
}
- if (TYPE_PTRMEMFUNC_P (type))
- type = TYPE_PTRMEMFUNC_FN_TYPE (type);
-
/* Handle anachronistic conversions from (::*)() to cv void* or (*)(). */
if (TREE_CODE (type) == POINTER_TYPE
&& (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
@@ -128,16 +125,14 @@ cp_convert_to_pointer (type, expr)
intype = TREE_TYPE (expr);
}
- if (TYPE_PTRMEMFUNC_P (intype))
- intype = TYPE_PTRMEMFUNC_FN_TYPE (intype);
-
form = TREE_CODE (intype);
- if (form == POINTER_TYPE || form == REFERENCE_TYPE)
+ if (POINTER_TYPE_P (intype))
{
intype = TYPE_MAIN_VARIANT (intype);
if (TYPE_MAIN_VARIANT (type) != intype
+ && TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
&& IS_AGGR_TYPE (TREE_TYPE (type))
&& IS_AGGR_TYPE (TREE_TYPE (intype))
@@ -181,12 +176,9 @@ cp_convert_to_pointer (type, expr)
}
}
}
- if (TREE_CODE (TREE_TYPE (intype)) == METHOD_TYPE
- && TREE_CODE (type) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
- return build_ptrmemfunc (type, expr, 1);
- if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE
+ if (TREE_CODE (type) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE
&& TREE_CODE (TREE_TYPE (intype)) == OFFSET_TYPE)
{
tree b1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (type));
@@ -205,10 +197,7 @@ cp_convert_to_pointer (type, expr)
if (binfo && ! TREE_VIA_VIRTUAL (binfo))
expr = size_binop (code, expr, BINFO_OFFSET (binfo));
}
-
- if (TREE_CODE (TREE_TYPE (intype)) == METHOD_TYPE
- || (TREE_CODE (type) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE))
+ else if (TYPE_PTRMEMFUNC_P (type))
{
cp_error ("cannot convert `%E' from type `%T' to type `%T'",
expr, intype, type);
@@ -219,6 +208,14 @@ cp_convert_to_pointer (type, expr)
TREE_CONSTANT (rval) = TREE_CONSTANT (expr);
return rval;
}
+ else if (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))
+ return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 1);
+ else if (TYPE_PTRMEMFUNC_P (intype))
+ {
+ cp_error ("cannot convert `%E' from type `%T' to type `%T'",
+ expr, intype, type);
+ return error_mark_node;
+ }
my_friendly_assert (form != OFFSET_TYPE, 186);
@@ -228,7 +225,7 @@ cp_convert_to_pointer (type, expr)
if (integer_zerop (expr))
{
- if (TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
+ if (TYPE_PTRMEMFUNC_P (type))
return build_ptrmemfunc (type, expr, 0);
expr = build_int_2 (0, 0);
TREE_TYPE (expr) = type;
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 7c9a518e161..8940acb3ea0 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -180,7 +180,8 @@ static void check_for_uninitialized_const_var PROTO((tree));
static unsigned long typename_hash PROTO((hash_table_key));
static boolean typename_compare PROTO((hash_table_key, hash_table_key));
static void push_binding PROTO((tree, tree, struct binding_level*));
-static void pop_binding PROTO((tree));
+static void add_binding PROTO((tree, tree));
+static void pop_binding PROTO((tree, tree));
#if defined (DEBUG_CP_BINDING_LEVELS)
static void indent PROTO((void));
@@ -602,7 +603,10 @@ push_decl_level (stack, obstack)
to catch class-local declarations. It is otherwise nonexistent.
Also there may be binding levels that catch cleanups that must be
- run when exceptions occur. */
+ run when exceptions occur. Thus, to see whether a name is bound in
+ the current scope, it is not enough to look in the
+ CURRENT_BINDING_LEVEL. You should use lookup_name_current_level
+ instead. */
/* Note that the information in the `names' component of the global contour
is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
@@ -637,7 +641,8 @@ struct binding_level
is the name of an entity bound in the class; the TREE_VALUE is
the IDENTIFIER_CLASS_VALUE before we entered the class. Thus,
when leaving class scope, we can restore the
- IDENTIFIER_CLASS_VALUE by walking this list. */
+ IDENTIFIER_CLASS_VALUE by walking this list. The TREE_TYPE is
+ the DECL bound by this name in the class. */
tree class_shadowed;
/* Similar to class_shadowed, but for IDENTIFIER_TYPE_VALUE, and
@@ -1072,6 +1077,7 @@ push_binding (id, decl, level)
/* Now, fill in the binding information. */
BINDING_VALUE (binding) = decl;
+ BINDING_TYPE (binding) = NULL_TREE;
BINDING_LEVEL (binding) = level;
LOCAL_BINDING_P (binding) = (level != class_binding_level);
@@ -1080,6 +1086,38 @@ push_binding (id, decl, level)
IDENTIFIER_BINDING (id) = binding;
}
+/* ID is already bound in the current scope. But, DECL is an
+ additional binding for ID in the same scope. This is the `struct
+ stat' hack whereby a non-typedef class-name or enum-name can be
+ bound at the same level as some other kind of entity. It's the
+ responsibility of the caller to check that inserting this name is
+ legal here. */
+static void
+add_binding (id, decl)
+ tree id;
+ tree decl;
+{
+ tree binding = IDENTIFIER_BINDING (id);
+
+ if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
+ /* The new name is the type name. */
+ BINDING_TYPE (binding) = decl;
+ else
+ {
+ /* The old name must be the type name. It was placed in
+ IDENTIFIER_VALUE because it was thought, at the point it
+ was declared, to be the only entity with such a name. */
+ my_friendly_assert (TREE_CODE (BINDING_VALUE (binding)) == TYPE_DECL
+ && DECL_ARTIFICIAL (BINDING_VALUE (binding)),
+ 0);
+
+ /* Move the type name into the type slot; it is now hidden by
+ the new binding. */
+ BINDING_TYPE (binding) = BINDING_VALUE (binding);
+ BINDING_VALUE (binding) = decl;
+ }
+}
+
/* Bind DECL to ID in the current_binding_level. */
void
@@ -1087,15 +1125,19 @@ push_local_binding (id, decl)
tree id;
tree decl;
{
- tree d = decl;;
+ tree d = decl;
if (TREE_CODE (decl) == OVERLOAD)
/* We must put the OVERLOAD into a TREE_LIST since the
TREE_CHAIN of an OVERLOAD is already used. */
decl = build_tree_list (NULL_TREE, decl);
- /* Create a binding, hanging off of ID. */
- push_binding (id, d, current_binding_level);
+ if (lookup_name_current_level (id))
+ /* Supplement the existing binding. */
+ add_binding (id, decl);
+ else
+ /* Create a new binding. */
+ push_binding (id, d, current_binding_level);
/* And put DECL on the list of things declared by the current
binding level. */
@@ -1110,32 +1152,63 @@ push_class_binding (id, decl)
tree id;
tree decl;
{
- push_binding (id, decl, class_binding_level);
+ if (IDENTIFIER_BINDING (id)
+ && BINDING_LEVEL (IDENTIFIER_BINDING (id)) == class_binding_level)
+ /* Supplement the existing binding. */
+ add_binding (id, decl);
+ else
+ /* Create a new binding. */
+ push_binding (id, decl, class_binding_level);
+
+ /* Update the IDENTIFIER_CLASS_VALUE for this ID to be the
+ class-level declaration. Note that we do not use DECL here
+ because of the possibility of the `struct stat' hack; if DECL is
+ a class-name or enum-name we might prefer a field-name, or some
+ such. */
+ IDENTIFIER_CLASS_VALUE (id) = BINDING_VALUE (IDENTIFIER_BINDING (id));
}
-/* Remove the innermost binding for ID; it has gone out of scope. */
+/* Remove the binding for DECL which should be the innermost binding
+ for ID. */
static void
-pop_binding (id)
+pop_binding (id, decl)
tree id;
+ tree decl;
{
tree binding;
-
+
if (id == NULL_TREE)
/* It's easiest to write the loops that call this function without
checking whether or not the entities involved have names. We
get here for such an entity. */
return;
- my_friendly_assert (IDENTIFIER_BINDING (id) != NULL_TREE, 0);
-
- /* Unhook the innermost binding from the list of bindings. */
+ /* Get the innermost binding for ID. */
binding = IDENTIFIER_BINDING (id);
- IDENTIFIER_BINDING (id) = TREE_CHAIN (binding);
- /* And place this list node on the free list. */
- TREE_CHAIN (binding) = free_binding_nodes;
- free_binding_nodes = binding;
+ /* The name should be bound. */
+ my_friendly_assert (binding != NULL_TREE, 0);
+
+ /* The DECL will be either the ordinary binding or the type
+ binding for this identifier. Remove that binding. */
+ if (BINDING_VALUE (binding) == decl)
+ BINDING_VALUE (binding) = NULL_TREE;
+ else if (BINDING_TYPE (binding) == decl)
+ BINDING_TYPE (binding) = NULL_TREE;
+ else
+ my_friendly_abort (0);
+
+ if (!BINDING_VALUE (binding) && !BINDING_TYPE (binding))
+ {
+ /* We're completely done with the innermost binding for this
+ identifier. Unhook it from the list of bindings. */
+ IDENTIFIER_BINDING (id) = TREE_CHAIN (binding);
+
+ /* And place it on the free list. */
+ TREE_CHAIN (binding) = free_binding_nodes;
+ free_binding_nodes = binding;
+ }
}
/* Exit a binding level.
@@ -1303,7 +1376,7 @@ poplevel (keep, reverse, functionbody)
and we are leaving the `for' scope. There's no reason to
keep the binding of the inner `i' in this case. */
- pop_binding (DECL_NAME (link));
+ pop_binding (DECL_NAME (link), link);
else if ((outer_binding
&& (TREE_CODE (BINDING_VALUE (outer_binding))
== TYPE_DECL))
@@ -1319,7 +1392,7 @@ poplevel (keep, reverse, functionbody)
We must pop the for-scope binding so we know what's a
type and what isn't. */
- pop_binding (DECL_NAME (link));
+ pop_binding (DECL_NAME (link), link);
else
{
/* Mark this VAR_DECL as dead so that we can tell we left it
@@ -1350,10 +1423,11 @@ poplevel (keep, reverse, functionbody)
{
/* Remove the binding. */
if (TREE_CODE_CLASS (TREE_CODE (link)) == 'd')
- pop_binding (DECL_NAME (link));
+ pop_binding (DECL_NAME (link), link);
else if (TREE_CODE (link) == TREE_LIST)
- pop_binding (DECL_NAME (OVL_FUNCTION (TREE_VALUE (link))));
- else
+ pop_binding (DECL_NAME (OVL_FUNCTION (TREE_VALUE (link))),
+ TREE_VALUE (link));
+ else
my_friendly_abort (0);
}
}
@@ -1362,7 +1436,7 @@ poplevel (keep, reverse, functionbody)
that we kept around. */
for (link = current_binding_level->dead_vars_from_for;
link; link = TREE_CHAIN (link))
- pop_binding (DECL_NAME (TREE_VALUE (link)));
+ pop_binding (DECL_NAME (TREE_VALUE (link)), TREE_VALUE (link));
/* Restore the IDENTIFIER_TYPE_VALUEs. */
for (link = current_binding_level->type_shadowed;
@@ -1607,7 +1681,7 @@ poplevel_class (force)
for (shadowed = level->class_shadowed;
shadowed;
shadowed = TREE_CHAIN (shadowed))
- pop_binding (TREE_PURPOSE (shadowed));
+ pop_binding (TREE_PURPOSE (shadowed), TREE_TYPE (shadowed));
GNU_xref_end_scope ((HOST_WIDE_INT) class_binding_level,
(HOST_WIDE_INT) class_binding_level->level_chain,
@@ -3617,12 +3691,6 @@ pushdecl (x)
set_identifier_type_value_with_scope (DECL_NAME (x), type,
current_binding_level);
- if (TREE_CODE (x) == TYPE_DECL
- && DECL_ARTIFICIAL (x)
- && t != NULL_TREE)
- /* We don't want an artificial TYPE_DECL is we already
- have another DECL with the same name. */
- need_new_binding = 0;
}
/* Multiple external decls of the same identifier ought to match.
@@ -3663,7 +3731,8 @@ pushdecl (x)
if (IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE && TREE_PUBLIC (x))
TREE_PUBLIC (name) = 1;
- if (need_new_binding)
+ if (!(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)
+ && t != NULL_TREE))
{
if (TREE_CODE (x) == FUNCTION_DECL)
my_friendly_assert
@@ -3999,23 +4068,20 @@ push_class_level_binding (name, x)
if (!class_binding_level)
return;
- if (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)
- && purpose_member (name, class_binding_level->class_shadowed))
- return;
-
/* If this declaration shadows a declaration from an enclosing
class, then we will need to restore IDENTIFIER_CLASS_VALUE when
we leave this class. Record the shadowed declaration here. */
maybe_push_cache_obstack ();
class_binding_level->class_shadowed
- = tree_cons (name, IDENTIFIER_CLASS_VALUE (name),
- class_binding_level->class_shadowed);
+ = tree_cons (name, IDENTIFIER_CLASS_VALUE (name),
+ class_binding_level->class_shadowed);
+ TREE_TYPE (class_binding_level->class_shadowed)
+ = x;
pop_obstacks ();
/* Put the binding on the stack of bindings for the identifier, and
update IDENTIFIER_CLASS_VALUE. */
push_class_binding (name, x);
- IDENTIFIER_CLASS_VALUE (name) = x;
obstack_ptr_grow (&decl_obstack, x);
}
@@ -4155,8 +4221,8 @@ push_overloaded_decl (decl, forgettable)
/* We only create an OVERLOAD if there was a previous binding at
this level. In that case, we need to remove the old binding
and replace it with the new binding. We must also run
- through the NAMES on the current binding level to update the
- chain. */
+ through the NAMES on the binding level where the name was
+ bound to update the chain. */
if (TREE_CODE (new_binding) == OVERLOAD)
{
tree *d;
@@ -4168,11 +4234,21 @@ push_overloaded_decl (decl, forgettable)
|| (TREE_CODE (*d) == TREE_LIST
&& TREE_VALUE (*d) == old))
{
- *d = TREE_CHAIN (*d);
- break;
+ if (TREE_CODE (*d) == TREE_LIST)
+ /* Just replace the old binding with the new. */
+ TREE_VALUE (*d) = new_binding;
+ else
+ /* Build a TREE_LIST to wrap the OVERLOAD. */
+ *d = build_tree_list (NULL_TREE, new_binding);
+
+ /* And update the CPLUS_BINDING node. */
+ BINDING_VALUE (IDENTIFIER_BINDING (name))
+ = new_binding;
+ return decl;
}
- pop_binding (name);
+ /* We should always find a previous binding in this case. */
+ my_friendly_abort (0);
}
/* Install the new binding. */
@@ -4887,9 +4963,16 @@ lookup_namespace_name (namespace, name)
my_friendly_assert (TREE_CODE (namespace) == NAMESPACE_DECL, 370);
- /* This happens for A::B<int> when B is a namespace. */
if (TREE_CODE (name) == NAMESPACE_DECL)
+ /* This happens for A::B<int> when B is a namespace. */
return name;
+ else if (TREE_CODE (name) == TEMPLATE_DECL)
+ {
+ /* This happens for A::B where B is a template, and there are no
+ template arguments. */
+ cp_error ("invalid use of `%D'", name);
+ return error_mark_node;
+ }
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373);
@@ -5321,15 +5404,27 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
else
flags = lookup_flags (prefer_type, namespaces_only);
- /* First, look in a non-global scope, carefully avoiding any
- class-scope bindings if required. */
+ /* First, look in non-namespace scopes. */
val = IDENTIFIER_BINDING (name);
- while (val && nonclass && !LOCAL_BINDING_P (val))
- val = TREE_CHAIN (val);
-
- /* Get the DECL actually bound. */
- if (val)
- val = BINDING_VALUE (val);
+ for (val = IDENTIFIER_BINDING (name); val; val = TREE_CHAIN (val))
+ {
+ if (!LOCAL_BINDING_P (val) && nonclass)
+ /* We're not looking for class-scoped bindings, so keep going. */
+ continue;
+
+ /* If this is the kind of thing we're looking for, we're done. */
+ if (qualify_lookup (BINDING_VALUE (val), flags))
+ {
+ val = BINDING_VALUE (val);
+ break;
+ }
+ else if ((flags & LOOKUP_PREFER_TYPES)
+ && qualify_lookup (BINDING_TYPE (val), flags))
+ {
+ val = BINDING_TYPE (val);
+ break;
+ }
+ }
/* If VAL is a type from a dependent base, we're not really supposed
to be able to see it; the fact that we can is the "implicit
@@ -5342,10 +5437,6 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
&& uses_template_parms (current_class_type))
val = lookup_field (current_class_type, name, 0, 1);
- /* Make sure that this binding is the sort of thing we're looking
- for. */
- val = qualify_lookup (val, flags);
-
/* We don't put names from baseclasses onto the IDENTIFIER_BINDING
list when we're defining a type. It would probably be simpler to
do this, but we don't. So, we must lookup names from base
@@ -5361,8 +5452,8 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
}
/* If we found a type from a dependent base class (using the
- implicit typename extension), turn it into the TYPE_DECL for a
- TYPENAME_TYPE here. */
+ implicit typename extension) make sure that there's not some
+ global name which should be chosen instead. */
if (val && TREE_CODE (val) == TYPE_DECL
&& IMPLICIT_TYPENAME_P (TREE_TYPE (val)))
{
@@ -8575,7 +8666,8 @@ grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
return decl;
}
-/* Create a canonical pointer to member function type. */
+/* Create and return a canonical pointer to member function type, for
+ TYPE, which is a POINTER_TYPE to a METHOD_TYPE. */
tree
build_ptrmemfunc_type (type)
@@ -9790,7 +9882,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
/* If this involves a template parameter, it'll be
constant, but we don't know what the value is yet. */
- if (processing_template_decl)
+ if (uses_template_parms (size))
{
/* Resolve a qualified reference to an enumerator or
static const data member of ours. */
@@ -10141,9 +10233,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
type = build_reference_type (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
type = build_pointer_type (type);
@@ -13976,7 +14066,7 @@ finish_method (decl)
for (link = current_binding_level->names; link; link = TREE_CHAIN (link))
{
if (DECL_NAME (link) != NULL_TREE)
- pop_binding (DECL_NAME (link));
+ pop_binding (DECL_NAME (link), link);
my_friendly_assert (TREE_CODE (link) != FUNCTION_DECL, 163);
DECL_CONTEXT (link) = NULL_TREE;
}
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 630e262183f..fba06619cfb 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -3547,7 +3547,7 @@ reparse_absdcl_as_expr (type, decl)
return build_functional_cast (type, NULL_TREE);
/* recurse */
- decl = reparse_decl_as_expr (type, TREE_OPERAND (decl, 0));
+ decl = reparse_absdcl_as_expr (type, TREE_OPERAND (decl, 0));
decl = build_x_function_call (decl, NULL_TREE, current_class_ref);
@@ -3770,11 +3770,28 @@ build_expr_from_tree (t)
TREE_OPERAND (ref, 1),
build_expr_from_tree (TREE_OPERAND (t, 2)));
}
- return build_method_call
- (build_expr_from_tree (TREE_OPERAND (t, 1)),
- TREE_OPERAND (t, 0),
- build_expr_from_tree (TREE_OPERAND (t, 2)),
- NULL_TREE, LOOKUP_NORMAL);
+ else
+ {
+ tree fn = TREE_OPERAND (t, 0);
+
+ /* We can get a TEMPLATE_ID_EXPR here on code like:
+
+ x->f<2>();
+
+ so we must resolve that. However, we can also get things
+ like a BIT_NOT_EXPR here, when referring to a destructor,
+ and things like that are not correctly resolved by
+ build_expr_from_tree. So, just use build_expr_from_tree
+ when we really need it. */
+ if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
+ fn = build_expr_from_tree (fn);
+
+ return build_method_call
+ (build_expr_from_tree (TREE_OPERAND (t, 1)),
+ fn,
+ build_expr_from_tree (TREE_OPERAND (t, 2)),
+ NULL_TREE, LOOKUP_NORMAL);
+ }
case CALL_EXPR:
if (TREE_CODE (TREE_OPERAND (t, 0)) == SCOPE_REF)
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index bdf85dd760f..ece3f29c841 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -2710,9 +2710,6 @@ convert_nontype_argument (type, expr)
case RECORD_TYPE:
{
- tree fns;
- tree fn;
-
if (!TYPE_PTRMEMFUNC_P (type))
/* This handles templates like
template<class T, T t> void f();
@@ -2743,16 +2740,11 @@ convert_nontype_argument (type, expr)
if (TREE_CODE (expr) != ADDR_EXPR)
return error_mark_node;
- fns = TREE_OPERAND (expr, 0);
-
- fn = instantiate_type (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type)),
- fns, 0);
+ expr = instantiate_type (type, expr, 0);
- if (fn == error_mark_node)
+ if (expr == error_mark_node)
return error_mark_node;
- expr = build_unary_op (ADDR_EXPR, fn, 0);
-
my_friendly_assert (same_type_p (type, TREE_TYPE (expr)),
0);
return expr;
@@ -6972,8 +6964,7 @@ maybe_adjust_types_for_deduction (strict, parm, arg)
deduction. */
if (TREE_CODE (*arg) == ARRAY_TYPE)
*arg = build_pointer_type (TREE_TYPE (*arg));
- else if (TREE_CODE (*arg) == FUNCTION_TYPE
- || TREE_CODE (*arg) == METHOD_TYPE)
+ else if (TREE_CODE (*arg) == FUNCTION_TYPE)
*arg = build_pointer_type (*arg);
else
*arg = TYPE_MAIN_VARIANT (*arg);
@@ -7163,6 +7154,11 @@ resolve_overloaded_unification (tparms, targs, parm, arg, strict,
if (TREE_CODE (arg) == ADDR_EXPR)
arg = TREE_OPERAND (arg, 0);
+ if (TREE_CODE (arg) == COMPONENT_REF)
+ /* Handle `&x' where `x' is some static or non-static member
+ function name. */
+ arg = TREE_OPERAND (arg, 1);
+
/* Strip baselink information. */
while (TREE_CODE (arg) == TREE_LIST)
arg = TREE_VALUE (arg);
@@ -7188,6 +7184,8 @@ resolve_overloaded_unification (tparms, targs, parm, arg, strict,
if (subargs)
{
elem = tsubst (TREE_TYPE (fn), subargs, NULL_TREE);
+ if (TREE_CODE (elem) == METHOD_TYPE)
+ elem = build_ptrmemfunc_type (build_pointer_type (elem));
good += try_one_overload (tparms, targs, tempargs, parm, elem,
strict, sub_strict, explicit_mask);
}
@@ -7196,9 +7194,14 @@ resolve_overloaded_unification (tparms, targs, parm, arg, strict,
else if (TREE_CODE (arg) == OVERLOAD)
{
for (; arg; arg = OVL_NEXT (arg))
- good += try_one_overload (tparms, targs, tempargs, parm,
- TREE_TYPE (OVL_CURRENT (arg)),
- strict, sub_strict, explicit_mask);
+ {
+ tree type = TREE_TYPE (OVL_CURRENT (arg));
+ if (TREE_CODE (type) == METHOD_TYPE)
+ type = build_ptrmemfunc_type (build_pointer_type (type));
+ good += try_one_overload (tparms, targs, tempargs, parm,
+ type,
+ strict, sub_strict, explicit_mask);
+ }
}
else
my_friendly_abort (981006);
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 7660d386217..8bb750a6617 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -416,7 +416,7 @@ build_cplus_array_type_1 (elt_type, index_type)
saveable_obstack = &permanent_obstack;
}
- if (processing_template_decl
+ if (uses_template_parms (elt_type)
|| uses_template_parms (index_type))
{
t = make_node (ARRAY_TYPE);
@@ -1467,15 +1467,20 @@ build_exception_variant (type, raises)
for (; v; v = TYPE_NEXT_VARIANT (v))
{
+ tree t;
+ tree u;
+
if (TYPE_QUALS (v) != type_quals)
continue;
- /* @@ This should do set equality, not exact match. */
- if (simple_cst_list_equal (TYPE_RAISES_EXCEPTIONS (v), raises))
- /* List of exceptions raised matches previously found list.
+ for (t = TYPE_RAISES_EXCEPTIONS (v), u = raises;
+ t != NULL_TREE && u != NULL_TREE;
+ t = TREE_CHAIN (t), u = TREE_CHAIN (v))
+ if (!same_type_p (TREE_VALUE (t), TREE_VALUE (u)))
+ break;
- @@ Nice to free up storage used in consing up the
- @@ list of exceptions raised. */
+ if (!t && !u)
+ /* There's a memory leak here; RAISES is not freed. */
return v;
}
diff --git a/gcc/testsuite/g++.old-deja/g++.eh/tmpl3.C b/gcc/testsuite/g++.old-deja/g++.eh/tmpl3.C
index 738e7d85825..521315e17e2 100644
--- a/gcc/testsuite/g++.old-deja/g++.eh/tmpl3.C
+++ b/gcc/testsuite/g++.old-deja/g++.eh/tmpl3.C
@@ -3,9 +3,9 @@
// Posted by Trevor Taylor <ttaylor@powerup.com.au>
template<class T> struct A {
- void X() throw(T); // gets bogus error - previous decl - XFAIL *-*-*
+ void X() throw(T);
};
template<class T>
inline void A<T>::X()
-throw(T) { } // gets bogus error - different throws - XFAIL *-*-*
+throw(T) { }
diff --git a/gcc/testsuite/g++.old-deja/g++.ns/crash3.C b/gcc/testsuite/g++.old-deja/g++.ns/crash3.C
new file mode 100644
index 00000000000..842ed090bcc
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.ns/crash3.C
@@ -0,0 +1,10 @@
+// Build don't link:
+
+namespace N {
+ template <class T> struct S;
+};
+
+void f()
+{
+ N::S(); // ERROR - invalid use of template
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/expr1.C b/gcc/testsuite/g++.old-deja/g++.other/expr1.C
index 0f5fdcf12ee..fece8d48c29 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/expr1.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/expr1.C
@@ -1,11 +1,9 @@
// Build don't link:
-// crash test - XFAIL *-*-*
-
// Simplified from bug report by Trevor Taylor <ttaylor@powerup.com.au>
struct T {
- int operator()(int) { }
+ int operator()(int) { } // ERROR - candidate
};
int main() {
diff --git a/gcc/testsuite/g++.old-deja/g++.other/lookup8.C b/gcc/testsuite/g++.old-deja/g++.other/lookup8.C
new file mode 100644
index 00000000000..f81572ab260
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.other/lookup8.C
@@ -0,0 +1,14 @@
+// Build don't link:
+
+struct S {
+ int A;
+ struct A {
+ enum { a = 0 };
+ };
+
+ void f();
+};
+
+void S::f() {
+ A = A::a;
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/array2.C b/gcc/testsuite/g++.old-deja/g++.pt/array2.C
new file mode 100644
index 00000000000..6c5810ed77b
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.pt/array2.C
@@ -0,0 +1,14 @@
+// Build don't link:
+
+template<int N, class C>
+class Bar {};
+
+template<class C>
+class Huh {};
+
+template<int N>
+void foo(const Bar<N,Huh<float[1]> > &x) {}
+
+int main() {
+ foo(Bar<3,Huh<float[1]> >());
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/memtemp81.C b/gcc/testsuite/g++.old-deja/g++.pt/memtemp81.C
new file mode 100644
index 00000000000..1584f88b802
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.pt/memtemp81.C
@@ -0,0 +1,24 @@
+// Build don't link:
+
+template <int i> class a
+{
+public :
+int k;
+
+template <int j> int f() const { return this->f<j-1>(); }
+
+int g() const { return f<i>(); };
+};
+
+template <>
+template <>
+int a<2>::f<0>() const {
+ return 0;
+}
+
+int main()
+{
+a<2> x;
+return x.g();
+}
+
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/overload11.C b/gcc/testsuite/g++.old-deja/g++.pt/overload11.C
new file mode 100644
index 00000000000..300d91ea2b8
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.pt/overload11.C
@@ -0,0 +1,27 @@
+// Build don't run:
+
+template <class T>
+int f(int (*fn)(T))
+{
+ return (*fn)(3);
+}
+
+struct S {
+ static int g(int) { return 1; }
+ static void g();
+
+ int h();
+};
+
+int S::h()
+{
+ return f(&g);
+}
+
+
+int main()
+{
+ S s;
+ if (s.h () != 1)
+ return 1;
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ptrmem4.C b/gcc/testsuite/g++.old-deja/g++.pt/ptrmem4.C
new file mode 100644
index 00000000000..139be923550
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.pt/ptrmem4.C
@@ -0,0 +1,28 @@
+// Build don't run:
+
+template<class T,class T1>
+int connect_to_method(T* receiver,
+ int (T1::*method)())
+{
+ return (receiver->*method)();
+}
+
+class Gtk_Container
+{
+public:
+ int remove_callback() { return 1; }
+ void remove_callback(int);
+ int f();
+};
+
+int Gtk_Container::f()
+{
+ return connect_to_method(this, &Gtk_Container::remove_callback);
+}
+
+int main()
+{
+ Gtk_Container gc;
+ if (gc.f () != 1)
+ return 1;
+}
OpenPOWER on IntegriCloud