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
This commit is contained in:
parent
7c9fee34e5
commit
c8b2e872a8
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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))
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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. */
|
||||
|
@ -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)
|
||||
|
7
gcc/testsuite/g++.dg/expr/ptrmem5.C
Normal file
7
gcc/testsuite/g++.dg/expr/ptrmem5.C
Normal file
@ -0,0 +1,7 @@
|
||||
// PR c++/15696
|
||||
|
||||
struct A {};
|
||||
|
||||
typedef void (A::*ftype)();
|
||||
|
||||
void foo() { A().*ftype(); } // { dg-error "" }
|
@ -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" "" }
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
78
gcc/testsuite/g++.dg/ext/packed6.C
Normal file
78
gcc/testsuite/g++.dg/ext/packed6.C
Normal file
@ -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;
|
||||
}
|
@ -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 "" }
|
||||
}
|
||||
|
22
gcc/testsuite/g++.dg/template/friend27.C
Normal file
22
gcc/testsuite/g++.dg/template/friend27.C
Normal file
@ -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;
|
||||
}
|
||||
|
||||
|
23
gcc/testsuite/g++.dg/template/friend28.C
Normal file
23
gcc/testsuite/g++.dg/template/friend28.C
Normal file
@ -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();
|
||||
}
|
9
gcc/testsuite/g++.dg/warn/Wreturn-1.C
Normal file
9
gcc/testsuite/g++.dg/warn/Wreturn-1.C
Normal file
@ -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); }
|
||||
};
|
Loading…
Reference in New Issue
Block a user