This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCHes: PR c++/13113, c++/13854, c++/13907
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 2 Feb 2004 08:47:10 -0800
- Subject: C++ PATCHes: PR c++/13113, c++/13854, c++/13907
- Reply-to: mark at codesourcery dot com
This patch fixes several regressions:
(1) We forgot to issue such nice error messages about invalid attempts
to form a pointer-to-member using a parenthesized member function
name. We now issue that message again. We still issue another
message afterwards -- but at least the first message is the
helpful one we want. It's not easy to get rid of the second
message, and I don't consider that a regression, really.
(2) We were mishandling interaction betweens exceptions and
attributes. For a function type to be "the same" in the C++ front
end we need to have both the same set of exceptions and the same
set of attributes; in some places we checked one condition and in
some the other!
(3) We were forgetting that a bad user-defined conversion as the first
part of a conversion sequence makes the entire sequence bad.
Tested on i686-pc-linux-gnu, applied on the mainline and on the
branch.
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
2004-01-30 Mark Mitchell <mark@codesourcery.com>
PR c++/13113
* init.c (build_offset_ref): Improve error recovery for invalid
uses of non-static member functions.
PR c++/13854
* cp-tree.h (cp_build_type_attribute_variant): New function.
* class.c (build_clone): Use cp_build_type_attribute_variant.
* decl.c (duplicate_decls): Likewise.
* pt.c (copy_default_args_to_explicit_spec): Likewise.
(tsubst_function_type): Likewise.
* tree.c (build_exception_variant): Check attributes before
concluding that two types are the same.
(cp_build_type-attribute_variant): New method.
* typeck.c (merge_types): Use cp_build_type_attribute_variant.
PR c++/13907
* call.c (convert_class_to_reference): Keep better track of
pedantically invalid user-defined conversions.
2004-02-02 Mark Mitchell <mark@codesourcery.com>
PR c++/13113
* g++.old-deja/g++.mike/net36.C: Adjust error messages.
PR c++/13854
* g++.dg/ext/attrib13.C: New test.
PR c++/13907
* g++.dg/conversion/op2.C: New test.
Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.452.2.4
diff -c -5 -p -r1.452.2.4 call.c
*** cp/call.c 30 Jan 2004 16:21:24 -0000 1.452.2.4
--- cp/call.c 2 Feb 2004 16:11:55 -0000
*************** convert_class_to_reference (tree t, tree
*** 826,844 ****
TYPE_BINFO (s),
TREE_PURPOSE (conversions),
LOOKUP_NORMAL);
if (cand)
! /* Build a standard conversion sequence indicating the
! binding from the reference type returned by the
! function to the desired REFERENCE_TYPE. */
! cand->second_conv
! = (direct_reference_binding
! (reference_type,
! build1 (IDENTITY_CONV,
! TREE_TYPE (TREE_TYPE (TREE_TYPE (cand->fn))),
! NULL_TREE)));
}
conversions = TREE_CHAIN (conversions);
}
candidates = splice_viable (candidates, pedantic, &any_viable_p);
--- 826,848 ----
TYPE_BINFO (s),
TREE_PURPOSE (conversions),
LOOKUP_NORMAL);
if (cand)
! {
! /* Build a standard conversion sequence indicating the
! binding from the reference type returned by the
! function to the desired REFERENCE_TYPE. */
! cand->second_conv
! = (direct_reference_binding
! (reference_type,
! build1 (IDENTITY_CONV,
! TREE_TYPE (TREE_TYPE (TREE_TYPE (cand->fn))),
! NULL_TREE)));
! ICS_BAD_FLAG (cand->second_conv)
! |= ICS_BAD_FLAG (TREE_VEC_ELT (cand->convs, 0));
! }
}
conversions = TREE_CHAIN (conversions);
}
candidates = splice_viable (candidates, pedantic, &any_viable_p);
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.595.4.3
diff -c -5 -p -r1.595.4.3 class.c
*** cp/class.c 26 Jan 2004 17:45:58 -0000 1.595.4.3
--- cp/class.c 2 Feb 2004 16:11:55 -0000
*************** build_clone (tree fn, tree name)
*** 3871,3882 ****
parmtypes);
if (exceptions)
TREE_TYPE (clone) = build_exception_variant (TREE_TYPE (clone),
exceptions);
TREE_TYPE (clone)
! = build_type_attribute_variant (TREE_TYPE (clone),
! TYPE_ATTRIBUTES (TREE_TYPE (fn)));
}
/* Copy the function parameters. But, DECL_ARGUMENTS on a TEMPLATE_DECL
aren't function parameters; those are the template parameters. */
if (TREE_CODE (clone) != TEMPLATE_DECL)
--- 3871,3882 ----
parmtypes);
if (exceptions)
TREE_TYPE (clone) = build_exception_variant (TREE_TYPE (clone),
exceptions);
TREE_TYPE (clone)
! = cp_build_type_attribute_variant (TREE_TYPE (clone),
! TYPE_ATTRIBUTES (TREE_TYPE (fn)));
}
/* Copy the function parameters. But, DECL_ARGUMENTS on a TEMPLATE_DECL
aren't function parameters; those are the template parameters. */
if (TREE_CODE (clone) != TEMPLATE_DECL)
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.946.4.2
diff -c -5 -p -r1.946.4.2 cp-tree.h
*** cp/cp-tree.h 27 Jan 2004 02:35:20 -0000 1.946.4.2
--- cp/cp-tree.h 2 Feb 2004 16:11:55 -0000
*************** extern void debug_binfo (tree);
*** 4152,4161 ****
--- 4152,4162 ----
extern tree build_dummy_object (tree);
extern tree maybe_dummy_object (tree, tree *);
extern int is_dummy_object (tree);
extern const struct attribute_spec cxx_attribute_table[];
extern tree make_ptrmem_cst (tree, tree);
+ extern tree cp_build_type_attribute_variant (tree, tree);
extern tree cp_build_qualified_type_real (tree, int, tsubst_flags_t);
#define cp_build_qualified_type(TYPE, QUALS) \
cp_build_qualified_type_real ((TYPE), (QUALS), tf_error | tf_warning)
extern tree build_shared_int_cst (int);
extern special_function_kind special_function_p (tree);
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1174.2.2
diff -c -5 -p -r1.1174.2.2 decl.c
*** cp/decl.c 23 Jan 2004 23:10:22 -0000 1.1174.2.2
--- cp/decl.c 2 Feb 2004 16:11:56 -0000
*************** duplicate_decls (tree newdecl, tree oldd
*** 1264,1274 ****
{
tree type = TREE_TYPE (newdecl);
tree attribs = (*targetm.merge_type_attributes)
(TREE_TYPE (olddecl), type);
! type = build_type_attribute_variant (type, attribs);
TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = type;
}
/* Whether or not the builtin can throw exceptions has no
bearing on this declarator. */
--- 1264,1274 ----
{
tree type = TREE_TYPE (newdecl);
tree attribs = (*targetm.merge_type_attributes)
(TREE_TYPE (olddecl), type);
! type = cp_build_type_attribute_variant (type, attribs);
TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = type;
}
/* Whether or not the builtin can throw exceptions has no
bearing on this declarator. */
Index: cp/init.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/init.c,v
retrieving revision 1.356.2.3
diff -c -5 -p -r1.356.2.3 init.c
*** cp/init.c 26 Jan 2004 17:46:00 -0000 1.356.2.3
--- cp/init.c 2 Feb 2004 16:11:57 -0000
*************** build_offset_ref (tree type, tree name,
*** 1557,1576 ****
-- in a mem-initializer for a constructor for that class or for
a class derived from that class (_class.base.init_). */
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (member))
{
/* In Microsoft mode, treat a non-static member function as if
it were a pointer-to-member. */
if (flag_ms_extensions)
{
- member = build (OFFSET_REF, TREE_TYPE (member), decl, member);
PTRMEM_OK_P (member) = 1;
return build_unary_op (ADDR_EXPR, member, 0);
}
! error ("invalid use of non-static member function `%D'", member);
! return error_mark_node;
}
else if (TREE_CODE (member) == FIELD_DECL)
{
error ("invalid use of non-static data member `%D'", member);
return error_mark_node;
--- 1557,1580 ----
-- in a mem-initializer for a constructor for that class or for
a class derived from that class (_class.base.init_). */
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (member))
{
+ /* Build a representation of a the qualified name suitable
+ for use as the operand to "&" -- even though the "&" is
+ not actually present. */
+ member = build (OFFSET_REF, TREE_TYPE (member), decl, member);
/* In Microsoft mode, treat a non-static member function as if
it were a pointer-to-member. */
if (flag_ms_extensions)
{
PTRMEM_OK_P (member) = 1;
return build_unary_op (ADDR_EXPR, member, 0);
}
! error ("invalid use of non-static member function `%D'",
! TREE_OPERAND (member, 1));
! return member;
}
else if (TREE_CODE (member) == FIELD_DECL)
{
error ("invalid use of non-static data member `%D'", member);
return error_mark_node;
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.816.2.5
diff -c -5 -p -r1.816.2.5 pt.c
*** cp/pt.c 26 Jan 2004 17:46:01 -0000 1.816.2.5
--- cp/pt.c 2 Feb 2004 16:11:57 -0000
*************** copy_default_args_to_explicit_spec (tree
*** 1524,1535 ****
new_spec_types);
}
else
new_type = build_function_type (TREE_TYPE (old_type),
new_spec_types);
! new_type = build_type_attribute_variant (new_type,
! TYPE_ATTRIBUTES (old_type));
new_type = build_exception_variant (new_type,
TYPE_RAISES_EXCEPTIONS (old_type));
TREE_TYPE (decl) = new_type;
}
--- 1524,1535 ----
new_spec_types);
}
else
new_type = build_function_type (TREE_TYPE (old_type),
new_spec_types);
! new_type = cp_build_type_attribute_variant (new_type,
! TYPE_ATTRIBUTES (old_type));
new_type = build_exception_variant (new_type,
TYPE_RAISES_EXCEPTIONS (old_type));
TREE_TYPE (decl) = new_type;
}
*************** tsubst_function_type (tree t,
*** 6474,6484 ****
fntype = build_method_type_directly (r, return_type,
TREE_CHAIN (arg_types));
}
fntype = cp_build_qualified_type_real (fntype, TYPE_QUALS (t), complain);
! fntype = build_type_attribute_variant (fntype, TYPE_ATTRIBUTES (t));
return fntype;
}
/* Substitute into the PARMS of a call-declarator. */
--- 6474,6484 ----
fntype = build_method_type_directly (r, return_type,
TREE_CHAIN (arg_types));
}
fntype = cp_build_qualified_type_real (fntype, TYPE_QUALS (t), complain);
! fntype = cp_build_type_attribute_variant (fntype, TYPE_ATTRIBUTES (t));
return fntype;
}
/* Substitute into the PARMS of a call-declarator. */
Index: cp/tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/tree.c,v
retrieving revision 1.360
diff -c -5 -p -r1.360 tree.c
*** cp/tree.c 30 Dec 2003 10:07:10 -0000 1.360
--- cp/tree.c 2 Feb 2004 16:11:57 -0000
*************** build_exception_variant (tree type, tree
*** 983,993 ****
tree v = TYPE_MAIN_VARIANT (type);
int type_quals = TYPE_QUALS (type);
for (; v; v = TYPE_NEXT_VARIANT (v))
if (TYPE_QUALS (v) == type_quals
! && comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (v), 1))
return v;
/* Need to build a new variant. */
v = build_type_copy (type);
TYPE_RAISES_EXCEPTIONS (v) = raises;
--- 983,994 ----
tree v = TYPE_MAIN_VARIANT (type);
int type_quals = TYPE_QUALS (type);
for (; v; v = TYPE_NEXT_VARIANT (v))
if (TYPE_QUALS (v) == type_quals
! && comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (v), 1)
! && (*targetm.comp_type_attributes) (type, v))
return v;
/* Need to build a new variant. */
v = build_type_copy (type);
TYPE_RAISES_EXCEPTIONS (v) = raises;
*************** make_ptrmem_cst (tree type, tree member)
*** 1952,1961 ****
--- 1953,1979 ----
TREE_CONSTANT for things of class `c', but it does not. */
TREE_CONSTANT (ptrmem_cst) = 1;
TREE_TYPE (ptrmem_cst) = type;
PTRMEM_CST_MEMBER (ptrmem_cst) = member;
return ptrmem_cst;
+ }
+
+ /* Build a variant of TYPE that has the indicated ATTRIBUTES. May
+ return an existing type of an appropriate type already exists. */
+
+ tree
+ cp_build_type_attribute_variant (tree type, tree attributes)
+ {
+ tree new_type;
+
+ new_type = build_type_attribute_variant (type, attributes);
+ if (TREE_CODE (new_type) == FUNCTION_TYPE
+ && (TYPE_RAISES_EXCEPTIONS (new_type)
+ != TYPE_RAISES_EXCEPTIONS (type)))
+ new_type = build_exception_variant (new_type,
+ TYPE_RAISES_EXCEPTIONS (type));
+ return new_type;
}
/* Apply FUNC to all language-specific sub-trees of TP in a pre-order
traversal. Called from walk_tree(). */
Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.519.2.3
diff -c -5 -p -r1.519.2.3 typeck.c
*** cp/typeck.c 29 Jan 2004 02:22:51 -0000 1.519.2.3
--- cp/typeck.c 2 Feb 2004 16:11:58 -0000
*************** merge_types (tree t1, tree t2)
*** 664,692 ****
tree p2 = TYPE_ARG_TYPES (t2);
tree rval, raises;
/* Save space: see if the result is identical to one of the args. */
if (valtype == TREE_TYPE (t1) && ! p2)
! return build_type_attribute_variant (t1, attributes);
if (valtype == TREE_TYPE (t2) && ! p1)
! return build_type_attribute_variant (t2, attributes);
/* Simple way if one arg fails to specify argument types. */
if (p1 == NULL_TREE || TREE_VALUE (p1) == void_type_node)
{
rval = build_function_type (valtype, p2);
if ((raises = TYPE_RAISES_EXCEPTIONS (t2)))
rval = build_exception_variant (rval, raises);
! return build_type_attribute_variant (rval, attributes);
}
raises = TYPE_RAISES_EXCEPTIONS (t1);
if (p2 == NULL_TREE || TREE_VALUE (p2) == void_type_node)
{
rval = build_function_type (valtype, p1);
if (raises)
rval = build_exception_variant (rval, raises);
! return build_type_attribute_variant (rval, attributes);
}
rval = build_function_type (valtype, commonparms (p1, p2));
t1 = build_exception_variant (rval, raises);
break;
--- 664,692 ----
tree p2 = TYPE_ARG_TYPES (t2);
tree rval, raises;
/* Save space: see if the result is identical to one of the args. */
if (valtype == TREE_TYPE (t1) && ! p2)
! return cp_build_type_attribute_variant (t1, attributes);
if (valtype == TREE_TYPE (t2) && ! p1)
! return cp_build_type_attribute_variant (t2, attributes);
/* Simple way if one arg fails to specify argument types. */
if (p1 == NULL_TREE || TREE_VALUE (p1) == void_type_node)
{
rval = build_function_type (valtype, p2);
if ((raises = TYPE_RAISES_EXCEPTIONS (t2)))
rval = build_exception_variant (rval, raises);
! return cp_build_type_attribute_variant (rval, attributes);
}
raises = TYPE_RAISES_EXCEPTIONS (t1);
if (p2 == NULL_TREE || TREE_VALUE (p2) == void_type_node)
{
rval = build_function_type (valtype, p1);
if (raises)
rval = build_exception_variant (rval, raises);
! return cp_build_type_attribute_variant (rval, attributes);
}
rval = build_function_type (valtype, commonparms (p1, p2));
t1 = build_exception_variant (rval, raises);
break;
*************** merge_types (tree t1, tree t2)
*** 720,730 ****
attributes result from the instantiation. */
return t1;
default:;
}
! return build_type_attribute_variant (t1, attributes);
}
/* Return the common type of two types.
We assume that comptypes has already been done and returned 1;
if that isn't so, this may crash.
--- 720,730 ----
attributes result from the instantiation. */
return t1;
default:;
}
! return cp_build_type_attribute_variant (t1, attributes);
}
/* Return the common type of two types.
We assume that comptypes has already been done and returned 1;
if that isn't so, this may crash.
Index: testsuite/g++.dg/conversion/op2.C
===================================================================
RCS file: testsuite/g++.dg/conversion/op2.C
diff -N testsuite/g++.dg/conversion/op2.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/conversion/op2.C 2 Feb 2004 16:12:01 -0000
***************
*** 0 ****
--- 1,16 ----
+ // PR c++/13907
+
+ struct A {
+ operator int & ();
+ operator const int & () const;
+ };
+
+
+ void f(int &);
+ void f(const int &);
+
+
+ int main() {
+ const A x = A();
+ f(x);
+ }
Index: testsuite/g++.dg/ext/attrib13.C
===================================================================
RCS file: testsuite/g++.dg/ext/attrib13.C
diff -N testsuite/g++.dg/ext/attrib13.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/ext/attrib13.C 2 Feb 2004 16:12:01 -0000
***************
*** 0 ****
--- 1,4 ----
+ // PR c++/13854
+
+ extern char *rindex (__const char *__s, int __c) throw () __attribute__ ((__pure__));
+ extern char *rindex (__const char *__s, int __c) throw () __attribute__ ((__pure__));
Index: testsuite/g++.old-deja/g++.mike/net36.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.old-deja/g++.mike/net36.C,v
retrieving revision 1.7
diff -c -5 -p -r1.7 net36.C
*** testsuite/g++.old-deja/g++.mike/net36.C 4 Jul 2003 05:05:19 -0000 1.7
--- testsuite/g++.old-deja/g++.mike/net36.C 2 Feb 2004 16:12:02 -0000
*************** public:
*** 9,19 ****
typedef void (A::*handler) (X*);
class B {
public:
! void setHandler(handler);
};
void f(B* b) {
b->setHandler(A::handlerFn); // { dg-error "" }
}
--- 9,19 ----
typedef void (A::*handler) (X*);
class B {
public:
! void setHandler(handler); // { dg-error "candidate" }
};
void f(B* b) {
b->setHandler(A::handlerFn); // { dg-error "" }
}