This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: PR 15742, 15696, 15625, 15629, 15209
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 31 May 2004 14:28:37 -0700
- Subject: C++ PATCH: PR 15742, 15696, 15625, 15629, 15209
- Reply-to: mark at codesourcery dot com
This patch fixes an additional five regressions in GCC 3.4.0. These
are:
15742 -- A false-positive warning about functions that do not return a
value in templates.
15696 -- An ICE-on-invalid for use of non-static member functions for
purposes other than to call the function.
15625 -- A rejects-valid case involving friends and templates.
15629 -- A problem with argument-dependent lookup involving friends
and templates.
15209 -- A problem with "__attribute__((packed))". Nathan modified
the compiler (correctly) to treat packed fields much like bitfields in
the sense that they may be bound to a const reference, but the
compiler must introduce a temporary. However, we were treating more
things as packed than we should have, in this sense.
Tested on i686-pc-linux-gnu, applied on the 3.4 branch and on the
mainline.
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
2004-05-31 Mark Mitchell <mark@codesourcery.com>
PR c++/15742
* call.c (build_over_call): Set
current_function_returns_abnormally even in template functions.
PR c++/15696
* cp-tree.h (invalid_nonstatic_memfn_p): New function.
* cvt.c (convert_to_void): Use it.
* typeck.c (invalid_nonstatic_memfn_p): New function.
(decay_conversion): Use it.
PR c++/15625
* pt.c (tsubst_decl): Set DECL_FRIEND_CONTEXT for instantiated
templates.
PR c++/15629
* name-lookup.c (arg_assoc_class): Do not find template
specializations.
PR c++/15209
* tree.c (lvalue_p_1): Only consider the right-hand side of "."
expressions when determining whether or not an express is packed.
2004-05-31 Mark Mitchell <mark@codesourcery.com>
PR c++/15742
* g++.dg/warn/Wreturn-1.C: New test.
PR c++/15696
* g++.dg/expr/ptrmem5.C: New test.
PR c++/15625
* g++.dg/template/friend27.C: New test.
PR c++/15629
* g++.dg/template/friend28.C: New test.
* g++.dg/template/friend.C: Do not depend on <iostream>. Add
error message.
PR c++/15209
* g++.dg/ext/packed3.C: Remove bogus error.
* g++.dg/ext/packed4.C: Remove bogus check.
* g++.dg/ext/packed6.C: New test.
Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.452.2.16
diff -c -5 -p -r1.452.2.16 call.c
*** cp/call.c 20 Mar 2004 00:13:07 -0000 1.452.2.16
--- cp/call.c 31 May 2004 20:48:58 -0000
*************** build_over_call (struct z_candidate *can
*** 4351,4360 ****
--- 4351,4362 ----
{
tree expr;
tree return_type;
return_type = TREE_TYPE (TREE_TYPE (fn));
expr = build (CALL_EXPR, return_type, fn, args);
+ if (TREE_THIS_VOLATILE (fn) && cfun)
+ current_function_returns_abnormally = 1;
if (!VOID_TYPE_P (return_type))
require_complete_type (return_type);
return convert_from_reference (expr);
}
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.946.4.12
diff -c -5 -p -r1.946.4.12 cp-tree.h
*** cp/cp-tree.h 28 May 2004 23:33:33 -0000 1.946.4.12
--- cp/cp-tree.h 31 May 2004 20:48:58 -0000
*************** extern tree check_return_expr
*** 4246,4255 ****
--- 4246,4256 ----
extern tree build_ptrmemfunc_access_expr (tree, tree);
extern tree build_address (tree);
extern tree build_nop (tree, tree);
extern tree non_reference (tree);
extern tree lookup_anon_field (tree, tree);
+ extern bool invalid_nonstatic_memfn_p (tree);
/* in typeck2.c */
extern void require_complete_eh_spec_types (tree, tree);
extern void cxx_incomplete_type_diagnostic (tree, tree, int);
#undef cxx_incomplete_type_error
Index: cp/cvt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cvt.c,v
retrieving revision 1.151.4.1
diff -c -5 -p -r1.151.4.1 cvt.c
*** cp/cvt.c 23 Feb 2004 12:46:37 -0000 1.151.4.1
--- cp/cvt.c 31 May 2004 20:48:58 -0000
*************** convert_to_void (tree expr, const char *
*** 789,798 ****
--- 789,800 ----
if (expr == error_mark_node
|| TREE_TYPE (expr) == error_mark_node)
return error_mark_node;
if (!TREE_TYPE (expr))
return expr;
+ if (invalid_nonstatic_memfn_p (expr))
+ return error_mark_node;
if (VOID_TYPE_P (TREE_TYPE (expr)))
return expr;
switch (TREE_CODE (expr))
{
case COND_EXPR:
Index: cp/name-lookup.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/name-lookup.c,v
retrieving revision 1.34.2.13
diff -c -5 -p -r1.34.2.13 name-lookup.c
*** cp/name-lookup.c 28 May 2004 22:29:41 -0000 1.34.2.13
--- cp/name-lookup.c 31 May 2004 20:48:58 -0000
*************** arg_assoc_class (struct arg_lookup *k, t
*** 4287,4301 ****
for (list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); list;
list = TREE_CHAIN (list))
if (k->name == FRIEND_NAME (list))
for (friends = FRIEND_DECLS (list); friends;
friends = TREE_CHAIN (friends))
! /* Only interested in global functions with potentially hidden
! (i.e. unqualified) declarations. */
! if (CP_DECL_CONTEXT (TREE_VALUE (friends)) == context)
! if (add_function (k, TREE_VALUE (friends)))
return true;
/* Process template arguments. */
if (CLASSTYPE_TEMPLATE_INFO (type))
{
list = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type));
--- 4287,4311 ----
for (list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); list;
list = TREE_CHAIN (list))
if (k->name == FRIEND_NAME (list))
for (friends = FRIEND_DECLS (list); friends;
friends = TREE_CHAIN (friends))
! {
! tree fn = TREE_VALUE (friends);
!
! /* Only interested in global functions with potentially hidden
! (i.e. unqualified) declarations. */
! if (CP_DECL_CONTEXT (fn) != context)
! continue;
! /* Template specializations are never found by name lookup.
! (Templates themselves can be found, but not template
! specializations.) */
! if (TREE_CODE (fn) == FUNCTION_DECL && DECL_USE_TEMPLATE (fn))
! continue;
! if (add_function (k, fn))
return true;
+ }
/* Process template arguments. */
if (CLASSTYPE_TEMPLATE_INFO (type))
{
list = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type));
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.816.2.26
diff -c -5 -p -r1.816.2.26 pt.c
*** cp/pt.c 23 May 2004 22:45:04 -0000 1.816.2.26
--- cp/pt.c 31 May 2004 20:48:58 -0000
*************** tsubst_decl (tree t, tree args, tree typ
*** 6259,6268 ****
--- 6259,6273 ----
clone_function_decl (r, /*update_method_vec_p=*/0);
}
else if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
grok_op_properties (r, DECL_FRIEND_P (r),
(complain & tf_error) != 0);
+
+ if (DECL_FRIEND_P (t) && DECL_FRIEND_CONTEXT (t))
+ SET_DECL_FRIEND_CONTEXT (r,
+ tsubst (DECL_FRIEND_CONTEXT (t),
+ args, complain, in_decl));
}
break;
case PARM_DECL:
{
Index: cp/tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/tree.c,v
retrieving revision 1.360.4.5
diff -c -5 -p -r1.360.4.5 tree.c
*** cp/tree.c 19 Mar 2004 07:13:37 -0000 1.360.4.5
--- cp/tree.c 31 May 2004 20:48:58 -0000
*************** lvalue_p_1 (tree ref,
*** 88,97 ****
--- 88,101 ----
treat_class_rvalues_as_lvalues);
case COMPONENT_REF:
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
treat_class_rvalues_as_lvalues);
+ /* In an expression of the form "X.Y", the packed-ness of the
+ expression does not depend on "X". */
+ op1_lvalue_kind &= ~clk_packed;
+ /* Look at the member designator. */
if (!op1_lvalue_kind
/* The "field" can be a FUNCTION_DECL or an OVERLOAD in some
situations. */
|| TREE_CODE (TREE_OPERAND (ref, 1)) != FIELD_DECL)
;
Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.519.2.18
diff -c -5 -p -r1.519.2.18 typeck.c
*** cp/typeck.c 28 May 2004 23:33:35 -0000 1.519.2.18
--- cp/typeck.c 31 May 2004 20:48:59 -0000
*************** cxx_sizeof_or_alignof_expr (tree e, enum
*** 1282,1291 ****
--- 1282,1318 ----
return cxx_sizeof_or_alignof_type (e, op, true);
}
+ /* EXPR is being used in a context that is not a function call.
+ Enforce:
+
+ [expr.ref]
+
+ The expression can be used only as the left-hand operand of a
+ member function call.
+
+ [expr.mptr.operator]
+
+ If the result of .* or ->* is a function, then that result can be
+ used only as the operand for the function call operator ().
+
+ by issuing an error message if appropriate. Returns true iff EXPR
+ violates these rules. */
+
+ bool
+ invalid_nonstatic_memfn_p (tree expr)
+ {
+ if (TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE)
+ {
+ error ("invalid use of non-static member function");
+ return true;
+ }
+ return false;
+ }
+
/* Perform the conversions in [expr] that apply when an lvalue appears
in an rvalue context: the lvalue-to-rvalue, array-to-pointer, and
function-to-pointer conversions.
In addition manifest constants are replaced by their values. */
*************** decay_conversion (tree exp)
*** 1334,1348 ****
if (code == VOID_TYPE)
{
error ("void value not ignored as it ought to be");
return error_mark_node;
}
! if (code == METHOD_TYPE)
! {
! error ("invalid use of non-static member function");
! return error_mark_node;
! }
if (code == FUNCTION_TYPE || is_overloaded_fn (exp))
return build_unary_op (ADDR_EXPR, exp, 0);
if (code == ARRAY_TYPE)
{
tree adr;
--- 1361,1372 ----
if (code == VOID_TYPE)
{
error ("void value not ignored as it ought to be");
return error_mark_node;
}
! if (invalid_nonstatic_memfn_p (exp))
! return error_mark_node;
if (code == FUNCTION_TYPE || is_overloaded_fn (exp))
return build_unary_op (ADDR_EXPR, exp, 0);
if (code == ARRAY_TYPE)
{
tree adr;
Index: testsuite/g++.dg/expr/ptrmem5.C
===================================================================
RCS file: testsuite/g++.dg/expr/ptrmem5.C
diff -N testsuite/g++.dg/expr/ptrmem5.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/expr/ptrmem5.C 31 May 2004 20:48:59 -0000
***************
*** 0 ****
--- 1,7 ----
+ // PR c++/15696
+
+ struct A {};
+
+ typedef void (A::*ftype)();
+
+ void foo() { A().*ftype(); } // { dg-error "" }
Index: testsuite/g++.dg/ext/packed3.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/ext/packed3.C,v
retrieving revision 1.1
diff -c -5 -p -r1.1 packed3.C
*** testsuite/g++.dg/ext/packed3.C 22 Jul 2003 09:53:34 -0000 1.1
--- testsuite/g++.dg/ext/packed3.C 31 May 2004 20:48:59 -0000
*************** struct __attribute__ ((packed)) Packed
*** 18,25 ****
};
void Foo (Packed &p)
{
Ref (p.i); // { dg-error "cannot bind packed field" "" }
! Ref (p.u.i); // { dg-error "cannot bind packed field" "" }
Ref (p.u); // { dg-error "cannot bind packed field" "" }
}
--- 18,25 ----
};
void Foo (Packed &p)
{
Ref (p.i); // { dg-error "cannot bind packed field" "" }
! Ref (p.u.i);
Ref (p.u); // { dg-error "cannot bind packed field" "" }
}
Index: testsuite/g++.dg/ext/packed4.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/ext/packed4.C,v
retrieving revision 1.1
diff -c -5 -p -r1.1 packed4.C
*** testsuite/g++.dg/ext/packed4.C 22 Jul 2003 09:53:34 -0000 1.1
--- testsuite/g++.dg/ext/packed4.C 31 May 2004 20:48:59 -0000
*************** int Foo (Packed &p, int i, int ui)
*** 57,70 ****
if ((r = Val (p.u, ui)))
return r + 4;
if ((r = ConstRef (p.i, &p.i, i)))
return r + 6;
- if ((r = ConstRef (p.u.i, &p.u.i, ui)))
- return r + 8;
- if ((r = ConstRef (p.u, &p.u, ui)))
- return r + 10;
return 0;
}
int main ()
--- 57,66 ----
Index: testsuite/g++.dg/ext/packed6.C
===================================================================
RCS file: testsuite/g++.dg/ext/packed6.C
diff -N testsuite/g++.dg/ext/packed6.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/ext/packed6.C 31 May 2004 20:48:59 -0000
***************
*** 0 ****
--- 1,78 ----
+ // PR c++/15209
+ // { dg-options "-w" }
+
+ typedef unsigned int size_t;
+ typedef unsigned char uint8_t;
+ typedef unsigned short int uint16_t;
+
+ typedef unsigned int uint32_t;
+ __extension__ typedef unsigned long long int uint64_t;
+
+ typedef uint8_t u8;
+ typedef uint16_t u16;
+ typedef uint32_t u32;
+ typedef uint64_t u64;
+
+ struct MAGIC {u8 magic[8];} __attribute__ ((packed));
+ struct PACKETTYPE {u8 type[16];} __attribute__ ((packed));
+
+
+ typedef u16 leu16;
+ typedef u32 leu32;
+ typedef u64 leu64;
+
+ class MD5Hash
+ {
+ public:
+
+ MD5Hash(void) {};
+
+ void *print(void) const;
+ MD5Hash(const MD5Hash &other);
+ MD5Hash& operator=(const MD5Hash &other);
+
+ public:
+ u8 hash[16];
+ };
+
+ struct PACKET_HEADER
+ {
+
+ MAGIC magic;
+ leu64 length;
+ MD5Hash hash;
+ MD5Hash setid;
+ PACKETTYPE type;
+ } __attribute__ ((packed));
+
+
+ struct MAINPACKET
+ {
+ PACKET_HEADER header;
+
+ leu64 blocksize;
+ leu32 recoverablefilecount;
+ MD5Hash fileid[0];
+
+
+ } __attribute__ ((packed));
+
+ struct CriticalPacket
+ {
+ u8 *packetdata;
+ size_t packetlength;
+ };
+
+ class MainPacket : public CriticalPacket
+ {
+ const MD5Hash& SetId(void) const;
+
+ u64 blocksize;
+ u32 totalfilecount;
+ u32 recoverablefilecount;
+ };
+
+ inline const MD5Hash& MainPacket::SetId(void) const
+ {
+ return ((const MAINPACKET*)packetdata)->header.setid;
+ }
Index: testsuite/g++.dg/template/friend.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/template/friend.C,v
retrieving revision 1.5
diff -c -5 -p -r1.5 friend.C
*** testsuite/g++.dg/template/friend.C 18 Mar 2002 13:27:03 -0000 1.5
--- testsuite/g++.dg/template/friend.C 31 May 2004 20:48:59 -0000
***************
*** 1,11 ****
// Contribued by Gabriel Dos Reis <gdr@codesourcery.com>
// Origin: iskey@i100.ryd.student.liu.se
- // { dg-do link }
! #include <iostream>
! using namespace std;
template <class T> struct s;
template <class T>
ostream& operator<<(ostream &o, const typename s<T>::t &x)
--- 1,10 ----
// Contribued by Gabriel Dos Reis <gdr@codesourcery.com>
// Origin: iskey@i100.ryd.student.liu.se
! class ostream;
! extern ostream& cout;
template <class T> struct s;
template <class T>
ostream& operator<<(ostream &o, const typename s<T>::t &x)
*************** struct s {
*** 24,30 ****
};
int main()
{
s<int>::t y;
! cout << y;
}
--- 23,29 ----
};
int main()
{
s<int>::t y;
! cout << y; // { dg-error "" }
}
Index: testsuite/g++.dg/template/friend27.C
===================================================================
RCS file: testsuite/g++.dg/template/friend27.C
diff -N testsuite/g++.dg/template/friend27.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/friend27.C 31 May 2004 20:48:59 -0000
***************
*** 0 ****
--- 1,22 ----
+ // PR c++/15265
+
+ enum Relation {equalOp};
+ template<typename B>
+ class A {
+ public:
+ static
+ bool Relop(const A&, const A&, Relation);
+
+ friend
+ bool operator==(const A& a1, const A& a2) {
+ return Relop(a1, a2, equalOp);
+ }
+ B* b;
+ };
+
+ int main() {
+ A<int> a; a == a;
+ return 0;
+ }
+
+
Index: testsuite/g++.dg/template/friend28.C
===================================================================
RCS file: testsuite/g++.dg/template/friend28.C
diff -N testsuite/g++.dg/template/friend28.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/friend28.C 31 May 2004 20:48:59 -0000
***************
*** 0 ****
--- 1,23 ----
+ // PR c++/15629
+ // { dg-do link }
+
+ template<int a, int b> class T;
+
+ template<int a, int b> void func(T<a, b> * t);
+ template<int a> void func(T<a, 3> * t) {}
+ template void func<2>(T<2, 3>*);
+
+ template<int a, int b> struct T {
+ friend void func<a, b>(T<a, b> * t);
+ friend void func<a> (T<a, 3> * t);
+
+ void foo();
+ };
+
+ template<int a, int b> void T<a, b>::foo() {
+ func((T<2,3>*)0);
+ }
+
+ int main() {
+ T<2,3>().foo();
+ }
Index: testsuite/g++.dg/warn/Wreturn-1.C
===================================================================
RCS file: testsuite/g++.dg/warn/Wreturn-1.C
diff -N testsuite/g++.dg/warn/Wreturn-1.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/warn/Wreturn-1.C 31 May 2004 20:48:59 -0000
***************
*** 0 ****
--- 1,9 ----
+ // { dg-options "-Wreturn-type" }
+ // PR c++/15742
+
+ extern void exit(int) __attribute__ ((noreturn));
+
+ template<typename T>
+ struct A {
+ int find_cmp(void) { exit(1); }
+ };