c-typeck.c (enum impl_conv): New.
authorJoseph Myers <jsm@polyomino.org.uk>
Fri, 8 Oct 2004 10:21:42 +0000 (11:21 +0100)
committerJoseph Myers <jsm28@gcc.gnu.org>
Fri, 8 Oct 2004 10:21:42 +0000 (11:21 +0100)
* c-typeck.c (enum impl_conv): New.
(convert_for_assignment): Use it.  Take tree for function called
instead of its name.  Handle ObjC selectors for diagnostics at
start of function.  Select diagnostic text within the function
using full sentences for diagnsotics.  Use %qE to name functions
in diagnostics.
(convert_arguments, build_modify_expr,
c_convert_parm_for_inlining, digest_init, c_finish_return): Update
callers to convert_for_assignment.
(warn_for_assignment): Remove.

testsuite:
* gcc.dg/assign-warn-1.c, gcc.dg/assign-warn-2.c: New tests.
* gcc.dg/warn-1.c, gcc.dg/noncompile/20020213-1.c,
objc.dg/method-9.m: Update expected diagnostics.

From-SVN: r88741

gcc/ChangeLog
gcc/c-typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/assign-warn-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/assign-warn-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/noncompile/20020213-1.c
gcc/testsuite/gcc.dg/warn-1.c
gcc/testsuite/objc.dg/method-9.m

index d3ae0a9..2c0a905 100644 (file)
@@ -1,3 +1,16 @@
+2004-10-08  Joseph S. Myers  <jsm@polyomino.org.uk>
+
+       * c-typeck.c (enum impl_conv): New.
+       (convert_for_assignment): Use it.  Take tree for function called
+       instead of its name.  Handle ObjC selectors for diagnostics at
+       start of function.  Select diagnostic text within the function
+       using full sentences for diagnsotics.  Use %qE to name functions
+       in diagnostics.
+       (convert_arguments, build_modify_expr,
+       c_convert_parm_for_inlining, digest_init, c_finish_return): Update
+       callers to convert_for_assignment.
+       (warn_for_assignment): Remove.
+
 2004-10-08  Nick Clifton  <nickc@redhat.com>
 
        * config/sh/symbian.c (symbian_possibly_export_base_class):
index 6d77233..64669c8 100644 (file)
@@ -55,6 +55,15 @@ enum lvalue_use {
   lv_asm
 };
 
+/* Possible cases of implicit bad conversions.  Used to select
+   diagnostic messages in convert_for_assignment.  */
+enum impl_conv {
+  ic_argpass,
+  ic_assign,
+  ic_init,
+  ic_return
+};
+
 /* The level of nesting inside "__alignof__".  */
 int in_alignof;
 
@@ -81,9 +90,8 @@ static tree default_function_array_conversion (tree);
 static tree lookup_field (tree, tree);
 static tree convert_arguments (tree, tree, tree, tree);
 static tree pointer_diff (tree, tree);
-static tree convert_for_assignment (tree, tree, const char *, tree, tree,
+static tree convert_for_assignment (tree, tree, enum impl_conv, tree, tree,
                                    int);
-static void warn_for_assignment (const char *, const char *, tree, int);
 static tree valid_compound_expr_initializer (tree, tree);
 static void push_string (const char *);
 static void push_member_name (tree);
@@ -2029,16 +2037,12 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl)
   tree result = NULL;
   int parmnum;
   tree selector;
-  tree name = NULL_TREE;
 
-  /* Determine the function name for the use of convert_for_assignment
-     and warn_for_assignment called from there.  */
+  /* Change pointer to function to the function itself for
+     diagnostics.  */
   if (TREE_CODE (function) == ADDR_EXPR
       && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL)
-    {
-      function = TREE_OPERAND (function, 0);
-      name = DECL_NAME (function);
-    }
+    function = TREE_OPERAND (function, 0);
 
   /* Handle an ObjC selector specially for diagnostics.  */
   selector = objc_message_selector ();
@@ -2189,9 +2193,9 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl)
                    }
                }
 
