diff options
author | Mark Mitchell <mmitchel@gcc.gnu.org> | 2004-05-31 21:24:31 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2004-05-31 21:24:31 +0000 |
commit | c8b2e872a83dd3869ffc4443201a1f3096bc3a6c (patch) | |
tree | 5e0812c5ac7d5a81ea49d40fed31c165f91fb9df /gcc | |
parent | 7c9fee34e5688d79d96db0e2b2e56d7273cb4335 (diff) | |
download | gcc-c8b2e872a83dd3869ffc4443201a1f3096bc3a6c.zip gcc-c8b2e872a83dd3869ffc4443201a1f3096bc3a6c.tar.gz gcc-c8b2e872a83dd3869ffc4443201a1f3096bc3a6c.tar.bz2 |
re PR c++/15742 ('noreturn' attribute ignored in method of template functions.)
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.
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.
From-SVN: r82499
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/call.c | 2 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 2 | ||||
-rw-r--r-- | gcc/cp/name-lookup.c | 18 | ||||
-rw-r--r-- | gcc/cp/pt.c | 5 | ||||
-rw-r--r-- | gcc/cp/tree.c | 4 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 34 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/expr/ptrmem5.C | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/packed3.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/packed4.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/packed6.C | 78 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/friend.C | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/friend27.C | 22 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/friend28.C | 23 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/Wreturn-1.C | 9 |
15 files changed, 200 insertions, 18 deletions
diff --git a/gcc/cp/call.c b/gcc/cp/call.c index d65f0ee..ecace2d 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -4561,6 +4561,8 @@ build_over_call (struct z_candidate *cand, int flags) tree return_type; return_type = TREE_TYPE (TREE_TYPE (fn)); expr = build (CALL_EXPR, return_type, fn, args, NULL_TREE); + 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); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 8b4e7f7..086090c 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4244,6 +4244,7 @@ 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); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index b229481..61e179e 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -784,6 +784,8 @@ convert_to_void (tree expr, const char *implicit) 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)) diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 195070a..238023d 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -4306,11 +4306,21 @@ arg_assoc_class (struct arg_lookup *k, tree type) 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))) + { + 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) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 09f1e92..cbe4bd9 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -6273,6 +6273,11 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain) 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; diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index e9bfdb8..365e075 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -90,6 +90,10 @@ lvalue_p_1 (tree ref, 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. */ diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index b8e48b4..5e5dcc4 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1292,6 +1292,33 @@ cxx_sizeof_or_alignof_expr (tree e, enum tree_code op) } +/* 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. @@ -1344,11 +1371,8 @@ decay_conversion (tree exp) 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 (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) diff --git a/gcc/testsuite/g++.dg/expr/ptrmem5.C b/gcc/testsuite/g++.dg/expr/ptrmem5.C new file mode 100644 index 0000000..e36983d --- /dev/null +++ b/gcc/testsuite/g++.dg/expr/ptrmem5.C @@ -0,0 +1,7 @@ +// PR c++/15696 + +struct A {}; + +typedef void (A::*ftype)(); + +void foo() { A().*ftype(); } // { dg-error "" } diff --git a/gcc/testsuite/g++.dg/ext/packed3.C b/gcc/testsuite/g++.dg/ext/packed3.C index b6e891f..1d3ef53 100644 --- a/gcc/testsuite/g++.dg/ext/packed3.C +++ b/gcc/testsuite/g++.dg/ext/packed3.C @@ -20,6 +20,6 @@ struct __attribute__ ((packed)) Packed 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.i); Ref (p.u); // { dg-error "cannot bind packed field" "" } } diff --git a/gcc/testsuite/g++.dg/ext/packed4.C b/gcc/testsuite/g++.dg/ext/packed4.C index c32a0fa..1ac9048 100644 --- a/gcc/testsuite/g++.dg/ext/packed4.C +++ b/gcc/testsuite/g++.dg/ext/packed4.C @@ -59,10 +59,6 @@ int Foo (Packed &p, int i, int ui) 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; } diff --git a/gcc/testsuite/g++.dg/ext/packed6.C b/gcc/testsuite/g++.dg/ext/packed6.C new file mode 100644 index 0000000..f89aafe --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/packed6.C @@ -0,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; +} diff --git a/gcc/testsuite/g++.dg/template/friend.C b/gcc/testsuite/g++.dg/template/friend.C index 59564ad..5e9abb0 100644 --- a/gcc/testsuite/g++.dg/template/friend.C +++ b/gcc/testsuite/g++.dg/template/friend.C @@ -1,9 +1,8 @@ // Contribued by Gabriel Dos Reis <gdr@codesourcery.com> // Origin: iskey@i100.ryd.student.liu.se -// { dg-do link } -#include <iostream> -using namespace std; +class ostream; +extern ostream& cout; template <class T> struct s; @@ -26,5 +25,5 @@ struct s { int main() { s<int>::t y; - cout << y; + cout << y; // { dg-error "" } } diff --git a/gcc/testsuite/g++.dg/template/friend27.C b/gcc/testsuite/g++.dg/template/friend27.C new file mode 100644 index 0000000..6317da5 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/friend27.C @@ -0,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; +} + + diff --git a/gcc/testsuite/g++.dg/template/friend28.C b/gcc/testsuite/g++.dg/template/friend28.C new file mode 100644 index 0000000..a7d160d --- /dev/null +++ b/gcc/testsuite/g++.dg/template/friend28.C @@ -0,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(); +} diff --git a/gcc/testsuite/g++.dg/warn/Wreturn-1.C b/gcc/testsuite/g++.dg/warn/Wreturn-1.C new file mode 100644 index 0000000..f0dba50 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wreturn-1.C @@ -0,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); } +}; |