re PR c++/15742 ('noreturn' attribute ignored in method of template functions.)
authorMark Mitchell <mmitchel@gcc.gnu.org>
Mon, 31 May 2004 21:24:31 +0000 (21:24 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Mon, 31 May 2004 21:24:31 +0000 (21:24 +0000)
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

15 files changed:
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/cp/name-lookup.c
gcc/cp/pt.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/testsuite/g++.dg/expr/ptrmem5.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ext/packed3.C
gcc/testsuite/g++.dg/ext/packed4.C
gcc/testsuite/g++.dg/ext/packed6.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/friend.C
gcc/testsuite/g++.dg/template/friend27.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/friend28.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/Wreturn-1.C [new file with mode: 0644]

index d65f0eeb23adb46ed223a079e01f26a596f7e6c5..ecace2dd78ea7dc48edd6df62a6110dc29a939e9 100644 (file)
@@ -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);
index 8b4e7f7af15870bc0c296372b71ccdd995e8ad31..086090c0d22be2f26eacdd84d809cb815cf9fc4e 100644 (file)
@@ -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);
index b22948106b2daf18894a5e4857c2687f7268e5d1..61e179ed1b6dba336155b8b3bd6e31533f17574b 100644 (file)
@@ -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))
index 195070a8033492ffef490fd7f02b312247a1d591..238023da87754fe80726356570a9e79bad40e25d 100644 (file)
@@ -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) 
index 09f1e9263f5a929a6074c0868485860eba3b95ed..cbe4bd9b0707fd6c4d5987540f887aa65351487f 100644 (file)
@@ -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;
 
index e9bfdb8be9a3c2932454e9c041dc8ec8b727c0a9..365e07530743fd7ab873413c85353c438ba77505 100644 (file)
@@ -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.  */
index b8e48b420d843c1a484aebf1c46e6759a41a6259..5e5dcc4a2ae552bce76977902a6c0fb97395581c 100644 (file)
@@ -1292,6 +1292,33 @@ cxx_sizeof_or_alignof_expr (tree e, enum tree_code op)
 }
   
 \f
+/* 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 (file)
index 0000000..e36983d
--- /dev/null
@@ -0,0 +1,7 @@
+// PR c++/15696
+
+struct A {};
+
+typedef void (A::*ftype)();
+
+void foo() { A().*ftype(); } // { dg-error "" }
index b6e891f337f011a9e2256b5ff64557a1b08c6871..1d3ef534ae1b91175eeb8099755537ba79411082 100644 (file)
@@ -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" "" }
 }
index c32a0fa6993e30fadefdab4cab47ae1a75b0569d..1ac9048d4e09e475a35d5eafb9ef3dadbdda3556 100644 (file)
@@ -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 (file)
index 0000000..f89aafe
--- /dev/null
@@ -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;
+}
index 59564ad94372efaf808ed49db1a3ba12f37b370b..5e9abb0b52a051e50e45225b0037d13ed9eaa431 100644 (file)
@@ -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 (file)
index 0000000..6317da5
--- /dev/null
@@ -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 (file)
index 0000000..a7d160d
--- /dev/null
@@ -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 (file)
index 0000000..f0dba50
--- /dev/null
@@ -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); }
+};