-             parmval = convert_for_assignment (type, val,
-                                               (char *) 0, /* arg passing  */
-                                               fundecl, name, parmnum + 1);
+             parmval = convert_for_assignment (type, val, ic_argpass,
+                                               fundecl, function,
+                                               parmnum + 1);
 
              if (targetm.calls.promote_prototypes (fundecl ? TREE_TYPE (fundecl) : 0)
                  && INTEGRAL_TYPE_P (type)
@@ -3390,7 +3394,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
 
   /* Convert new value to destination type.  */
 
-  newrhs = convert_for_assignment (lhstype, newrhs, _("assignment"),
+  newrhs = convert_for_assignment (lhstype, newrhs, ic_assign,
                                   NULL_TREE, NULL_TREE, 0);
   if (TREE_CODE (newrhs) == ERROR_MARK)
     return error_mark_node;
@@ -3407,7 +3411,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
 
   if (olhstype == TREE_TYPE (result))
     return result;
-  return convert_for_assignment (olhstype, result, _("assignment"),
+  return convert_for_assignment (olhstype, result, ic_assign,
                                 NULL_TREE, NULL_TREE, 0);
 }
 \f
@@ -3416,21 +3420,63 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
    The real work of conversion is done by `convert'.
    The purpose of this function is to generate error messages
    for assignments that are not allowed in C.
-   ERRTYPE is a string to use in error messages:
-   "assignment", "return", etc.  If it is null, this is parameter passing
-   for a function call (and different error messages are output).
+   ERRTYPE says whether it is argument passing, assignment,
+   initialization or return.
 
-   FUNNAME is the name of the function being called,
-   as an IDENTIFIER_NODE, or null.
+   FUNCTION is a tree for the function being called.
    PARMNUM is the number of the argument, for printing in error messages.  */
 
 static tree
-convert_for_assignment (tree type, tree rhs, const char *errtype,
-                       tree fundecl, tree funname, int parmnum)
+convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
+                       tree fundecl, tree function, int parmnum)
 {
   enum tree_code codel = TREE_CODE (type);
   tree rhstype;
   enum tree_code coder;
+  tree rname = NULL_TREE;
+
+  if (errtype == ic_argpass)
+    {
+      tree selector;
+      /* Change pointer to function to the function itself for
+        diagnostics.  */
+      if (TREE_CODE (function) == ADDR_EXPR
+         && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL)
+       function = TREE_OPERAND (function, 0);
+
+      /* Handle an ObjC selector specially for diagnostics.  */
+      selector = objc_message_selector ();
+      rname = function;
+      if (selector && parmnum > 2)
+       {
+         rname = selector;
+         parmnum -= 2;
+       }
+    }
+
+  /* This macro is used to emit diagnostics to ensure that all format
+     strings are complete sentences, visible to gettext and checked at
+     compile time.  */
+#define WARN_FOR_ASSIGNMENT(AR, AS, IN, RE)    \
+  do {                                         \
+    switch (errtype)                           \
+      {                                                \
+      case ic_argpass:                         \
+       pedwarn (AR, parmnum, rname);           \
+       break;                                  \
+      case ic_assign:                          \
+       pedwarn (AS);                           \
+       break;                                  \
+      case ic_init:                            \
+       pedwarn (IN);                           \
+       break;                                  \
+      case ic_return:                          \
+       pedwarn (RE);                           \
+       break;                                  \
+      default:                                 \
+       gcc_unreachable ();                     \
+      }                                                \
+  } while (0)
 
   /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */
   /* Do not use STRIP_NOPS here.  We do not want an enumerator
@@ -3507,7 +3553,8 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
 
   /* Conversion to a transparent union from its member types.
      This applies only to function arguments.  */
-  else if (codel == UNION_TYPE && TYPE_TRANSPARENT_UNION (type) && !errtype)
+  else if (codel == UNION_TYPE && TYPE_TRANSPARENT_UNION (type)
+          && errtype == ic_argpass)
     {
       tree memb_types;
       tree marginal_memb_type = 0;
@@ -3582,13 +3629,27 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
                     function where an ordinary one is wanted, but not
                     vice-versa.  */
                  if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
-                   warn_for_assignment ("%s makes qualified function pointer from unqualified",
-                                        errtype, funname, parmnum);
+                   WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE "
+                                           "makes qualified function "
+                                           "pointer from unqualified"),
+                                        N_("assignment makes qualified "
+                                           "function pointer from "
+                                           "unqualified"),
+                                        N_("initialization makes qualified "
+                                           "function pointer from "
+                                           "unqualified"),
+                                        N_("return makes qualified function "
+                                           "pointer from unqualified"));
                }
              else if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
-               warn_for_assignment ("%s discards qualifiers from pointer target type",
-                                    errtype, funname,
-                                    parmnum);
+               WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE discards "
+                                       "qualifiers from pointer target type"),
+                                    N_("assignment discards qualifiers "
+                                       "from pointer target type"),
+                                    N_("initialization discards qualifiers "
+                                       "from pointer target type"),
+                                    N_("return discards qualifiers from "
+                                       "pointer target type"));
            }
 
          if (pedantic && !DECL_IN_SYSTEM_HEADER (fundecl))
@@ -3630,17 +3691,29 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
                      which are not ANSI null ptr constants.  */
                   && (!integer_zerop (rhs) || TREE_CODE (rhs) == NOP_EXPR)
                   && TREE_CODE (ttl) == FUNCTION_TYPE)))
-           warn_for_assignment ("ISO C forbids %s between function "
-                                "pointer and %<void *%>",
-                                errtype, funname, parmnum);
+           WARN_FOR_ASSIGNMENT (N_("ISO C forbids passing argument %d of "
+                                   "%qE between function pointer "
+                                   "and %<void *%>"),
+                                N_("ISO C forbids assignment between "
+                                   "function pointer and %<void *%>"),
+                                N_("ISO C forbids initialization between "
+                                   "function pointer and %<void *%>"),
+                                N_("ISO C forbids return between function "
+                                   "pointer and %<void *%>"));
          /* Const and volatile mean something different for function types,
             so the usual warnings are not appropriate.  */
          else if (TREE_CODE (ttr) != FUNCTION_TYPE
                   && TREE_CODE (ttl) != FUNCTION_TYPE)
            {
              if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
-               warn_for_assignment ("%s discards qualifiers from pointer target type",
-                                    errtype, funname, parmnum);
+               WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE discards "
+                                       "qualifiers from pointer target type"),
+                                    N_("assignment discards qualifiers "
+                                       "from pointer target type"),
+                                    N_("initialization discards qualifiers "
+                                       "from pointer target type"),
+                                    N_("return discards qualifiers from "
+                                       "pointer target type"));
              /* If this is not a case of ignoring a mismatch in signedness,
                 no warning.  */
              else if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
@@ -3648,8 +3721,14 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
                ;
              /* If there is a mismatch, do warn.  */
              else
-               warn_for_assignment ("pointer targets in %s differ in signedness",
-                                    errtype, funname, parmnum);
+               WARN_FOR_ASSIGNMENT (N_("pointer targets in passing argument "
+                                       "%d of %qE differ in signedness"),
+                                    N_("pointer targets in assignment "
+                                       "differ in signedness"),
+                                    N_("pointer targets in initialization "
+                                       "differ in signedness"),
+                                    N_("pointer targets in return differ "
+                                       "in signedness"));
            }
          else if (TREE_CODE (ttl) == FUNCTION_TYPE
                   && TREE_CODE (ttr) == FUNCTION_TYPE)
@@ -3659,13 +3738,24 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
                 it is okay to use a const or volatile function
                 where an ordinary one is wanted, but not vice-versa.  */
              if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
-               warn_for_assignment ("%s makes qualified function pointer from unqualified",
-                                    errtype, funname, parmnum);
+               WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE makes "
+                                       "qualified function pointer "
+                                       "from unqualified"),
+                                    N_("assignment makes qualified function "
+                                       "pointer from unqualified"),
+                                    N_("initialization makes qualified "
+                                       "function pointer from unqualified"),
+                                    N_("return makes qualified function "
+                                       "pointer from unqualified"));
            }
        }
       else
-       warn_for_assignment ("%s from incompatible pointer type",
-                            errtype, funname, parmnum);
+       WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE from "
+                               "incompatible pointer type"),
+                            N_("assignment from incompatible pointer type"),
+                            N_("initialization from incompatible "
+                               "pointer type"),
+                            N_("return from incompatible pointer type"));
       return convert (type, rhs);
     }
   else if (codel == POINTER_TYPE && coder == ARRAY_TYPE)
@@ -3684,39 +3774,49 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
            && TREE_CODE (TREE_TYPE (rhs)) == INTEGER_TYPE
            && TREE_CODE (TREE_OPERAND (rhs, 0)) == INTEGER_CST
            && integer_zerop (TREE_OPERAND (rhs, 0))))
-         warn_for_assignment ("%s makes pointer from integer without a cast",
-                              errtype, funname, parmnum);
+       WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE makes "
+                               "pointer from integer without a cast"),
+                            N_("assignment makes pointer from integer "
+                               "without a cast"),
+                            N_("initialization makes pointer from "
+                               "integer without a cast"),
+                            N_("return makes pointer from integer "
+                               "without a cast"));
 
       return convert (type, rhs);
     }
   else if (codel == INTEGER_TYPE && coder == POINTER_TYPE)
     {
-      warn_for_assignment ("%s makes integer from pointer without a cast",
-                          errtype, funname, parmnum);
+      WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE makes integer "
+                             "from pointer without a cast"),
+                          N_("assignment makes integer from pointer "
+                             "without a cast"),
+                          N_("initialization makes integer from pointer "
+                             "without a cast"),
+                          N_("return makes integer from pointer "
+                             "without a cast"));
       return convert (type, rhs);
     }
   else if (codel == BOOLEAN_TYPE && coder == POINTER_TYPE)
     return convert (type, rhs);
 
-  if (!errtype)
+  switch (errtype)
     {
-      if (funname)
-       {
-         tree selector = objc_message_selector ();
-
-         if (selector && parmnum > 2)
-           error ("incompatible type for argument %d of %qs",
-                  parmnum - 2, IDENTIFIER_POINTER (selector));
-         else
-           error ("incompatible type for argument %d of %qs",
-                  parmnum, IDENTIFIER_POINTER (funname));
-       }
-      else
-       error ("incompatible type for argument %d of indirect function call",
-              parmnum);
+    case ic_argpass:
+      error ("incompatible type for argument %d of %qE", parmnum, rname);
+      break;
+    case ic_assign:
+      error ("incompatible types in assignment");
+      break;
+    case ic_init:
+      error ("incompatible types in initialization");
+      break;
+    case ic_return:
+      error ("incompatible types in return");
+      break;
+    default:
+      gcc_unreachable ();
     }
-  else
-    error ("incompatible types in %s", errtype);
 
   return error_mark_node;
 }
@@ -3737,56 +3837,14 @@ c_convert_parm_for_inlining (tree parm, tree value, tree fn, int argnum)
 
   type = TREE_TYPE (parm);
   ret = convert_for_assignment (type, value,
-                               (char *) 0 /* arg passing  */, fn,
-                               DECL_NAME (fn), argnum);
+                               ic_argpass, fn,
+                               fn, argnum);
   if (targetm.calls.promote_prototypes (TREE_TYPE (fn))
       && INTEGRAL_TYPE_P (type)
       && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
     ret = default_conversion (ret);
   return ret;
 }
-
-/* Print a warning using MSGID.
-   It gets OPNAME as its one parameter.
-   If OPNAME is null, it is replaced by "passing arg ARGNUM of 'FUNCTION'".
-   FUNCTION and ARGNUM are handled specially if we are building an
-   Objective-C selector.  */
-
-static void
-warn_for_assignment (const char *msgid, const char *opname, tree function,
-                    int argnum)
-{
-  if (opname == 0)
-    {
-      tree selector = objc_message_selector ();
-      char * new_opname;
-
-      if (selector && argnum > 2)
-       {
-         function = selector;
-         argnum -= 2;
-       }
-      gcc_assert (argnum > 0);
-      if (function)
-       {
-         /* Function name is known; supply it.  */
-         const char *const argstring = _("passing arg %d of '%s'");
-         new_opname = (char *) alloca (IDENTIFIER_LENGTH (function)
-                              + strlen (argstring) + 1 + 25 /*%d*/ + 1);
-         sprintf (new_opname, argstring, argnum,
-                  IDENTIFIER_POINTER (function));
-       }
-      else
-       {
-         /* Function name unknown (call through ptr); just give arg number.  */
-         const char *const argnofun = _("passing arg %d of pointer to function");
-         new_opname = (char *) alloca (strlen (argnofun) + 1 + 25 /*%d*/ + 1);
-         sprintf (new_opname, argnofun, argnum);
-       }
-      opname = new_opname;
-    }
-  pedwarn (msgid, opname);
-}
 \f
 /* If VALUE is a compound expr all of whose expressions are constant, then
    return its value.  Otherwise, return error_mark_node.
@@ -4254,7 +4312,7 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
         for arrays and functions.  We must not call it in the
         case where inside_init is a null pointer constant.  */
       inside_init
-       = convert_for_assignment (type, init, _("initialization"),
+       = convert_for_assignment (type, init, ic_init,
                                  NULL_TREE, NULL_TREE, 0);
 
       /* Check to see if we have already given an error message.  */
@@ -6394,7 +6452,7 @@ c_finish_return (tree retval)
     }
   else
     {
-      tree t = convert_for_assignment (valtype, retval, _("return"),
+      tree t = convert_for_assignment (valtype, retval, ic_return,
                                       NULL_TREE, NULL_TREE, 0);
       tree res = DECL_RESULT (current_function_decl);
       tree inner;
index 6a0cd62..616e74c 100644 (file)
@@ -1,3 +1,9 @@
+2004-10-08  Joseph S. Myers  <jsm@polyomino.org.uk>
+
+       * gcc.dg/assign-warn-1.c, gcc.dg/assign-warn-2.c: New tests.
+       * gcc.dg/warn-1.c, gcc.dg/noncompile/20020213-1.c,
+       objc.dg/method-9.m: Update expected diagnostics.
+
 2004-10-07  Geoffrey Keating  <geoffk@apple.com>
 
        * gcc.dg/ppc-fsel-3.c: New file.
diff --git a/gcc/testsuite/gcc.dg/assign-warn-1.c b/gcc/testsuite/gcc.dg/assign-warn-1.c
new file mode 100644 (file)
index 0000000..857b1a8
--- /dev/null
@@ -0,0 +1,123 @@
+/* Test diagnostics for bad implicit type conversions.  */
+/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
+/* { dg-do compile } */
+/* { dg-options "-pedantic" } */
+
+#define TESTARG(ID, TL, TR) void ID##F(TL); void ID##F2(TR x) { ID##F(x); } extern int dummy
+#define TESTARP(ID, TL, TR) struct { void (*x)(TL); } ID##Fp; void ID##F2(TR x) { ID##Fp.x(x); } extern int dummy
+#define TESTASS(ID, TL, TR) void ID##F(TR x) { TL y; y = x; } extern int dummy
+#define TESTINI(ID, TL, TR) void ID##F(TR x) { TL y = x; } extern int dummy
+#define TESTRET(ID, TL, TR) TR ID##V; TL ID##F(void) { return ID##V; } extern int dummy
+
+typedef void (*fp)(void);
+typedef void (*nrfp)(void) __attribute__((noreturn));
+
+TESTARG(fqa, nrfp, fp); /* { dg-warning "warning: passing argument 1 of 'fqaF' makes qualified function pointer from unqualified" } */
+TESTARP(fqb, nrfp, fp); /* { dg-warning "warning: passing argument 1 of 'fqbFp.x' makes qualified function pointer from unqualified" } */
+TESTASS(fqc, nrfp, fp); /* { dg-warning "warning: assignment makes qualified function pointer from unqualified" } */
+TESTINI(fqd, nrfp, fp); /* { dg-warning "warning: initialization makes qualified function pointer from unqualified" } */
+TESTRET(fqe, nrfp, fp); /* { dg-warning "warning: return makes qualified function pointer from unqualified" } */
+
+TESTARG(ofqa, fp, nrfp);
+TESTARP(ofqb, fp, nrfp);
+TESTASS(ofqc, fp, nrfp);
+TESTINI(ofqd, fp, nrfp);
+TESTRET(ofqe, fp, nrfp);
+
+TESTARG(qa, char *, const char *); /* { dg-warning "warning: passing argument 1 of 'qaF' discards qualifiers from pointer target type" } */
+TESTARP(qb, char *, const char *); /* { dg-warning "warning: passing argument 1 of 'qbFp.x' discards qualifiers from pointer target type" } */
+TESTASS(qc, char *, const char *); /* { dg-warning "warning: assignment discards qualifiers from pointer target type" } */
+TESTINI(qd, char *, const char *); /* { dg-warning "warning: initialization discards qualifiers from pointer target type" } */
+TESTRET(qe, char *, const char *); /* { dg-warning "warning: return discards qualifiers from pointer target type" } */
+
+TESTARG(oqa, const char *, char *);
+TESTARP(oqb, const char *, char *);
+TESTASS(oqc, const char *, char *);
+TESTINI(oqd, const char *, char *);
+TESTRET(oqe, const char *, char *);
+
+TESTARG(fda, fp, void *); /* { dg-warning "warning: ISO C forbids passing argument 1 of 'fdaF' between function pointer and 'void \\*'" } */
+TESTARP(fdb, fp, void *); /* { dg-warning "warning: ISO C forbids passing argument 1 of 'fdbFp.x' between function pointer and 'void \\*'" } */
+TESTASS(fdc, fp, void *); /* { dg-warning "warning: ISO C forbids assignment between function pointer and 'void \\*'" } */
+TESTINI(fdd, fp, void *); /* { dg-warning "warning: ISO C forbids initialization between function pointer and 'void \\*'" } */
+TESTRET(fde, fp, void *); /* { dg-warning "warning: ISO C forbids return between function pointer and 'void \\*'" } */
+
+TESTARG(dfa, void *, fp); /* { dg-warning "warning: ISO C forbids passing argument 1 of 'dfaF' between function pointer and 'void \\*'" } */
+TESTARP(dfb, void *, fp); /* { dg-warning "warning: ISO C forbids passing argument 1 of 'dfbFp.x' between function pointer and 'void \\*'" } */
+TESTASS(dfc, void *, fp); /* { dg-warning "warning: ISO C forbids assignment between function pointer and 'void \\*'" } */
+TESTINI(dfd, void *, fp); /* { dg-warning "warning: ISO C forbids initialization between function pointer and 'void \\*'" } */
+TESTRET(dfe, void *, fp); /* { dg-warning "warning: ISO C forbids return between function pointer and 'void \\*'" } */
+
+TESTARG(sua, int *, unsigned int *); /* { dg-warning "warning: pointer targets in passing argument 1 of 'suaF' differ in signedness" } */
+TESTARP(sub, int *, unsigned int *); /* { dg-warning "warning: pointer targets in passing argument 1 of 'subFp.x' differ in signedness" } */
+TESTASS(suc, int *, unsigned int *); /* { dg-warning "warning: pointer targets in assignment differ in signedness" } */
+TESTINI(sud, int *, unsigned int *); /* { dg-warning "warning: pointer targets in initialization differ in signedness" } */
+TESTRET(sue, int *, unsigned int *); /* { dg-warning "warning: pointer targets in return differ in signedness" } */
+
+TESTARG(usa, unsigned int *, int *); /* { dg-warning "warning: pointer targets in passing argument 1 of 'usaF' differ in signedness" } */
+TESTARP(usb, unsigned int *, int *); /* { dg-warning "warning: pointer targets in passing argument 1 of 'usbFp.x' differ in signedness" } */
+TESTASS(usc, unsigned int *, int *); /* { dg-warning "warning: pointer targets in assignment differ in signedness" } */
+TESTINI(usd, unsigned int *, int *); /* { dg-warning "warning: pointer targets in initialization differ in signedness" } */
+TESTRET(use, unsigned int *, int *); /* { dg-warning "warning: pointer targets in return differ in signedness" } */
+
+TESTARG(cua, char *, unsigned char *); /* { dg-warning "warning: pointer targets in passing argument 1 of 'cuaF' differ in signedness" } */
+TESTARP(cub, char *, unsigned char *); /* { dg-warning "warning: pointer targets in passing argument 1 of 'cubFp.x' differ in signedness" } */
+TESTASS(cuc, char *, unsigned char *); /* { dg-warning "warning: pointer targets in assignment differ in signedness" } */
+TESTINI(cud, char *, unsigned char *); /* { dg-warning "warning: pointer targets in initialization differ in signedness" } */
+TESTRET(cue, char *, unsigned char *); /* { dg-warning "warning: pointer targets in return differ in signedness" } */
+
+TESTARG(uca, unsigned char *, char *); /* { dg-warning "warning: pointer targets in passing argument 1 of 'ucaF' differ in signedness" } */
+TESTARP(ucb, unsigned char *, char *); /* { dg-warning "warning: pointer targets in passing argument 1 of 'ucbFp.x' differ in signedness" } */
+TESTASS(ucc, unsigned char *, char *); /* { dg-warning "warning: pointer targets in assignment differ in signedness" } */
+TESTINI(ucd, unsigned char *, char *); /* { dg-warning "warning: pointer targets in initialization differ in signedness" } */
+TESTRET(uce, unsigned char *, char *); /* { dg-warning "warning: pointer targets in return differ in signedness" } */
+
+TESTARG(csa, char *, signed char *); /* { dg-warning "warning: pointer targets in passing argument 1 of 'csaF' differ in signedness" } */
+TESTARP(csb, char *, signed char *); /* { dg-warning "warning: pointer targets in passing argument 1 of 'csbFp.x' differ in signedness" } */
+TESTASS(csc, char *, signed char *); /* { dg-warning "warning: pointer targets in assignment differ in signedness" } */
+TESTINI(csd, char *, signed char *); /* { dg-warning "warning: pointer targets in initialization differ in signedness" } */
+TESTRET(cse, char *, signed char *); /* { dg-warning "warning: pointer targets in return differ in signedness" } */
+
+TESTARG(sca, signed char *, char *); /* { dg-warning "warning: pointer targets in passing argument 1 of 'scaF' differ in signedness" } */
+TESTARP(scb, signed char *, char *); /* { dg-warning "warning: pointer targets in passing argument 1 of 'scbFp.x' differ in signedness" } */
+TESTASS(scc, signed char *, char *); /* { dg-warning "warning: pointer targets in assignment differ in signedness" } */
+TESTINI(scd, signed char *, char *); /* { dg-warning "warning: pointer targets in initialization differ in signedness" } */
+TESTRET(sce, signed char *, char *); /* { dg-warning "warning: pointer targets in return differ in signedness" } */
+
+TESTARG(cia, char *, int *); /* { dg-warning "warning: passing argument 1 of 'ciaF' from incompatible pointer type" } */
+TESTARP(cib, char *, int *); /* { dg-warning "warning: passing argument 1 of 'cibFp.x' from incompatible pointer type" } */
+TESTASS(cic, char *, int *); /* { dg-warning "warning: assignment from incompatible pointer type" } */
+TESTINI(cid, char *, int *); /* { dg-warning "warning: initialization from incompatible pointer type" } */
+TESTRET(cie, char *, int *); /* { dg-warning "warning: return from incompatible pointer type" } */
+
+TESTARG(ica, int *, char *); /* { dg-warning "warning: passing argument 1 of 'icaF' from incompatible pointer type" } */
+TESTARP(icb, int *, char *); /* { dg-warning "warning: passing argument 1 of 'icbFp.x' from incompatible pointer type" } */
+TESTASS(icc, int *, char *); /* { dg-warning "warning: assignment from incompatible pointer type" } */
+TESTINI(icd, int *, char *); /* { dg-warning "warning: initialization from incompatible pointer type" } */
+TESTRET(ice, int *, char *); /* { dg-warning "warning: return from incompatible pointer type" } */
+
+TESTARG(ciia, char *, int); /* { dg-warning "warning: passing argument 1 of 'ciiaF' makes pointer from integer without a cast" } */
+TESTARP(ciib, char *, int); /* { dg-warning "warning: passing argument 1 of 'ciibFp.x' makes pointer from integer without a cast" } */
+TESTASS(ciic, char *, int); /* { dg-warning "warning: assignment makes pointer from integer without a cast" } */
+TESTINI(ciid, char *, int); /* { dg-warning "warning: initialization makes pointer from integer without a cast" } */
+TESTRET(ciie, char *, int); /* { dg-warning "warning: return makes pointer from integer without a cast" } */
+
+TESTARG(iica, int, char *); /* { dg-warning "warning: passing argument 1 of 'iicaF' makes integer from pointer without a cast" } */
+TESTARP(iicb, int, char *); /* { dg-warning "warning: passing argument 1 of 'iicbFp.x' makes integer from pointer without a cast" } */
+TESTASS(iicc, int, char *); /* { dg-warning "warning: assignment makes integer from pointer without a cast" } */
+TESTINI(iicd, int, char *); /* { dg-warning "warning: initialization makes integer from pointer without a cast" } */
+TESTRET(iice, int, char *); /* { dg-warning "warning: return makes integer from pointer without a cast" } */
+
+struct s { int a; };
+
+TESTARG(stria, struct s, int); /* { dg-error "error: incompatible type for argument 1 of 'striaF'" } */
+TESTARP(strib, struct s, int); /* { dg-error "error: incompatible type for argument 1 of 'stribFp.x'" } */
+TESTASS(stric, struct s, int); /* { dg-error "error: incompatible types in assignment" } */
+TESTINI(strid, struct s, int); /* { dg-error "error: invalid initializer" } */
+TESTRET(strie, struct s, int); /* { dg-error "error: incompatible types in return" } */
+
+TESTARG(istra, int, struct s); /* { dg-error "error: incompatible type for argument 1 of 'istraF'" } */
+TESTARP(istrb, int, struct s); /* { dg-error "error: incompatible type for argument 1 of 'istrbFp.x'" } */
+TESTASS(istrc, int, struct s); /* { dg-error "error: incompatible types in assignment" } */
+TESTINI(istrd, int, struct s); /* { dg-error "error: incompatible types in initialization" } */
+TESTRET(istre, int, struct s); /* { dg-error "error: incompatible types in return" } */
diff --git a/gcc/testsuite/gcc.dg/assign-warn-2.c b/gcc/testsuite/gcc.dg/assign-warn-2.c
new file mode 100644 (file)
index 0000000..eae22d1
--- /dev/null
@@ -0,0 +1,124 @@
+/* Test diagnostics for bad implicit type conversions.
+   -pedantic-errors test.  */
+/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
+/* { dg-do compile } */
+/* { dg-options "-pedantic-errors" } */
+
+#define TESTARG(ID, TL, TR) void ID##F(TL); void ID##F2(TR x) { ID##F(x); } extern int dummy
+#define TESTARP(ID, TL, TR) struct { void (*x)(TL); } ID##Fp; void ID##F2(TR x) { ID##Fp.x(x); } extern int dummy
+#define TESTASS(ID, TL, TR) void ID##F(TR x) { TL y; y = x; } extern int dummy
+#define TESTINI(ID, TL, TR) void ID##F(TR x) { TL y = x; } extern int dummy
+#define TESTRET(ID, TL, TR) TR ID##V; TL ID##F(void) { return ID##V; } extern int dummy
+
+typedef void (*fp)(void);
+typedef void (*nrfp)(void) __attribute__((noreturn));
+
+TESTARG(fqa, nrfp, fp); /* { dg-error "error: passing argument 1 of 'fqaF' makes qualified function pointer from unqualified" } */
+TESTARP(fqb, nrfp, fp); /* { dg-error "error: passing argument 1 of 'fqbFp.x' makes qualified function pointer from unqualified" } */
+TESTASS(fqc, nrfp, fp); /* { dg-error "error: assignment makes qualified function pointer from unqualified" } */
+TESTINI(fqd, nrfp, fp); /* { dg-error "error: initialization makes qualified function pointer from unqualified" } */
+TESTRET(fqe, nrfp, fp); /* { dg-error "error: return makes qualified function pointer from unqualified" } */
+
+TESTARG(ofqa, fp, nrfp);
+TESTARP(ofqb, fp, nrfp);
+TESTASS(ofqc, fp, nrfp);
+TESTINI(ofqd, fp, nrfp);
+TESTRET(ofqe, fp, nrfp);
+
+TESTARG(qa, char *, const char *); /* { dg-error "error: passing argument 1 of 'qaF' discards qualifiers from pointer target type" } */
+TESTARP(qb, char *, const char *); /* { dg-error "error: passing argument 1 of 'qbFp.x' discards qualifiers from pointer target type" } */
+TESTASS(qc, char *, const char *); /* { dg-error "error: assignment discards qualifiers from pointer target type" } */
+TESTINI(qd, char *, const char *); /* { dg-error "error: initialization discards qualifiers from pointer target type" } */
+TESTRET(qe, char *, const char *); /* { dg-error "error: return discards qualifiers from pointer target type" } */
+
+TESTARG(oqa, const char *, char *);
+TESTARP(oqb, const char *, char *);
+TESTASS(oqc, const char *, char *);
+TESTINI(oqd, const char *, char *);
+TESTRET(oqe, const char *, char *);
+
+TESTARG(fda, fp, void *); /* { dg-error "error: ISO C forbids passing argument 1 of 'fdaF' between function pointer and 'void \\*'" } */
+TESTARP(fdb, fp, void *); /* { dg-error "error: ISO C forbids passing argument 1 of 'fdbFp.x' between function pointer and 'void \\*'" } */
+TESTASS(fdc, fp, void *); /* { dg-error "error: ISO C forbids assignment between function pointer and 'void \\*'" } */
+TESTINI(fdd, fp, void *); /* { dg-error "error: ISO C forbids initialization between function pointer and 'void \\*'" } */
+TESTRET(fde, fp, void *); /* { dg-error "error: ISO C forbids return between function pointer and 'void \\*'" } */
+
+TESTARG(dfa, void *, fp); /* { dg-error "error: ISO C forbids passing argument 1 of 'dfaF' between function pointer and 'void \\*'" } */
+TESTARP(dfb, void *, fp); /* { dg-error "error: ISO C forbids passing argument 1 of 'dfbFp.x' between function pointer and 'void \\*'" } */
+TESTASS(dfc, void *, fp); /* { dg-error "error: ISO C forbids assignment between function pointer and 'void \\*'" } */
+TESTINI(dfd, void *, fp); /* { dg-error "error: ISO C forbids initialization between function pointer and 'void \\*'" } */
+TESTRET(dfe, void *, fp); /* { dg-error "error: ISO C forbids return between function pointer and 'void \\*'" } */
+
+TESTARG(sua, int *, unsigned int *); /* { dg-error "error: pointer targets in passing argument 1 of 'suaF' differ in signedness" } */
+TESTARP(sub, int *, unsigned int *); /* { dg-error "error: pointer targets in passing argument 1 of 'subFp.x' differ in signedness" } */
+TESTASS(suc, int *, unsigned int *); /* { dg-error "error: pointer targets in assignment differ in signedness" } */
+TESTINI(sud, int *, unsigned int *); /* { dg-error "error: pointer targets in initialization differ in signedness" } */
+TESTRET(sue, int *, unsigned int *); /* { dg-error "error: pointer targets in return differ in signedness" } */
+
+TESTARG(usa, unsigned int *, int *); /* { dg-error "error: pointer targets in passing argument 1 of 'usaF' differ in signedness" } */
+TESTARP(usb, unsigned int *, int *); /* { dg-error "error: pointer targets in passing argument 1 of 'usbFp.x' differ in signedness" } */
+TESTASS(usc, unsigned int *, int *); /* { dg-error "error: pointer targets in assignment differ in signedness" } */
+TESTINI(usd, unsigned int *, int *); /* { dg-error "error: pointer targets in initialization differ in signedness" } */
+TESTRET(use, unsigned int *, int *); /* { dg-error "error: pointer targets in return differ in signedness" } */
+
+TESTARG(cua, char *, unsigned char *); /* { dg-error "error: pointer targets in passing argument 1 of 'cuaF' differ in signedness" } */
+TESTARP(cub, char *, unsigned char *); /* { dg-error "error: pointer targets in passing argument 1 of 'cubFp.x' differ in signedness" } */
+TESTASS(cuc, char *, unsigned char *); /* { dg-error "error: pointer targets in assignment differ in signedness" } */
+TESTINI(cud, char *, unsigned char *); /* { dg-error "error: pointer targets in initialization differ in signedness" } */
+TESTRET(cue, char *, unsigned char *); /* { dg-error "error: pointer targets in return differ in signedness" } */
+
+TESTARG(uca, unsigned char *, char *); /* { dg-error "error: pointer targets in passing argument 1 of 'ucaF' differ in signedness" } */
+TESTARP(ucb, unsigned char *, char *); /* { dg-error "error: pointer targets in passing argument 1 of 'ucbFp.x' differ in signedness" } */
+TESTASS(ucc, unsigned char *, char *); /* { dg-error "error: pointer targets in assignment differ in signedness" } */
+TESTINI(ucd, unsigned char *, char *); /* { dg-error "error: pointer targets in initialization differ in signedness" } */
+TESTRET(uce, unsigned char *, char *); /* { dg-error "error: pointer targets in return differ in signedness" } */
+
+TESTARG(csa, char *, signed char *); /* { dg-error "error: pointer targets in passing argument 1 of 'csaF' differ in signedness" } */
+TESTARP(csb, char *, signed char *); /* { dg-error "error: pointer targets in passing argument 1 of 'csbFp.x' differ in signedness" } */
+TESTASS(csc, char *, signed char *); /* { dg-error "error: pointer targets in assignment differ in signedness" } */
+TESTINI(csd, char *, signed char *); /* { dg-error "error: pointer targets in initialization differ in signedness" } */
+TESTRET(cse, char *, signed char *); /* { dg-error "error: pointer targets in return differ in signedness" } */
+
+TESTARG(sca, signed char *, char *); /* { dg-error "error: pointer targets in passing argument 1 of 'scaF' differ in signedness" } */
+TESTARP(scb, signed char *, char *); /* { dg-error "error: pointer targets in passing argument 1 of 'scbFp.x' differ in signedness" } */
+TESTASS(scc, signed char *, char *); /* { dg-error "error: pointer targets in assignment differ in signedness" } */
+TESTINI(scd, signed char *, char *); /* { dg-error "error: pointer targets in initialization differ in signedness" } */
+TESTRET(sce, signed char *, char *); /* { dg-error "error: pointer targets in return differ in signedness" } */
+
+TESTARG(cia, char *, int *); /* { dg-error "error: passing argument 1 of 'ciaF' from incompatible pointer type" } */
+TESTARP(cib, char *, int *); /* { dg-error "error: passing argument 1 of 'cibFp.x' from incompatible pointer type" } */
+TESTASS(cic, char *, int *); /* { dg-error "error: assignment from incompatible pointer type" } */
+TESTINI(cid, char *, int *); /* { dg-error "error: initialization from incompatible pointer type" } */
+TESTRET(cie, char *, int *); /* { dg-error "error: return from incompatible pointer type" } */
+
+TESTARG(ica, int *, char *); /* { dg-error "error: passing argument 1 of 'icaF' from incompatible pointer type" } */
+TESTARP(icb, int *, char *); /* { dg-error "error: passing argument 1 of 'icbFp.x' from incompatible pointer type" } */
+TESTASS(icc, int *, char *); /* { dg-error "error: assignment from incompatible pointer type" } */
+TESTINI(icd, int *, char *); /* { dg-error "error: initialization from incompatible pointer type" } */
+TESTRET(ice, int *, char *); /* { dg-error "error: return from incompatible pointer type" } */
+
+TESTARG(ciia, char *, int); /* { dg-error "error: passing argument 1 of 'ciiaF' makes pointer from integer without a cast" } */
+TESTARP(ciib, char *, int); /* { dg-error "error: passing argument 1 of 'ciibFp.x' makes pointer from integer without a cast" } */
+TESTASS(ciic, char *, int); /* { dg-error "error: assignment makes pointer from integer without a cast" } */
+TESTINI(ciid, char *, int); /* { dg-error "error: initialization makes pointer from integer without a cast" } */
+TESTRET(ciie, char *, int); /* { dg-error "error: return makes pointer from integer without a cast" } */
+
+TESTARG(iica, int, char *); /* { dg-error "error: passing argument 1 of 'iicaF' makes integer from pointer without a cast" } */
+TESTARP(iicb, int, char *); /* { dg-error "error: passing argument 1 of 'iicbFp.x' makes integer from pointer without a cast" } */
+TESTASS(iicc, int, char *); /* { dg-error "error: assignment makes integer from pointer without a cast" } */
+TESTINI(iicd, int, char *); /* { dg-error "error: initialization makes integer from pointer without a cast" } */
+TESTRET(iice, int, char *); /* { dg-error "error: return makes integer from pointer without a cast" } */
+
+struct s { int a; };
+
+TESTARG(stria, struct s, int); /* { dg-error "error: incompatible type for argument 1 of 'striaF'" } */
+TESTARP(strib, struct s, int); /* { dg-error "error: incompatible type for argument 1 of 'stribFp.x'" } */
+TESTASS(stric, struct s, int); /* { dg-error "error: incompatible types in assignment" } */
+TESTINI(strid, struct s, int); /* { dg-error "error: invalid initializer" } */
+TESTRET(strie, struct s, int); /* { dg-error "error: incompatible types in return" } */
+
+TESTARG(istra, int, struct s); /* { dg-error "error: incompatible type for argument 1 of 'istraF'" } */
+TESTARP(istrb, int, struct s); /* { dg-error "error: incompatible type for argument 1 of 'istrbFp.x'" } */
+TESTASS(istrc, int, struct s); /* { dg-error "error: incompatible types in assignment" } */
+TESTINI(istrd, int, struct s); /* { dg-error "error: incompatible types in initialization" } */
+TESTRET(istre, int, struct s); /* { dg-error "error: incompatible types in return" } */
index 77798b5..c1de566 100644 (file)
@@ -24,8 +24,8 @@ int main ()
   return 0;
 }
 
-/* { dg-warning "passing arg 2 of" "2nd incompatible" { target *-*-* } 15 } */
-/* { dg-warning "passing arg 1 of" "1st incompatible" { target *-*-* } 16 } */
-/* { dg-warning "passing arg 2 of" "2nd incompatible" { target *-*-* } 16 } */
-/* { dg-warning "passing arg 1 of" "1st incompatible" { target *-*-* } 18 } */
-/* { dg-warning "passing arg 1 of" "1st incompatible" { target *-*-* } 20 } */
+/* { dg-warning "passing argument 2 of" "2nd incompatible" { target *-*-* } 15 } */
+/* { dg-warning "passing argument 1 of" "1st incompatible" { target *-*-* } 16 } */
+/* { dg-warning "passing argument 2 of" "2nd incompatible" { target *-*-* } 16 } */
+/* { dg-warning "passing argument 1 of" "1st incompatible" { target *-*-* } 18 } */
+/* { dg-warning "passing argument 1 of" "1st incompatible" { target *-*-* } 20 } */
index ce35b41..dc2cd0e 100644 (file)
@@ -12,5 +12,5 @@ void bar (void)
 {
   void *vp;
 
-  foo (vp);    /* { dg-warning "passing arg 1 of" } */
+  foo (vp);    /* { dg-warning "passing argument 1 of" } */
 }
index ba83284..3921663 100644 (file)
@@ -37,7 +37,7 @@
      /* { dg-warning "also found .\\-\\(id\\)initWithData:\\(int\\)data." "" { target *-*-* } 13 } */
 
      /* The following warning is a consequence of picking the "wrong" method signature.  */
-     /* { dg-warning "passing arg 1 of .initWithData:. from incompatible pointer type" "" { target *-*-* } 33 } */
+     /* { dg-warning "passing argument 1 of .initWithData:. from incompatible pointer type" "" { target *-*-* } 33 } */
     return result;
 }
 @end